From 5efa640e232ba7069b44da6daab6e72e80323c6d Mon Sep 17 00:00:00 2001 From: Marcin Mielniczuk Date: Tue, 7 Jan 2020 17:08:51 +0100 Subject: [PATCH 01/28] Add a test for path_open read rights --- .../src/bin/path_open_read_without_rights.rs | 88 +++++++++++++++++++ crates/test-programs/wasi-tests/src/lib.rs | 21 +++++ 2 files changed, 109 insertions(+) create mode 100644 crates/test-programs/wasi-tests/src/bin/path_open_read_without_rights.rs diff --git a/crates/test-programs/wasi-tests/src/bin/path_open_read_without_rights.rs b/crates/test-programs/wasi-tests/src/bin/path_open_read_without_rights.rs new file mode 100644 index 0000000000..c3f499bc9d --- /dev/null +++ b/crates/test-programs/wasi-tests/src/bin/path_open_read_without_rights.rs @@ -0,0 +1,88 @@ +use std::{env, process}; +use wasi_tests::open_scratch_directory; +use wasi_tests::{drop_rights, fd_get_rights}; + +const TEST_FILENAME: &'static str = "file"; + +unsafe fn create_testfile(dir_fd: wasi::Fd) { + let fd = wasi::path_open( + dir_fd, + 0, + TEST_FILENAME, + wasi::OFLAGS_CREAT | wasi::OFLAGS_EXCL, + wasi::RIGHTS_FD_READ | wasi::RIGHTS_FD_WRITE, + 0, + 0, + ) + .expect("creating a file"); + wasi::fd_close(fd).expect("closing a file"); +} + +unsafe fn try_read_file(dir_fd: wasi::Fd) { + let fd = wasi::path_open(dir_fd, 0, TEST_FILENAME, 0, 0, 0, 0).expect("opening the file"); + + // Check that we don't have the right to exeucute fd_read + let (rbase, rinher) = fd_get_rights(fd); + assert_eq!( + rbase & wasi::RIGHTS_FD_READ, + 0, + "should not have base RIGHTS_FD_READ" + ); + assert_eq!( + rinher & wasi::RIGHTS_FD_READ, + 0, + "should not have inheriting RIGHTS_FD_READ" + ); + + let contents = &mut [0u8; 1]; + let iovec = wasi::Iovec { + buf: contents.as_mut_ptr() as *mut _, + buf_len: contents.len(), + }; + // Since we no longer have the right to fd_read, trying to read a file + // should be an error. + let err = wasi::fd_read(fd, &[iovec]).expect_err("reading bytes from file should fail"); + assert_eq!(err, wasi::ERRNO_NOTCAPABLE, "the errno should be ENOTCAPABLE"); +} + +unsafe fn test_read_rights(dir_fd: wasi::Fd) { + create_testfile(dir_fd); + drop_rights(dir_fd, wasi::RIGHTS_FD_READ, wasi::RIGHTS_FD_READ); + + let (rbase, rinher) = fd_get_rights(dir_fd); + assert_eq!( + rbase & wasi::RIGHTS_FD_READ, + 0, + "dir should not have base RIGHTS_FD_READ" + ); + assert_eq!( + rinher & wasi::RIGHTS_FD_READ, + 0, + "dir should not have inheriting RIGHTS_FD_READ" + ); + + try_read_file(dir_fd); +} + +fn main() { + let mut args = env::args(); + let prog = args.next().unwrap(); + let arg = if let Some(arg) = args.next() { + arg + } else { + eprintln!("usage: {} ", prog); + process::exit(1); + }; + + // Open scratch directory + let dir_fd = match open_scratch_directory(&arg) { + Ok(dir_fd) => dir_fd, + Err(err) => { + eprintln!("{}", err); + process::exit(1) + } + }; + + // Run the tests. + unsafe { test_read_rights(dir_fd) } +} diff --git a/crates/test-programs/wasi-tests/src/lib.rs b/crates/test-programs/wasi-tests/src/lib.rs index a1080c00be..c785b7769a 100644 --- a/crates/test-programs/wasi-tests/src/lib.rs +++ b/crates/test-programs/wasi-tests/src/lib.rs @@ -43,3 +43,24 @@ pub unsafe fn create_file(dir_fd: wasi::Fd, filename: &str) { ); wasi::fd_close(file_fd).expect("closing a file"); } + +// Returns: (rights_base, rights_inheriting) +pub unsafe fn fd_get_rights(fd: wasi::Fd) -> (wasi::Rights, wasi::Rights) { + let fdstat = wasi::fd_fdstat_get(fd).expect("fd_fdstat_get failed"); + (fdstat.fs_rights_base, fdstat.fs_rights_inheriting) +} + +pub unsafe fn drop_rights( + fd: wasi::Fd, + drop_base: wasi::Rights, + drop_inheriting: wasi::Rights, +) { + let (current_base, current_inheriting) = fd_get_rights(fd); + + let new_base = current_base & !drop_base; + let new_inheriting = current_inheriting & !drop_inheriting; + + wasi::fd_fdstat_set_rights(fd, new_base, new_inheriting).expect( + "dropping fd rights", + ); +} From f7f10c12b33b2f78107646c76f31c5b9046414a3 Mon Sep 17 00:00:00 2001 From: Marcin Mielniczuk Date: Tue, 7 Jan 2020 17:19:20 +0100 Subject: [PATCH 02/28] Fix rights checks across the codebase. * Fix path_open granting more rights than requested * Add missing rights checks in: fd_fdstat_set_flags, fd_filestat_get, poll_oneoff * Fix `open_scratch_directory` not requesting any rights. * Properly request needed rights in various tests * Add some extra trace-level logging * Remove a no-op restriction of rights to the ones returned by `determine_type_rights`. It was redundant, because `FdEntry:from` internally also called `determine_type_rights` and only dropped some of them. --- .../wasi-tests/src/bin/fd_advise.rs | 6 +++- .../wasi-tests/src/bin/fd_filestat_set.rs | 6 +++- .../wasi-tests/src/bin/fd_readdir.rs | 5 +++- .../wasi-tests/src/bin/file_allocate.rs | 5 +++- .../wasi-tests/src/bin/file_seek_tell.rs | 2 +- .../wasi-tests/src/bin/path_link.rs | 11 ++++++-- .../src/bin/path_open_read_without_rights.rs | 18 ++---------- .../wasi-tests/src/bin/poll_oneoff.rs | 2 +- crates/test-programs/wasi-tests/src/lib.rs | 3 +- crates/wasi-common/src/fdentry.rs | 17 +++++++++-- crates/wasi-common/src/hostcalls_impl/fs.rs | 28 ++++++++++++++----- crates/wasi-common/src/hostcalls_impl/misc.rs | 4 +-- 12 files changed, 71 insertions(+), 36 deletions(-) diff --git a/crates/test-programs/wasi-tests/src/bin/fd_advise.rs b/crates/test-programs/wasi-tests/src/bin/fd_advise.rs index 359f47fbb6..408edf3490 100644 --- a/crates/test-programs/wasi-tests/src/bin/fd_advise.rs +++ b/crates/test-programs/wasi-tests/src/bin/fd_advise.rs @@ -9,7 +9,11 @@ unsafe fn test_fd_advise(dir_fd: wasi::Fd) { 0, "file", wasi::OFLAGS_CREAT, - wasi::RIGHTS_FD_READ | wasi::RIGHTS_FD_WRITE, + wasi::RIGHTS_FD_READ + | wasi::RIGHTS_FD_WRITE + | wasi::RIGHTS_FD_ADVISE + | wasi::RIGHTS_FD_FILESTAT_GET + | wasi::RIGHTS_FD_ALLOCATE, 0, 0, ) diff --git a/crates/test-programs/wasi-tests/src/bin/fd_filestat_set.rs b/crates/test-programs/wasi-tests/src/bin/fd_filestat_set.rs index ea1be8fe1a..0f7cefcfe5 100644 --- a/crates/test-programs/wasi-tests/src/bin/fd_filestat_set.rs +++ b/crates/test-programs/wasi-tests/src/bin/fd_filestat_set.rs @@ -9,7 +9,11 @@ unsafe fn test_fd_filestat_set(dir_fd: wasi::Fd) { 0, "file", wasi::OFLAGS_CREAT, - wasi::RIGHTS_FD_READ | wasi::RIGHTS_FD_WRITE, + wasi::RIGHTS_FD_READ + | wasi::RIGHTS_FD_WRITE + | wasi::RIGHTS_FD_FILESTAT_GET + | wasi::RIGHTS_FD_FILESTAT_SET_SIZE + | wasi::RIGHTS_FD_FILESTAT_SET_TIMES, 0, 0, ) diff --git a/crates/test-programs/wasi-tests/src/bin/fd_readdir.rs b/crates/test-programs/wasi-tests/src/bin/fd_readdir.rs index 8a3931cde8..8790ea0218 100644 --- a/crates/test-programs/wasi-tests/src/bin/fd_readdir.rs +++ b/crates/test-programs/wasi-tests/src/bin/fd_readdir.rs @@ -90,7 +90,10 @@ unsafe fn test_fd_readdir(dir_fd: wasi::Fd) { 0, "file", wasi::OFLAGS_CREAT, - wasi::RIGHTS_FD_READ | wasi::RIGHTS_FD_WRITE, + wasi::RIGHTS_FD_READ + | wasi::RIGHTS_FD_WRITE + | wasi::RIGHTS_FD_READDIR + | wasi::RIGHTS_FD_FILESTAT_GET, 0, 0, ) diff --git a/crates/test-programs/wasi-tests/src/bin/file_allocate.rs b/crates/test-programs/wasi-tests/src/bin/file_allocate.rs index f1df5e8060..cadee68ab5 100644 --- a/crates/test-programs/wasi-tests/src/bin/file_allocate.rs +++ b/crates/test-programs/wasi-tests/src/bin/file_allocate.rs @@ -9,7 +9,10 @@ unsafe fn test_file_allocate(dir_fd: wasi::Fd) { 0, "file", wasi::OFLAGS_CREAT, - wasi::RIGHTS_FD_READ | wasi::RIGHTS_FD_WRITE, + wasi::RIGHTS_FD_READ + | wasi::RIGHTS_FD_WRITE + | wasi::RIGHTS_FD_ALLOCATE + | wasi::RIGHTS_FD_FILESTAT_GET, 0, 0, ) diff --git a/crates/test-programs/wasi-tests/src/bin/file_seek_tell.rs b/crates/test-programs/wasi-tests/src/bin/file_seek_tell.rs index 9c179580e6..59357d3ad8 100644 --- a/crates/test-programs/wasi-tests/src/bin/file_seek_tell.rs +++ b/crates/test-programs/wasi-tests/src/bin/file_seek_tell.rs @@ -9,7 +9,7 @@ unsafe fn test_file_seek_tell(dir_fd: wasi::Fd) { 0, "file", wasi::OFLAGS_CREAT, - wasi::RIGHTS_FD_READ | wasi::RIGHTS_FD_WRITE, + wasi::RIGHTS_FD_READ | wasi::RIGHTS_FD_WRITE | wasi::RIGHTS_FD_SEEK | wasi::RIGHTS_FD_TELL, 0, 0, ) diff --git a/crates/test-programs/wasi-tests/src/bin/path_link.rs b/crates/test-programs/wasi-tests/src/bin/path_link.rs index 3e39e5f2cb..3e005012fd 100644 --- a/crates/test-programs/wasi-tests/src/bin/path_link.rs +++ b/crates/test-programs/wasi-tests/src/bin/path_link.rs @@ -2,8 +2,15 @@ use more_asserts::assert_gt; use std::{env, process}; use wasi_tests::{create_file, open_scratch_directory}; +const TEST_RIGHTS: wasi::Rights = wasi::RIGHTS_FD_READ + | wasi::RIGHTS_PATH_LINK_SOURCE + | wasi::RIGHTS_PATH_LINK_TARGET + | wasi::RIGHTS_FD_FILESTAT_GET + | wasi::RIGHTS_PATH_OPEN + | wasi::RIGHTS_PATH_UNLINK_FILE; + unsafe fn create_or_open(dir_fd: wasi::Fd, name: &str, flags: wasi::Oflags) -> wasi::Fd { - let file_fd = wasi::path_open(dir_fd, 0, name, flags, 0, 0, 0) + let file_fd = wasi::path_open(dir_fd, 0, name, flags, TEST_RIGHTS, TEST_RIGHTS, 0) .unwrap_or_else(|_| panic!("opening '{}'", name)); assert_gt!( file_fd, @@ -14,7 +21,7 @@ unsafe fn create_or_open(dir_fd: wasi::Fd, name: &str, flags: wasi::Oflags) -> w } unsafe fn open_link(dir_fd: wasi::Fd, name: &str) -> wasi::Fd { - let file_fd = wasi::path_open(dir_fd, 0, name, 0, 0, 0, 0) + let file_fd = wasi::path_open(dir_fd, 0, name, 0, TEST_RIGHTS, TEST_RIGHTS, 0) .unwrap_or_else(|_| panic!("opening a link '{}'", name)); assert_gt!( file_fd, diff --git a/crates/test-programs/wasi-tests/src/bin/path_open_read_without_rights.rs b/crates/test-programs/wasi-tests/src/bin/path_open_read_without_rights.rs index c3f499bc9d..47d4c7aaa3 100644 --- a/crates/test-programs/wasi-tests/src/bin/path_open_read_without_rights.rs +++ b/crates/test-programs/wasi-tests/src/bin/path_open_read_without_rights.rs @@ -1,23 +1,9 @@ use std::{env, process}; use wasi_tests::open_scratch_directory; -use wasi_tests::{drop_rights, fd_get_rights}; +use wasi_tests::{drop_rights, fd_get_rights, create_file}; const TEST_FILENAME: &'static str = "file"; -unsafe fn create_testfile(dir_fd: wasi::Fd) { - let fd = wasi::path_open( - dir_fd, - 0, - TEST_FILENAME, - wasi::OFLAGS_CREAT | wasi::OFLAGS_EXCL, - wasi::RIGHTS_FD_READ | wasi::RIGHTS_FD_WRITE, - 0, - 0, - ) - .expect("creating a file"); - wasi::fd_close(fd).expect("closing a file"); -} - unsafe fn try_read_file(dir_fd: wasi::Fd) { let fd = wasi::path_open(dir_fd, 0, TEST_FILENAME, 0, 0, 0, 0).expect("opening the file"); @@ -46,7 +32,7 @@ unsafe fn try_read_file(dir_fd: wasi::Fd) { } unsafe fn test_read_rights(dir_fd: wasi::Fd) { - create_testfile(dir_fd); + create_file(dir_fd, TEST_FILENAME); drop_rights(dir_fd, wasi::RIGHTS_FD_READ, wasi::RIGHTS_FD_READ); let (rbase, rinher) = fd_get_rights(dir_fd); diff --git a/crates/test-programs/wasi-tests/src/bin/poll_oneoff.rs b/crates/test-programs/wasi-tests/src/bin/poll_oneoff.rs index 1af4ed0575..235e2d8741 100644 --- a/crates/test-programs/wasi-tests/src/bin/poll_oneoff.rs +++ b/crates/test-programs/wasi-tests/src/bin/poll_oneoff.rs @@ -197,7 +197,7 @@ unsafe fn test_fd_readwrite_valid_fd(dir_fd: wasi::Fd) { 0, "file", wasi::OFLAGS_CREAT, - wasi::RIGHTS_FD_READ | wasi::RIGHTS_FD_WRITE, + wasi::RIGHTS_FD_READ | wasi::RIGHTS_FD_WRITE | wasi::RIGHTS_POLL_FD_READWRITE, 0, 0, ) diff --git a/crates/test-programs/wasi-tests/src/lib.rs b/crates/test-programs/wasi-tests/src/lib.rs index c785b7769a..008e570bb4 100644 --- a/crates/test-programs/wasi-tests/src/lib.rs +++ b/crates/test-programs/wasi-tests/src/lib.rs @@ -24,7 +24,8 @@ pub fn open_scratch_directory(path: &str) -> Result { } dst.set_len(stat.u.dir.pr_name_len); if dst == path.as_bytes() { - return Ok(wasi::path_open(i, 0, ".", wasi::OFLAGS_DIRECTORY, 0, 0, 0) + let (base, inherit) = fd_get_rights(i); + return Ok(wasi::path_open(i, 0, ".", wasi::OFLAGS_DIRECTORY, base, inherit, 0) .expect("failed to open dir")); } } diff --git a/crates/wasi-common/src/fdentry.rs b/crates/wasi-common/src/fdentry.rs index 73027cda1d..a86e6ce8b4 100644 --- a/crates/wasi-common/src/fdentry.rs +++ b/crates/wasi-common/src/fdentry.rs @@ -155,8 +155,21 @@ impl FdEntry { rights_base: wasi::__wasi_rights_t, rights_inheriting: wasi::__wasi_rights_t, ) -> Result<()> { - if !self.rights_base & rights_base != 0 || !self.rights_inheriting & rights_inheriting != 0 - { + let missing_base = !self.rights_base & rights_base; + let missing_inheriting = !self.rights_inheriting & rights_inheriting; + if missing_base != 0 || missing_inheriting != 0 { + log::trace!( + " | validate_rights failed: required: \ + rights_base = {:#x}, rights_inheriting = {:#x}; \ + actual: rights_base = {:#x}, rights_inheriting = {:#x}; \ + missing_base = {:#x}, missing_inheriting = {:#x}", + rights_base, + rights_inheriting, + self.rights_base, + self.rights_inheriting, + missing_base, + missing_inheriting + ); Err(Error::ENOTCAPABLE) } else { Ok(()) diff --git a/crates/wasi-common/src/hostcalls_impl/fs.rs b/crates/wasi-common/src/hostcalls_impl/fs.rs index 7f93fbc27d..cd321e47b0 100644 --- a/crates/wasi-common/src/hostcalls_impl/fs.rs +++ b/crates/wasi-common/src/hostcalls_impl/fs.rs @@ -5,7 +5,6 @@ use crate::fdentry::{Descriptor, FdEntry}; use crate::helpers::*; use crate::memory::*; use crate::sandboxed_tty_writer::SandboxedTTYWriter; -use crate::sys::fdentry_impl::determine_type_rights; use crate::sys::hostcalls_impl::fs_helpers::path_open_rights; use crate::sys::{host_impl, hostcalls_impl}; use crate::{helpers, host, wasi, wasi32, Error, Result}; @@ -308,7 +307,7 @@ pub(crate) unsafe fn fd_fdstat_set_flags( let fd = wasi_ctx .get_fd_entry(fd)? - .as_descriptor(0, 0)? + .as_descriptor(wasi::__WASI_RIGHTS_FD_FDSTAT_SET_FLAGS, 0)? .as_os_handle(); hostcalls_impl::fd_fdstat_set_flags(&fd, fdflags) @@ -574,6 +573,11 @@ pub(crate) unsafe fn path_open( let (needed_base, needed_inheriting) = path_open_rights(fs_rights_base, fs_rights_inheriting, oflags, fs_flags); + trace!( + " | needed_base = {}, needed_inheriting = {}", + needed_base, + needed_inheriting + ); let fe = wasi_ctx.get_fd_entry(dirfd)?; let resolved = path_get( fe, @@ -593,13 +597,20 @@ pub(crate) unsafe fn path_open( | wasi::__WASI_RIGHTS_FD_FILESTAT_SET_SIZE) != 0; + trace!( + " | calling path_open impl: read={}, write={}", + read, + write + ); let fd = hostcalls_impl::path_open(resolved, read, write, oflags, fs_flags)?; - // Determine the type of the new file descriptor and which rights contradict with this type - let (_ty, max_base, max_inheriting) = determine_type_rights(&fd)?; let mut fe = FdEntry::from(fd)?; - fe.rights_base &= max_base; - fe.rights_inheriting &= max_inheriting; + // We need to manually deny the rights which are not explicitly requested. + // This should not be needed, but currently determine_type_and_access_rights, + // which is used by FdEntry::from, may grant extra rights while inferring it + // from the open mode. + fe.rights_base &= fs_rights_base; + fe.rights_inheriting &= fs_rights_inheriting; let guest_fd = wasi_ctx.insert_fd_entry(fe)?; trace!(" | *fd={:?}", guest_fd); @@ -709,7 +720,10 @@ pub(crate) unsafe fn fd_filestat_get( filestat_ptr ); - let fd = wasi_ctx.get_fd_entry(fd)?.as_descriptor(0, 0)?.as_file()?; + let fd = wasi_ctx + .get_fd_entry(fd)? + .as_descriptor(wasi::__WASI_RIGHTS_FD_FILESTAT_GET, 0)? + .as_file()?; let host_filestat = hostcalls_impl::fd_filestat_get(fd)?; trace!(" | *filestat_ptr={:?}", host_filestat); diff --git a/crates/wasi-common/src/hostcalls_impl/misc.rs b/crates/wasi-common/src/hostcalls_impl/misc.rs index 696eb1b7ba..7e266033f8 100644 --- a/crates/wasi-common/src/hostcalls_impl/misc.rs +++ b/crates/wasi-common/src/hostcalls_impl/misc.rs @@ -242,9 +242,9 @@ pub(crate) fn poll_oneoff( { let wasi_fd = unsafe { subscription.u.fd_readwrite.file_descriptor }; let rights = if r#type == wasi::__WASI_EVENTTYPE_FD_READ { - wasi::__WASI_RIGHTS_FD_READ + wasi::__WASI_RIGHTS_FD_READ | wasi::__WASI_RIGHTS_POLL_FD_READWRITE } else { - wasi::__WASI_RIGHTS_FD_WRITE + wasi::__WASI_RIGHTS_FD_WRITE | wasi::__WASI_RIGHTS_POLL_FD_READWRITE }; match unsafe { From 4e0c1c08c18f1943505ffe7b1a257e157f99437c Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Thu, 9 Jan 2020 10:54:47 -0800 Subject: [PATCH 03/28] Update Cargo.lock. Cargo.lock is checked into the repositoryu now, so we need to explicitly keep it up to date. --- Cargo.lock | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index d91401e018..a6353468c8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1966,7 +1966,9 @@ name = "wasmtime" version = "0.7.0" dependencies = [ "anyhow", + "cfg-if", "file-per-thread-logger", + "libc", "pretty_env_logger", "rayon", "region", @@ -1979,6 +1981,7 @@ dependencies = [ "wasmtime-wasi", "wasmtime-wast", "wat", + "winapi", ] [[package]] @@ -2155,6 +2158,7 @@ name = "wasmtime-runtime" version = "0.7.0" dependencies = [ "cc", + "cfg-if", "indexmap", "lazy_static", "libc", From 036fd8ead5e3637bc3f9965643313c64d270d473 Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Thu, 9 Jan 2020 21:16:31 +0100 Subject: [PATCH 04/28] Fix path_open_read_without_rights test Fixes `path_open_read_without_rights` test making the CI green again. --- .../src/bin/path_open_read_without_rights.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/crates/test-programs/wasi-tests/src/bin/path_open_read_without_rights.rs b/crates/test-programs/wasi-tests/src/bin/path_open_read_without_rights.rs index 47d4c7aaa3..26113c08c8 100644 --- a/crates/test-programs/wasi-tests/src/bin/path_open_read_without_rights.rs +++ b/crates/test-programs/wasi-tests/src/bin/path_open_read_without_rights.rs @@ -1,6 +1,6 @@ use std::{env, process}; use wasi_tests::open_scratch_directory; -use wasi_tests::{drop_rights, fd_get_rights, create_file}; +use wasi_tests::{create_file, drop_rights, fd_get_rights}; const TEST_FILENAME: &'static str = "file"; @@ -27,8 +27,13 @@ unsafe fn try_read_file(dir_fd: wasi::Fd) { }; // Since we no longer have the right to fd_read, trying to read a file // should be an error. - let err = wasi::fd_read(fd, &[iovec]).expect_err("reading bytes from file should fail"); - assert_eq!(err, wasi::ERRNO_NOTCAPABLE, "the errno should be ENOTCAPABLE"); + assert_eq!( + wasi::fd_read(fd, &[iovec]) + .expect_err("reading bytes from file should fail") + .raw_error(), + wasi::ERRNO_NOTCAPABLE, + "the errno should be ENOTCAPABLE" + ); } unsafe fn test_read_rights(dir_fd: wasi::Fd) { From 64afd0305a2747b8906efddd2de45ab15db1131e Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Thu, 9 Jan 2020 22:01:56 +0100 Subject: [PATCH 05/28] Remove HostRefs in custom_signal_handlers --- tests/custom_signal_handler.rs | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/tests/custom_signal_handler.rs b/tests/custom_signal_handler.rs index 253d62d49d..3bea15adf7 100644 --- a/tests/custom_signal_handler.rs +++ b/tests/custom_signal_handler.rs @@ -74,11 +74,11 @@ mod tests { #[test] fn test_custom_signal_handler_single_instance() { - let engine = HostRef::new(Engine::new(&Config::default())); - let store = HostRef::new(Store::new(&engine)); + let engine = Engine::new(&Config::default()); + let store = Store::new(&engine); let data = std::fs::read("tests/custom_signal_handler.wasm").expect("failed to read wasm file"); - let module = HostRef::new(Module::new(&store, &data).expect("failed to create module")); + let module = Module::new(&store, &data).expect("failed to create module"); let instance = HostRef::new( Instance::new(&store, &module, &[]).expect("failed to instantiate module"), ); @@ -128,7 +128,6 @@ mod tests { println!("calling read_out_of_bounds..."); let trap = read_out_of_bounds_func.borrow().call(&[]).unwrap_err(); assert!(trap - .borrow() .message() .starts_with("wasm trap: out of bounds memory access")); } @@ -136,11 +135,11 @@ mod tests { #[test] fn test_custom_signal_handler_multiple_instances() { - let engine = HostRef::new(Engine::new(&Config::default())); - let store = HostRef::new(Store::new(&engine)); + let engine = Engine::new(&Config::default()); + let store = Store::new(&engine); let data = std::fs::read("tests/custom_signal_handler.wasm").expect("failed to read wasm file"); - let module = HostRef::new(Module::new(&store, &data).expect("failed to create module")); + let module = Module::new(&store, &data).expect("failed to create module"); // Set up multiple instances @@ -237,13 +236,13 @@ mod tests { #[test] fn test_custom_signal_handler_instance_calling_another_instance() { - let engine = HostRef::new(Engine::new(&Config::default())); - let store = HostRef::new(Store::new(&engine)); + let engine = Engine::new(&Config::default()); + let store = Store::new(&engine); // instance1 which defines 'read' let data1 = std::fs::read("tests/custom_signal_handler.wasm").expect("failed to read wasm file"); - let module1 = HostRef::new(Module::new(&store, &data1).expect("failed to create module")); + let module1 = Module::new(&store, &data1).expect("failed to create module"); let instance1: HostRef = HostRef::new( Instance::new(&store, &module1, &[]).expect("failed to instantiate module"), ); @@ -262,7 +261,7 @@ mod tests { // instance2 wich calls 'instance1.read' let data2 = std::fs::read("tests/custom_signal_handler_2.wasm").expect("failed to read wasm file"); - let module2 = HostRef::new(Module::new(&store, &data2).expect("failed to create module")); + let module2 = Module::new(&store, &data2).expect("failed to create module"); let instance2 = HostRef::new( Instance::new(&store, &module2, &[instance1_read]) .expect("failed to instantiate module"), From f83eafd6c29a35235c94e48ec7996f7dd34aedcf Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Thu, 9 Jan 2020 22:04:21 +0100 Subject: [PATCH 06/28] Add missing dev-dependency: wasmtime-runtime --- Cargo.lock | 1 + Cargo.toml | 1 + 2 files changed, 2 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index a6353468c8..b4a44fa796 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2006,6 +2006,7 @@ dependencies = [ "wasmtime-interface-types", "wasmtime-jit", "wasmtime-obj", + "wasmtime-runtime", "wasmtime-wasi", "wasmtime-wasi-c", "wasmtime-wast", diff --git a/Cargo.toml b/Cargo.toml index 3e72c70c8b..813ce9edfd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,6 +40,7 @@ rayon = "1.2.1" wasm-webidl-bindings = "0.6" [dev-dependencies] +wasmtime-runtime = { path = "crates/runtime" } more-asserts = "0.2.1" # This feature requires the wasm32-wasi target be installed. It enables # wasm32-wasi integration tests. To enable, run From 037c9d652b9b0a61980c6a79b10b7f8e203ccd5a Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Thu, 9 Jan 2020 13:26:29 -0800 Subject: [PATCH 07/28] Fix expected trap messages. --- tests/custom_signal_handler.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/custom_signal_handler.rs b/tests/custom_signal_handler.rs index 3bea15adf7..0b45f69f0a 100644 --- a/tests/custom_signal_handler.rs +++ b/tests/custom_signal_handler.rs @@ -104,7 +104,7 @@ mod tests { println!("calling read_out_of_bounds..."); let trap = invoke_export(&instance, &data, "read_out_of_bounds").unwrap_err(); assert!(trap.root_cause().to_string().starts_with( - "trapped: Ref(Trap { message: \"wasm trap: out of bounds memory access" + "trapped: Trap { message: \"call error: wasm trap: out of bounds memory access" )); } @@ -129,7 +129,7 @@ mod tests { let trap = read_out_of_bounds_func.borrow().call(&[]).unwrap_err(); assert!(trap .message() - .starts_with("wasm trap: out of bounds memory access")); + .starts_with("call error: wasm trap: out of bounds memory access")); } } From 317f5989691203e0c3d816b3a565f166d09964f5 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 9 Jan 2020 16:22:49 -0600 Subject: [PATCH 08/28] Update `CodeMemory` to be `Send + Sync` (#780) * Update `CodeMemory` to be `Send + Sync` This commit updates the `CodeMemory` type in wasmtime to be both `Send` and `Sync` by updating the implementation of `Mmap` to not store raw pointers. This avoids the need for an `unsafe impl` and leaves the unsafety as it is currently. * Run rustfmt * Rename `offset` to `ptr` --- crates/jit/src/code_memory.rs | 5 +++++ crates/runtime/src/mmap.rs | 39 +++++++++++++++++++++-------------- 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/crates/jit/src/code_memory.rs b/crates/jit/src/code_memory.rs index 49dc86a9e1..49e6d5ee2d 100644 --- a/crates/jit/src/code_memory.rs +++ b/crates/jit/src/code_memory.rs @@ -14,6 +14,11 @@ pub struct CodeMemory { published: usize, } +fn _assert() { + fn _assert_send_sync() {} + _assert_send_sync::(); +} + impl CodeMemory { /// Create a new `CodeMemory` instance. pub fn new() -> Self { diff --git a/crates/runtime/src/mmap.rs b/crates/runtime/src/mmap.rs index 570cfb1a32..8cba107404 100644 --- a/crates/runtime/src/mmap.rs +++ b/crates/runtime/src/mmap.rs @@ -1,11 +1,8 @@ //! Low-level abstraction for allocating and managing zero-filled pages //! of memory. -#[cfg(not(target_os = "windows"))] -use libc; use more_asserts::assert_le; use more_asserts::assert_lt; -use region; use std::io; use std::ptr; use std::slice; @@ -19,7 +16,11 @@ fn round_up_to_page_size(size: usize, page_size: usize) -> usize { /// and initially-zeroed memory and a length. #[derive(Debug)] pub struct Mmap { - ptr: *mut u8, + // Note that this is stored as a `usize` instead of a `*const` or `*mut` + // pointer to allow this structure to be natively `Send` and `Sync` without + // `unsafe impl`. This type is sendable across threads and shareable since + // the coordination all happens at the OS layer. + ptr: usize, len: usize, } @@ -29,8 +30,9 @@ impl Mmap { // Rust's slices require non-null pointers, even when empty. `Vec` // contains code to create a non-null dangling pointer value when // constructed empty, so we reuse that here. + let empty = Vec::::new(); Self { - ptr: Vec::new().as_mut_ptr(), + ptr: empty.as_ptr() as usize, len: 0, } } @@ -78,7 +80,7 @@ impl Mmap { } Self { - ptr: ptr as *mut u8, + ptr: ptr as usize, len: mapping_size, } } else { @@ -98,7 +100,7 @@ impl Mmap { } let mut result = Self { - ptr: ptr as *mut u8, + ptr: ptr as usize, len: mapping_size, }; @@ -142,7 +144,7 @@ impl Mmap { } Self { - ptr: ptr as *mut u8, + ptr: ptr as usize, len: mapping_size, } } else { @@ -154,7 +156,7 @@ impl Mmap { } let mut result = Self { - ptr: ptr as *mut u8, + ptr: ptr as usize, len: mapping_size, }; @@ -179,7 +181,8 @@ impl Mmap { assert_lt!(start, self.len - len); // Commit the accessible size. - unsafe { region::protect(self.ptr.add(start), len, region::Protection::ReadWrite) } + let ptr = self.ptr as *const u8; + unsafe { region::protect(ptr.add(start), len, region::Protection::ReadWrite) } .map_err(|e| e.to_string()) } @@ -198,9 +201,10 @@ impl Mmap { assert_lt!(start, self.len - len); // Commit the accessible size. + let ptr = self.ptr as *const u8; if unsafe { VirtualAlloc( - self.ptr.add(start) as *mut c_void, + ptr.add(start) as *mut c_void, len, MEM_COMMIT, PAGE_READWRITE, @@ -216,22 +220,22 @@ impl Mmap { /// Return the allocated memory as a slice of u8. pub fn as_slice(&self) -> &[u8] { - unsafe { slice::from_raw_parts(self.ptr, self.len) } + unsafe { slice::from_raw_parts(self.ptr as *const u8, self.len) } } /// Return the allocated memory as a mutable slice of u8. pub fn as_mut_slice(&mut self) -> &mut [u8] { - unsafe { slice::from_raw_parts_mut(self.ptr, self.len) } + unsafe { slice::from_raw_parts_mut(self.ptr as *mut u8, self.len) } } /// Return the allocated memory as a pointer to u8. pub fn as_ptr(&self) -> *const u8 { - self.ptr + self.ptr as *const u8 } /// Return the allocated memory as a mutable pointer to u8. pub fn as_mut_ptr(&mut self) -> *mut u8 { - self.ptr + self.ptr as *mut u8 } /// Return the length of the allocated memory. @@ -266,6 +270,11 @@ impl Drop for Mmap { } } +fn _assert() { + fn _assert_send_sync() {} + _assert_send_sync::(); +} + #[cfg(test)] mod tests { use super::*; From 4197cc562e9e72edb5981ff914334efef64f2280 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 9 Jan 2020 17:10:05 -0600 Subject: [PATCH 09/28] Don't rebuild the test suite if wast files change (#787) They're read dynamically so there's no need to rebuild the test suite, it'll automatically pick up the changes when it's read while the tests are executed. --- build.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/build.rs b/build.rs index 4eed5d4154..10613feef6 100644 --- a/build.rs +++ b/build.rs @@ -139,7 +139,6 @@ fn write_testsuite_tests( strategy: &str, ) -> anyhow::Result<()> { let path = path.as_ref(); - println!("cargo:rerun-if-changed={}", path.display()); let testname = extract_name(path); writeln!(out, "#[test]")?; From 8fdd776f81cc533468e3112d77f5b67b5e90c1e3 Mon Sep 17 00:00:00 2001 From: Peter Huene Date: Tue, 10 Dec 2019 14:38:38 -0800 Subject: [PATCH 10/28] Implement fd_fdstat_set_flags for Windows. This commit implements `fd_fdstat_set_flags` for Windows. Additionally, it fixes a problem where `O_APPEND` was not working correctly because `GENERIC_WRITE` was always being set; as a result, `FILE_WRITE_DATA` could not be removed from the permission set to properly enable append-only mode. It also treats `O_TRUNC` with `O_APPEND` as an invalid argument error. This is because Windows cannot support these two flags together. To support `O_TRUNC`, the `GENERIC_WRITE` bit must be set for the file access flags. Setting this bit will cause `FILE_WRITE_DATA` to be set, which will not properly treat the file as append-only (it requires `FILE_APPEND_DATA` without `FILE_WRITE_DATA`). --- .../wasi-tests/src/bin/fd_flags_set.rs | 165 ++++++++++++++++++ crates/wasi-common/src/hostcalls/fs.rs | 2 +- crates/wasi-common/src/hostcalls_impl/fs.rs | 17 +- .../src/sys/unix/hostcalls_impl/fs.rs | 9 +- .../src/sys/windows/hostcalls_impl/fs.rs | 51 +++++- crates/wasi-common/winx/src/file.rs | 17 ++ 6 files changed, 245 insertions(+), 16 deletions(-) create mode 100644 crates/test-programs/wasi-tests/src/bin/fd_flags_set.rs diff --git a/crates/test-programs/wasi-tests/src/bin/fd_flags_set.rs b/crates/test-programs/wasi-tests/src/bin/fd_flags_set.rs new file mode 100644 index 0000000000..e642ca19a5 --- /dev/null +++ b/crates/test-programs/wasi-tests/src/bin/fd_flags_set.rs @@ -0,0 +1,165 @@ +use std::{env, process}; +use wasi; +use wasi_tests::open_scratch_directory; + +unsafe fn test_fd_fdstat_set_flags(dir_fd: wasi::Fd) { + const FILE_NAME: &str = "file"; + let data = &[0u8; 100]; + + let file_fd = wasi::path_open( + dir_fd, + 0, + FILE_NAME, + wasi::OFLAGS_CREAT, + wasi::RIGHTS_FD_READ + | wasi::RIGHTS_FD_WRITE + | wasi::RIGHTS_FD_SEEK + | wasi::RIGHTS_FD_TELL + | wasi::RIGHTS_FD_FDSTAT_SET_FLAGS, + 0, + wasi::FDFLAGS_APPEND, + ) + .expect("opening a file"); + + // Write some data and then verify the written data + assert_eq!( + wasi::fd_write( + file_fd, + &[wasi::Ciovec { + buf: data.as_ptr(), + buf_len: data.len(), + }], + ) + .expect("writing to a file"), + data.len(), + "should write {} bytes", + data.len(), + ); + + wasi::fd_seek(file_fd, 0, wasi::WHENCE_SET).expect("seeking file"); + + let buffer = &mut [0u8; 100]; + + assert_eq!( + wasi::fd_read( + file_fd, + &[wasi::Iovec { + buf: buffer.as_mut_ptr(), + buf_len: buffer.len(), + }] + ) + .expect("reading file"), + buffer.len(), + "shoudl read {} bytes", + buffer.len() + ); + + assert_eq!(&data[..], &buffer[..]); + + let data = &[1u8; 100]; + + // Seek back to the start to ensure we're in append-only mode + wasi::fd_seek(file_fd, 0, wasi::WHENCE_SET).expect("seeking file"); + + assert_eq!( + wasi::fd_write( + file_fd, + &[wasi::Ciovec { + buf: data.as_ptr(), + buf_len: data.len(), + }], + ) + .expect("writing to a file"), + data.len(), + "should write {} bytes", + data.len(), + ); + + wasi::fd_seek(file_fd, 100, wasi::WHENCE_SET).expect("seeking file"); + + assert_eq!( + wasi::fd_read( + file_fd, + &[wasi::Iovec { + buf: buffer.as_mut_ptr(), + buf_len: buffer.len(), + }] + ) + .expect("reading file"), + buffer.len(), + "shoudl read {} bytes", + buffer.len() + ); + + assert_eq!(&data[..], &buffer[..]); + + wasi::fd_fdstat_set_flags(file_fd, 0).expect("disabling flags"); + + // Overwrite some existing data to ensure the append mode is now off + wasi::fd_seek(file_fd, 0, wasi::WHENCE_SET).expect("seeking file"); + + let data = &[2u8; 100]; + + assert_eq!( + wasi::fd_write( + file_fd, + &[wasi::Ciovec { + buf: data.as_ptr(), + buf_len: data.len(), + }], + ) + .expect("writing to a file"), + data.len(), + "should write {} bytes", + data.len(), + ); + + wasi::fd_seek(file_fd, 0, wasi::WHENCE_SET).expect("seeking file"); + + assert_eq!( + wasi::fd_read( + file_fd, + &[wasi::Iovec { + buf: buffer.as_mut_ptr(), + buf_len: buffer.len(), + }] + ) + .expect("reading file"), + buffer.len(), + "shoudl read {} bytes", + buffer.len() + ); + + assert_eq!(&data[..], &buffer[..]); + + wasi::fd_close(file_fd).expect("close file"); + + let stat = wasi::path_filestat_get(dir_fd, 0, FILE_NAME).expect("stat path"); + + assert_eq!(stat.size, 200, "expected a file size of 200"); + + wasi::path_unlink_file(dir_fd, FILE_NAME).expect("unlinking file"); +} + +fn main() { + let mut args = env::args(); + let prog = args.next().unwrap(); + let arg = if let Some(arg) = args.next() { + arg + } else { + eprintln!("usage: {} ", prog); + process::exit(1); + }; + + let dir_fd = match open_scratch_directory(&arg) { + Ok(dir_fd) => dir_fd, + Err(err) => { + eprintln!("{}", err); + process::exit(1) + } + }; + + unsafe { + test_fd_fdstat_set_flags(dir_fd); + } +} diff --git a/crates/wasi-common/src/hostcalls/fs.rs b/crates/wasi-common/src/hostcalls/fs.rs index f9a140869c..6746ba79d4 100644 --- a/crates/wasi-common/src/hostcalls/fs.rs +++ b/crates/wasi-common/src/hostcalls/fs.rs @@ -67,7 +67,7 @@ hostcalls! { ) -> wasi::__wasi_errno_t; pub unsafe fn fd_fdstat_set_flags( - wasi_ctx: &WasiCtx, + wasi_ctx: &mut WasiCtx, memory: &mut [u8], fd: wasi::__wasi_fd_t, fdflags: wasi::__wasi_fdflags_t, diff --git a/crates/wasi-common/src/hostcalls_impl/fs.rs b/crates/wasi-common/src/hostcalls_impl/fs.rs index cd321e47b0..3d2e732433 100644 --- a/crates/wasi-common/src/hostcalls_impl/fs.rs +++ b/crates/wasi-common/src/hostcalls_impl/fs.rs @@ -298,19 +298,24 @@ pub(crate) unsafe fn fd_fdstat_get( } pub(crate) unsafe fn fd_fdstat_set_flags( - wasi_ctx: &WasiCtx, + wasi_ctx: &mut WasiCtx, _memory: &mut [u8], fd: wasi::__wasi_fd_t, fdflags: wasi::__wasi_fdflags_t, ) -> Result<()> { trace!("fd_fdstat_set_flags(fd={:?}, fdflags={:#x?})", fd, fdflags); - let fd = wasi_ctx - .get_fd_entry(fd)? - .as_descriptor(wasi::__WASI_RIGHTS_FD_FDSTAT_SET_FLAGS, 0)? - .as_os_handle(); + let descriptor = wasi_ctx + .get_fd_entry_mut(fd)? + .as_descriptor_mut(wasi::__WASI_RIGHTS_FD_FDSTAT_SET_FLAGS, 0)?; - hostcalls_impl::fd_fdstat_set_flags(&fd, fdflags) + if let Some(new_handle) = + hostcalls_impl::fd_fdstat_set_flags(&descriptor.as_os_handle(), fdflags)? + { + *descriptor = Descriptor::OsHandle(new_handle); + } + + Ok(()) } pub(crate) unsafe fn fd_fdstat_set_rights( diff --git a/crates/wasi-common/src/sys/unix/hostcalls_impl/fs.rs b/crates/wasi-common/src/sys/unix/hostcalls_impl/fs.rs index e96d7252cc..cf7c143a41 100644 --- a/crates/wasi-common/src/sys/unix/hostcalls_impl/fs.rs +++ b/crates/wasi-common/src/sys/unix/hostcalls_impl/fs.rs @@ -29,9 +29,14 @@ pub(crate) fn fd_fdstat_get(fd: &File) -> Result { .map_err(Into::into) } -pub(crate) fn fd_fdstat_set_flags(fd: &File, fdflags: wasi::__wasi_fdflags_t) -> Result<()> { +pub(crate) fn fd_fdstat_set_flags( + fd: &File, + fdflags: wasi::__wasi_fdflags_t, +) -> Result> { let nix_flags = host_impl::nix_from_fdflags(fdflags); - unsafe { yanix::fcntl::set_status_flags(fd.as_raw_fd(), nix_flags) }.map_err(Into::into) + unsafe { yanix::fcntl::set_status_flags(fd.as_raw_fd(), nix_flags) } + .map(|_| None) + .map_err(Into::into) } pub(crate) fn fd_advise( diff --git a/crates/wasi-common/src/sys/windows/hostcalls_impl/fs.rs b/crates/wasi-common/src/sys/windows/hostcalls_impl/fs.rs index 654a475b2d..0330af907c 100644 --- a/crates/wasi-common/src/sys/windows/hostcalls_impl/fs.rs +++ b/crates/wasi-common/src/sys/windows/hostcalls_impl/fs.rs @@ -5,7 +5,7 @@ use crate::ctx::WasiCtx; use crate::fdentry::FdEntry; use crate::host::{Dirent, FileType}; use crate::hostcalls_impl::{fd_filestat_set_times_impl, PathGet}; -use crate::sys::fdentry_impl::determine_type_rights; +use crate::sys::fdentry_impl::{determine_type_rights, OsHandle}; use crate::sys::host_impl::{self, path_from_host}; use crate::sys::hostcalls_impl::fs_helpers::PathGetExt; use crate::{wasi, Error, Result}; @@ -78,8 +78,25 @@ pub(crate) fn fd_fdstat_get(fd: &File) -> Result { Ok(fdflags) } -pub(crate) fn fd_fdstat_set_flags(fd: &File, fdflags: wasi::__wasi_fdflags_t) -> Result<()> { - unimplemented!("fd_fdstat_set_flags") +pub(crate) fn fd_fdstat_set_flags( + fd: &File, + fdflags: wasi::__wasi_fdflags_t, +) -> Result> { + let handle = unsafe { fd.as_raw_handle() }; + + let access_mode = winx::file::query_access_information(handle)?; + + let new_access_mode = file_access_mode_from_fdflags( + fdflags, + (access_mode & AccessMode::FILE_READ_DATA).bits() != 0, + (access_mode & (AccessMode::FILE_WRITE_DATA | AccessMode::FILE_APPEND_DATA)).bits() != 0, + ); + + unsafe { + Ok(Some(OsHandle::from(File::from_raw_handle( + winx::file::reopen_file(handle, new_access_mode, file_flags_from_fdflags(fdflags))?, + )))) + } } pub(crate) fn fd_advise( @@ -119,9 +136,22 @@ pub(crate) fn path_open( ) -> Result { use winx::file::{AccessMode, CreationDisposition, Flags}; + let is_trunc = oflags & wasi::__WASI_OFLAGS_TRUNC != 0; + + if is_trunc { + // Windows requires write access for truncation + if !write { + return Err(Error::ENOTCAPABLE); + } + // Windows does not support append mode with truncation + if fdflags & wasi::__WASI_FDFLAGS_APPEND != 0 { + return Err(Error::EINVAL); + } + } + // convert open flags // note: the calls to `write(true)` are to bypass an internal OpenOption check - // the write flag will ultimately be ignored when `access_mode` is called below. + // the write flag will ultimately be ignored when `access_mode` is calculated below. let mut opts = OpenOptions::new(); match creation_disposition_from_oflags(oflags) { CreationDisposition::CREATE_ALWAYS => { @@ -168,7 +198,14 @@ pub(crate) fn path_open( }, } - opts.access_mode(file_access_mode_from_fdflags(fdflags, read, write).bits()) + let mut access_mode = file_access_mode_from_fdflags(fdflags, read, write); + + // Truncation requires the special `GENERIC_WRITE` bit set (this is why it doesn't work with append-only mode) + if is_trunc { + access_mode |= AccessMode::GENERIC_WRITE; + } + + opts.access_mode(access_mode.bits()) .custom_flags(file_flags_from_fdflags(fdflags).bits()) .open(&path) .map_err(Into::into) @@ -196,11 +233,11 @@ fn file_access_mode_from_fdflags( let mut access_mode = AccessMode::READ_CONTROL; if read { - access_mode.insert(AccessMode::GENERIC_READ); + access_mode.insert(AccessMode::FILE_GENERIC_READ); } if write { - access_mode.insert(AccessMode::GENERIC_WRITE); + access_mode.insert(AccessMode::FILE_GENERIC_WRITE); } // For append, grant the handle FILE_APPEND_DATA access but *not* FILE_WRITE_DATA. diff --git a/crates/wasi-common/winx/src/file.rs b/crates/wasi-common/winx/src/file.rs index a5fd7537b3..e301a1be34 100644 --- a/crates/wasi-common/winx/src/file.rs +++ b/crates/wasi-common/winx/src/file.rs @@ -434,3 +434,20 @@ pub fn query_mode_information(handle: RawHandle) -> Result Ok(FileModeInformation::from_bits_truncate(info.Mode)) } + +pub fn reopen_file(handle: RawHandle, access_mode: AccessMode, flags: Flags) -> Result { + let new_handle = unsafe { + winbase::ReOpenFile( + handle, + access_mode.bits(), + winnt::FILE_SHARE_DELETE | winnt::FILE_SHARE_READ | winnt::FILE_SHARE_WRITE, + flags.bits(), + ) + }; + + if new_handle == winapi::um::handleapi::INVALID_HANDLE_VALUE { + return Err(winerror::WinError::last()); + } + + Ok(new_handle) +} From 1c4c78ab03a569e17d931bf2700487d1430bf849 Mon Sep 17 00:00:00 2001 From: Peter Huene Date: Thu, 9 Jan 2020 13:57:32 -0800 Subject: [PATCH 11/28] Add the Cargo.lock for the test programs. --- crates/test-programs/wasi-tests/Cargo.lock | 30 ++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 crates/test-programs/wasi-tests/Cargo.lock diff --git a/crates/test-programs/wasi-tests/Cargo.lock b/crates/test-programs/wasi-tests/Cargo.lock new file mode 100644 index 0000000000..83b94cc7b8 --- /dev/null +++ b/crates/test-programs/wasi-tests/Cargo.lock @@ -0,0 +1,30 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "libc" +version = "0.2.66" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "more-asserts" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "wasi-tests" +version = "0.7.0" +dependencies = [ + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "more-asserts 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "wasi 0.9.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[metadata] +"checksum libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)" = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558" +"checksum more-asserts 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0debeb9fcf88823ea64d64e4a815ab1643f33127d995978e099942ce38f25238" +"checksum wasi 0.9.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)" = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" From 4b7677e4dab8dff92815bda8fb978b43e3408d17 Mon Sep 17 00:00:00 2001 From: Peter Huene Date: Thu, 9 Jan 2020 14:09:56 -0800 Subject: [PATCH 12/28] Additional PR feedback changes. * Add more comments. * Use `contains` from bitflags. * Format wasi-test source. * Remove permission check from Windows `path_open` impl. --- crates/test-programs/wasi-tests/src/lib.rs | 16 ++++++---------- .../src/sys/windows/hostcalls_impl/fs.rs | 18 ++++++++++-------- crates/wasi-common/winx/src/file.rs | 2 ++ 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/crates/test-programs/wasi-tests/src/lib.rs b/crates/test-programs/wasi-tests/src/lib.rs index 008e570bb4..0a9bee6f9d 100644 --- a/crates/test-programs/wasi-tests/src/lib.rs +++ b/crates/test-programs/wasi-tests/src/lib.rs @@ -25,8 +25,10 @@ pub fn open_scratch_directory(path: &str) -> Result { dst.set_len(stat.u.dir.pr_name_len); if dst == path.as_bytes() { let (base, inherit) = fd_get_rights(i); - return Ok(wasi::path_open(i, 0, ".", wasi::OFLAGS_DIRECTORY, base, inherit, 0) - .expect("failed to open dir")); + return Ok( + wasi::path_open(i, 0, ".", wasi::OFLAGS_DIRECTORY, base, inherit, 0) + .expect("failed to open dir"), + ); } } @@ -51,17 +53,11 @@ pub unsafe fn fd_get_rights(fd: wasi::Fd) -> (wasi::Rights, wasi::Rights) { (fdstat.fs_rights_base, fdstat.fs_rights_inheriting) } -pub unsafe fn drop_rights( - fd: wasi::Fd, - drop_base: wasi::Rights, - drop_inheriting: wasi::Rights, -) { +pub unsafe fn drop_rights(fd: wasi::Fd, drop_base: wasi::Rights, drop_inheriting: wasi::Rights) { let (current_base, current_inheriting) = fd_get_rights(fd); let new_base = current_base & !drop_base; let new_inheriting = current_inheriting & !drop_inheriting; - wasi::fd_fdstat_set_rights(fd, new_base, new_inheriting).expect( - "dropping fd rights", - ); + wasi::fd_fdstat_set_rights(fd, new_base, new_inheriting).expect("dropping fd rights"); } diff --git a/crates/wasi-common/src/sys/windows/hostcalls_impl/fs.rs b/crates/wasi-common/src/sys/windows/hostcalls_impl/fs.rs index 0330af907c..1baacb5e05 100644 --- a/crates/wasi-common/src/sys/windows/hostcalls_impl/fs.rs +++ b/crates/wasi-common/src/sys/windows/hostcalls_impl/fs.rs @@ -88,8 +88,9 @@ pub(crate) fn fd_fdstat_set_flags( let new_access_mode = file_access_mode_from_fdflags( fdflags, - (access_mode & AccessMode::FILE_READ_DATA).bits() != 0, - (access_mode & (AccessMode::FILE_WRITE_DATA | AccessMode::FILE_APPEND_DATA)).bits() != 0, + access_mode.contains(AccessMode::FILE_READ_DATA), + access_mode.contains(AccessMode::FILE_WRITE_DATA) + | access_mode.contains(AccessMode::FILE_APPEND_DATA), ); unsafe { @@ -139,13 +140,11 @@ pub(crate) fn path_open( let is_trunc = oflags & wasi::__WASI_OFLAGS_TRUNC != 0; if is_trunc { - // Windows requires write access for truncation - if !write { - return Err(Error::ENOTCAPABLE); - } - // Windows does not support append mode with truncation + // Windows does not support append mode when opening for truncation + // This is because truncation requires `GENERIC_WRITE` access, which will override the removal + // of the `FILE_WRITE_DATA` permission. if fdflags & wasi::__WASI_FDFLAGS_APPEND != 0 { - return Err(Error::EINVAL); + return Err(Error::ENOTSUP); } } @@ -232,6 +231,9 @@ fn file_access_mode_from_fdflags( ) -> AccessMode { let mut access_mode = AccessMode::READ_CONTROL; + // Note that `GENERIC_READ` and `GENERIC_WRITE` cannot be used to properly support append-only mode + // The file-specific flags `FILE_GENERIC_READ` and `FILE_GENERIC_WRITE` are used here instead + // These flags have the same semantic meaning for file objects, but allow removal of specific permissions (see below) if read { access_mode.insert(AccessMode::FILE_GENERIC_READ); } diff --git a/crates/wasi-common/winx/src/file.rs b/crates/wasi-common/winx/src/file.rs index e301a1be34..2a1bee7cfd 100644 --- a/crates/wasi-common/winx/src/file.rs +++ b/crates/wasi-common/winx/src/file.rs @@ -436,6 +436,8 @@ pub fn query_mode_information(handle: RawHandle) -> Result } pub fn reopen_file(handle: RawHandle, access_mode: AccessMode, flags: Flags) -> Result { + // Files on Windows are opened with DELETE, READ, and WRITE share mode by default (see OpenOptions in stdlib) + // This keeps the same share mode when reopening the file handle let new_handle = unsafe { winbase::ReOpenFile( handle, From e22d93f750b1f8f0c10d0b21dbe1e2f6c26e69e7 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 9 Jan 2020 14:21:56 -0800 Subject: [PATCH 13/28] Tidy up the custom signal handler test No need to check raw `*.wasm` files into the repo, and `*.wat` files can typically be written inline in the test to avoid tabbing back and forth. --- tests/custom_signal_handler.rs | 83 ++++++++++++++++++----------- tests/custom_signal_handler.wasm | Bin 108 -> 0 bytes tests/custom_signal_handler.wat | 20 ------- tests/custom_signal_handler_2.wasm | Bin 59 -> 0 bytes tests/custom_signal_handler_2.wat | 5 -- 5 files changed, 51 insertions(+), 57 deletions(-) delete mode 100644 tests/custom_signal_handler.wasm delete mode 100644 tests/custom_signal_handler.wat delete mode 100644 tests/custom_signal_handler_2.wasm delete mode 100644 tests/custom_signal_handler_2.wat diff --git a/tests/custom_signal_handler.rs b/tests/custom_signal_handler.rs index 0b45f69f0a..613bb2db04 100644 --- a/tests/custom_signal_handler.rs +++ b/tests/custom_signal_handler.rs @@ -6,14 +6,43 @@ mod tests { use wasmtime::*; use wasmtime_interface_types::{ModuleData, Value}; + const WAT1: &str = r#" +(module + (func $read (export "read") (result i32) + (i32.load (i32.const 0)) + ) + (func $read_out_of_bounds (export "read_out_of_bounds") (result i32) + (i32.load + (i32.mul + ;; memory size in Wasm pages + (memory.size) + ;; Wasm page size + (i32.const 65536) + ) + ) + ) + (func $start + (i32.store (i32.const 0) (i32.const 123)) + ) + (start $start) + (memory (export "memory") 1 4) +) +"#; + + const WAT2: &str = r#" +(module + (import "other_module" "read" (func $other_module.read (result i32))) + (func $run (export "run") (result i32) + call $other_module.read) +) +"#; + fn invoke_export( instance: &HostRef, data: &[u8], func_name: &str, ) -> Result, anyhow::Error> { - ModuleData::new(&data) - .expect("module data") - .invoke_export(instance, func_name, &[]) + ModuleData::new(&data)?.invoke_export(instance, func_name, &[]) } // Locate "memory" export, get base address and size and set memory protection to PROT_NONE @@ -73,15 +102,12 @@ mod tests { } #[test] - fn test_custom_signal_handler_single_instance() { + fn test_custom_signal_handler_single_instance() -> anyhow::Result<()> { let engine = Engine::new(&Config::default()); let store = Store::new(&engine); - let data = - std::fs::read("tests/custom_signal_handler.wasm").expect("failed to read wasm file"); - let module = Module::new(&store, &data).expect("failed to create module"); - let instance = HostRef::new( - Instance::new(&store, &module, &[]).expect("failed to instantiate module"), - ); + let data = wat::parse_str(WAT1)?; + let module = Module::new(&store, &data)?; + let instance = HostRef::new(Instance::new(&store, &module, &[])?); let (base, length) = set_up_memory(&instance); instance @@ -131,21 +157,19 @@ mod tests { .message() .starts_with("call error: wasm trap: out of bounds memory access")); } + Ok(()) } #[test] - fn test_custom_signal_handler_multiple_instances() { + fn test_custom_signal_handler_multiple_instances() -> anyhow::Result<()> { let engine = Engine::new(&Config::default()); let store = Store::new(&engine); - let data = - std::fs::read("tests/custom_signal_handler.wasm").expect("failed to read wasm file"); - let module = Module::new(&store, &data).expect("failed to create module"); + let data = wat::parse_str(WAT1)?; + let module = Module::new(&store, &data)?; // Set up multiple instances - let instance1 = HostRef::new( - Instance::new(&store, &module, &[]).expect("failed to instantiate module"), - ); + let instance1 = HostRef::new(Instance::new(&store, &module, &[])?); let instance1_handler_triggered = Rc::new(AtomicBool::new(false)); { @@ -232,20 +256,18 @@ mod tests { "instance1 signal handler has been triggered" ); } + Ok(()) } #[test] - fn test_custom_signal_handler_instance_calling_another_instance() { + fn test_custom_signal_handler_instance_calling_another_instance() -> anyhow::Result<()> { let engine = Engine::new(&Config::default()); let store = Store::new(&engine); // instance1 which defines 'read' - let data1 = - std::fs::read("tests/custom_signal_handler.wasm").expect("failed to read wasm file"); - let module1 = Module::new(&store, &data1).expect("failed to create module"); - let instance1: HostRef = HostRef::new( - Instance::new(&store, &module1, &[]).expect("failed to instantiate module"), - ); + let data1 = wat::parse_str(WAT1)?; + let module1 = Module::new(&store, &data1)?; + let instance1: HostRef = HostRef::new(Instance::new(&store, &module1, &[])?); let (base1, length1) = set_up_memory(&instance1); instance1 .borrow_mut() @@ -259,13 +281,9 @@ mod tests { let instance1_read = instance1_exports[0].clone(); // instance2 wich calls 'instance1.read' - let data2 = - std::fs::read("tests/custom_signal_handler_2.wasm").expect("failed to read wasm file"); - let module2 = Module::new(&store, &data2).expect("failed to create module"); - let instance2 = HostRef::new( - Instance::new(&store, &module2, &[instance1_read]) - .expect("failed to instantiate module"), - ); + let data2 = wat::parse_str(WAT2)?; + let module2 = Module::new(&store, &data2)?; + let instance2 = HostRef::new(Instance::new(&store, &module2, &[instance1_read])?); // since 'instance2.run' calls 'instance1.read' we need to set up the signal handler to handle // SIGSEGV originating from within the memory of instance1 instance2 @@ -275,7 +293,8 @@ mod tests { }); println!("calling instance2.run"); - let result = invoke_export(&instance2, &data2, "run").expect("instance2.run succeeded"); + let result = invoke_export(&instance2, &data2, "run")?; assert_eq!("123", result[0].clone().to_string()); + Ok(()) } } diff --git a/tests/custom_signal_handler.wasm b/tests/custom_signal_handler.wasm deleted file mode 100644 index 9348e1a61e406405d22c64d8f06f42eb77f0d49f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 108 zcmWlNJr05}7(n0GehNV+Z{T7)fh*}r3Iv#_O@Izga&H#O^nPfUAb^ynLH-R`wK*>; zB3itx&O_V7OrFOy7P%u3-pq{uxR!)zcO@-iF(q8nR;`(>e7%HW-d NQNHyXO``%U^ABNU3X=c; diff --git a/tests/custom_signal_handler_2.wat b/tests/custom_signal_handler_2.wat deleted file mode 100644 index a93c5db8d0..0000000000 --- a/tests/custom_signal_handler_2.wat +++ /dev/null @@ -1,5 +0,0 @@ -(module - (import "other_module" "read" (func $other_module.read (result i32))) - (func $run (export "run") (result i32) - call $other_module.read) -) From 41780fb1a68a792f113464960149e3c548c2cb91 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 5 Dec 2019 15:45:57 -0800 Subject: [PATCH 14/28] Handle same-named imports with different signatures This commit fixes the `wasmtime::Instance` instantiation API when imports have the same name but might be imported under different types. This is handled in the API by listing imports as a list instead of as a name map, but they were interpreted as a name map under the hood causing collisions. This commit now keeps track of the index used to define each import, and the index is passed through in the `Resolver`. Existing implementaitons of `Resolver` all ignore this, but the API now uses it exclusivley to match up `Extern` definitions to imports. --- crates/api/src/externals.rs | 2 +- crates/api/src/instance.rs | 24 ++++------ crates/api/tests/import-indexes.rs | 68 ++++++++++++++++++++++++++++ crates/environ/src/module.rs | 11 +++-- crates/environ/src/module_environ.rs | 42 ++++++++++------- crates/jit/src/link.rs | 16 +++---- crates/jit/src/namespace.rs | 2 +- crates/jit/src/resolver.rs | 13 ++++-- 8 files changed, 128 insertions(+), 50 deletions(-) create mode 100644 crates/api/tests/import-indexes.rs diff --git a/crates/api/src/externals.rs b/crates/api/src/externals.rs index c5be5b27a0..c0b6156c77 100644 --- a/crates/api/src/externals.rs +++ b/crates/api/src/externals.rs @@ -56,7 +56,7 @@ impl Extern { } } - pub(crate) fn get_wasmtime_export(&mut self) -> wasmtime_runtime::Export { + pub(crate) fn get_wasmtime_export(&self) -> wasmtime_runtime::Export { match self { Extern::Func(f) => f.borrow().wasmtime_export().clone(), Extern::Global(g) => g.borrow().wasmtime_export().clone(), diff --git a/crates/api/src/instance.rs b/crates/api/src/instance.rs index 81b2a4ccee..166848cb12 100644 --- a/crates/api/src/instance.rs +++ b/crates/api/src/instance.rs @@ -12,23 +12,21 @@ use std::rc::Rc; use wasmtime_jit::{instantiate, Resolver, SetupError}; use wasmtime_runtime::{Export, InstanceHandle, InstantiationError}; -struct SimpleResolver { - imports: Vec<(String, String, Extern)>, +struct SimpleResolver<'a> { + imports: &'a [Extern], } -impl Resolver for SimpleResolver { - fn resolve(&mut self, name: &str, field: &str) -> Option { - // TODO speedup lookup +impl Resolver for SimpleResolver<'_> { + fn resolve(&mut self, idx: u32, _name: &str, _field: &str) -> Option { self.imports - .iter_mut() - .find(|(n, f, _)| name == n && field == f) - .map(|(_, _, e)| e.get_wasmtime_export()) + .get(idx as usize) + .map(|i| i.get_wasmtime_export()) } } pub fn instantiate_in_context( data: &[u8], - imports: Vec<(String, String, Extern)>, + imports: &[Extern], module_name: Option, context: Context, exports: Rc>>>, @@ -73,15 +71,9 @@ impl Instance { pub fn new(store: &Store, module: &Module, externs: &[Extern]) -> Result { let context = store.context().clone(); let exports = store.global_exports().clone(); - let imports = module - .imports() - .iter() - .zip(externs.iter()) - .map(|(i, e)| (i.module().to_string(), i.name().to_string(), e.clone())) - .collect::>(); let (mut instance_handle, contexts) = instantiate_in_context( module.binary().expect("binary"), - imports, + externs, module.name().cloned(), context, exports, diff --git a/crates/api/tests/import-indexes.rs b/crates/api/tests/import-indexes.rs new file mode 100644 index 0000000000..8e35f6cbf6 --- /dev/null +++ b/crates/api/tests/import-indexes.rs @@ -0,0 +1,68 @@ +use std::rc::Rc; +use wasmtime::*; + +#[test] +fn same_import_names_still_distinct() -> anyhow::Result<()> { + const WAT: &str = r#" +(module + (import "" "" (func $a (result i32))) + (import "" "" (func $b (result f32))) + (func (export "foo") (result i32) + call $a + call $b + i32.trunc_f32_u + i32.add) +) + "#; + + struct Ret1; + + impl Callable for Ret1 { + fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), Trap> { + assert!(params.is_empty()); + assert_eq!(results.len(), 1); + results[0] = 1i32.into(); + Ok(()) + } + } + + struct Ret2; + + impl Callable for Ret2 { + fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), Trap> { + assert!(params.is_empty()); + assert_eq!(results.len(), 1); + results[0] = 2.0f32.into(); + Ok(()) + } + } + + let store = Store::default(); + let wasm = wat::parse_str(WAT)?; + let module = Module::new(&store, &wasm)?; + + let imports = [ + HostRef::new(Func::new( + &store, + FuncType::new(Box::new([]), Box::new([ValType::I32])), + Rc::new(Ret1), + )) + .into(), + HostRef::new(Func::new( + &store, + FuncType::new(Box::new([]), Box::new([ValType::F32])), + Rc::new(Ret2), + )) + .into(), + ]; + let instance = Instance::new(&store, &module, &imports)?; + + let func = instance.find_export_by_name("foo").unwrap().func().unwrap(); + let results = func.borrow().call(&[])?; + assert_eq!(results.len(), 1); + match results[0] { + Val::I32(n) => assert_eq!(n, 3), + _ => panic!("unexpected type of return"), + } + Ok(()) +} diff --git a/crates/environ/src/module.rs b/crates/environ/src/module.rs index 0ff8c79d04..766eacf11c 100644 --- a/crates/environ/src/module.rs +++ b/crates/environ/src/module.rs @@ -136,17 +136,18 @@ pub struct Module { /// Unprocessed signatures exactly as provided by `declare_signature()`. pub signatures: PrimaryMap, - /// Names of imported functions. - pub imported_funcs: PrimaryMap, + /// Names of imported functions, as well as the index of the import that + /// performed this import. + pub imported_funcs: PrimaryMap, /// Names of imported tables. - pub imported_tables: PrimaryMap, + pub imported_tables: PrimaryMap, /// Names of imported memories. - pub imported_memories: PrimaryMap, + pub imported_memories: PrimaryMap, /// Names of imported globals. - pub imported_globals: PrimaryMap, + pub imported_globals: PrimaryMap, /// Types of functions, imported and local. pub functions: PrimaryMap, diff --git a/crates/environ/src/module_environ.rs b/crates/environ/src/module_environ.rs index 1acc61e63b..ee0ad17202 100644 --- a/crates/environ/src/module_environ.rs +++ b/crates/environ/src/module_environ.rs @@ -55,6 +55,7 @@ impl<'data> ModuleTranslation<'data> { pub struct ModuleEnvironment<'data> { /// The result to be filled in. result: ModuleTranslation<'data>, + imports: u32, } impl<'data> ModuleEnvironment<'data> { @@ -69,6 +70,7 @@ impl<'data> ModuleEnvironment<'data> { tunables, module_translation: None, }, + imports: 0, } } @@ -123,10 +125,12 @@ impl<'data> cranelift_wasm::ModuleEnvironment<'data> for ModuleEnvironment<'data ); self.result.module.functions.push(sig_index); - self.result - .module - .imported_funcs - .push((String::from(module), String::from(field))); + self.result.module.imported_funcs.push(( + String::from(module), + String::from(field), + self.imports, + )); + self.imports += 1; Ok(()) } @@ -139,10 +143,12 @@ impl<'data> cranelift_wasm::ModuleEnvironment<'data> for ModuleEnvironment<'data let plan = TablePlan::for_table(table, &self.result.tunables); self.result.module.table_plans.push(plan); - self.result - .module - .imported_tables - .push((String::from(module), String::from(field))); + self.result.module.imported_tables.push(( + String::from(module), + String::from(field), + self.imports, + )); + self.imports += 1; Ok(()) } @@ -160,10 +166,12 @@ impl<'data> cranelift_wasm::ModuleEnvironment<'data> for ModuleEnvironment<'data let plan = MemoryPlan::for_memory(memory, &self.result.tunables); self.result.module.memory_plans.push(plan); - self.result - .module - .imported_memories - .push((String::from(module), String::from(field))); + self.result.module.imported_memories.push(( + String::from(module), + String::from(field), + self.imports, + )); + self.imports += 1; Ok(()) } @@ -180,10 +188,12 @@ impl<'data> cranelift_wasm::ModuleEnvironment<'data> for ModuleEnvironment<'data ); self.result.module.globals.push(global); - self.result - .module - .imported_globals - .push((String::from(module), String::from(field))); + self.result.module.imported_globals.push(( + String::from(module), + String::from(field), + self.imports, + )); + self.imports += 1; Ok(()) } diff --git a/crates/jit/src/link.rs b/crates/jit/src/link.rs index 867ddea681..f8c9c62589 100644 --- a/crates/jit/src/link.rs +++ b/crates/jit/src/link.rs @@ -30,8 +30,8 @@ pub fn link_module( let mut dependencies = HashSet::new(); let mut function_imports = PrimaryMap::with_capacity(module.imported_funcs.len()); - for (index, (ref module_name, ref field)) in module.imported_funcs.iter() { - match resolver.resolve(module_name, field) { + for (index, (module_name, field, import_idx)) in module.imported_funcs.iter() { + match resolver.resolve(*import_idx, module_name, field) { Some(export_value) => match export_value { Export::Function { address, @@ -71,8 +71,8 @@ pub fn link_module( } let mut table_imports = PrimaryMap::with_capacity(module.imported_tables.len()); - for (index, (ref module_name, ref field)) in module.imported_tables.iter() { - match resolver.resolve(module_name, field) { + for (index, (module_name, field, import_idx)) in module.imported_tables.iter() { + match resolver.resolve(*import_idx, module_name, field) { Some(export_value) => match export_value { Export::Table { definition, @@ -110,8 +110,8 @@ pub fn link_module( } let mut memory_imports = PrimaryMap::with_capacity(module.imported_memories.len()); - for (index, (ref module_name, ref field)) in module.imported_memories.iter() { - match resolver.resolve(module_name, field) { + for (index, (module_name, field, import_idx)) in module.imported_memories.iter() { + match resolver.resolve(*import_idx, module_name, field) { Some(export_value) => match export_value { Export::Memory { definition, @@ -163,8 +163,8 @@ pub fn link_module( } let mut global_imports = PrimaryMap::with_capacity(module.imported_globals.len()); - for (index, (ref module_name, ref field)) in module.imported_globals.iter() { - match resolver.resolve(module_name, field) { + for (index, (module_name, field, import_idx)) in module.imported_globals.iter() { + match resolver.resolve(*import_idx, module_name, field) { Some(export_value) => match export_value { Export::Table { .. } | Export::Memory { .. } | Export::Function { .. } => { return Err(LinkError(format!( diff --git a/crates/jit/src/namespace.rs b/crates/jit/src/namespace.rs index dc2c0a9e1f..a8f5449c6f 100644 --- a/crates/jit/src/namespace.rs +++ b/crates/jit/src/namespace.rs @@ -36,7 +36,7 @@ impl Namespace { } impl Resolver for Namespace { - fn resolve(&mut self, name: &str, field: &str) -> Option { + fn resolve(&mut self, _idx: u32, name: &str, field: &str) -> Option { if let Some(instance) = self.names.get_mut(name) { instance.lookup(field) } else { diff --git a/crates/jit/src/resolver.rs b/crates/jit/src/resolver.rs index 9b8ba197cb..34f052c45a 100644 --- a/crates/jit/src/resolver.rs +++ b/crates/jit/src/resolver.rs @@ -5,15 +5,22 @@ use wasmtime_runtime::Export; /// Import resolver connects imports with available exported values. pub trait Resolver { - /// Resolve the given module/field combo. - fn resolve(&mut self, module: &str, field: &str) -> Option; + /// Resolves an import a WebAssembly module to an export it's hooked up to. + /// + /// The `index` provided is the index of the import in the wasm module + /// that's being resolved. For example 1 means that it's the second import + /// listed in the wasm module. + /// + /// The `module` and `field` arguments provided are the module/field names + /// listed on the import itself. + fn resolve(&mut self, index: u32, module: &str, field: &str) -> Option; } /// `Resolver` implementation that always resolves to `None`. pub struct NullResolver {} impl Resolver for NullResolver { - fn resolve(&mut self, _module: &str, _field: &str) -> Option { + fn resolve(&mut self, _idx: u32, _module: &str, _field: &str) -> Option { None } } From 336ee94c8974162b8127d95f720bd617640669fa Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Thu, 9 Jan 2020 21:57:40 -0800 Subject: [PATCH 15/28] Bump version to 0.9.0 (#790) --- .gitmodules | 2 +- Cargo.lock | 298 ++++++++++-------- Cargo.toml | 2 +- crates/api/Cargo.toml | 12 +- crates/debug/Cargo.toml | 4 +- crates/environ/Cargo.toml | 4 +- crates/fuzzing/Cargo.toml | 8 +- crates/interface-types/Cargo.toml | 12 +- crates/jit/Cargo.toml | 8 +- crates/lightbeam/Cargo.toml | 2 +- crates/misc/py/Cargo.toml | 12 +- crates/misc/rust/Cargo.toml | 10 +- crates/misc/rust/macro/Cargo.toml | 2 +- crates/obj/Cargo.toml | 4 +- crates/runtime/Cargo.toml | 4 +- crates/test-programs/Cargo.toml | 14 +- crates/test-programs/wasi-tests/Cargo.toml | 2 +- crates/wasi-c/Cargo.toml | 8 +- crates/wasi-common/Cargo.toml | 10 +- .../wasi-common-cbindgen/Cargo.toml | 2 +- crates/wasi-common/wig/Cargo.toml | 5 +- crates/wasi-common/{ => wig}/WASI | 0 crates/wasi-common/wig/src/utils.rs | 2 +- crates/wasi-common/winx/Cargo.toml | 2 +- crates/wasi-common/yanix/Cargo.toml | 2 +- crates/wasi/Cargo.toml | 14 +- crates/wast/Cargo.toml | 4 +- fuzz/Cargo.toml | 2 +- scripts/publish-all.sh | 6 +- src/commands/wasm2obj.rs | 2 +- 30 files changed, 250 insertions(+), 209 deletions(-) rename crates/wasi-common/{ => wig}/WASI (100%) diff --git a/.gitmodules b/.gitmodules index 6447c5a6c9..2bb139cd81 100644 --- a/.gitmodules +++ b/.gitmodules @@ -5,5 +5,5 @@ path = crates/api/c-examples/wasm-c-api url = https://github.com/WebAssembly/wasm-c-api [submodule "crates/wasi-common/WASI"] - path = crates/wasi-common/WASI + path = crates/wasi-common/wig/WASI url = https://github.com/WebAssembly/WASI diff --git a/Cargo.lock b/Cargo.lock index b4a44fa796..da9a3565fd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -20,9 +20,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.25" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9267dff192e68f3399525901e709a48c1d3982c9c072fa32f2127a0cb0babf14" +checksum = "7825f6833612eb2414095684fcf6c635becf3ce97fe48cf6421321e93bfbd53c" [[package]] name = "arbitrary" @@ -53,10 +53,11 @@ checksum = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" [[package]] name = "atty" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ + "hermit-abi", "libc", "winapi", ] @@ -67,6 +68,12 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" +[[package]] +name = "autocfg" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" + [[package]] name = "backtrace" version = "0.3.40" @@ -191,9 +198,9 @@ checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" [[package]] name = "blake2b_simd" -version = "0.5.9" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b83b7baab1e671718d78204225800d6b170e648188ac7dc992e9d6bddf87d0c0" +checksum = "d8fb2d74254a3a0b5cac33ac9f8ed0e44aa50378d9dbb2e5d83bd21ed1dc2c8a" dependencies = [ "arrayref", "arrayvec 0.5.1", @@ -262,12 +269,11 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.48" +version = "1.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f52a465a666ca3d838ebbf08b241383421412fe7ebb463527bba275526d89f76" +checksum = "95e28fa049fda1c330bcf9d723be7663a899c4679724b34c81e9f5a326aab8cd" dependencies = [ "jobserver", - "num_cpus", ] [[package]] @@ -443,7 +449,7 @@ dependencies = [ "log", "serde", "thiserror", - "wasmparser 0.45.1", + "wasmparser 0.45.2", ] [[package]] @@ -462,7 +468,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5064ebdbf05ce3cb95e45c8b086f72263f4166b29b97f6baff7ef7fe047b55ac" dependencies = [ - "autocfg", + "autocfg 0.1.7", "cfg-if", "crossbeam-utils 0.7.0", "lazy_static", @@ -472,10 +478,11 @@ dependencies = [ [[package]] name = "crossbeam-queue" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfd6515864a82d2f877b42813d4553292c6659498c9a2aa31bab5a15243c2700" +checksum = "c695eeca1e7173472a32221542ae469b3e9aac3a4fc81f7696bcad82029493db" dependencies = [ + "cfg-if", "crossbeam-utils 0.7.0", ] @@ -495,7 +502,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce446db02cdc3165b94ae73111e570793400d0794e46125cc4056c81cbb039f4" dependencies = [ - "autocfg", + "autocfg 0.1.7", "cfg-if", "lazy_static", ] @@ -723,9 +730,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.1.13" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7db7ca94ed4cd01190ceee0d8a8052f08a247aa1b469a7f68c6a3b71afcf407" +checksum = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb" dependencies = [ "cfg-if", "libc", @@ -764,9 +771,9 @@ checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" [[package]] name = "goblin" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88a79ef1f0dad46fd78075b6f80f92d97710eddf87b3e18a15a66761e8942672" +checksum = "3081214398d39e4bd7f2c1975f0488ed04614ffdd976c6fc7a0708278552c0da" dependencies = [ "log", "plain", @@ -784,9 +791,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.1.3" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "307c3c9f937f38e3534b1d6447ecf090cafcc9744e4a6360e8b037b2cf5af120" +checksum = "eff2656d88f158ce120947499e971d743c05dbcbed62e5bd2f38f1698bbc3772" dependencies = [ "libc", ] @@ -812,7 +819,7 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712d7b3ea5827fcb9d4fda14bf4da5f136f0db2ae9c8f4bd4e2d1c6fde4e6db2" dependencies = [ - "autocfg", + "autocfg 0.1.7", ] [[package]] @@ -840,9 +847,9 @@ dependencies = [ [[package]] name = "inventory" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4cece20baea71d9f3435e7bbe9adf4765f091c5fe404975f844006964a71299" +checksum = "2bf98296081bd2cb540acc09ef9c97f22b7e487841520350293605db1b2c7a27" dependencies = [ "ctor", "ghost", @@ -851,9 +858,9 @@ dependencies = [ [[package]] name = "inventory-impl" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2869bf972e998977b1cb87e60df70341d48e48dca0823f534feb91ea44adaf9" +checksum = "0a8e30575afe28eea36a9a39136b70b2fb6b0dd0a212a5bd1f30a498395c0274" dependencies = [ "proc-macro2", "quote", @@ -877,13 +884,11 @@ checksum = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" [[package]] name = "jobserver" -version = "0.1.17" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2b1d42ef453b30b7387e113da1c83ab1605d90c5b4e0eb8e96d016ed3b8c160" +checksum = "230ae9adf468173aecd4176c7233bddc84a15871a586c5971ace9a55f881c075" dependencies = [ - "getrandom", "libc", - "log", ] [[package]] @@ -931,7 +936,7 @@ dependencies = [ [[package]] name = "lightbeam" -version = "0.7.0" +version = "0.9.0" dependencies = [ "anyhow", "capstone", @@ -948,7 +953,7 @@ dependencies = [ "smallvec", "thiserror", "typemap", - "wasmparser 0.45.1", + "wasmparser 0.45.2", "wat", ] @@ -1042,27 +1047,27 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcb0cf31fb3ff77e6d2a6ebd6800df7fdcd106f2ad89113c9130bcd07f93dffc" dependencies = [ - "autocfg", + "autocfg 0.1.7", "num-traits", ] [[package]] name = "num-integer" -version = "0.1.41" +version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09" +checksum = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba" dependencies = [ - "autocfg", + "autocfg 1.0.0", "num-traits", ] [[package]] name = "num-iter" -version = "0.1.39" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76bd5272412d173d6bf9afdf98db8612bbabc9a7a830b7bfc9c188911716132e" +checksum = "dfb0800a0291891dd9f4fe7bd9c19384f98f7fbe0cd0f39a2c6b88b9868bbc00" dependencies = [ - "autocfg", + "autocfg 1.0.0", "num-integer", "num-traits", ] @@ -1073,18 +1078,18 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2885278d5fe2adc2f75ced642d52d879bffaceb5a2e0b1d4309ffdfb239b454" dependencies = [ - "autocfg", + "autocfg 0.1.7", "num-integer", "num-traits", ] [[package]] name = "num-traits" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4c81ffc11c212fa327657cb19dd85eb7419e163b5b076bede2bdb5c974c07e4" +checksum = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096" dependencies = [ - "autocfg", + "autocfg 1.0.0", ] [[package]] @@ -1175,13 +1180,28 @@ dependencies = [ [[package]] name = "proc-macro-error" -version = "0.2.6" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aeccfe4d5d8ea175d5f0e4a2ad0637e0f4121d63bd99d356fb1f39ab2e7c6097" +checksum = "53c98547ceaea14eeb26fcadf51dc70d01a2479a7839170eae133721105e4428" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "rustversion", + "syn", +] + +[[package]] +name = "proc-macro-error-attr" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2bf5d493cf5d3e296beccfd61794e445e830dfc8070a9c248ad3ee071392c6c" dependencies = [ "proc-macro2", "quote", + "rustversion", "syn", + "syn-mid", ] [[package]] @@ -1197,18 +1217,18 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27" +checksum = "0319972dcae462681daf4da1adeeaa066e3ebd29c69be96c6abb1259d2ee2bcc" dependencies = [ "unicode-xid", ] [[package]] name = "pyo3" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b338139584e698b341996e4f453c71fa937daa408aaf301e042383724e0caca" +checksum = "e1bfe257586436fbe1296d917f14a167d4253d0873bf43e2c9b9bdd58a3f9f35" dependencies = [ "indoc", "inventory", @@ -1227,9 +1247,9 @@ dependencies = [ [[package]] name = "pyo3-derive-backend" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b8c805249a82c04a00d96f562e66537e8ddfe5d895bc2a414a8e6b6ae3d53be" +checksum = "4882d8237fd8c7373cc25cb802fe0dab9ff70830fd56f47ef6c7f3f287fcc057" dependencies = [ "proc-macro2", "quote", @@ -1238,9 +1258,9 @@ dependencies = [ [[package]] name = "pyo3cls" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3575ad614aa547044119f3ff78aff7bdcba6bcde53fcd67065611546d2b8a122" +checksum = "fdf321cfab555f7411298733c86d21e5136f5ded13f5872fabf9de3337beecda" dependencies = [ "proc-macro2", "pyo3-derive-backend", @@ -1250,9 +1270,9 @@ dependencies = [ [[package]] name = "quick-error" -version = "1.2.2" +version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quickcheck" @@ -1368,9 +1388,9 @@ dependencies = [ [[package]] name = "rayon" -version = "1.2.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43739f8831493b276363637423d3622d4bd6394ab6f0a9c4a552e208aeb7fddd" +checksum = "db6ce3297f9c85e16621bb8cca38a06779ffc31bb8184e1be4bed2be4678a098" dependencies = [ "crossbeam-deque", "either", @@ -1379,9 +1399,9 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.6.1" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8bf17de6f23b05473c437eb958b9c850bfc8af0961fe17b4cc92d5a627b4791" +checksum = "08a89b46efaf957e52b18062fb2f4660f8b8a4dde1807ca002690868ef2c85a9" dependencies = [ "crossbeam-deque", "crossbeam-queue", @@ -1419,9 +1439,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.3.1" +version = "1.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc220bd33bdce8f093101afe22a037b8eb0e5af33592e6a9caafff0d4cb81cbd" +checksum = "b5508c1941e4e7cb19965abef075d35a9a8b5cdf0846f30b4050e9b55dc55e87" dependencies = [ "aho-corasick", "memchr", @@ -1431,9 +1451,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.12" +version = "0.6.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716" +checksum = "e734e891f5b408a29efbf8309e656876276f49ab6a6ac208600b4419bd893d90" [[package]] name = "region" @@ -1491,6 +1511,17 @@ dependencies = [ "semver", ] +[[package]] +name = "rustversion" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a0538bd897e17257b0128d2fd95c2ed6df939374073a36166051a79e2eb7986" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "ryu" version = "1.0.2" @@ -1540,18 +1571,18 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.103" +version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1217f97ab8e8904b57dd22eb61cde455fa7446a9c1cf43966066da047c1f3702" +checksum = "414115f25f818d7dfccec8ee535d76949ae78584fc4f79a6f45a904bf8ab4449" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.103" +version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8c6faef9a2e64b0064f48570289b4bf8823b7581f1d6157c1b52152306651d0" +checksum = "128f9e303a5a29922045a830221b8f78ec74a5f544944f3d5984f8ec3895ef64" dependencies = [ "proc-macro2", "quote", @@ -1571,9 +1602,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d" +checksum = "27044adfd2e1f077f649f59deb9490d3941d674002f7d062870a60ebe9bd47a0" dependencies = [ "block-buffer", "digest", @@ -1589,9 +1620,9 @@ checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2" [[package]] name = "smallvec" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ecf3b85f68e8abaa7555aa5abdb1153079387e60b718283d732f03897fcfc86" +checksum = "44e59e0c9fa00817912ae6e4e6e3c4fe04455e75699d06eedc7d85917ed8e8f4" [[package]] name = "spin" @@ -1622,9 +1653,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" [[package]] name = "structopt" -version = "0.3.5" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30b3a3e93f5ad553c38b3301c8a0a0cec829a36783f6a0c467fc4bf553a5f5bf" +checksum = "884ae79d6aad1e738f4a70dff314203fd498490a63ebc4d03ea83323c40b7b72" dependencies = [ "clap", "structopt-derive", @@ -1632,9 +1663,9 @@ dependencies = [ [[package]] name = "structopt-derive" -version = "0.3.5" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea692d40005b3ceba90a9fe7a78fa8d4b82b0ce627eebbffc329aab850f3410e" +checksum = "0a97f829a34a0a9d5b353a881025a23b8c9fd09d46be6045df6b22920dbd7a93" dependencies = [ "heck", "proc-macro-error", @@ -1645,15 +1676,26 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.11" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff0acdb207ae2fe6d5976617f887eb1e35a2ba52c13c7234c790960cdad9238" +checksum = "1e4ff033220a41d1a57d8125eab57bf5263783dfdcc18688b1dacc6ce9651ef8" dependencies = [ "proc-macro2", "quote", "unicode-xid", ] +[[package]] +name = "syn-mid" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fd3937748a7eccff61ba5b90af1a20dbf610858923a9192ea0ecb0cb77db1d0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "synstructure" version = "0.12.3" @@ -1697,7 +1739,7 @@ dependencies = [ [[package]] name = "test-programs" -version = "0.7.0" +version = "0.9.0" dependencies = [ "anyhow", "cfg-if", @@ -1745,9 +1787,9 @@ dependencies = [ [[package]] name = "thread_local" -version = "0.3.6" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" +checksum = "88ddf1ad580c7e3d1efff877d972bcc93f995556b9087a5a259630985c88ceab" dependencies = [ "lazy_static", ] @@ -1780,9 +1822,9 @@ checksum = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" [[package]] name = "trybuild" -version = "1.0.18" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b75e31d624df08744532e935f1d4bfedd319a277d5a162c5b15f6ced59307575" +checksum = "987d6fdc45ddd7f3be5aa7386c8c8a844d1655c95b9ed948a9cd9cded8f2b79f" dependencies = [ "glob", "lazy_static", @@ -1886,13 +1928,13 @@ dependencies = [ [[package]] name = "wasi" -version = "0.7.0" +version = "0.9.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" [[package]] name = "wasi-common" -version = "0.7.0" +version = "0.9.0" dependencies = [ "anyhow", "cfg-if", @@ -1913,7 +1955,7 @@ dependencies = [ [[package]] name = "wasi-common-cbindgen" -version = "0.7.0" +version = "0.9.0" dependencies = [ "proc-macro2", "quote", @@ -1947,9 +1989,9 @@ checksum = "1527c84a5bd585215f29c06b0e2a5274e478ad4dfc970d26ffad66fdc6cb311d" [[package]] name = "wasmparser" -version = "0.45.1" +version = "0.45.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ee23c9b67aa5d7a2381ae56805ced08960d21b7cf6ca11f78b42d68e698d03b" +checksum = "8b4eab1d9971d0803729cba3617b56eb04fcb4bd25361cb63880ed41a42f20d5" [[package]] name = "wasmprinter" @@ -1963,7 +2005,7 @@ dependencies = [ [[package]] name = "wasmtime" -version = "0.7.0" +version = "0.9.0" dependencies = [ "anyhow", "cfg-if", @@ -1974,19 +2016,17 @@ dependencies = [ "region", "target-lexicon", "wasi-common", - "wasmparser 0.45.1", + "wasmparser 0.45.2", "wasmtime-environ", "wasmtime-jit", "wasmtime-runtime", - "wasmtime-wasi", - "wasmtime-wast", "wat", "winapi", ] [[package]] name = "wasmtime-cli" -version = "0.7.0" +version = "0.9.0" dependencies = [ "anyhow", "faerie", @@ -2015,7 +2055,7 @@ dependencies = [ [[package]] name = "wasmtime-debug" -version = "0.7.0" +version = "0.9.0" dependencies = [ "anyhow", "faerie", @@ -2023,13 +2063,13 @@ dependencies = [ "more-asserts", "target-lexicon", "thiserror", - "wasmparser 0.45.1", + "wasmparser 0.45.2", "wasmtime-environ", ] [[package]] name = "wasmtime-environ" -version = "0.7.0" +version = "0.9.0" dependencies = [ "anyhow", "base64 0.11.0", @@ -2057,14 +2097,14 @@ dependencies = [ "tempfile", "thiserror", "toml", - "wasmparser 0.45.1", + "wasmparser 0.45.2", "winapi", "zstd", ] [[package]] name = "wasmtime-fuzz" -version = "0.7.0" +version = "0.9.0" dependencies = [ "arbitrary", "env_logger 0.7.1", @@ -2077,14 +2117,14 @@ dependencies = [ [[package]] name = "wasmtime-fuzzing" -version = "0.1.0" +version = "0.9.0" dependencies = [ "anyhow", "arbitrary", "binaryen", "env_logger 0.7.1", "log", - "wasmparser 0.45.1", + "wasmparser 0.45.2", "wasmprinter", "wasmtime", "wasmtime-environ", @@ -2094,12 +2134,12 @@ dependencies = [ [[package]] name = "wasmtime-interface-types" -version = "0.7.0" +version = "0.9.0" dependencies = [ "anyhow", "walrus", "wasm-webidl-bindings", - "wasmparser 0.45.1", + "wasmparser 0.45.2", "wasmtime", "wasmtime-environ", "wasmtime-jit", @@ -2109,7 +2149,7 @@ dependencies = [ [[package]] name = "wasmtime-jit" -version = "0.7.0" +version = "0.9.0" dependencies = [ "anyhow", "cranelift-codegen", @@ -2121,7 +2161,7 @@ dependencies = [ "region", "target-lexicon", "thiserror", - "wasmparser 0.45.1", + "wasmparser 0.45.2", "wasmtime-debug", "wasmtime-environ", "wasmtime-runtime", @@ -2130,7 +2170,7 @@ dependencies = [ [[package]] name = "wasmtime-obj" -version = "0.7.0" +version = "0.9.0" dependencies = [ "anyhow", "faerie", @@ -2140,13 +2180,13 @@ dependencies = [ [[package]] name = "wasmtime-py" -version = "0.7.0" +version = "0.9.0" dependencies = [ "anyhow", "pyo3", "region", "target-lexicon", - "wasmparser 0.45.1", + "wasmparser 0.45.2", "wasmtime", "wasmtime-environ", "wasmtime-interface-types", @@ -2156,7 +2196,7 @@ dependencies = [ [[package]] name = "wasmtime-runtime" -version = "0.7.0" +version = "0.9.0" dependencies = [ "cc", "cfg-if", @@ -2173,7 +2213,7 @@ dependencies = [ [[package]] name = "wasmtime-rust" -version = "0.7.0" +version = "0.9.0" dependencies = [ "anyhow", "wasmtime", @@ -2184,7 +2224,7 @@ dependencies = [ [[package]] name = "wasmtime-rust-macro" -version = "0.7.0" +version = "0.9.0" dependencies = [ "proc-macro2", "quote", @@ -2193,7 +2233,7 @@ dependencies = [ [[package]] name = "wasmtime-wasi" -version = "0.7.0" +version = "0.9.0" dependencies = [ "cranelift-codegen", "cranelift-entity", @@ -2210,7 +2250,7 @@ dependencies = [ [[package]] name = "wasmtime-wasi-c" -version = "0.7.0" +version = "0.9.0" dependencies = [ "bindgen 0.51.1", "cmake", @@ -2228,7 +2268,7 @@ dependencies = [ [[package]] name = "wasmtime-wast" -version = "0.7.0" +version = "0.9.0" dependencies = [ "anyhow", "wasmtime", @@ -2244,15 +2284,6 @@ dependencies = [ "leb128", ] -[[package]] -name = "wast" -version = "4.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdd03645007fe5c76cdacbcf51c145db79ab82756e977f7ed051b7cf896dc7df" -dependencies = [ - "leb128", -] - [[package]] name = "wast" version = "5.0.1" @@ -2263,12 +2294,21 @@ dependencies = [ ] [[package]] -name = "wat" -version = "1.0.5" +name = "wast" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ba86afa8d9f69291394de512e10e5ca6788998f4c426a56113770048826dc9" +checksum = "3ed3db7029d1d31a15c10126e78b58e51781faefafbc8afb20fb01291b779984" dependencies = [ - "wast 4.0.0", + "leb128", +] + +[[package]] +name = "wat" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d59ba5b224f5507d55e4f89d0b18cc6452d84640ab11b4c9086d61a3ee62d03" +dependencies = [ + "wast 6.0.0", ] [[package]] @@ -2282,7 +2322,7 @@ dependencies = [ [[package]] name = "wig" -version = "0.7.0" +version = "0.9.2" dependencies = [ "heck", "proc-macro2", @@ -2333,7 +2373,7 @@ dependencies = [ [[package]] name = "winx" -version = "0.7.0" +version = "0.9.0" dependencies = [ "bitflags", "cvt", @@ -2343,6 +2383,8 @@ dependencies = [ [[package]] name = "witx" version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abc432537dbc9940e06816ebc3e1c4694fc835b90720615c32038769d7b2967d" dependencies = [ "clap", "thiserror", @@ -2351,7 +2393,7 @@ dependencies = [ [[package]] name = "yanix" -version = "0.1.0" +version = "0.9.0" dependencies = [ "bitflags", "cfg-if", diff --git a/Cargo.toml b/Cargo.toml index 813ce9edfd..9eaba429dd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmtime-cli" -version = "0.7.0" +version = "0.9.0" authors = ["The Wasmtime Project Developers"] description = "Command-line interface for Wasmtime" license = "Apache-2.0 WITH LLVM-exception" diff --git a/crates/api/Cargo.toml b/crates/api/Cargo.toml index 75850b0503..b441217640 100644 --- a/crates/api/Cargo.toml +++ b/crates/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmtime" -version = "0.7.0" +version = "0.9.0" authors = ["The Wasmtime Project Developers"] description = "High-level API to expose the Wasmtime runtime" license = "Apache-2.0 WITH LLVM-exception" @@ -13,9 +13,9 @@ name = "wasmtime" crate-type = ["lib", "staticlib", "cdylib"] [dependencies] -wasmtime-runtime = { path = "../runtime" } -wasmtime-environ = { path = "../environ" } -wasmtime-jit = { path = "../jit" } +wasmtime-runtime = { path = "../runtime", version = "0.9.0" } +wasmtime-environ = { path = "../environ", version = "0.9.0" } +wasmtime-jit = { path = "../jit", version = "0.9.0" } wasmparser = { version = "0.45.1", default-features = false } target-lexicon = { version = "0.9.0", default-features = false } anyhow = "1.0.19" @@ -28,10 +28,8 @@ winapi = "0.3.7" [dev-dependencies] # for wasmtime.rs -wasi-common = { path = "../wasi-common" } +wasi-common = { path = "../wasi-common", version = "0.9.0" } pretty_env_logger = "0.3.0" -wasmtime-wast = { path = "../wast" } -wasmtime-wasi = { path = "../wasi" } rayon = "1.2.1" file-per-thread-logger = "0.1.1" wat = "1.0" diff --git a/crates/debug/Cargo.toml b/crates/debug/Cargo.toml index 02fca694f2..a85387c326 100644 --- a/crates/debug/Cargo.toml +++ b/crates/debug/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmtime-debug" -version = "0.7.0" +version = "0.9.0" authors = ["The Wasmtime Project Developers"] description = "Debug utils for WebAsssembly code in Cranelift" license = "Apache-2.0 WITH LLVM-exception" @@ -15,7 +15,7 @@ edition = "2018" gimli = "0.19.0" wasmparser = "0.45.1" faerie = "0.13.0" -wasmtime-environ = { path = "../environ" } +wasmtime-environ = { path = "../environ", version = "0.9.0" } target-lexicon = { version = "0.9.0", default-features = false } anyhow = "1.0" thiserror = "1.0.4" diff --git a/crates/environ/Cargo.toml b/crates/environ/Cargo.toml index e4e3a5465d..260b8a468f 100644 --- a/crates/environ/Cargo.toml +++ b/crates/environ/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmtime-environ" -version = "0.7.0" +version = "0.9.0" authors = ["The Wasmtime Project Developers"] description = "Standalone environment support for WebAsssembly code in Cranelift" license = "Apache-2.0 WITH LLVM-exception" @@ -17,7 +17,7 @@ cranelift-codegen = { version = "0.52.0", features = ["enable-serde"] } cranelift-entity = { version = "0.52.0", features = ["enable-serde"] } cranelift-wasm = { version = "0.52.0", features = ["enable-serde"] } wasmparser = "0.45.1" -lightbeam = { path = "../lightbeam", optional = true } +lightbeam = { path = "../lightbeam", optional = true, version = "0.9.0" } indexmap = "1.0.2" rayon = "1.2.1" thiserror = "1.0.4" diff --git a/crates/fuzzing/Cargo.toml b/crates/fuzzing/Cargo.toml index a99134b03a..76d65fc05e 100644 --- a/crates/fuzzing/Cargo.toml +++ b/crates/fuzzing/Cargo.toml @@ -4,7 +4,7 @@ description = "Fuzzing infrastructure for Wasmtime" edition = "2018" name = "wasmtime-fuzzing" publish = false -version = "0.1.0" +version = "0.9.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -16,9 +16,9 @@ env_logger = { version = "0.7.1", optional = true } log = "0.4.8" wasmparser = "0.45.1" wasmprinter = "0.2.0" -wasmtime = { path = "../api" } -wasmtime-environ = { path = "../environ" } -wasmtime-jit = { path = "../jit" } +wasmtime = { path = "../api", version = "0.9.0" } +wasmtime-environ = { path = "../environ", version = "0.9.0" } +wasmtime-jit = { path = "../jit", version = "0.9.0" } [dev-dependencies] wat = "1.0" diff --git a/crates/interface-types/Cargo.toml b/crates/interface-types/Cargo.toml index 2b5892cbd5..72572c59b0 100644 --- a/crates/interface-types/Cargo.toml +++ b/crates/interface-types/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmtime-interface-types" -version = "0.7.0" +version = "0.9.0" authors = ["The Wasmtime Project Developers"] description = "Support for wasm interface types with wasmtime" license = "Apache-2.0 WITH LLVM-exception" @@ -15,11 +15,11 @@ anyhow = "1.0.19" walrus = "0.13" wasmparser = { version = "0.45.1", default-features = false } wasm-webidl-bindings = "0.6" -wasmtime = { path = '../api' } -wasmtime-jit = { path = '../jit' } -wasmtime-environ = { path = '../environ' } -wasmtime-runtime = { path = '../runtime' } -wasmtime-wasi = { path = '../wasi' } +wasmtime = { path = "../api", version = "0.9.0" } +wasmtime-jit = { path = "../jit", version = "0.9.0" } +wasmtime-environ = { path = "../environ", version = "0.9.0" } +wasmtime-runtime = { path = "../runtime", version = "0.9.0" } +wasmtime-wasi = { path = "../wasi", version = "0.9.0" } [badges] maintenance = { status = "actively-developed" } diff --git a/crates/jit/Cargo.toml b/crates/jit/Cargo.toml index 9ef028bee4..a4a1c59a4c 100644 --- a/crates/jit/Cargo.toml +++ b/crates/jit/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmtime-jit" -version = "0.7.0" +version = "0.9.0" authors = ["The Wasmtime Project Developers"] description = "JIT-style execution for WebAsssembly code in Cranelift" license = "Apache-2.0 WITH LLVM-exception" @@ -16,9 +16,9 @@ cranelift-entity = { version = "0.52.0", features = ["enable-serde"] } cranelift-wasm = { version = "0.52.0", features = ["enable-serde"] } cranelift-native = "0.52.0" cranelift-frontend = "0.52.0" -wasmtime-environ = { path = "../environ" } -wasmtime-runtime = { path = "../runtime" } -wasmtime-debug = { path = "../debug" } +wasmtime-environ = { path = "../environ", version = "0.9.0" } +wasmtime-runtime = { path = "../runtime", version = "0.9.0" } +wasmtime-debug = { path = "../debug", version = "0.9.0" } region = "2.0.0" thiserror = "1.0.4" target-lexicon = { version = "0.9.0", default-features = false } diff --git a/crates/lightbeam/Cargo.toml b/crates/lightbeam/Cargo.toml index 3e19cd3d04..b5af145c84 100644 --- a/crates/lightbeam/Cargo.toml +++ b/crates/lightbeam/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "lightbeam" -version = "0.7.0" +version = "0.9.0" authors = ["The Lightbeam Project Developers"] description = "An optimising one-pass streaming compiler for WebAssembly" license = "Apache-2.0 WITH LLVM-exception" diff --git a/crates/misc/py/Cargo.toml b/crates/misc/py/Cargo.toml index be738b34de..335e843794 100644 --- a/crates/misc/py/Cargo.toml +++ b/crates/misc/py/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmtime-py" -version = "0.7.0" +version = "0.9.0" authors = ["The Wasmtime Project Developers"] description = "Python extension for Wasmtime" license = "Apache-2.0 WITH LLVM-exception" @@ -17,11 +17,11 @@ test = false doc = false [dependencies] -wasmtime = { path = "../../api" } -wasmtime-environ = { path = "../../environ" } -wasmtime-interface-types = { path = "../../interface-types" } -wasmtime-runtime = { path = "../../runtime" } -wasmtime-wasi = { path = "../../wasi" } +wasmtime = { path = "../../api", version = "0.9.0" } +wasmtime-environ = { path = "../../environ", version = "0.9.0" } +wasmtime-interface-types = { path = "../../interface-types", version = "0.9.0" } +wasmtime-runtime = { path = "../../runtime", version = "0.9.0" } +wasmtime-wasi = { path = "../../wasi", version = "0.9.0" } target-lexicon = { version = "0.9.0", default-features = false } anyhow = "1.0.19" region = "2.0.0" diff --git a/crates/misc/rust/Cargo.toml b/crates/misc/rust/Cargo.toml index c6e778090c..be1584f6da 100644 --- a/crates/misc/rust/Cargo.toml +++ b/crates/misc/rust/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmtime-rust" -version = "0.7.0" +version = "0.9.0" authors = ["Alex Crichton "] description = "Rust extension for Wasmtime" license = "Apache-2.0 WITH LLVM-exception" @@ -15,10 +15,10 @@ test = false doctest = false [dependencies] -wasmtime-interface-types = { path = "../../interface-types" } -wasmtime-rust-macro = { path = "./macro" } -wasmtime-wasi = { path = "../../wasi" } -wasmtime = { path = "../../api" } +wasmtime-interface-types = { path = "../../interface-types", version = "0.9.0" } +wasmtime-rust-macro = { path = "./macro", version = "0.9.0" } +wasmtime-wasi = { path = "../../wasi", version = "0.9.0" } +wasmtime = { path = "../../api", version = "0.9.0" } anyhow = "1.0.19" [badges] diff --git a/crates/misc/rust/macro/Cargo.toml b/crates/misc/rust/macro/Cargo.toml index 2093ba7892..7c0b022686 100644 --- a/crates/misc/rust/macro/Cargo.toml +++ b/crates/misc/rust/macro/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmtime-rust-macro" -version = "0.7.0" +version = "0.9.0" authors = ["Alex Crichton "] description = "Macro support crate for wasmtime-rust" license = "Apache-2.0 WITH LLVM-exception" diff --git a/crates/obj/Cargo.toml b/crates/obj/Cargo.toml index fabe65a65f..15056b8245 100644 --- a/crates/obj/Cargo.toml +++ b/crates/obj/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmtime-obj" -version = "0.7.0" +version = "0.9.0" authors = ["The Wasmtime Project Developers"] description = "Native object file output for WebAsssembly code in Wasmtime" license = "Apache-2.0 WITH LLVM-exception" @@ -12,7 +12,7 @@ edition = "2018" [dependencies] anyhow = "1.0" -wasmtime-environ = { path = "../environ" } +wasmtime-environ = { path = "../environ", version = "0.9.0" } faerie = "0.13.0" more-asserts = "0.2.1" diff --git a/crates/runtime/Cargo.toml b/crates/runtime/Cargo.toml index f613d42e27..21c62fcf42 100644 --- a/crates/runtime/Cargo.toml +++ b/crates/runtime/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmtime-runtime" -version = "0.7.0" +version = "0.9.0" authors = ["The Wasmtime Project Developers"] description = "Runtime library support for Wasmtime" license = "Apache-2.0 WITH LLVM-exception" @@ -11,7 +11,7 @@ readme = "README.md" edition = "2018" [dependencies] -wasmtime-environ = { path = "../environ" } +wasmtime-environ = { path = "../environ", version = "0.9.0" } region = "2.0.0" lazy_static = "1.2.0" libc = { version = "0.2.60", default-features = false } diff --git a/crates/test-programs/Cargo.toml b/crates/test-programs/Cargo.toml index 4f24e2f9c1..50f2254757 100644 --- a/crates/test-programs/Cargo.toml +++ b/crates/test-programs/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "test-programs" -version = "0.7.0" +version = "0.9.0" authors = ["The Wasmtime Project Developers"] readme = "README.md" edition = "2018" @@ -10,12 +10,12 @@ publish = false cfg-if = "0.1.9" [dev-dependencies] -wasi-common = { path = "../wasi-common" } -wasmtime-runtime = { path = "../runtime" } -wasmtime-environ = { path = "../environ" } -wasmtime-jit = { path = "../jit" } -wasmtime-wasi = { path = "../wasi" } -wasmtime = { path = "../api" } +wasi-common = { path = "../wasi-common", version = "0.9.0" } +wasmtime-runtime = { path = "../runtime", version = "0.9.0" } +wasmtime-environ = { path = "../environ", version = "0.9.0" } +wasmtime-jit = { path = "../jit", version = "0.9.0" } +wasmtime-wasi = { path = "../wasi", version = "0.9.0" } +wasmtime = { path = "../api", version = "0.9.0" } target-lexicon = "0.9.0" pretty_env_logger = "0.3.0" tempfile = "3.1.0" diff --git a/crates/test-programs/wasi-tests/Cargo.toml b/crates/test-programs/wasi-tests/Cargo.toml index 3a874d56f4..68a9a7add1 100644 --- a/crates/test-programs/wasi-tests/Cargo.toml +++ b/crates/test-programs/wasi-tests/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasi-tests" -version = "0.7.0" +version = "0.9.0" authors = ["The Wasmtime Project Developers"] readme = "README.md" edition = "2018" diff --git a/crates/wasi-c/Cargo.toml b/crates/wasi-c/Cargo.toml index 6104753440..423fb4d346 100644 --- a/crates/wasi-c/Cargo.toml +++ b/crates/wasi-c/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmtime-wasi-c" -version = "0.7.0" +version = "0.9.0" authors = ["The Cranelift Project Developers"] description = "WASI API support for Wasmtime" license = "Apache-2.0 WITH LLVM-exception" @@ -11,9 +11,9 @@ readme = "README.md" edition = "2018" [dependencies] -wasmtime-runtime = { path = "../runtime" } -wasmtime-environ = { path = "../environ" } -wasmtime-jit = { path = "../jit" } +wasmtime-runtime = { path = "../runtime", version = "0.9.0" } +wasmtime-environ = { path = "../environ", version = "0.9.0" } +wasmtime-jit = { path = "../jit", version = "0.9.0" } cranelift-codegen = { version = "0.52.0", features = ["enable-serde"] } cranelift-entity = { version = "0.52.0", features = ["enable-serde"] } cranelift-wasm = { version = "0.52.0", features = ["enable-serde"] } diff --git a/crates/wasi-common/Cargo.toml b/crates/wasi-common/Cargo.toml index f9d0f08ec2..6c17f64a52 100644 --- a/crates/wasi-common/Cargo.toml +++ b/crates/wasi-common/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasi-common" -version = "0.7.0" +version = "0.9.0" authors = ["The Wasmtime Project Developers"] description = "WASI implementation in Rust" license = "Apache-2.0 WITH LLVM-exception" @@ -11,7 +11,7 @@ readme = "README.md" edition = "2018" [dependencies] -wasi-common-cbindgen = { path = "wasi-common-cbindgen" } +wasi-common-cbindgen = { path = "wasi-common-cbindgen", version = "0.9.0" } anyhow = "1.0" thiserror = "1.0" libc = "0.2" @@ -21,13 +21,13 @@ log = "0.4" filetime = "0.2.7" lazy_static = "1.4.0" num = { version = "0.2.0", default-features = false } -wig = { path = "wig" } +wig = { path = "wig", version = "0.9.2" } [target.'cfg(unix)'.dependencies] -yanix = { path = "yanix" } +yanix = { path = "yanix", version = "0.9.0" } [target.'cfg(windows)'.dependencies] -winx = { path = "winx" } +winx = { path = "winx", version = "0.9.0" } winapi = "0.3" cpu-time = "1.0" diff --git a/crates/wasi-common/wasi-common-cbindgen/Cargo.toml b/crates/wasi-common/wasi-common-cbindgen/Cargo.toml index dadae6a915..c30668c212 100644 --- a/crates/wasi-common/wasi-common-cbindgen/Cargo.toml +++ b/crates/wasi-common/wasi-common-cbindgen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasi-common-cbindgen" -version = "0.7.0" +version = "0.9.0" authors = ["Jakub Konka "] description = "Interface generator utilities used by wasi-common" license = "Apache-2.0 WITH LLVM-exception" diff --git a/crates/wasi-common/wig/Cargo.toml b/crates/wasi-common/wig/Cargo.toml index c5a537d815..fb2720923e 100644 --- a/crates/wasi-common/wig/Cargo.toml +++ b/crates/wasi-common/wig/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wig" -version = "0.7.0" +version = "0.9.2" authors = ["Dan Gohman "] description = "WebAssembly Interface Generator" license = "Apache-2.0 WITH LLVM-exception" @@ -8,6 +8,7 @@ categories = ["wasm"] keywords = ["webassembly", "wasm"] repository = "https://github.com/bytecodealliance/wasmtime" edition = "2018" +include = ["src/**/*", "LICENSE", "WASI"] [lib] proc-macro = true @@ -19,7 +20,7 @@ heck = "0.3.1" # We include the WASI repo primarily for the witx files, but it's also useful # to use the witx parser it contains, rather than the witx crate from # crates.io, so that it always matches the version of the witx files. -witx = { path = "../WASI/tools/witx" } +witx = "0.6.0" [badges] maintenance = { status = "actively-developed" } diff --git a/crates/wasi-common/WASI b/crates/wasi-common/wig/WASI similarity index 100% rename from crates/wasi-common/WASI rename to crates/wasi-common/wig/WASI diff --git a/crates/wasi-common/wig/src/utils.rs b/crates/wasi-common/wig/src/utils.rs index 74d71e5eb4..a3a29963c3 100644 --- a/crates/wasi-common/wig/src/utils.rs +++ b/crates/wasi-common/wig/src/utils.rs @@ -28,7 +28,7 @@ pub(crate) fn witx_path_from_args(args: TokenStream) -> (String, String) { fn witx_path(phase: &str, id: &str) -> String { let root = env!("CARGO_MANIFEST_DIR"); - format!("{}/../WASI/phases/{}/witx/{}.witx", root, phase, id) + format!("{}/WASI/phases/{}/witx/{}.witx", root, phase, id) } // Convert a `Literal` holding a string literal into the `String`. diff --git a/crates/wasi-common/winx/Cargo.toml b/crates/wasi-common/winx/Cargo.toml index e3ee6519fa..fc04ffa22b 100644 --- a/crates/wasi-common/winx/Cargo.toml +++ b/crates/wasi-common/winx/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "winx" -version = "0.7.0" +version = "0.9.0" authors = ["Jakub Konka "] description = "Windows API helper library" license = "Apache-2.0 WITH LLVM-exception" diff --git a/crates/wasi-common/yanix/Cargo.toml b/crates/wasi-common/yanix/Cargo.toml index 61c52488cb..417ff89c4d 100644 --- a/crates/wasi-common/yanix/Cargo.toml +++ b/crates/wasi-common/yanix/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "yanix" -version = "0.1.0" +version = "0.9.0" authors = ["The Wasmtime Project Developers"] description = "Yet Another Nix crate: a Unix API helper library" license = "Apache-2.0 WITH LLVM-exception" diff --git a/crates/wasi/Cargo.toml b/crates/wasi/Cargo.toml index 71a2f09928..fa3607dfc5 100644 --- a/crates/wasi/Cargo.toml +++ b/crates/wasi/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmtime-wasi" -version = "0.7.0" +version = "0.9.0" authors = ["The Cranelift Project Developers"] description = "WASI API support for Wasmtime" license = "Apache-2.0 WITH LLVM-exception" @@ -11,17 +11,17 @@ readme = "README.md" edition = "2018" [dependencies] -wasmtime = { path = "../api" } -wasmtime-runtime = { path = "../runtime" } -wasmtime-environ = { path = "../environ" } -wasmtime-jit = { path = "../jit" } -wasi-common = { path = "../wasi-common" } +wasmtime = { path = "../api", version = "0.9.0" } +wasmtime-runtime = { path = "../runtime", version = "0.9.0" } +wasmtime-environ = { path = "../environ", version = "0.9.0" } +wasmtime-jit = { path = "../jit", version = "0.9.0" } +wasi-common = { path = "../wasi-common", version = "0.9.0" } cranelift-codegen = { version = "0.52.0", features = ["enable-serde"] } cranelift-entity = { version = "0.52.0", features = ["enable-serde"] } cranelift-wasm = { version = "0.52.0", features = ["enable-serde"] } target-lexicon = "0.9.0" log = { version = "0.4.8", default-features = false } -wig = { path = "../wasi-common/wig" } +wig = { path = "../wasi-common/wig", version = "0.9.2" } [badges] maintenance = { status = "actively-developed" } diff --git a/crates/wast/Cargo.toml b/crates/wast/Cargo.toml index 29270d75f5..f3baca6e2e 100644 --- a/crates/wast/Cargo.toml +++ b/crates/wast/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmtime-wast" -version = "0.7.0" +version = "0.9.0" authors = ["The Wasmtime Project Developers"] description = "wast testing support for wasmtime" license = "Apache-2.0 WITH LLVM-exception" @@ -12,7 +12,7 @@ edition = "2018" [dependencies] anyhow = "1.0.19" -wasmtime = { path = "../api" } +wasmtime = { path = "../api", version = "0.9.0" } wast = "5.0.1" [badges] diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index a1d2e97545..996c53b2f3 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmtime-fuzz" -version = "0.7.0" +version = "0.9.0" authors = ["The Wasmtime Project Developers"] edition = "2018" publish = false diff --git a/scripts/publish-all.sh b/scripts/publish-all.sh index ae00756dcc..af472c6607 100755 --- a/scripts/publish-all.sh +++ b/scripts/publish-all.sh @@ -9,7 +9,7 @@ topdir=$(dirname "$0")/.. cd "$topdir" # All the wasmtime-* crates have the same version number -version="0.7.0" +version="0.9.0" # Update the version numbers of the crates to $version. echo "Updating crate versions to $version" @@ -42,10 +42,10 @@ for cargo_toml in \ crates/runtime/Cargo.toml \ crates/debug/Cargo.toml \ crates/jit/Cargo.toml \ - crates/wast/Cargo.toml \ crates/wasi-c/Cargo.toml \ - crates/wasi/Cargo.toml \ crates/api/Cargo.toml \ + crates/wasi/Cargo.toml \ + crates/wast/Cargo.toml \ crates/interface-types/Cargo.toml \ crates/misc/py/Cargo.toml \ crates/misc/rust/macro/Cargo.toml \ diff --git a/src/commands/wasm2obj.rs b/src/commands/wasm2obj.rs index 0c5f04b972..b33d8c08b7 100644 --- a/src/commands/wasm2obj.rs +++ b/src/commands/wasm2obj.rs @@ -154,7 +154,7 @@ impl WasmToObjCommand { &module_translation, lazy_function_body_inputs, &*isa, - generate_debug_info, + self.common.debug_info, ), #[cfg(not(feature = "lightbeam"))] Strategy::Lightbeam => bail!("lightbeam support not enabled"), From 068c24943909a8a5f257755e82a13c9555d613ca Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Fri, 10 Jan 2020 07:34:49 -0800 Subject: [PATCH 16/28] Add code to publish-all.sh for bumping path dependency versions. (#792) In a multi-crate repo, path dependencies still need to specify versions when publishing on crates.io. This adds a very simple way to keep all these versions in sync. --- scripts/publish-all.sh | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/scripts/publish-all.sh b/scripts/publish-all.sh index af472c6607..b5ef28c216 100755 --- a/scripts/publish-all.sh +++ b/scripts/publish-all.sh @@ -17,6 +17,13 @@ find -name Cargo.toml \ -not -path ./crates/wasi-common/WASI/tools/witx/Cargo.toml \ -exec sed -i.bk -e "s/^version = \"[[:digit:]].*/version = \"$version\"/" {} \; +# Update the required version numbers of path dependencies. +find -name Cargo.toml \ + -not -path ./crates/wasi-common/wig/WASI/tools/witx/Cargo.toml \ + -exec sed -i.bk \ + -e "/\> *= *{.*\ Date: Fri, 10 Jan 2020 10:42:14 -0600 Subject: [PATCH 17/28] Remove `HostRef` from the `wasmtime` public API (#788) * Remove `HostRef` from the `wasmtime` public API This commit removes all remaining usages of `HostRef` in the public API of the `wasmtime` crate. This involved a number of API decisions such as: * None of `Func`, `Global`, `Table`, or `Memory` are wrapped in `HostRef` * All of `Func`, `Global`, `Table`, and `Memory` implement `Clone` now. * Methods called `type` are renamed to `ty` to avoid typing `r#type`. * Methods requiring mutability for external items now no longer require mutability. The mutable reference here is sort of a lie anyway since the internals are aliased by the underlying module anyway. This affects: * `Table::set` * `Table::grow` * `Memory::grow` * `Instance::set_signal_handler` * The `Val::FuncRef` type is now no longer automatically coerced to `AnyRef`. This is technically a breaking change which is pretty bad, but I'm hoping that we can live with this interim state while we sort out the `AnyRef` story in general. * The implementation of the C API was refactored and updated in a few locations to account for these changes: * Accessing the exports of an instance are now cached to ensure we always hand out the same `HostRef` values. * `wasm_*_t` for external values no longer have internal cache, instead they all wrap `wasm_external_t` and have an unchecked accessor for the underlying variant (since the type is proof that it's there). This makes casting back and forth much more trivial. This is all related to #708 and while there's still more work to be done in terms of documentation, this is the major bulk of the rest of the implementation work on #708 I believe. * More API updates * Run rustfmt * Fix a doc test * More test updates --- crates/api/examples/gcd.rs | 2 +- crates/api/examples/hello.rs | 8 +- crates/api/examples/memory.rs | 41 +-- crates/api/examples/multi.rs | 4 +- crates/api/src/callable.rs | 8 +- crates/api/src/externals.rs | 185 +++++----- crates/api/src/instance.rs | 12 +- crates/api/src/values.rs | 27 +- crates/api/src/wasm.rs | 337 +++++++++--------- crates/api/tests/import-indexes.rs | 10 +- crates/api/tests/import_calling_export.rs | 23 +- crates/api/tests/traps.rs | 10 +- crates/fuzzing/src/oracles.rs | 27 +- crates/fuzzing/src/oracles/dummy.rs | 16 +- crates/interface-types/src/lib.rs | 17 +- crates/misc/py/src/function.rs | 13 +- crates/misc/py/src/instance.rs | 9 +- crates/misc/py/src/lib.rs | 6 +- crates/misc/py/src/memory.rs | 8 +- crates/misc/rust/macro/src/lib.rs | 9 +- .../test-programs/tests/wasm_tests/runtime.rs | 8 +- crates/wast/src/spectest.rs | 26 +- crates/wast/src/wast.rs | 17 +- src/commands/run.rs | 37 +- tests/custom_signal_handler.rs | 64 ++-- 25 files changed, 435 insertions(+), 489 deletions(-) diff --git a/crates/api/examples/gcd.rs b/crates/api/examples/gcd.rs index 93313cb708..c510a176ca 100644 --- a/crates/api/examples/gcd.rs +++ b/crates/api/examples/gcd.rs @@ -54,7 +54,7 @@ fn main() -> anyhow::Result<()> { // Invoke `gcd` export let gcd = instance.exports()[gcd_index].func().expect("gcd"); - let result = gcd.borrow().call(&[Val::from(6i32), Val::from(27i32)])?; + let result = gcd.call(&[Val::from(6i32), Val::from(27i32)])?; println!("{:?}", result); Ok(()) diff --git a/crates/api/examples/hello.rs b/crates/api/examples/hello.rs index 5caaa75af6..8924dfcb7d 100644 --- a/crates/api/examples/hello.rs +++ b/crates/api/examples/hello.rs @@ -41,15 +41,15 @@ fn main() -> Result<()> { // `HelloCallback` type and its associated implementation of `Callback. println!("Creating callback..."); let hello_type = FuncType::new(Box::new([]), Box::new([])); - let hello_func = HostRef::new(Func::new(&store, hello_type, Rc::new(HelloCallback))); + let hello_func = Func::new(&store, hello_type, Rc::new(HelloCallback)); // Once we've got that all set up we can then move to the instantiation // phase, pairing together a compiled module as well as a set of imports. // Note that this is where the wasm `start` function, if any, would run. println!("Instantiating module..."); let imports = vec![hello_func.into()]; - let instance = Instance::new(&store, &module, imports.as_slice()) - .context("> Error instantiating module!")?; + let instance = + Instance::new(&store, &module, &imports).context("> Error instantiating module!")?; // Next we poke around a bit to extract the `run` function from the module. println!("Extracting export..."); @@ -59,7 +59,7 @@ fn main() -> Result<()> { // And last but not least we can call it! println!("Calling export..."); - run_func.borrow().call(&[])?; + run_func.call(&[])?; println!("Done."); Ok(()) diff --git a/crates/api/examples/memory.rs b/crates/api/examples/memory.rs index bd7d0be21a..f9df469669 100644 --- a/crates/api/examples/memory.rs +++ b/crates/api/examples/memory.rs @@ -3,7 +3,7 @@ use anyhow::{bail, ensure, Context as _, Error}; use wasmtime::*; -fn get_export_memory(exports: &[Extern], i: usize) -> Result, Error> { +fn get_export_memory(exports: &[Extern], i: usize) -> Result { if exports.len() <= i { bail!("> Error accessing memory export {}!", i); } @@ -13,7 +13,7 @@ fn get_export_memory(exports: &[Extern], i: usize) -> Result, Er .clone()) } -fn get_export_func(exports: &[Extern], i: usize) -> Result, Error> { +fn get_export_func(exports: &[Extern], i: usize) -> Result { if exports.len() <= i { bail!("> Error accessing function export {}!", i); } @@ -33,7 +33,7 @@ macro_rules! check { macro_rules! check_ok { ($func:expr, $($p:expr),*) => { - if let Err(_) = $func.borrow().call(&[$($p.into()),*]) { + if let Err(_) = $func.call(&[$($p.into()),*]) { bail!("> Error on result, expected return"); } } @@ -41,7 +41,7 @@ macro_rules! check_ok { macro_rules! check_trap { ($func:expr, $($p:expr),*) => { - if let Ok(_) = $func.borrow().call(&[$($p.into()),*]) { + if let Ok(_) = $func.call(&[$($p.into()),*]) { bail!("> Error on result, expected trap"); } } @@ -49,7 +49,7 @@ macro_rules! check_trap { macro_rules! call { ($func:expr, $($p:expr),*) => { - match $func.borrow().call(&[$($p.into()),*]) { + match $func.call(&[$($p.into()),*]) { Ok(result) => { let result: i32 = result[0].unwrap_i32(); result @@ -101,16 +101,13 @@ fn main() -> Result<(), Error> { let load_func = get_export_func(&exports, 2)?; let store_func = get_export_func(&exports, 3)?; - // Try cloning. - check!(memory.clone().ptr_eq(&memory), true); - // Check initial memory. println!("Checking memory..."); - check!(memory.borrow().size(), 2u32); - check!(memory.borrow().data_size(), 0x20000usize); - check!(unsafe { memory.borrow().data()[0] }, 0); - check!(unsafe { memory.borrow().data()[0x1000] }, 1); - check!(unsafe { memory.borrow().data()[0x1003] }, 4); + check!(memory.size(), 2u32); + check!(memory.data_size(), 0x20000usize); + check!(unsafe { memory.data()[0] }, 0); + check!(unsafe { memory.data()[0x1000] }, 1); + check!(unsafe { memory.data()[0x1003] }, 4); check!(call!(size_func,), 2); check!(call!(load_func, 0), 0); @@ -122,36 +119,36 @@ fn main() -> Result<(), Error> { // Mutate memory. println!("Mutating memory..."); unsafe { - memory.borrow_mut().data()[0x1003] = 5; + memory.data()[0x1003] = 5; } check_ok!(store_func, 0x1002, 6); check_trap!(store_func, 0x20000, 0); - check!(unsafe { memory.borrow().data()[0x1002] }, 6); - check!(unsafe { memory.borrow().data()[0x1003] }, 5); + check!(unsafe { memory.data()[0x1002] }, 6); + check!(unsafe { memory.data()[0x1003] }, 5); check!(call!(load_func, 0x1002), 6); check!(call!(load_func, 0x1003), 5); // Grow memory. println!("Growing memory..."); - check!(memory.borrow_mut().grow(1), true); - check!(memory.borrow().size(), 3u32); - check!(memory.borrow().data_size(), 0x30000usize); + check!(memory.grow(1), true); + check!(memory.size(), 3u32); + check!(memory.data_size(), 0x30000usize); check!(call!(load_func, 0x20000), 0); check_ok!(store_func, 0x20000, 0); check_trap!(load_func, 0x30000); check_trap!(store_func, 0x30000, 0); - check!(memory.borrow_mut().grow(1), false); - check!(memory.borrow_mut().grow(0), true); + check!(memory.grow(1), false); + check!(memory.grow(0), true); // Create stand-alone memory. // TODO(wasm+): Once Wasm allows multiple memories, turn this into import. println!("Creating stand-alone memory..."); let memorytype = MemoryType::new(Limits::new(5, Some(5))); - let mut memory2 = Memory::new(&store, memorytype); + let memory2 = Memory::new(&store, memorytype); check!(memory2.size(), 5u32); check!(memory2.grow(1), false); check!(memory2.grow(0), true); diff --git a/crates/api/examples/multi.rs b/crates/api/examples/multi.rs index 8898accf11..d3236501cb 100644 --- a/crates/api/examples/multi.rs +++ b/crates/api/examples/multi.rs @@ -62,7 +62,7 @@ fn main() -> Result<()> { Box::new([ValType::I32, ValType::I64]), Box::new([ValType::I64, ValType::I32]), ); - let callback_func = HostRef::new(Func::new(&store, callback_type, Rc::new(Callback))); + let callback_func = Func::new(&store, callback_type, Rc::new(Callback)); // Instantiate. println!("Instantiating module..."); @@ -83,7 +83,6 @@ fn main() -> Result<()> { println!("Calling export \"g\"..."); let args = vec![Val::I32(1), Val::I64(3)]; let results = g - .borrow() .call(&args) .map_err(|e| format_err!("> Error calling g! {:?}", e))?; @@ -108,7 +107,6 @@ fn main() -> Result<()> { Val::I64(9), ]; let results = round_trip_many - .borrow() .call(&args) .map_err(|e| format_err!("> Error calling round_trip_many! {:?}", e))?; diff --git a/crates/api/src/callable.rs b/crates/api/src/callable.rs index 317875a7fd..4aefa8b206 100644 --- a/crates/api/src/callable.rs +++ b/crates/api/src/callable.rs @@ -12,7 +12,7 @@ use wasmtime_runtime::Export; /// WebAssembly. /// # Example /// ``` -/// use wasmtime::{HostRef, Val}; +/// use wasmtime::Val; /// /// struct TimesTwo; /// @@ -54,9 +54,8 @@ use wasmtime_runtime::Export; /// ); /// /// // Build a reference to the "times_two" function that can be used. -/// let times_two_function = HostRef::new( -/// wasmtime::Func::new(&store, times_two_type, std::rc::Rc::new(TimesTwo)) -/// ); +/// let times_two_function = +/// wasmtime::Func::new(&store, times_two_type, std::rc::Rc::new(TimesTwo)); /// /// // Create module instance that imports our function /// let instance = wasmtime::Instance::new( @@ -71,7 +70,6 @@ use wasmtime_runtime::Export; /// // Borrow and call "run". Returning any error message from Wasm as a string. /// let original = 5i32; /// let results = run_function -/// .borrow() /// .call(&[original.into()]) /// .map_err(|trap| trap.to_string())?; /// diff --git a/crates/api/src/externals.rs b/crates/api/src/externals.rs index c0b6156c77..98afc5a691 100644 --- a/crates/api/src/externals.rs +++ b/crates/api/src/externals.rs @@ -1,5 +1,5 @@ use crate::callable::{Callable, NativeCallable, WasmtimeFn, WrappedCallable}; -use crate::r#ref::{AnyRef, HostRef}; +use crate::r#ref::AnyRef; use crate::runtime::Store; use crate::trampoline::{generate_global_export, generate_memory_export, generate_table_export}; use crate::trap::Trap; @@ -15,53 +15,53 @@ use wasmtime_runtime::InstanceHandle; #[derive(Clone)] pub enum Extern { - Func(HostRef), - Global(HostRef), - Table(HostRef), - Memory(HostRef), + Func(Func), + Global(Global), + Table(Table), + Memory(Memory), } impl Extern { - pub fn func(&self) -> Option<&HostRef> { + pub fn func(&self) -> Option<&Func> { match self { Extern::Func(func) => Some(func), _ => None, } } - pub fn global(&self) -> Option<&HostRef> { + pub fn global(&self) -> Option<&Global> { match self { Extern::Global(global) => Some(global), _ => None, } } - pub fn table(&self) -> Option<&HostRef
> { + pub fn table(&self) -> Option<&Table> { match self { Extern::Table(table) => Some(table), _ => None, } } - pub fn memory(&self) -> Option<&HostRef> { + pub fn memory(&self) -> Option<&Memory> { match self { Extern::Memory(memory) => Some(memory), _ => None, } } - pub fn r#type(&self) -> ExternType { + pub fn ty(&self) -> ExternType { match self { - Extern::Func(ft) => ExternType::Func(ft.borrow().r#type().clone()), - Extern::Memory(ft) => ExternType::Memory(ft.borrow().r#type().clone()), - Extern::Table(tt) => ExternType::Table(tt.borrow().r#type().clone()), - Extern::Global(gt) => ExternType::Global(gt.borrow().r#type().clone()), + Extern::Func(ft) => ExternType::Func(ft.ty().clone()), + Extern::Memory(ft) => ExternType::Memory(ft.ty().clone()), + Extern::Table(tt) => ExternType::Table(tt.ty().clone()), + Extern::Global(gt) => ExternType::Global(gt.ty().clone()), } } pub(crate) fn get_wasmtime_export(&self) -> wasmtime_runtime::Export { match self { - Extern::Func(f) => f.borrow().wasmtime_export().clone(), - Extern::Global(g) => g.borrow().wasmtime_export().clone(), - Extern::Memory(m) => m.borrow().wasmtime_export().clone(), - Extern::Table(t) => t.borrow().wasmtime_export().clone(), + Extern::Func(f) => f.wasmtime_export().clone(), + Extern::Global(g) => g.wasmtime_export().clone(), + Extern::Memory(m) => m.wasmtime_export().clone(), + Extern::Table(t) => t.wasmtime_export().clone(), } } @@ -71,50 +71,51 @@ impl Extern { export: wasmtime_runtime::Export, ) -> Extern { match export { - wasmtime_runtime::Export::Function { .. } => Extern::Func(HostRef::new( - Func::from_wasmtime_function(export, store, instance_handle), - )), - wasmtime_runtime::Export::Memory { .. } => Extern::Memory(HostRef::new( - Memory::from_wasmtime_memory(export, store, instance_handle), - )), - wasmtime_runtime::Export::Global { .. } => { - Extern::Global(HostRef::new(Global::from_wasmtime_global(export, store))) + wasmtime_runtime::Export::Function { .. } => { + Extern::Func(Func::from_wasmtime_function(export, store, instance_handle)) + } + wasmtime_runtime::Export::Memory { .. } => { + Extern::Memory(Memory::from_wasmtime_memory(export, store, instance_handle)) + } + wasmtime_runtime::Export::Global { .. } => { + Extern::Global(Global::from_wasmtime_global(export, store)) + } + wasmtime_runtime::Export::Table { .. } => { + Extern::Table(Table::from_wasmtime_table(export, store, instance_handle)) } - wasmtime_runtime::Export::Table { .. } => Extern::Table(HostRef::new( - Table::from_wasmtime_table(export, store, instance_handle), - )), } } } -impl From> for Extern { - fn from(r: HostRef) -> Self { +impl From for Extern { + fn from(r: Func) -> Self { Extern::Func(r) } } -impl From> for Extern { - fn from(r: HostRef) -> Self { +impl From for Extern { + fn from(r: Global) -> Self { Extern::Global(r) } } -impl From> for Extern { - fn from(r: HostRef) -> Self { +impl From for Extern { + fn from(r: Memory) -> Self { Extern::Memory(r) } } -impl From> for Extern { - fn from(r: HostRef
) -> Self { +impl From
for Extern { + fn from(r: Table) -> Self { Extern::Table(r) } } +#[derive(Clone)] pub struct Func { _store: Store, callable: Rc, - r#type: FuncType, + ty: FuncType, } impl Func { @@ -125,26 +126,26 @@ impl Func { fn from_wrapped( store: &Store, - r#type: FuncType, + ty: FuncType, callable: Rc, ) -> Func { Func { _store: store.clone(), callable, - r#type, + ty, } } - pub fn r#type(&self) -> &FuncType { - &self.r#type + pub fn ty(&self) -> &FuncType { + &self.ty } pub fn param_arity(&self) -> usize { - self.r#type.params().len() + self.ty.params().len() } pub fn result_arity(&self) -> usize { - self.r#type.results().len() + self.ty.results().len() } pub fn call(&self, params: &[Val]) -> Result, Trap> { @@ -178,32 +179,39 @@ impl fmt::Debug for Func { } } +#[derive(Clone)] pub struct Global { + inner: Rc, +} + +struct GlobalInner { _store: Store, - r#type: GlobalType, + ty: GlobalType, wasmtime_export: wasmtime_runtime::Export, #[allow(dead_code)] wasmtime_state: Option, } impl Global { - pub fn new(store: &Store, r#type: GlobalType, val: Val) -> Global { + pub fn new(store: &Store, ty: GlobalType, val: Val) -> Global { let (wasmtime_export, wasmtime_state) = - generate_global_export(&r#type, val).expect("generated global"); + generate_global_export(&ty, val).expect("generated global"); Global { - _store: store.clone(), - r#type, - wasmtime_export, - wasmtime_state: Some(wasmtime_state), + inner: Rc::new(GlobalInner { + _store: store.clone(), + ty, + wasmtime_export, + wasmtime_state: Some(wasmtime_state), + }), } } - pub fn r#type(&self) -> &GlobalType { - &self.r#type + pub fn ty(&self) -> &GlobalType { + &self.inner.ty } fn wasmtime_global_definition(&self) -> *mut wasmtime_runtime::VMGlobalDefinition { - match self.wasmtime_export { + match self.inner.wasmtime_export { wasmtime_runtime::Export::Global { definition, .. } => definition, _ => panic!("global definition not found"), } @@ -212,22 +220,22 @@ impl Global { pub fn get(&self) -> Val { let definition = unsafe { &mut *self.wasmtime_global_definition() }; unsafe { - match self.r#type().content() { + match self.ty().content() { ValType::I32 => Val::from(*definition.as_i32()), ValType::I64 => Val::from(*definition.as_i64()), ValType::F32 => Val::F32(*definition.as_u32()), ValType::F64 => Val::F64(*definition.as_u64()), - _ => unimplemented!("Global::get for {:?}", self.r#type().content()), + _ => unimplemented!("Global::get for {:?}", self.ty().content()), } } } - pub fn set(&mut self, val: Val) { - if val.r#type() != *self.r#type().content() { + pub fn set(&self, val: Val) { + if val.ty() != *self.ty().content() { panic!( "global of type {:?} cannot be set to {:?}", - self.r#type().content(), - val.r#type() + self.ty().content(), + val.ty() ); } let definition = unsafe { &mut *self.wasmtime_global_definition() }; @@ -237,13 +245,13 @@ impl Global { Val::I64(i) => *definition.as_i64_mut() = i, Val::F32(f) => *definition.as_u32_mut() = f, Val::F64(f) => *definition.as_u64_mut() = f, - _ => unimplemented!("Global::set for {:?}", val.r#type()), + _ => unimplemented!("Global::set for {:?}", val.ty()), } } } pub(crate) fn wasmtime_export(&self) -> &wasmtime_runtime::Export { - &self.wasmtime_export + &self.inner.wasmtime_export } pub(crate) fn from_wasmtime_global(export: wasmtime_runtime::Export, store: &Store) -> Global { @@ -254,17 +262,20 @@ impl Global { }; let ty = GlobalType::from_wasmtime_global(&global); Global { - _store: store.clone(), - r#type: ty, - wasmtime_export: export, - wasmtime_state: None, + inner: Rc::new(GlobalInner { + _store: store.clone(), + ty: ty, + wasmtime_export: export, + wasmtime_state: None, + }), } } } +#[derive(Clone)] pub struct Table { store: Store, - r#type: TableType, + ty: TableType, wasmtime_handle: InstanceHandle, wasmtime_export: wasmtime_runtime::Export, } @@ -299,13 +310,13 @@ fn set_table_item( } impl Table { - pub fn new(store: &Store, r#type: TableType, init: Val) -> Table { - match r#type.element() { + pub fn new(store: &Store, ty: TableType, init: Val) -> Table { + match ty.element() { ValType::FuncRef => (), _ => panic!("table is not for funcref"), } let (mut wasmtime_handle, wasmtime_export) = - generate_table_export(&r#type).expect("generated table"); + generate_table_export(&ty).expect("generated table"); // Initialize entries with the init value. match wasmtime_export { @@ -323,14 +334,14 @@ impl Table { Table { store: store.clone(), - r#type, + ty, wasmtime_handle, wasmtime_export, } } - pub fn r#type(&self) -> &TableType { - &self.r#type + pub fn ty(&self) -> &TableType { + &self.ty } fn wasmtime_table_index(&self) -> wasm::DefinedTableIndex { @@ -362,9 +373,9 @@ impl Table { } } - pub fn grow(&mut self, delta: u32, init: Val) -> bool { + pub fn grow(&self, delta: u32, init: Val) -> bool { let index = self.wasmtime_table_index(); - if let Some(len) = self.wasmtime_handle.table_grow(index, delta) { + if let Some(len) = self.wasmtime_handle.clone().table_grow(index, delta) { let mut wasmtime_handle = self.wasmtime_handle.clone(); for i in 0..delta { let i = len - (delta - i); @@ -395,34 +406,35 @@ impl Table { let ty = TableType::from_wasmtime_table(&table.table); Table { store: store.clone(), - r#type: ty, + ty: ty, wasmtime_handle: instance_handle, wasmtime_export: export, } } } +#[derive(Clone)] pub struct Memory { _store: Store, - r#type: MemoryType, + ty: MemoryType, wasmtime_handle: InstanceHandle, wasmtime_export: wasmtime_runtime::Export, } impl Memory { - pub fn new(store: &Store, r#type: MemoryType) -> Memory { + pub fn new(store: &Store, ty: MemoryType) -> Memory { let (wasmtime_handle, wasmtime_export) = - generate_memory_export(&r#type).expect("generated memory"); + generate_memory_export(&ty).expect("generated memory"); Memory { _store: store.clone(), - r#type, + ty, wasmtime_handle, wasmtime_export, } } - pub fn r#type(&self) -> &MemoryType { - &self.r#type + pub fn ty(&self) -> &MemoryType { + &self.ty } fn wasmtime_memory_definition(&self) -> *mut wasmtime_runtime::VMMemoryDefinition { @@ -453,12 +465,15 @@ impl Memory { (self.data_size() / wasmtime_environ::WASM_PAGE_SIZE as usize) as u32 } - pub fn grow(&mut self, delta: u32) -> bool { + pub fn grow(&self, delta: u32) -> bool { match self.wasmtime_export { wasmtime_runtime::Export::Memory { definition, .. } => { let definition = unsafe { &(*definition) }; let index = self.wasmtime_handle.memory_index(definition); - self.wasmtime_handle.memory_grow(index, delta).is_some() + self.wasmtime_handle + .clone() + .memory_grow(index, delta) + .is_some() } _ => panic!("memory definition not found"), } @@ -481,7 +496,7 @@ impl Memory { let ty = MemoryType::from_wasmtime_memory(&memory.memory); Memory { _store: store.clone(), - r#type: ty, + ty: ty, wasmtime_handle: instance_handle, wasmtime_export: export, } diff --git a/crates/api/src/instance.rs b/crates/api/src/instance.rs index 166848cb12..b78048b892 100644 --- a/crates/api/src/instance.rs +++ b/crates/api/src/instance.rs @@ -167,29 +167,29 @@ cfg_if::cfg_if! { impl Instance { /// The signal handler must be /// [async-signal-safe](http://man7.org/linux/man-pages/man7/signal-safety.7.html). - pub fn set_signal_handler(&mut self, handler: H) + pub fn set_signal_handler(&self, handler: H) where H: 'static + Fn(libc::c_int, *const libc::siginfo_t, *const libc::c_void) -> bool, { - self.instance_handle.set_signal_handler(handler); + self.instance_handle.clone().set_signal_handler(handler); } } } else if #[cfg(target_os = "windows")] { impl Instance { - pub fn set_signal_handler(&mut self, handler: H) + pub fn set_signal_handler(&self, handler: H) where H: 'static + Fn(winapi::um::winnt::EXCEPTION_POINTERS) -> bool, { - self.instance_handle.set_signal_handler(handler); + self.instance_handle.clone().set_signal_handler(handler); } } } else if #[cfg(target_os = "macos")] { impl Instance { - pub fn set_signal_handler(&mut self, handler: H) + pub fn set_signal_handler(&self, handler: H) where H: 'static + Fn(libc::c_int, *const libc::siginfo_t, *const libc::c_void) -> bool, { - self.instance_handle.set_signal_handler(handler); + self.instance_handle.clone().set_signal_handler(handler); } } } diff --git a/crates/api/src/values.rs b/crates/api/src/values.rs index 419f4534f9..4d470a2e23 100644 --- a/crates/api/src/values.rs +++ b/crates/api/src/values.rs @@ -1,5 +1,5 @@ use crate::externals::Func; -use crate::r#ref::{AnyRef, HostRef}; +use crate::r#ref::AnyRef; use crate::runtime::Store; use crate::types::ValType; use std::ptr; @@ -34,7 +34,7 @@ pub enum Val { AnyRef(AnyRef), /// A first-class reference to a WebAssembly function. - FuncRef(HostRef), + FuncRef(Func), /// A 128-bit number V128(u128), @@ -71,7 +71,7 @@ impl Val { } /// Returns the corresponding [`ValType`] for this `Val`. - pub fn r#type(&self) -> ValType { + pub fn ty(&self) -> ValType { match self { Val::I32(_) => ValType::I32, Val::I64(_) => ValType::I64, @@ -111,7 +111,7 @@ impl Val { (I64(i64) i64 unwrap_i64 *e) (F32(f32) f32 unwrap_f32 f32::from_bits(*e)) (F64(f64) f64 unwrap_f64 f64::from_bits(*e)) - (FuncRef(&HostRef) funcref unwrap_funcref e) + (FuncRef(&Func) funcref unwrap_funcref e) (V128(u128) v128 unwrap_v128 *e) } @@ -122,7 +122,6 @@ impl Val { pub fn anyref(&self) -> Option { match self { Val::AnyRef(e) => Some(e.clone()), - Val::FuncRef(e) => Some(e.anyref()), _ => None, } } @@ -164,21 +163,12 @@ impl From for Val { impl From for Val { fn from(val: AnyRef) -> Val { - match &val { - AnyRef::Ref(r) => { - if r.is_ref::() { - Val::FuncRef(r.get_ref()) - } else { - Val::AnyRef(val) - } - } - _ => unimplemented!("AnyRef::Other"), - } + Val::AnyRef(val) } } -impl From> for Val { - fn from(val: HostRef) -> Val { +impl From for Val { + fn from(val: Func) -> Val { Val::FuncRef(val) } } @@ -206,7 +196,6 @@ pub(crate) fn into_checked_anyfunc( vmctx: ptr::null_mut(), }, Val::FuncRef(f) => { - let f = f.borrow(); let (vmctx, func_ptr, signature) = match f.wasmtime_export() { wasmtime_runtime::Export::Function { vmctx, @@ -243,5 +232,5 @@ pub(crate) fn from_checked_anyfunc( vmctx: item.vmctx, }; let f = Func::from_wasmtime_function(export, store, instance_handle); - Val::FuncRef(HostRef::new(f)) + Val::FuncRef(f) } diff --git a/crates/api/src/wasm.rs b/crates/api/src/wasm.rs index 1776eb06ec..f5591ece5b 100644 --- a/crates/api/src/wasm.rs +++ b/crates/api/src/wasm.rs @@ -10,6 +10,7 @@ use super::{ HostInfo, HostRef, ImportType, Instance, Limits, Memory, MemoryType, Module, Store, Table, TableType, Trap, Val, ValType, }; +use std::cell::RefCell; use std::rc::Rc; use std::{mem, ptr, slice}; @@ -243,6 +244,12 @@ enum wasm_externtype_t_type_cache { declare_vec!(wasm_externtype_vec_t, *mut wasm_externtype_t); pub type wasm_externkind_t = u8; + +const WASM_EXTERN_FUNC: wasm_externkind_t = 0; +const WASM_EXTERN_GLOBAL: wasm_externkind_t = 1; +const WASM_EXTERN_TABLE: wasm_externkind_t = 2; +const WASM_EXTERN_MEMORY: wasm_externkind_t = 3; + #[repr(C)] #[derive(Clone)] pub struct wasm_importtype_t { @@ -312,6 +319,7 @@ declare_vec!(wasm_frame_vec_t, *mut wasm_frame_t); #[derive(Clone)] pub struct wasm_instance_t { instance: HostRef, + exports_cache: RefCell>>, } pub type wasm_message_t = wasm_name_t; #[repr(C)] @@ -336,12 +344,22 @@ pub struct wasm_module_t { pub struct wasm_shared_module_t { _unused: [u8; 0], } -#[repr(C)] + #[derive(Clone)] +#[repr(transparent)] pub struct wasm_func_t { - func: HostRef, - ext: Option>, + ext: wasm_extern_t, } + +impl wasm_func_t { + fn func(&self) -> &HostRef { + match &self.ext.which { + ExternHost::Func(f) => f, + _ => unsafe { std::hint::unreachable_unchecked() }, + } + } +} + pub type wasm_func_callback_t = std::option::Option< unsafe extern "C" fn(args: *const wasm_val_t, results: *mut wasm_val_t) -> *mut wasm_trap_t, >; @@ -352,40 +370,67 @@ pub type wasm_func_callback_with_env_t = std::option::Option< results: *mut wasm_val_t, ) -> *mut wasm_trap_t, >; -#[repr(C)] + #[derive(Clone)] +#[repr(transparent)] pub struct wasm_global_t { - global: HostRef, - ext: Option>, + ext: wasm_extern_t, } -#[repr(C)] -#[derive(Clone)] -pub struct wasm_table_t { - table: HostRef
, - ext: Option>, -} -pub type wasm_table_size_t = u32; -#[repr(C)] -#[derive(Clone)] -pub struct wasm_memory_t { - memory: HostRef, - ext: Option>, -} -pub type wasm_memory_pages_t = u32; -#[repr(C)] -#[derive(Clone)] -pub struct wasm_extern_t { - ext: Extern, - cache: wasm_extern_t_type_cache, + +impl wasm_global_t { + fn global(&self) -> &HostRef { + match &self.ext.which { + ExternHost::Global(g) => g, + _ => unsafe { std::hint::unreachable_unchecked() }, + } + } } #[derive(Clone)] -enum wasm_extern_t_type_cache { - Empty, - Func(wasm_func_t), - Global(wasm_global_t), - Memory(wasm_memory_t), - Table(wasm_table_t), +#[repr(transparent)] +pub struct wasm_table_t { + ext: wasm_extern_t, +} + +impl wasm_table_t { + fn table(&self) -> &HostRef
{ + match &self.ext.which { + ExternHost::Table(t) => t, + _ => unsafe { std::hint::unreachable_unchecked() }, + } + } +} + +pub type wasm_table_size_t = u32; + +#[derive(Clone)] +#[repr(transparent)] +pub struct wasm_memory_t { + ext: wasm_extern_t, +} + +impl wasm_memory_t { + fn memory(&self) -> &HostRef { + match &self.ext.which { + ExternHost::Memory(m) => m, + _ => unsafe { std::hint::unreachable_unchecked() }, + } + } +} + +pub type wasm_memory_pages_t = u32; + +#[derive(Clone)] +pub struct wasm_extern_t { + which: ExternHost, +} + +#[derive(Clone)] +enum ExternHost { + Func(HostRef), + Global(HostRef), + Memory(HostRef), + Table(HostRef
), } declare_vec!(wasm_extern_vec_t, *mut wasm_extern_t); @@ -415,16 +460,9 @@ pub unsafe extern "C" fn wasm_engine_new() -> *mut wasm_engine_t { #[no_mangle] pub unsafe extern "C" fn wasm_extern_as_func(e: *mut wasm_extern_t) -> *mut wasm_func_t { - if let wasm_extern_t_type_cache::Empty = (*e).cache { - (*e).cache = wasm_extern_t_type_cache::Func(wasm_func_t { - func: (*e).ext.func().unwrap().clone(), - ext: None, - }); - } - - match &mut (*e).cache { - wasm_extern_t_type_cache::Func(f) => f, - _ => panic!("wasm_extern_as_func"), + match &(*e).which { + ExternHost::Func(_) => e.cast(), + _ => ptr::null_mut(), } } @@ -435,17 +473,7 @@ pub unsafe extern "C" fn wasm_extern_vec_delete(v: *mut wasm_extern_vec_t) { #[no_mangle] pub unsafe extern "C" fn wasm_func_as_extern(f: *mut wasm_func_t) -> *mut wasm_extern_t { - if (*f).ext.is_none() { - (*f).ext = Some(Box::new(wasm_extern_t { - ext: Extern::Func((*f).func.clone()), - cache: wasm_extern_t_type_cache::Empty, - })); - } - - match &mut (*f).ext { - Some(e) => e.as_mut(), - _ => panic!("wasm_func_as_extern"), - } + &mut (*f).ext } #[no_mangle] @@ -454,7 +482,7 @@ pub unsafe extern "C" fn wasm_func_call( args: *const wasm_val_t, results: *mut wasm_val_t, ) -> *mut wasm_trap_t { - let func = (*func).func.borrow(); + let func = (*func).func().borrow(); let mut params = Vec::with_capacity(func.param_arity()); for i in 0..func.param_arity() { let val = &(*args.add(i)); @@ -606,8 +634,9 @@ pub unsafe extern "C" fn wasm_func_new( let ty = (*ty).functype.clone(); let callback = Rc::new(callback); let func = Box::new(wasm_func_t { - func: HostRef::new(Func::new(store, ty, callback)), - ext: None, + ext: wasm_extern_t { + which: ExternHost::Func(HostRef::new(Func::new(store, ty, callback))), + }, }); Box::into_raw(func) } @@ -660,13 +689,19 @@ pub unsafe extern "C" fn wasm_instance_new( let mut externs: Vec = Vec::with_capacity((*module).imports.len()); for i in 0..(*module).imports.len() { let import = *imports.add(i); - externs.push((*import).ext.clone()); + externs.push(match &(*import).which { + ExternHost::Func(e) => Extern::Func(e.borrow().clone()), + ExternHost::Table(e) => Extern::Table(e.borrow().clone()), + ExternHost::Global(e) => Extern::Global(e.borrow().clone()), + ExternHost::Memory(e) => Extern::Memory(e.borrow().clone()), + }); } let module = &(*module).module.borrow(); match Instance::new(store, module, &externs) { Ok(instance) => { let instance = Box::new(wasm_instance_t { instance: HostRef::new(instance), + exports_cache: RefCell::new(None), }); if !result.is_null() { (*result) = ptr::null_mut(); @@ -694,14 +729,23 @@ pub unsafe extern "C" fn wasm_instance_exports( instance: *const wasm_instance_t, out: *mut wasm_extern_vec_t, ) { - let instance = &(*instance).instance.borrow(); - let exports = instance.exports(); + let mut cache = (*instance).exports_cache.borrow_mut(); + let exports = cache.get_or_insert_with(|| { + let instance = &(*instance).instance.borrow(); + instance + .exports() + .iter() + .map(|e| match e { + Extern::Func(f) => ExternHost::Func(HostRef::new(f.clone())), + Extern::Global(f) => ExternHost::Global(HostRef::new(f.clone())), + Extern::Memory(f) => ExternHost::Memory(HostRef::new(f.clone())), + Extern::Table(f) => ExternHost::Table(HostRef::new(f.clone())), + }) + .collect() + }); let mut buffer = Vec::with_capacity(exports.len()); - for e in exports.iter() { - let ext = Box::new(wasm_extern_t { - ext: e.clone(), - cache: wasm_extern_t_type_cache::Empty, - }); + for e in exports { + let ext = Box::new(wasm_extern_t { which: e.clone() }); buffer.push(Box::into_raw(ext)); } (*out).set_buffer(buffer); @@ -817,8 +861,9 @@ pub unsafe extern "C" fn wasm_func_new_with_env( finalizer, }); let func = Box::new(wasm_func_t { - func: HostRef::new(Func::new(store, ty, callback)), - ext: None, + ext: wasm_extern_t { + which: ExternHost::Func(HostRef::new(Func::new(store, ty, callback))), + }, }); Box::into_raw(func) } @@ -1012,24 +1057,25 @@ pub unsafe extern "C" fn wasm_exporttype_vec_delete(et: *mut wasm_exporttype_vec (*et).uninitialize(); } -fn from_externtype(ty: &ExternType) -> wasm_externkind_t { - match ty { - ExternType::Func(_) => 0, - ExternType::Global(_) => 1, - ExternType::Table(_) => 2, - ExternType::Memory(_) => 3, - } -} - #[no_mangle] pub unsafe extern "C" fn wasm_extern_kind(e: *const wasm_extern_t) -> wasm_externkind_t { - from_externtype(&(*e).ext.r#type()) + match (*e).which { + ExternHost::Func(_) => WASM_EXTERN_FUNC, + ExternHost::Global(_) => WASM_EXTERN_GLOBAL, + ExternHost::Table(_) => WASM_EXTERN_TABLE, + ExternHost::Memory(_) => WASM_EXTERN_MEMORY, + } } #[no_mangle] pub unsafe extern "C" fn wasm_extern_type(e: *const wasm_extern_t) -> *mut wasm_externtype_t { let et = Box::new(wasm_externtype_t { - ty: (*e).ext.r#type(), + ty: match &(*e).which { + ExternHost::Func(f) => ExternType::Func(f.borrow().ty().clone()), + ExternHost::Global(f) => ExternType::Global(f.borrow().ty().clone()), + ExternHost::Table(f) => ExternType::Table(f.borrow().ty().clone()), + ExternHost::Memory(f) => ExternType::Memory(f.borrow().ty().clone()), + }, cache: wasm_externtype_t_type_cache::Empty, }); Box::into_raw(et) @@ -1120,17 +1166,22 @@ pub unsafe extern "C" fn wasm_externtype_delete(et: *mut wasm_externtype_t) { #[no_mangle] pub unsafe extern "C" fn wasm_externtype_kind(et: *const wasm_externtype_t) -> wasm_externkind_t { - from_externtype(&(*et).ty) + match &(*et).ty { + ExternType::Func(_) => WASM_EXTERN_FUNC, + ExternType::Table(_) => WASM_EXTERN_TABLE, + ExternType::Global(_) => WASM_EXTERN_GLOBAL, + ExternType::Memory(_) => WASM_EXTERN_MEMORY, + } } #[no_mangle] pub unsafe extern "C" fn wasm_func_param_arity(f: *const wasm_func_t) -> usize { - (*f).func.borrow().param_arity() + (*f).func().borrow().param_arity() } #[no_mangle] pub unsafe extern "C" fn wasm_func_result_arity(f: *const wasm_func_t) -> usize { - (*f).func.borrow().result_arity() + (*f).func().borrow().result_arity() } #[no_mangle] @@ -1279,32 +1330,15 @@ pub unsafe extern "C" fn wasm_valtype_kind(vt: *const wasm_valtype_t) -> wasm_va #[no_mangle] pub unsafe extern "C" fn wasm_extern_as_global(e: *mut wasm_extern_t) -> *mut wasm_global_t { - if let wasm_extern_t_type_cache::Empty = (*e).cache { - (*e).cache = wasm_extern_t_type_cache::Global(wasm_global_t { - global: (*e).ext.global().unwrap().clone(), - ext: None, - }); - } - - match &mut (*e).cache { - wasm_extern_t_type_cache::Global(g) => g, - _ => panic!("wasm_extern_as_global"), + match &(*e).which { + ExternHost::Global(_) => e.cast(), + _ => ptr::null_mut(), } } #[no_mangle] pub unsafe extern "C" fn wasm_global_as_extern(g: *mut wasm_global_t) -> *mut wasm_extern_t { - if (*g).ext.is_none() { - (*g).ext = Some(Box::new(wasm_extern_t { - ext: Extern::Global((*g).global.clone()), - cache: wasm_extern_t_type_cache::Empty, - })); - } - - match &mut (*g).ext { - Some(e) => e.as_mut(), - _ => panic!("wasm_global_as_extern"), - } + &mut (*g).ext } #[no_mangle] @@ -1322,7 +1356,7 @@ pub unsafe extern "C" fn wasm_global_same( g1: *const wasm_global_t, g2: *const wasm_global_t, ) -> bool { - (*g1).global.ptr_eq(&(*g2).global) + (*g1).global().ptr_eq(&(*g2).global()) } #[no_mangle] @@ -1336,18 +1370,22 @@ pub unsafe extern "C" fn wasm_global_new( (*gt).globaltype.clone(), (*val).val(), )); - let g = Box::new(wasm_global_t { global, ext: None }); + let g = Box::new(wasm_global_t { + ext: wasm_extern_t { + which: ExternHost::Global(global), + }, + }); Box::into_raw(g) } #[no_mangle] pub unsafe extern "C" fn wasm_global_get(g: *const wasm_global_t, out: *mut wasm_val_t) { - (*out).set((*g).global.borrow_mut().get()); + (*out).set((*g).global().borrow().get()); } #[no_mangle] pub unsafe extern "C" fn wasm_global_set(g: *mut wasm_global_t, val: *const wasm_val_t) { - (*g).global.borrow_mut().set((*val).val()) + (*g).global().borrow().set((*val).val()) } #[no_mangle] @@ -1377,32 +1415,15 @@ pub unsafe extern "C" fn wasm_globaltype_new( #[no_mangle] pub unsafe extern "C" fn wasm_extern_as_memory(e: *mut wasm_extern_t) -> *mut wasm_memory_t { - if let wasm_extern_t_type_cache::Empty = (*e).cache { - (*e).cache = wasm_extern_t_type_cache::Memory(wasm_memory_t { - memory: (*e).ext.memory().unwrap().clone(), - ext: None, - }); - } - - match &mut (*e).cache { - wasm_extern_t_type_cache::Memory(m) => m, - _ => panic!("wasm_extern_as_memory"), + match &(*e).which { + ExternHost::Memory(_) => e.cast(), + _ => ptr::null_mut(), } } #[no_mangle] pub unsafe extern "C" fn wasm_memory_as_extern(m: *mut wasm_memory_t) -> *mut wasm_extern_t { - if (*m).ext.is_none() { - (*m).ext = Some(Box::new(wasm_extern_t { - ext: Extern::Memory((*m).memory.clone()), - cache: wasm_extern_t_type_cache::Empty, - })); - } - - match &mut (*m).ext { - Some(e) => e.as_mut(), - _ => panic!("wasm_global_as_extern"), - } + &mut (*m).ext } #[no_mangle] @@ -1420,22 +1441,22 @@ pub unsafe extern "C" fn wasm_memory_same( m1: *const wasm_memory_t, m2: *const wasm_memory_t, ) -> bool { - (*m1).memory.ptr_eq(&(*m2).memory) + (*m1).memory().ptr_eq(&(*m2).memory()) } #[no_mangle] pub unsafe extern "C" fn wasm_memory_data(m: *mut wasm_memory_t) -> *mut u8 { - (*m).memory.borrow().data_ptr() + (*m).memory().borrow().data_ptr() } #[no_mangle] pub unsafe extern "C" fn wasm_memory_data_size(m: *const wasm_memory_t) -> usize { - (*m).memory.borrow().data_size() + (*m).memory().borrow().data_size() } #[no_mangle] pub unsafe extern "C" fn wasm_memory_size(m: *const wasm_memory_t) -> wasm_memory_pages_t { - (*m).memory.borrow().size() + (*m).memory().borrow().size() } #[no_mangle] @@ -1443,7 +1464,7 @@ pub unsafe extern "C" fn wasm_memory_grow( m: *mut wasm_memory_t, delta: wasm_memory_pages_t, ) -> bool { - (*m).memory.borrow_mut().grow(delta) + (*m).memory().borrow().grow(delta) } #[no_mangle] @@ -1455,7 +1476,11 @@ pub unsafe extern "C" fn wasm_memory_new( &(*store).store.borrow(), (*mt).memorytype.clone(), )); - let m = Box::new(wasm_memory_t { memory, ext: None }); + let m = Box::new(wasm_memory_t { + ext: wasm_extern_t { + which: ExternHost::Memory(memory), + }, + }); Box::into_raw(m) } @@ -1483,37 +1508,20 @@ pub unsafe extern "C" fn wasm_memorytype_new( #[no_mangle] pub unsafe extern "C" fn wasm_extern_as_table(e: *mut wasm_extern_t) -> *mut wasm_table_t { - if let wasm_extern_t_type_cache::Empty = (*e).cache { - (*e).cache = wasm_extern_t_type_cache::Table(wasm_table_t { - table: (*e).ext.table().unwrap().clone(), - ext: None, - }); - } - - match &mut (*e).cache { - wasm_extern_t_type_cache::Table(t) => t, - _ => panic!("wasm_extern_as_table"), + match &(*e).which { + ExternHost::Table(_) => e.cast(), + _ => ptr::null_mut(), } } #[no_mangle] pub unsafe extern "C" fn wasm_table_as_extern(t: *mut wasm_table_t) -> *mut wasm_extern_t { - if (*t).ext.is_none() { - (*t).ext = Some(Box::new(wasm_extern_t { - ext: Extern::Table((*t).table.clone()), - cache: wasm_extern_t_type_cache::Empty, - })); - } - - match &mut (*t).ext { - Some(e) => e.as_mut(), - _ => panic!("wasm_table_as_extern"), - } + &mut (*t).ext } #[no_mangle] pub unsafe extern "C" fn wasm_func_as_ref(f: *mut wasm_func_t) -> *mut wasm_ref_t { - let r = (*f).func.anyref(); + let r = (*f).func().anyref(); let f = Box::new(wasm_ref_t { r }); Box::into_raw(f) } @@ -1547,12 +1555,13 @@ pub unsafe extern "C" fn wasm_table_new( Val::AnyRef(AnyRef::Null) }; let t = Box::new(wasm_table_t { - table: HostRef::new(Table::new( - &(*store).store.borrow(), - (*tt).tabletype.clone(), - init, - )), - ext: None, + ext: wasm_extern_t { + which: ExternHost::Table(HostRef::new(Table::new( + &(*store).store.borrow(), + (*tt).tabletype.clone(), + init, + ))), + }, }); Box::into_raw(t) } @@ -1582,7 +1591,7 @@ pub unsafe extern "C" fn wasm_table_get( t: *const wasm_table_t, index: wasm_table_size_t, ) -> *mut wasm_ref_t { - let val = (*t).table.borrow().get(index); + let val = (*t).table().borrow().get(index); into_funcref(val) } @@ -1593,12 +1602,12 @@ pub unsafe extern "C" fn wasm_table_set( r: *mut wasm_ref_t, ) -> bool { let val = from_funcref(r); - (*t).table.borrow().set(index, val) + (*t).table().borrow().set(index, val) } #[no_mangle] pub unsafe extern "C" fn wasm_table_size(t: *const wasm_table_t) -> wasm_table_size_t { - (*t).table.borrow().size() + (*t).table().borrow().size() } #[no_mangle] @@ -1608,12 +1617,12 @@ pub unsafe extern "C" fn wasm_table_grow( init: *mut wasm_ref_t, ) -> bool { let init = from_funcref(init); - (*t).table.borrow_mut().grow(delta, init) + (*t).table().borrow().grow(delta, init) } #[no_mangle] pub unsafe extern "C" fn wasm_table_same(t1: *const wasm_table_t, t2: *const wasm_table_t) -> bool { - (*t1).table.ptr_eq(&(*t2).table) + (*t1).table().ptr_eq((*t2).table()) } #[no_mangle] diff --git a/crates/api/tests/import-indexes.rs b/crates/api/tests/import-indexes.rs index 8e35f6cbf6..18847da8e6 100644 --- a/crates/api/tests/import-indexes.rs +++ b/crates/api/tests/import-indexes.rs @@ -42,23 +42,23 @@ fn same_import_names_still_distinct() -> anyhow::Result<()> { let module = Module::new(&store, &wasm)?; let imports = [ - HostRef::new(Func::new( + Func::new( &store, FuncType::new(Box::new([]), Box::new([ValType::I32])), Rc::new(Ret1), - )) + ) .into(), - HostRef::new(Func::new( + Func::new( &store, FuncType::new(Box::new([]), Box::new([ValType::F32])), Rc::new(Ret2), - )) + ) .into(), ]; let instance = Instance::new(&store, &module, &imports)?; let func = instance.find_export_by_name("foo").unwrap().func().unwrap(); - let results = func.borrow().call(&[])?; + let results = func.call(&[])?; assert_eq!(results.len(), 1); match results[0] { Val::I32(n) => assert_eq!(n, 3), diff --git a/crates/api/tests/import_calling_export.rs b/crates/api/tests/import_calling_export.rs index e8d94e6e25..71991ae09b 100644 --- a/crates/api/tests/import_calling_export.rs +++ b/crates/api/tests/import_calling_export.rs @@ -1,4 +1,4 @@ -use std::cell::{Ref, RefCell}; +use std::cell::RefCell; use std::rc::Rc; use wasmtime::*; @@ -16,7 +16,7 @@ fn test_import_calling_export() { "#; struct Callback { - pub other: RefCell>>, + pub other: RefCell>, } impl Callable for Callback { @@ -25,7 +25,6 @@ fn test_import_calling_export() { .borrow() .as_ref() .expect("expected a function ref") - .borrow() .call(&[]) .expect("expected function not to trap"); Ok(()) @@ -40,18 +39,17 @@ fn test_import_calling_export() { other: RefCell::new(None), }); - let callback_func = HostRef::new(Func::new( + let callback_func = Func::new( &store, FuncType::new(Box::new([]), Box::new([])), callback.clone(), - )); - - let imports = vec![callback_func.into()]; - let instance = HostRef::new( - Instance::new(&store, &module, imports.as_slice()).expect("failed to instantiate module"), ); - let exports = Ref::map(instance.borrow(), |instance| instance.exports()); + let imports = vec![callback_func.into()]; + let instance = + Instance::new(&store, &module, imports.as_slice()).expect("failed to instantiate module"); + + let exports = instance.exports(); assert!(!exports.is_empty()); let run_func = exports[0] @@ -65,8 +63,5 @@ fn test_import_calling_export() { .clone(), ); - run_func - .borrow() - .call(&[]) - .expect("expected function not to trap"); + run_func.call(&[]).expect("expected function not to trap"); } diff --git a/crates/api/tests/traps.rs b/crates/api/tests/traps.rs index a5b8cc9caf..9973236578 100644 --- a/crates/api/tests/traps.rs +++ b/crates/api/tests/traps.rs @@ -26,20 +26,16 @@ fn test_trap_return() -> Result<(), String> { let module = Module::new(&store, &binary).map_err(|e| format!("failed to compile module: {}", e))?; let hello_type = FuncType::new(Box::new([]), Box::new([])); - let hello_func = HostRef::new(Func::new(&store, hello_type, Rc::new(HelloCallback))); + let hello_func = Func::new(&store, hello_type, Rc::new(HelloCallback)); let imports = vec![hello_func.into()]; - let instance = Instance::new(&store, &module, imports.as_slice()) + let instance = Instance::new(&store, &module, &imports) .map_err(|e| format!("failed to instantiate module: {:?}", e))?; let run_func = instance.exports()[0] .func() .expect("expected function export"); - let e = run_func - .borrow() - .call(&[]) - .err() - .expect("error calling function"); + let e = run_func.call(&[]).err().expect("error calling function"); assert_eq!(e.message(), "test 123"); diff --git a/crates/fuzzing/src/oracles.rs b/crates/fuzzing/src/oracles.rs index 1afd7467aa..2dab05f457 100644 --- a/crates/fuzzing/src/oracles.rs +++ b/crates/fuzzing/src/oracles.rs @@ -96,7 +96,7 @@ pub fn make_api_calls(api: crate::generators::api::ApiCalls) { let mut engine: Option = None; let mut store: Option = None; let mut modules: HashMap = Default::default(); - let mut instances: HashMap> = Default::default(); + let mut instances: HashMap = Default::default(); for call in api.calls { match call { @@ -153,7 +153,7 @@ pub fn make_api_calls(api: crate::generators::api::ApiCalls) { // table might not have room for an element segment that we want to // initialize into it. if let Ok(instance) = Instance::new(store.as_ref().unwrap(), &module, &imports) { - instances.insert(id, HostRef::new(instance)); + instances.insert(id, instance); } } @@ -175,25 +175,22 @@ pub fn make_api_calls(api: crate::generators::api::ApiCalls) { } }; - let funcs = { - let instance = instance.borrow(); - instance - .exports() - .iter() - .filter_map(|e| match e { - Extern::Func(f) => Some(f.clone()), - _ => None, - }) - .collect::>() - }; + let funcs = instance + .exports() + .iter() + .filter_map(|e| match e { + Extern::Func(f) => Some(f.clone()), + _ => None, + }) + .collect::>(); if funcs.is_empty() { continue; } let nth = nth % funcs.len(); - let f = funcs[nth].borrow(); - let ty = f.r#type(); + let f = &funcs[nth]; + let ty = f.ty(); let params = match ty .params() .iter() diff --git a/crates/fuzzing/src/oracles/dummy.rs b/crates/fuzzing/src/oracles/dummy.rs index f72cd4858f..0a0b06b69b 100644 --- a/crates/fuzzing/src/oracles/dummy.rs +++ b/crates/fuzzing/src/oracles/dummy.rs @@ -2,7 +2,7 @@ use std::rc::Rc; use wasmtime::{ - Callable, Extern, ExternType, Func, FuncType, Global, GlobalType, HostRef, ImportType, Memory, + Callable, Extern, ExternType, Func, FuncType, Global, GlobalType, ImportType, Memory, MemoryType, Store, Table, TableType, Trap, Val, ValType, }; @@ -11,18 +11,12 @@ pub fn dummy_imports(store: &Store, import_tys: &[ImportType]) -> Result { - Extern::Func(HostRef::new(DummyFunc::new(&store, func_ty.clone()))) - } + ExternType::Func(func_ty) => Extern::Func(DummyFunc::new(&store, func_ty.clone())), ExternType::Global(global_ty) => { - Extern::Global(HostRef::new(dummy_global(&store, global_ty.clone())?)) - } - ExternType::Table(table_ty) => { - Extern::Table(HostRef::new(dummy_table(&store, table_ty.clone())?)) - } - ExternType::Memory(mem_ty) => { - Extern::Memory(HostRef::new(dummy_memory(&store, mem_ty.clone()))) + Extern::Global(dummy_global(&store, global_ty.clone())?) } + ExternType::Table(table_ty) => Extern::Table(dummy_table(&store, table_ty.clone())?), + ExternType::Memory(mem_ty) => Extern::Memory(dummy_memory(&store, mem_ty.clone())), }); } Ok(imports) diff --git a/crates/interface-types/src/lib.rs b/crates/interface-types/src/lib.rs index 62122b62ac..4934e7370c 100644 --- a/crates/interface-types/src/lib.rs +++ b/crates/interface-types/src/lib.rs @@ -125,18 +125,17 @@ impl ModuleData { /// wasm interface types. pub fn invoke_export( &self, - instance: &wasmtime::HostRef, + instance: &wasmtime::Instance, export: &str, args: &[Value], ) -> Result> { - let mut handle = instance.borrow().handle().clone(); + let mut handle = instance.handle().clone(); let binding = self.binding_for_export(&mut handle, export)?; let incoming = binding.param_bindings()?; let outgoing = binding.result_bindings()?; let f = instance - .borrow() .find_export_by_name(export) .ok_or_else(|| format_err!("failed to find export `{}`", export))? .func() @@ -148,7 +147,7 @@ impl ModuleData { .into_iter() .map(|rv| rv.into()) .collect::>(); - let wasm_results = match f.borrow().call(&wasm_args) { + let wasm_results = match f.call(&wasm_args) { Ok(values) => values .to_vec() .into_iter() @@ -322,20 +321,19 @@ trait TranslateContext { unsafe fn get_memory(&mut self) -> Result<&mut [u8]>; } -struct InstanceTranslateContext(pub wasmtime::HostRef); +struct InstanceTranslateContext(pub wasmtime::Instance); impl TranslateContext for InstanceTranslateContext { fn invoke_alloc(&mut self, alloc_func_name: &str, len: i32) -> Result { let alloc = self .0 - .borrow() .find_export_by_name(alloc_func_name) .ok_or_else(|| format_err!("failed to find alloc function `{}`", alloc_func_name))? .func() .ok_or_else(|| format_err!("`{}` is not a (alloc) function", alloc_func_name))? .clone(); let alloc_args = vec![wasmtime::Val::I32(len)]; - let results = match alloc.borrow().call(&alloc_args) { + let results = match alloc.call(&alloc_args) { Ok(values) => values, Err(trap) => bail!("trapped: {:?}", trap), }; @@ -350,14 +348,13 @@ impl TranslateContext for InstanceTranslateContext { unsafe fn get_memory(&mut self) -> Result<&mut [u8]> { let memory = self .0 - .borrow() .find_export_by_name("memory") .ok_or_else(|| format_err!("failed to find `memory` export"))? .memory() .ok_or_else(|| format_err!("`memory` is not a memory"))? .clone(); - let ptr = memory.borrow().data_ptr(); - let len = memory.borrow().data_size(); + let ptr = memory.data_ptr(); + let len = memory.data_size(); Ok(std::slice::from_raw_parts_mut(ptr, len)) } } diff --git a/crates/misc/py/src/function.rs b/crates/misc/py/src/function.rs index 3b88dcccf0..8227394c7a 100644 --- a/crates/misc/py/src/function.rs +++ b/crates/misc/py/src/function.rs @@ -10,17 +10,16 @@ use wasmtime_interface_types::ModuleData; // TODO support non-export functions #[pyclass] pub struct Function { - pub instance: wasmtime::HostRef, + pub instance: wasmtime::Instance, pub export_name: String, pub args_types: Vec, pub data: Rc, } impl Function { - pub fn func(&self) -> wasmtime::HostRef { + pub fn func(&self) -> wasmtime::Func { let e = self .instance - .borrow() .find_export_by_name(&self.export_name) .expect("named export") .clone(); @@ -125,10 +124,7 @@ impl wasmtime::Callable for WrappedFn { } } -pub fn wrap_into_pyfunction( - store: &wasmtime::Store, - callable: &PyAny, -) -> PyResult> { +pub fn wrap_into_pyfunction(store: &wasmtime::Store, callable: &PyAny) -> PyResult { if !callable.hasattr("__annotations__")? { // TODO support calls without annotations? return Err(PyErr::new::( @@ -154,6 +150,5 @@ pub fn wrap_into_pyfunction( let gil = Python::acquire_gil(); let wrapped = WrappedFn::new(callable.to_object(gil.python()), returns); - let f = wasmtime::Func::new(store, ft, Rc::new(wrapped)); - Ok(wasmtime::HostRef::new(f)) + Ok(wasmtime::Func::new(store, ft, Rc::new(wrapped))) } diff --git a/crates/misc/py/src/instance.rs b/crates/misc/py/src/instance.rs index f5c0480885..717d24aa2a 100644 --- a/crates/misc/py/src/instance.rs +++ b/crates/misc/py/src/instance.rs @@ -9,7 +9,7 @@ use wasmtime_interface_types::ModuleData; #[pyclass] pub struct Instance { - pub instance: wasmtime::HostRef, + pub instance: wasmtime::Instance, pub data: Rc, } @@ -20,7 +20,7 @@ impl Instance { let gil = Python::acquire_gil(); let py = gil.python(); let exports = PyDict::new(py); - let module = self.instance.borrow().module().clone(); + let module = self.instance.module().clone(); for (i, e) in module.exports().iter().enumerate() { match e.ty() { wasmtime::ExternType::Func(ft) => { @@ -43,10 +43,7 @@ impl Instance { let f = Py::new( py, Memory { - memory: self.instance.borrow().exports()[i] - .memory() - .unwrap() - .clone(), + memory: self.instance.exports()[i].memory().unwrap().clone(), }, )?; exports.set_item(e.name().to_string(), f)?; diff --git a/crates/misc/py/src/lib.rs b/crates/misc/py/src/lib.rs index 7247b1e867..2bb164ddd2 100644 --- a/crates/misc/py/src/lib.rs +++ b/crates/misc/py/src/lib.rs @@ -122,10 +122,8 @@ pub fn instantiate( } } - let instance = wasmtime::HostRef::new( - wasmtime::Instance::new(&store, &module, &imports) - .map_err(|t| PyErr::new::(format!("instantiated with trap {:?}", t)))?, - ); + let instance = wasmtime::Instance::new(&store, &module, &imports) + .map_err(|t| PyErr::new::(format!("instantiated with trap {:?}", t)))?; let module = Py::new(py, Module { module })?; diff --git a/crates/misc/py/src/memory.rs b/crates/misc/py/src/memory.rs index c6e8430ebe..1a43c82d84 100644 --- a/crates/misc/py/src/memory.rs +++ b/crates/misc/py/src/memory.rs @@ -10,14 +10,14 @@ use std::ptr; #[pyclass] pub struct Memory { - pub memory: wasmtime::HostRef, + pub memory: wasmtime::Memory, } #[pymethods] impl Memory { #[getter(current)] pub fn current(&self) -> u32 { - self.memory.borrow().size() + self.memory.size() } pub fn grow(&self, _number: u32) -> u32 { @@ -48,8 +48,8 @@ impl PyBufferProtocol for Memory { }; unsafe { - let base = self.memory.borrow().data_ptr(); - let current_length = self.memory.borrow().data_size(); + let base = self.memory.data_ptr(); + let current_length = self.memory.data_size(); (*view).buf = base as *mut c_void; (*view).len = current_length as isize; diff --git a/crates/misc/rust/macro/src/lib.rs b/crates/misc/rust/macro/src/lib.rs index b70cccfa61..2d91664dd5 100644 --- a/crates/misc/rust/macro/src/lib.rs +++ b/crates/misc/rust/macro/src/lib.rs @@ -34,7 +34,7 @@ fn generate_struct(item: &syn::ItemTrait) -> syn::Result { let root = root(); Ok(quote! { #vis struct #name { - instance: #root::wasmtime::HostRef<#root::wasmtime::Instance>, + instance: #root::wasmtime::Instance, data: #root::wasmtime_interface_types::ModuleData, } }) @@ -48,7 +48,7 @@ fn generate_load(item: &syn::ItemTrait) -> syn::Result { #vis fn load_file(path: impl AsRef) -> #root::anyhow::Result<#name> { let bytes = std::fs::read(path)?; - use #root::wasmtime::{HostRef, Config, Extern, Engine, Store, Instance, Module}; + use #root::wasmtime::{Config, Extern, Engine, Store, Instance, Module}; use #root::anyhow::{bail, format_err}; let engine = Engine::new(Config::new().wasm_multi_value(true)); @@ -74,9 +74,8 @@ fn generate_load(item: &syn::ItemTrait) -> syn::Result { } } } - let instance = HostRef::new( - Instance::new(&store, &module, &imports).map_err(|t| format_err!("instantiation trap: {:?}", t))? - ); + let instance = + Instance::new(&store, &module, &imports).map_err(|t| format_err!("instantiation trap: {:?}", t))?; Ok(#name { instance, data }) } diff --git a/crates/test-programs/tests/wasm_tests/runtime.rs b/crates/test-programs/tests/wasm_tests/runtime.rs index 0970d31f26..c24ce862c3 100644 --- a/crates/test-programs/tests/wasm_tests/runtime.rs +++ b/crates/test-programs/tests/wasm_tests/runtime.rs @@ -1,7 +1,7 @@ use anyhow::{bail, Context}; use std::fs::File; use std::path::Path; -use wasmtime::{HostRef, Instance, Module, Store}; +use wasmtime::{Instance, Module, Store}; pub fn instantiate(data: &[u8], bin_name: &str, workspace: Option<&Path>) -> anyhow::Result<()> { let store = Store::default(); @@ -61,13 +61,12 @@ pub fn instantiate(data: &[u8], bin_name: &str, workspace: Option<&Path>) -> any }) .collect::, _>>()?; - let instance = HostRef::new(Instance::new(&store, &module, &imports).context(format!( + let instance = Instance::new(&store, &module, &imports).context(format!( "error while instantiating Wasm module '{}'", bin_name, - ))?); + ))?; let export = instance - .borrow() .find_export_by_name("_start") .context("expected a _start export")? .clone(); @@ -75,7 +74,6 @@ pub fn instantiate(data: &[u8], bin_name: &str, workspace: Option<&Path>) -> any if let Err(trap) = export .func() .context("expected export to be a func")? - .borrow() .call(&[]) { bail!("trapped: {:?}", trap); diff --git a/crates/wast/src/spectest.rs b/crates/wast/src/spectest.rs index 8d906f56c6..fb2cb96de6 100644 --- a/crates/wast/src/spectest.rs +++ b/crates/wast/src/spectest.rs @@ -31,35 +31,35 @@ pub fn instantiate_spectest(store: &Store) -> HashMap<&'static str, Extern> { let ty = FuncType::new(Box::new([]), Box::new([])); let func = wrap(store, ty, |_params, _results| Ok(())); - ret.insert("print", Extern::Func(HostRef::new(func))); + ret.insert("print", Extern::Func(func)); let ty = FuncType::new(Box::new([ValType::I32]), Box::new([])); let func = wrap(store, ty, |params, _results| { println!("{}: i32", params[0].unwrap_i32()); Ok(()) }); - ret.insert("print_i32", Extern::Func(HostRef::new(func))); + ret.insert("print_i32", Extern::Func(func)); let ty = FuncType::new(Box::new([ValType::I64]), Box::new([])); let func = wrap(store, ty, |params, _results| { println!("{}: i64", params[0].unwrap_i64()); Ok(()) }); - ret.insert("print_i64", Extern::Func(HostRef::new(func))); + ret.insert("print_i64", Extern::Func(func)); let ty = FuncType::new(Box::new([ValType::F32]), Box::new([])); let func = wrap(store, ty, |params, _results| { println!("{}: f32", params[0].unwrap_f32()); Ok(()) }); - ret.insert("print_f32", Extern::Func(HostRef::new(func))); + ret.insert("print_f32", Extern::Func(func)); let ty = FuncType::new(Box::new([ValType::F64]), Box::new([])); let func = wrap(store, ty, |params, _results| { println!("{}: f64", params[0].unwrap_f64()); Ok(()) }); - ret.insert("print_f64", Extern::Func(HostRef::new(func))); + ret.insert("print_f64", Extern::Func(func)); let ty = FuncType::new(Box::new([ValType::I32, ValType::F32]), Box::new([])); let func = wrap(store, ty, |params, _results| { @@ -67,7 +67,7 @@ pub fn instantiate_spectest(store: &Store) -> HashMap<&'static str, Extern> { println!("{}: f32", params[1].unwrap_f32()); Ok(()) }); - ret.insert("print_i32_f32", Extern::Func(HostRef::new(func))); + ret.insert("print_i32_f32", Extern::Func(func)); let ty = FuncType::new(Box::new([ValType::F64, ValType::F64]), Box::new([])); let func = wrap(store, ty, |params, _results| { @@ -75,31 +75,31 @@ pub fn instantiate_spectest(store: &Store) -> HashMap<&'static str, Extern> { println!("{}: f64", params[1].unwrap_f64()); Ok(()) }); - ret.insert("print_f64_f64", Extern::Func(HostRef::new(func))); + ret.insert("print_f64_f64", Extern::Func(func)); let ty = GlobalType::new(ValType::I32, Mutability::Const); let g = Global::new(store, ty, Val::I32(666)); - ret.insert("global_i32", Extern::Global(HostRef::new(g))); + ret.insert("global_i32", Extern::Global(g)); let ty = GlobalType::new(ValType::I64, Mutability::Const); let g = Global::new(store, ty, Val::I64(666)); - ret.insert("global_i64", Extern::Global(HostRef::new(g))); + ret.insert("global_i64", Extern::Global(g)); let ty = GlobalType::new(ValType::F32, Mutability::Const); let g = Global::new(store, ty, Val::F32(0x4426_8000)); - ret.insert("global_f32", Extern::Global(HostRef::new(g))); + ret.insert("global_f32", Extern::Global(g)); let ty = GlobalType::new(ValType::F64, Mutability::Const); let g = Global::new(store, ty, Val::F64(0x4084_d000_0000_0000)); - ret.insert("global_f64", Extern::Global(HostRef::new(g))); + ret.insert("global_f64", Extern::Global(g)); let ty = TableType::new(ValType::FuncRef, Limits::new(10, Some(20))); let table = Table::new(store, ty, Val::AnyRef(AnyRef::Null)); - ret.insert("table", Extern::Table(HostRef::new(table))); + ret.insert("table", Extern::Table(table)); let ty = MemoryType::new(Limits::new(1, Some(2))); let memory = Memory::new(store, ty); - ret.insert("memory", Extern::Memory(HostRef::new(memory))); + ret.insert("memory", Extern::Memory(memory)); return ret; } diff --git a/crates/wast/src/wast.rs b/crates/wast/src/wast.rs index 4f8f2ba0c6..3299b4f67f 100644 --- a/crates/wast/src/wast.rs +++ b/crates/wast/src/wast.rs @@ -27,9 +27,9 @@ fn runtime_value(v: &wast::Expression<'_>) -> Result { pub struct WastContext { /// Wast files have a concept of a "current" module, which is the most /// recently defined. - current: Option>, + current: Option, - instances: HashMap>, + instances: HashMap, store: Store, spectest: Option>, } @@ -50,7 +50,7 @@ impl WastContext { } } - fn get_instance(&self, instance_name: Option<&str>) -> Result> { + fn get_instance(&self, instance_name: Option<&str>) -> Result { match instance_name { Some(name) => self .instances @@ -64,7 +64,7 @@ impl WastContext { } } - fn instantiate(&self, module: &[u8]) -> Result>> { + fn instantiate(&self, module: &[u8]) -> Result> { let module = Module::new(&self.store, module)?; let mut imports = Vec::new(); for import in module.imports() { @@ -85,7 +85,6 @@ impl WastContext { .get(import.module()) .ok_or_else(|| anyhow!("no module named `{}`", import.module()))?; let export = instance - .borrow() .find_export_by_name(import.name()) .ok_or_else(|| anyhow!("unknown import `{}::{}`", import.name(), import.module()))? .clone(); @@ -101,7 +100,7 @@ impl WastContext { return Err(e); } }; - Ok(Outcome::Ok(HostRef::new(instance))) + Ok(Outcome::Ok(instance)) } /// Register "spectest" which is used by the spec testsuite. @@ -159,12 +158,11 @@ impl WastContext { ) -> Result { let values = args.iter().map(runtime_value).collect::>>()?; let instance = self.get_instance(instance_name.as_ref().map(|x| &**x))?; - let instance = instance.borrow(); let export = instance .find_export_by_name(field) .ok_or_else(|| anyhow!("no global named `{}`", field))?; let func = match export { - Extern::Func(f) => f.borrow(), + Extern::Func(f) => f, _ => bail!("export of `{}` wasn't a global", field), }; Ok(match func.call(&values) { @@ -176,12 +174,11 @@ impl WastContext { /// Get the value of an exported global from an instance. fn get(&mut self, instance_name: Option<&str>, field: &str) -> Result { let instance = self.get_instance(instance_name.as_ref().map(|x| &**x))?; - let instance = instance.borrow(); let export = instance .find_export_by_name(field) .ok_or_else(|| anyhow!("no global named `{}`", field))?; let global = match export { - Extern::Global(g) => g.borrow(), + Extern::Global(g) => g, _ => bail!("export of `{}` wasn't a global", field), }; Ok(Outcome::Ok(vec![global.get()])) diff --git a/src/commands/run.rs b/src/commands/run.rs index 3a71dc1900..3dd9a48033 100644 --- a/src/commands/run.rs +++ b/src/commands/run.rs @@ -11,7 +11,7 @@ use std::{ }; use structopt::{clap::AppSettings, StructOpt}; use wasi_common::preopen_dir; -use wasmtime::{Config, Engine, HostRef, Instance, Module, Store}; +use wasmtime::{Config, Engine, Instance, Module, Store}; use wasmtime_environ::cache_init; use wasmtime_interface_types::ModuleData; use wasmtime_wasi::{ @@ -148,7 +148,7 @@ impl RunCommand { let preopen_dirs = self.compute_preopen_dirs()?; let argv = self.compute_argv(); - let wasi_unstable = HostRef::new(if self.enable_wasi_c { + let wasi_unstable = if self.enable_wasi_c { #[cfg(feature = "wasi-c")] { let global_exports = store.global_exports().clone(); @@ -161,14 +161,10 @@ impl RunCommand { } } else { create_wasi_instance_snapshot_0(&store, &preopen_dirs, &argv, &self.vars)? - }); + }; - let wasi_snapshot_preview1 = HostRef::new(create_wasi_instance( - &store, - &preopen_dirs, - &argv, - &self.vars, - )?); + let wasi_snapshot_preview1 = + create_wasi_instance(&store, &preopen_dirs, &argv, &self.vars)?; module_registry.insert("wasi_unstable".to_owned(), wasi_unstable); module_registry.insert("wasi_snapshot_preview1".to_owned(), wasi_snapshot_preview1); @@ -232,9 +228,9 @@ impl RunCommand { fn instantiate_module( store: &Store, - module_registry: &HashMap>, + module_registry: &HashMap, path: &Path, - ) -> Result<(HostRef, Module, Vec)> { + ) -> Result<(Instance, Module, Vec)> { // Read the wasm module binary either as `*.wat` or a raw binary let data = wat::parse_file(path)?; @@ -248,7 +244,7 @@ impl RunCommand { let module_name = i.module(); if let Some(instance) = module_registry.get(module_name) { let field_name = i.name(); - if let Some(export) = instance.borrow().find_export_by_name(field_name) { + if let Some(export) = instance.find_export_by_name(field_name) { Ok(export.clone()) } else { bail!( @@ -263,10 +259,8 @@ impl RunCommand { }) .collect::, _>>()?; - let instance = HostRef::new( - Instance::new(store, &module, &imports) - .context(format!("failed to instantiate {:?}", path))?, - ); + let instance = Instance::new(store, &module, &imports) + .context(format!("failed to instantiate {:?}", path))?; Ok((instance, module, data)) } @@ -274,7 +268,7 @@ impl RunCommand { fn handle_module( &self, store: &Store, - module_registry: &HashMap>, + module_registry: &HashMap, ) -> Result<()> { let (instance, module, data) = Self::instantiate_module(store, module_registry, &self.module)?; @@ -301,16 +295,11 @@ impl RunCommand { Ok(()) } - fn invoke_export( - &self, - instance: HostRef, - data: &ModuleData, - name: &str, - ) -> Result<()> { + fn invoke_export(&self, instance: Instance, data: &ModuleData, name: &str) -> Result<()> { use wasm_webidl_bindings::ast; use wasmtime_interface_types::Value; - let mut handle = instance.borrow().handle().clone(); + let mut handle = instance.handle().clone(); // Use the binding information in `ModuleData` to figure out what arguments // need to be passed to the function that we're invoking. Currently we take diff --git a/tests/custom_signal_handler.rs b/tests/custom_signal_handler.rs index 613bb2db04..66a449fb22 100644 --- a/tests/custom_signal_handler.rs +++ b/tests/custom_signal_handler.rs @@ -1,6 +1,5 @@ #[cfg(not(target_os = "windows"))] mod tests { - use core::cell::Ref; use std::rc::Rc; use std::sync::atomic::{AtomicBool, Ordering}; use wasmtime::*; @@ -38,7 +37,7 @@ mod tests { "#; fn invoke_export( - instance: &HostRef, + instance: &Instance, data: &[u8], func_name: &str, ) -> Result, anyhow::Error> { @@ -46,8 +45,8 @@ mod tests { } // Locate "memory" export, get base address and size and set memory protection to PROT_NONE - fn set_up_memory(instance: &HostRef) -> (*mut u8, usize) { - let mem_export = instance.borrow().get_wasmtime_memory().expect("memory"); + fn set_up_memory(instance: &Instance) -> (*mut u8, usize) { + let mem_export = instance.get_wasmtime_memory().expect("memory"); let (base, length) = if let wasmtime_runtime::Export::Memory { definition, @@ -107,16 +106,14 @@ mod tests { let store = Store::new(&engine); let data = wat::parse_str(WAT1)?; let module = Module::new(&store, &data)?; - let instance = HostRef::new(Instance::new(&store, &module, &[])?); + let instance = Instance::new(&store, &module, &[])?; let (base, length) = set_up_memory(&instance); - instance - .borrow_mut() - .set_signal_handler(move |signum, siginfo, _| { - handle_sigsegv(base, length, signum, siginfo) - }); + instance.set_signal_handler(move |signum, siginfo, _| { + handle_sigsegv(base, length, signum, siginfo) + }); - let exports = Ref::map(instance.borrow(), |instance| instance.exports()); + let exports = instance.exports(); assert!(!exports.is_empty()); // these invoke wasmtime_call_trampoline from action.rs @@ -140,10 +137,7 @@ mod tests { .func() .expect("expected a 'read' func in the module"); println!("calling read..."); - let result = read_func - .borrow() - .call(&[]) - .expect("expected function not to trap"); + let result = read_func.call(&[]).expect("expected function not to trap"); assert_eq!(123i32, result[0].clone().unwrap_i32()); } @@ -152,7 +146,7 @@ mod tests { .func() .expect("expected a 'read_out_of_bounds' func in the module"); println!("calling read_out_of_bounds..."); - let trap = read_out_of_bounds_func.borrow().call(&[]).unwrap_err(); + let trap = read_out_of_bounds_func.call(&[]).unwrap_err(); assert!(trap .message() .starts_with("call error: wasm trap: out of bounds memory access")); @@ -169,13 +163,13 @@ mod tests { // Set up multiple instances - let instance1 = HostRef::new(Instance::new(&store, &module, &[])?); + let instance1 = Instance::new(&store, &module, &[])?; let instance1_handler_triggered = Rc::new(AtomicBool::new(false)); { let (base1, length1) = set_up_memory(&instance1); - instance1.borrow_mut().set_signal_handler({ + instance1.set_signal_handler({ let instance1_handler_triggered = instance1_handler_triggered.clone(); move |_signum, _siginfo, _context| { // Remove protections so the execution may resume @@ -196,15 +190,13 @@ mod tests { }); } - let instance2 = HostRef::new( - Instance::new(&store, &module, &[]).expect("failed to instantiate module"), - ); + let instance2 = Instance::new(&store, &module, &[]).expect("failed to instantiate module"); let instance2_handler_triggered = Rc::new(AtomicBool::new(false)); { let (base2, length2) = set_up_memory(&instance2); - instance2.borrow_mut().set_signal_handler({ + instance2.set_signal_handler({ let instance2_handler_triggered = instance2_handler_triggered.clone(); move |_signum, _siginfo, _context| { // Remove protections so the execution may resume @@ -229,7 +221,7 @@ mod tests { // First instance1 { - let exports1 = Ref::map(instance1.borrow(), |i| i.exports()); + let exports1 = instance1.exports(); assert!(!exports1.is_empty()); println!("calling instance1.read..."); @@ -244,7 +236,7 @@ mod tests { // And then instance2 { - let exports2 = Ref::map(instance2.borrow(), |i| i.exports()); + let exports2 = instance2.exports(); assert!(!exports2.is_empty()); println!("calling instance2.read..."); @@ -267,30 +259,26 @@ mod tests { // instance1 which defines 'read' let data1 = wat::parse_str(WAT1)?; let module1 = Module::new(&store, &data1)?; - let instance1: HostRef = HostRef::new(Instance::new(&store, &module1, &[])?); + let instance1 = Instance::new(&store, &module1, &[])?; let (base1, length1) = set_up_memory(&instance1); - instance1 - .borrow_mut() - .set_signal_handler(move |signum, siginfo, _| { - println!("instance1"); - handle_sigsegv(base1, length1, signum, siginfo) - }); + instance1.set_signal_handler(move |signum, siginfo, _| { + println!("instance1"); + handle_sigsegv(base1, length1, signum, siginfo) + }); - let instance1_exports = Ref::map(instance1.borrow(), |i| i.exports()); + let instance1_exports = instance1.exports(); assert!(!instance1_exports.is_empty()); let instance1_read = instance1_exports[0].clone(); // instance2 wich calls 'instance1.read' let data2 = wat::parse_str(WAT2)?; let module2 = Module::new(&store, &data2)?; - let instance2 = HostRef::new(Instance::new(&store, &module2, &[instance1_read])?); + let instance2 = Instance::new(&store, &module2, &[instance1_read])?; // since 'instance2.run' calls 'instance1.read' we need to set up the signal handler to handle // SIGSEGV originating from within the memory of instance1 - instance2 - .borrow_mut() - .set_signal_handler(move |signum, siginfo, _| { - handle_sigsegv(base1, length1, signum, siginfo) - }); + instance2.set_signal_handler(move |signum, siginfo, _| { + handle_sigsegv(base1, length1, signum, siginfo) + }); println!("calling instance2.run"); let result = invoke_export(&instance2, &data2, "run")?; From 6b3ee479159c74c64defa97371c67e0828ae9a95 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 10 Jan 2020 13:17:41 -0600 Subject: [PATCH 18/28] Only require `str` in `new_with_name` (#796) * Only require `str` in `new_with_name` It's a bit more idiomatic to have APIs require `&str` rather than `String`, and the allocation doesn't matter much here since creating a `Module` is pretty expensive anyway. * Update a test --- crates/api/src/instance.rs | 4 ++-- crates/api/src/module.rs | 8 ++++---- crates/api/tests/name.rs | 14 ++++---------- crates/jit/src/instantiate.rs | 8 ++++---- 4 files changed, 14 insertions(+), 20 deletions(-) diff --git a/crates/api/src/instance.rs b/crates/api/src/instance.rs index b78048b892..49a51ba588 100644 --- a/crates/api/src/instance.rs +++ b/crates/api/src/instance.rs @@ -27,7 +27,7 @@ impl Resolver for SimpleResolver<'_> { pub fn instantiate_in_context( data: &[u8], imports: &[Extern], - module_name: Option, + module_name: Option<&str>, context: Context, exports: Rc>>>, ) -> Result<(InstanceHandle, HashSet), Error> { @@ -74,7 +74,7 @@ impl Instance { let (mut instance_handle, contexts) = instantiate_in_context( module.binary().expect("binary"), externs, - module.name().cloned(), + module.name(), context, exports, )?; diff --git a/crates/api/src/module.rs b/crates/api/src/module.rs index f7bed9928e..8ffb3d58db 100644 --- a/crates/api/src/module.rs +++ b/crates/api/src/module.rs @@ -270,9 +270,9 @@ impl Module { /// data. The provided `name` will be used in traps/backtrace details. /// /// See [`Module::new`] for other details. - pub fn new_with_name(store: &Store, binary: &[u8], name: String) -> Result { + pub fn new_with_name(store: &Store, binary: &[u8], name: &str) -> Result { Self::validate(store, binary)?; - unsafe { Self::create(store, binary, Some(name)) } + unsafe { Self::create(store, binary, Some(name.to_string())) } } /// Creates a new WebAssembly `Module` from the given in-memory `binary` @@ -376,8 +376,8 @@ impl Module { /// Returns identifier/name that this [`Module`] has. This name /// is used in traps/backtrace details. - pub fn name(&self) -> Option<&String> { - self.inner.name.as_ref() + pub fn name(&self) -> Option<&str> { + self.inner.name.as_deref() } /// Returns the list of imports that this [`Module`] has and must be diff --git a/crates/api/tests/name.rs b/crates/api/tests/name.rs index 0d83708639..69276af4ee 100644 --- a/crates/api/tests/name.rs +++ b/crates/api/tests/name.rs @@ -16,7 +16,7 @@ fn test_module_no_name() -> Result<(), String> { let module = HostRef::new( Module::new(&store, &binary).map_err(|e| format!("failed to compile module: {}", e))?, ); - assert_eq!(module.borrow().name().cloned(), None); + assert_eq!(module.borrow().name(), None); Ok(()) } @@ -36,19 +36,13 @@ fn test_module_name() -> Result<(), String> { let module = HostRef::new( Module::new(&store, &binary).map_err(|e| format!("failed to compile module: {}", e))?, ); - assert_eq!( - module.borrow().name().cloned(), - Some("from_name_section".to_string()) - ); + assert_eq!(module.borrow().name(), Some("from_name_section")); let module = HostRef::new( - Module::new_with_name(&store, &binary, "override".to_string()) + Module::new_with_name(&store, &binary, "override") .map_err(|e| format!("failed to compile module: {}", e))?, ); - assert_eq!( - module.borrow().name().cloned(), - Some("override".to_string()) - ); + assert_eq!(module.borrow().name(), Some("override")); Ok(()) } diff --git a/crates/jit/src/instantiate.rs b/crates/jit/src/instantiate.rs index 1a22399125..68e6fac6df 100644 --- a/crates/jit/src/instantiate.rs +++ b/crates/jit/src/instantiate.rs @@ -60,7 +60,7 @@ impl<'data> RawCompiledModule<'data> { fn new( compiler: &mut Compiler, data: &'data [u8], - module_name: Option, + module_name: Option<&str>, resolver: &mut dyn Resolver, debug_info: bool, ) -> Result { @@ -76,7 +76,7 @@ impl<'data> RawCompiledModule<'data> { None }; - translation.module.name = module_name; + translation.module.name = module_name.map(|s| s.to_string()); let (allocated_functions, jt_offsets, relocations, dbg_image) = compiler.compile( &translation.module, @@ -155,7 +155,7 @@ impl CompiledModule { pub fn new<'data>( compiler: &mut Compiler, data: &'data [u8], - module_name: Option, + module_name: Option<&str>, resolver: &mut dyn Resolver, global_exports: Rc>>>, debug_info: bool, @@ -263,7 +263,7 @@ impl OwnedDataInitializer { pub fn instantiate( compiler: &mut Compiler, data: &[u8], - module_name: Option, + module_name: Option<&str>, resolver: &mut dyn Resolver, global_exports: Rc>>>, debug_info: bool, From aa41d4b12bfb18ec34fecfde0f37a426674c63e3 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 10 Jan 2020 13:18:54 -0600 Subject: [PATCH 19/28] Refactor module creation slightly (#799) A few small updates to module creation in preparation for a future PR which is a bit more invasive here with interface types. * Move `read_imports_and_exports` to an instance method which configures fields directly rather than returning a number of fields. * Call between constructors as much as possible. * Leverage `Rc::get_mut` which we know will work at module creation time since we have the only reference. --- crates/api/src/module.rs | 300 +++++++++++++++++++-------------------- 1 file changed, 145 insertions(+), 155 deletions(-) diff --git a/crates/api/src/module.rs b/crates/api/src/module.rs index 8ffb3d58db..3704f11e14 100644 --- a/crates/api/src/module.rs +++ b/crates/api/src/module.rs @@ -56,138 +56,6 @@ fn into_table_type(tt: wasmparser::TableType) -> TableType { TableType::new(ty, limits) } -fn read_imports_and_exports( - binary: &[u8], -) -> Result<(Box<[ImportType]>, Box<[ExportType]>, Option)> { - let mut reader = ModuleReader::new(binary)?; - let mut imports = Vec::new(); - let mut exports = Vec::new(); - let mut memories = Vec::new(); - let mut tables = Vec::new(); - let mut func_sig = Vec::new(); - let mut sigs = Vec::new(); - let mut globals = Vec::new(); - let mut module_name = None; - while !reader.eof() { - let section = reader.read()?; - match section.code { - SectionCode::Memory => { - let section = section.get_memory_section_reader()?; - memories.reserve_exact(section.get_count() as usize); - for entry in section { - memories.push(into_memory_type(entry?)); - } - } - SectionCode::Type => { - let section = section.get_type_section_reader()?; - sigs.reserve_exact(section.get_count() as usize); - for entry in section { - sigs.push(into_func_type(entry?)); - } - } - SectionCode::Function => { - let section = section.get_function_section_reader()?; - func_sig.reserve_exact(section.get_count() as usize); - for entry in section { - func_sig.push(entry?); - } - } - SectionCode::Global => { - let section = section.get_global_section_reader()?; - globals.reserve_exact(section.get_count() as usize); - for entry in section { - globals.push(into_global_type(entry?.ty)); - } - } - SectionCode::Table => { - let section = section.get_table_section_reader()?; - tables.reserve_exact(section.get_count() as usize); - for entry in section { - tables.push(into_table_type(entry?)) - } - } - SectionCode::Import => { - let section = section.get_import_section_reader()?; - imports.reserve_exact(section.get_count() as usize); - for entry in section { - let entry = entry?; - let r#type = match entry.ty { - ImportSectionEntryType::Function(index) => { - func_sig.push(index); - let sig = &sigs[index as usize]; - ExternType::Func(sig.clone()) - } - ImportSectionEntryType::Table(tt) => { - let table = into_table_type(tt); - tables.push(table.clone()); - ExternType::Table(table) - } - ImportSectionEntryType::Memory(mt) => { - let memory = into_memory_type(mt); - memories.push(memory.clone()); - ExternType::Memory(memory) - } - ImportSectionEntryType::Global(gt) => { - let global = into_global_type(gt); - globals.push(global.clone()); - ExternType::Global(global) - } - }; - imports.push(ImportType::new(entry.module, entry.field, r#type)); - } - } - SectionCode::Export => { - let section = section.get_export_section_reader()?; - exports.reserve_exact(section.get_count() as usize); - for entry in section { - let entry = entry?; - let r#type = match entry.kind { - ExternalKind::Function => { - let sig_index = func_sig[entry.index as usize] as usize; - let sig = &sigs[sig_index]; - ExternType::Func(sig.clone()) - } - ExternalKind::Table => { - ExternType::Table(tables[entry.index as usize].clone()) - } - ExternalKind::Memory => { - ExternType::Memory(memories[entry.index as usize].clone()) - } - ExternalKind::Global => { - ExternType::Global(globals[entry.index as usize].clone()) - } - }; - exports.push(ExportType::new(entry.field, r#type)); - } - } - SectionCode::Custom { - kind: CustomSectionKind::Name, - .. - } => { - // Read name section. Per spec, ignore invalid custom section. - if let Ok(mut reader) = section.get_name_section_reader() { - while let Ok(entry) = reader.read() { - if let Name::Module(name) = entry { - if let Ok(name) = name.get_name() { - module_name = Some(name.to_string()); - } - break; - } - } - } - } - _ => { - // skip other sections - } - } - } - Ok(( - imports.into_boxed_slice(), - exports.into_boxed_slice(), - module_name, - )) -} - #[derive(Clone)] pub(crate) enum ModuleCodeSource { Binary(Box<[u8]>), @@ -259,11 +127,11 @@ impl Module { /// /// [binary]: https://webassembly.github.io/spec/core/binary/index.html pub fn new(store: &Store, binary: &[u8]) -> Result { - Self::validate(store, binary)?; + Module::validate(store, binary)?; // Note that the call to `unsafe` here should be ok because we // previously validated the binary, meaning we're guaranteed to pass a // valid binary for `store`. - unsafe { Self::create(store, binary, None) } + unsafe { Module::new_unchecked(store, binary) } } /// Creates a new WebAssembly `Module` from the given in-memory `binary` @@ -271,8 +139,9 @@ impl Module { /// /// See [`Module::new`] for other details. pub fn new_with_name(store: &Store, binary: &[u8], name: &str) -> Result { - Self::validate(store, binary)?; - unsafe { Self::create(store, binary, Some(name.to_string())) } + let mut ret = Module::new(store, binary)?; + Rc::get_mut(&mut ret.inner).unwrap().name = Some(name.to_string()); + Ok(ret) } /// Creates a new WebAssembly `Module` from the given in-memory `binary` @@ -302,24 +171,9 @@ impl Module { /// be somewhat valid for decoding purposes, and the basics of decoding can /// still fail. pub unsafe fn new_unchecked(store: &Store, binary: &[u8]) -> Result { - Self::create(store, binary, None) - } - - unsafe fn create( - store: &Store, - binary: &[u8], - name_override: Option, - ) -> Result { - let (imports, exports, name) = read_imports_and_exports(binary)?; - Ok(Module { - inner: Rc::new(ModuleInner { - store: store.clone(), - source: ModuleCodeSource::Binary(binary.into()), - imports, - exports, - name: name_override.or(name), - }), - }) + let mut ret = Module::empty(store); + ret.read_imports_and_exports(binary)?; + Ok(ret) } /// Validates `binary` input data as a WebAssembly binary given the @@ -356,12 +210,18 @@ impl Module { } pub fn from_exports(store: &Store, exports: Box<[ExportType]>) -> Self { + let mut ret = Module::empty(store); + Rc::get_mut(&mut ret.inner).unwrap().exports = exports; + return ret; + } + + fn empty(store: &Store) -> Self { Module { inner: Rc::new(ModuleInner { store: store.clone(), source: ModuleCodeSource::Unknown, imports: Box::new([]), - exports, + exports: Box::new([]), name: None, }), } @@ -396,4 +256,134 @@ impl Module { pub fn store(&self) -> &Store { &self.inner.store } + + fn read_imports_and_exports(&mut self, binary: &[u8]) -> Result<()> { + let inner = Rc::get_mut(&mut self.inner).unwrap(); + inner.source = ModuleCodeSource::Binary(binary.into()); + let mut reader = ModuleReader::new(binary)?; + let mut imports = Vec::new(); + let mut exports = Vec::new(); + let mut memories = Vec::new(); + let mut tables = Vec::new(); + let mut func_sig = Vec::new(); + let mut sigs = Vec::new(); + let mut globals = Vec::new(); + while !reader.eof() { + let section = reader.read()?; + match section.code { + SectionCode::Memory => { + let section = section.get_memory_section_reader()?; + memories.reserve_exact(section.get_count() as usize); + for entry in section { + memories.push(into_memory_type(entry?)); + } + } + SectionCode::Type => { + let section = section.get_type_section_reader()?; + sigs.reserve_exact(section.get_count() as usize); + for entry in section { + sigs.push(into_func_type(entry?)); + } + } + SectionCode::Function => { + let section = section.get_function_section_reader()?; + func_sig.reserve_exact(section.get_count() as usize); + for entry in section { + func_sig.push(entry?); + } + } + SectionCode::Global => { + let section = section.get_global_section_reader()?; + globals.reserve_exact(section.get_count() as usize); + for entry in section { + globals.push(into_global_type(entry?.ty)); + } + } + SectionCode::Table => { + let section = section.get_table_section_reader()?; + tables.reserve_exact(section.get_count() as usize); + for entry in section { + tables.push(into_table_type(entry?)) + } + } + SectionCode::Import => { + let section = section.get_import_section_reader()?; + imports.reserve_exact(section.get_count() as usize); + for entry in section { + let entry = entry?; + let r#type = match entry.ty { + ImportSectionEntryType::Function(index) => { + func_sig.push(index); + let sig = &sigs[index as usize]; + ExternType::Func(sig.clone()) + } + ImportSectionEntryType::Table(tt) => { + let table = into_table_type(tt); + tables.push(table.clone()); + ExternType::Table(table) + } + ImportSectionEntryType::Memory(mt) => { + let memory = into_memory_type(mt); + memories.push(memory.clone()); + ExternType::Memory(memory) + } + ImportSectionEntryType::Global(gt) => { + let global = into_global_type(gt); + globals.push(global.clone()); + ExternType::Global(global) + } + }; + imports.push(ImportType::new(entry.module, entry.field, r#type)); + } + } + SectionCode::Export => { + let section = section.get_export_section_reader()?; + exports.reserve_exact(section.get_count() as usize); + for entry in section { + let entry = entry?; + let r#type = match entry.kind { + ExternalKind::Function => { + let sig_index = func_sig[entry.index as usize] as usize; + let sig = &sigs[sig_index]; + ExternType::Func(sig.clone()) + } + ExternalKind::Table => { + ExternType::Table(tables[entry.index as usize].clone()) + } + ExternalKind::Memory => { + ExternType::Memory(memories[entry.index as usize].clone()) + } + ExternalKind::Global => { + ExternType::Global(globals[entry.index as usize].clone()) + } + }; + exports.push(ExportType::new(entry.field, r#type)); + } + } + SectionCode::Custom { + kind: CustomSectionKind::Name, + .. + } => { + // Read name section. Per spec, ignore invalid custom section. + if let Ok(mut reader) = section.get_name_section_reader() { + while let Ok(entry) = reader.read() { + if let Name::Module(name) = entry { + if let Ok(name) = name.get_name() { + inner.name = Some(name.to_string()); + } + break; + } + } + } + } + _ => { + // skip other sections + } + } + } + + inner.imports = imports.into(); + inner.exports = exports.into(); + Ok(()) + } } From 90db89d327be25806fc1b3c8c26a90ff082ffc69 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 10 Jan 2020 14:17:49 -0600 Subject: [PATCH 20/28] Refactor the `wasmtime-wast` crate, fix an early return (#798) This commit refactors the `wasmtime-wast` crate to internally make it a bit more concise with less repetition. Additionally it also improves the error messages by guaranteeing that all failed tests have context indicating where the test was defined. It turns out there was also a bug in the previous implementation where an `AssertMalformed` directive with a `quote` module would accidentally skip all further tests. This has now been fixed, and all futher tests continued to pass except for the `simd_const.wast` test. This test has been disabled temporarily but once the `wasmparser` and `wast` crates are updated (being worked on independently) this should be possible to re-enable. --- build.rs | 14 +- crates/wast/src/wast.rs | 572 +++++++++++++++++---------------------- tests/wast_testsuites.rs | 5 +- 3 files changed, 266 insertions(+), 325 deletions(-) diff --git a/build.rs b/build.rs index 10613feef6..44428b3e3c 100644 --- a/build.rs +++ b/build.rs @@ -43,12 +43,14 @@ fn main() -> anyhow::Result<()> { "simd", strategy, )?; - write_testsuite_tests( - &mut out, - "tests/spec_testsuite/proposals/simd/simd_const.wast", - "simd", - strategy, - )?; + // FIXME this uses some features from the reference types proposal + // (multi-table) which aren't fully implemented yet + // write_testsuite_tests( + // &mut out, + // "tests/spec_testsuite/proposals/simd/simd_const.wast", + // "simd", + // strategy, + // )?; finish_test_module(&mut out)?; test_directory( diff --git a/crates/wast/src/wast.rs b/crates/wast/src/wast.rs index 3299b4f67f..480e64fce5 100644 --- a/crates/wast/src/wast.rs +++ b/crates/wast/src/wast.rs @@ -39,6 +39,15 @@ enum Outcome> { Trap(Trap), } +impl Outcome { + fn into_result(self) -> Result { + match self { + Outcome::Ok(t) => Ok(t), + Outcome::Trap(t) => Err(t), + } + } +} + impl WastContext { /// Construct a new instance of `WastContext`. pub fn new(store: Store) -> Self { @@ -92,13 +101,7 @@ impl WastContext { } let instance = match Instance::new(&self.store, &module, &imports) { Ok(i) => i, - Err(e) => { - let err = e.chain().filter_map(|e| e.downcast_ref::()).next(); - if let Some(trap) = err { - return Ok(Outcome::Trap(trap.clone())); - } - return Err(e); - } + Err(e) => return e.downcast::().map(Outcome::Trap), }; Ok(Outcome::Ok(instance)) } @@ -126,7 +129,12 @@ impl WastContext { } fn perform_invoke(&mut self, exec: wast::WastInvoke<'_>) -> Result { - self.invoke(exec.module.map(|i| i.name()), exec.name, &exec.args) + let values = exec + .args + .iter() + .map(runtime_value) + .collect::>>()?; + self.invoke(exec.module.map(|i| i.name()), exec.name, &values) } /// Define a module and register it. @@ -154,9 +162,8 @@ impl WastContext { &mut self, instance_name: Option<&str>, field: &str, - args: &[wast::Expression], + args: &[Val], ) -> Result { - let values = args.iter().map(runtime_value).collect::>>()?; let instance = self.get_instance(instance_name.as_ref().map(|x| &**x))?; let export = instance .find_export_by_name(field) @@ -165,7 +172,7 @@ impl WastContext { Extern::Func(f) => f, _ => bail!("export of `{}` wasn't a global", field), }; - Ok(match func.call(&values) { + Ok(match func.call(args) { Ok(result) => Outcome::Ok(result.into()), Err(e) => Outcome::Trap(e), }) @@ -184,10 +191,34 @@ impl WastContext { Ok(Outcome::Ok(vec![global.get()])) } + fn assert_return(&self, result: Outcome, results: &[Val]) -> Result<()> { + let values = result.into_result()?; + for (v, e) in values.iter().zip(results) { + if values_equal(v, e)? { + continue; + } + bail!("expected {:?}, got {:?}", e, v) + } + Ok(()) + } + + fn assert_trap(&self, result: Outcome, message: &str) -> Result<()> { + let trap = match result { + Outcome::Ok(values) => bail!("expected trap, got {:?}", values), + Outcome::Trap(t) => t, + }; + if trap.message().contains(message) { + return Ok(()); + } + if cfg!(feature = "lightbeam") { + println!("TODO: Check the assert_trap message: {}", message); + return Ok(()); + } + bail!("expected {}, got {}", message, trap.message()) + } + /// Run a wast script from a byte buffer. pub fn run_buffer(&mut self, filename: &str, wast: &[u8]) -> Result<()> { - use wast::WastDirective::*; - let wast = str::from_utf8(wast)?; let adjust_wast = |mut err: wast::Error| { @@ -195,311 +226,216 @@ impl WastContext { err.set_text(wast); err }; - let context = |sp: wast::Span| { - let (line, col) = sp.linecol_in(wast); - format!("for directive on {}:{}:{}", filename, line + 1, col) - }; let buf = wast::parser::ParseBuffer::new(wast).map_err(adjust_wast)?; - let wast = wast::parser::parse::(&buf).map_err(adjust_wast)?; + let ast = wast::parser::parse::(&buf).map_err(adjust_wast)?; - for directive in wast.directives { - match directive { - Module(mut module) => { - let binary = module.encode().map_err(adjust_wast)?; - self.module(module.name.map(|s| s.name()), &binary) - .with_context(|| context(module.span))?; - } - Register { span, name, module } => { - self.register(module.map(|s| s.name()), name) - .with_context(|| context(span))?; - } - Invoke(i) => { - let span = i.span; - self.perform_invoke(i).with_context(|| context(span))?; - } - AssertReturn { - span, - exec, - results, - } => match self.perform_execute(exec).with_context(|| context(span))? { - Outcome::Ok(values) => { - for (v, e) in values.iter().zip(results.iter().map(runtime_value)) { - let e = e?; - if values_equal(v, &e)? { - continue; - } - bail!("{}\nexpected {:?}, got {:?}", context(span), e, v) - } - } - Outcome::Trap(t) => { - bail!("{}\nunexpected trap: {}", context(span), t.message()) - } - }, - AssertTrap { - span, - exec, - message, - } => match self.perform_execute(exec).with_context(|| context(span))? { - Outcome::Ok(values) => { - bail!("{}\nexpected trap, got {:?}", context(span), values) - } - Outcome::Trap(t) => { - if t.message().contains(message) { - continue; - } - if cfg!(feature = "lightbeam") { - println!( - "{}\nTODO: Check the assert_trap message: {}", - context(span), - message - ); - continue; - } - bail!( - "{}\nexpected {}, got {}", - context(span), - message, - t.message(), - ) - } - }, - AssertExhaustion { - span, - call, - message, - } => match self.perform_invoke(call).with_context(|| context(span))? { - Outcome::Ok(values) => { - bail!("{}\nexpected trap, got {:?}", context(span), values) - } - Outcome::Trap(t) => { - if t.message().contains(message) { - continue; - } - bail!( - "{}\nexpected exhaustion with {}, got {}", - context(span), - message, - t.message(), - ) - } - }, - AssertReturnCanonicalNan { span, invoke } => { - match self.perform_invoke(invoke).with_context(|| context(span))? { - Outcome::Ok(values) => { - for v in values.iter() { - match v { - Val::F32(x) => { - if !is_canonical_f32_nan(*x) { - bail!("{}\nexpected canonical NaN", context(span)) - } - } - Val::F64(x) => { - if !is_canonical_f64_nan(*x) { - bail!("{}\nexpected canonical NaN", context(span)) - } - } - other => bail!("expected float, got {:?}", other), - }; - } - } - Outcome::Trap(t) => { - bail!("{}\nunexpected trap: {}", context(span), t.message()) - } - } - } - AssertReturnCanonicalNanF32x4 { span, invoke } => { - match self.perform_invoke(invoke).with_context(|| context(span))? { - Outcome::Ok(values) => { - for v in values.iter() { - let val = match v { - Val::V128(x) => x, - other => bail!("expected v128, got {:?}", other), - }; - for l in 0..4 { - if !is_canonical_f32_nan(extract_lane_as_u32(val, l)?) { - bail!( - "{}\nexpected f32x4 canonical NaN in lane {}", - context(span), - l - ) - } - } - } - } - Outcome::Trap(t) => { - bail!("{}\nunexpected trap: {}", context(span), t.message()) - } - } - } - AssertReturnCanonicalNanF64x2 { span, invoke } => { - match self.perform_invoke(invoke).with_context(|| context(span))? { - Outcome::Ok(values) => { - for v in values.iter() { - let val = match v { - Val::V128(x) => x, - other => bail!("expected v128, got {:?}", other), - }; - for l in 0..2 { - if !is_canonical_f64_nan(extract_lane_as_u64(val, l)?) { - bail!( - "{}\nexpected f64x2 canonical NaN in lane {}", - context(span), - l - ) - } - } - } - } - Outcome::Trap(t) => { - bail!("{}\nunexpected trap: {}", context(span), t.message()) - } - } - } - AssertReturnArithmeticNan { span, invoke } => { - match self.perform_invoke(invoke).with_context(|| context(span))? { - Outcome::Ok(values) => { - for v in values.iter() { - match v { - Val::F32(x) => { - if !is_arithmetic_f32_nan(*x) { - bail!("{}\nexpected arithmetic NaN", context(span)) - } - } - Val::F64(x) => { - if !is_arithmetic_f64_nan(*x) { - bail!("{}\nexpected arithmetic NaN", context(span)) - } - } - other => bail!("expected float, got {:?}", other), - }; - } - } - Outcome::Trap(t) => { - bail!("{}\nunexpected trap: {}", context(span), t.message()) - } - } - } - AssertReturnArithmeticNanF32x4 { span, invoke } => { - match self.perform_invoke(invoke).with_context(|| context(span))? { - Outcome::Ok(values) => { - for v in values.iter() { - let val = match v { - Val::V128(x) => x, - other => bail!("expected v128, got {:?}", other), - }; - for l in 0..4 { - if !is_arithmetic_f32_nan(extract_lane_as_u32(val, l)?) { - bail!( - "{}\nexpected f32x4 arithmetic NaN in lane {}", - context(span), - l - ) - } - } - } - } - Outcome::Trap(t) => { - bail!("{}\nunexpected trap: {}", context(span), t.message()) - } - } - } - AssertReturnArithmeticNanF64x2 { span, invoke } => { - match self.perform_invoke(invoke).with_context(|| context(span))? { - Outcome::Ok(values) => { - for v in values.iter() { - let val = match v { - Val::V128(x) => x, - other => bail!("expected v128, got {:?}", other), - }; - for l in 0..2 { - if !is_arithmetic_f64_nan(extract_lane_as_u64(val, l)?) { - bail!( - "{}\nexpected f64x2 arithmetic NaN in lane {}", - context(span), - l - ) - } - } - } - } - Outcome::Trap(t) => { - bail!("{}\nunexpected trap: {}", context(span), t.message()) - } - } - } - AssertInvalid { - span, - mut module, - message, - } => { - let bytes = module.encode().map_err(adjust_wast)?; - let err = match self.module(None, &bytes) { - Ok(()) => bail!("{}\nexpected module to fail to build", context(span)), - Err(e) => e, - }; - let error_message = format!("{:?}", err); - if !error_message.contains(&message) { - // TODO: change to bail! - println!( - "{}\nassert_invalid: expected {}, got {}", - context(span), - message, - error_message - ) - } - } - AssertMalformed { - span, - module, - message, - } => { - let mut module = match module { - wast::QuoteModule::Module(m) => m, - // this is a `*.wat` parser test which we're not - // interested in - wast::QuoteModule::Quote(_) => return Ok(()), - }; - let bytes = module.encode().map_err(adjust_wast)?; - let err = match self.module(None, &bytes) { - Ok(()) => { - bail!("{}\nexpected module to fail to instantiate", context(span)) - } - Err(e) => e, - }; - let error_message = format!("{:?}", err); - if !error_message.contains(&message) { - // TODO: change to bail! - println!( - "{}\nassert_malformed: expected {}, got {}", - context(span), - message, - error_message - ) - } - } - AssertUnlinkable { - span, - mut module, - message, - } => { - let bytes = module.encode().map_err(adjust_wast)?; - let err = match self.module(None, &bytes) { - Ok(()) => bail!("{}\nexpected module to fail to link", context(span)), - Err(e) => e, - }; - let error_message = format!("{:?}", err); - if !error_message.contains(&message) { - bail!( - "{}\nassert_unlinkable: expected {}, got {}", - context(span), - message, - error_message - ) - } - } - AssertReturnFunc { .. } => bail!("need to implement assert_return_func"), + for directive in ast.directives { + let sp = directive.span(); + self.run_directive(directive).with_context(|| { + let (line, col) = sp.linecol_in(wast); + format!("failed directive on {}:{}:{}", filename, line + 1, col) + })?; + } + Ok(()) + } + + fn run_directive(&mut self, directive: wast::WastDirective) -> Result<()> { + use wast::WastDirective::*; + + match directive { + Module(mut module) => { + let binary = module.encode()?; + self.module(module.name.map(|s| s.name()), &binary)?; } + Register { + span: _, + name, + module, + } => { + self.register(module.map(|s| s.name()), name)?; + } + Invoke(i) => { + self.perform_invoke(i)?; + } + AssertReturn { + span: _, + exec, + results, + } => { + let results = results + .iter() + .map(runtime_value) + .collect::>>()?; + let result = self.perform_execute(exec)?; + self.assert_return(result, &results)?; + } + AssertTrap { + span: _, + exec, + message, + } => { + let result = self.perform_execute(exec)?; + self.assert_trap(result, message)?; + } + AssertExhaustion { + span: _, + call, + message, + } => { + let result = self.perform_invoke(call)?; + self.assert_trap(result, message)?; + } + AssertReturnCanonicalNan { span: _, invoke } => { + for v in self.perform_invoke(invoke)?.into_result()? { + match v { + Val::F32(x) => { + if !is_canonical_f32_nan(x) { + bail!("expected canonical NaN"); + } + } + Val::F64(x) => { + if !is_canonical_f64_nan(x) { + bail!("expected canonical NaN"); + } + } + other => bail!("expected float, got {:?}", other), + }; + } + } + AssertReturnCanonicalNanF32x4 { span: _, invoke } => { + for v in self.perform_invoke(invoke)?.into_result()? { + let val = match v { + Val::V128(x) => x, + other => bail!("expected v128, got {:?}", other), + }; + for l in 0..4 { + if !is_canonical_f32_nan(extract_lane_as_u32(val, l)?) { + bail!("expected f32x4 canonical NaN in lane {}", l) + } + } + } + } + AssertReturnCanonicalNanF64x2 { span: _, invoke } => { + for v in self.perform_invoke(invoke)?.into_result()? { + let val = match v { + Val::V128(x) => x, + other => bail!("expected v128, got {:?}", other), + }; + for l in 0..4 { + if !is_canonical_f64_nan(extract_lane_as_u64(val, l)?) { + bail!("expected f64x2 canonical NaN in lane {}", l) + } + } + } + } + AssertReturnArithmeticNan { span: _, invoke } => { + for v in self.perform_invoke(invoke)?.into_result()? { + match v { + Val::F32(x) => { + if !is_arithmetic_f32_nan(x) { + bail!("expected arithmetic NaN"); + } + } + Val::F64(x) => { + if !is_arithmetic_f64_nan(x) { + bail!("expected arithmetic NaN"); + } + } + other => bail!("expected float, got {:?}", other), + } + } + } + AssertReturnArithmeticNanF32x4 { span: _, invoke } => { + for v in self.perform_invoke(invoke)?.into_result()? { + let val = match v { + Val::V128(x) => x, + other => bail!("expected v128, got {:?}", other), + }; + for l in 0..4 { + if !is_arithmetic_f32_nan(extract_lane_as_u32(val, l)?) { + bail!("expected f32x4 arithmetic NaN in lane {}", l) + } + } + } + } + AssertReturnArithmeticNanF64x2 { span: _, invoke } => { + for v in self.perform_invoke(invoke)?.into_result()? { + let val = match v { + Val::V128(x) => x, + other => bail!("expected v128, got {:?}", other), + }; + for l in 0..4 { + if !is_arithmetic_f64_nan(extract_lane_as_u64(val, l)?) { + bail!("expected f64x2 arithmetic NaN in lane {}", l) + } + } + } + } + AssertInvalid { + span: _, + mut module, + message, + } => { + let bytes = module.encode()?; + let err = match self.module(None, &bytes) { + Ok(()) => bail!("expected module to fail to build"), + Err(e) => e, + }; + let error_message = format!("{:?}", err); + if !error_message.contains(&message) { + // TODO: change to bail! + println!( + "assert_invalid: expected {}, got {}", + message, error_message + ) + } + } + AssertMalformed { + span: _, + module, + message, + } => { + let mut module = match module { + wast::QuoteModule::Module(m) => m, + // this is a `*.wat` parser test which we're not + // interested in + wast::QuoteModule::Quote(_) => return Ok(()), + }; + let bytes = module.encode()?; + let err = match self.module(None, &bytes) { + Ok(()) => bail!("expected module to fail to instantiate"), + Err(e) => e, + }; + let error_message = format!("{:?}", err); + if !error_message.contains(&message) { + // TODO: change to bail! + println!( + "assert_malformed: expected {}, got {}", + message, error_message + ) + } + } + AssertUnlinkable { + span: _, + mut module, + message, + } => { + let bytes = module.encode()?; + let err = match self.module(None, &bytes) { + Ok(()) => bail!("expected module to fail to link"), + Err(e) => e, + }; + let error_message = format!("{:?}", err); + if !error_message.contains(&message) { + bail!( + "assert_unlinkable: expected {}, got {}", + message, + error_message + ) + } + } + AssertReturnFunc { .. } => bail!("need to implement assert_return_func"), } Ok(()) @@ -513,12 +449,12 @@ impl WastContext { } } -fn extract_lane_as_u32(bytes: &u128, lane: usize) -> Result { - Ok((*bytes >> (lane * 32)) as u32) +fn extract_lane_as_u32(bytes: u128, lane: usize) -> Result { + Ok((bytes >> (lane * 32)) as u32) } -fn extract_lane_as_u64(bytes: &u128, lane: usize) -> Result { - Ok((*bytes >> (lane * 64)) as u64) +fn extract_lane_as_u64(bytes: u128, lane: usize) -> Result { + Ok((bytes >> (lane * 64)) as u64) } fn is_canonical_f32_nan(bits: u32) -> bool { diff --git a/tests/wast_testsuites.rs b/tests/wast_testsuites.rs index 877c59ccfc..02734add70 100644 --- a/tests/wast_testsuites.rs +++ b/tests/wast_testsuites.rs @@ -10,8 +10,11 @@ include!(concat!(env!("OUT_DIR"), "/wast_testsuite_tests.rs")); fn run_wast(wast: &str, strategy: Strategy) -> anyhow::Result<()> { let wast = Path::new(wast); + let simd = wast.iter().any(|s| s == "simd"); + let mut cfg = Config::new(); - cfg.wasm_simd(wast.iter().any(|s| s == "simd")) + cfg.wasm_simd(simd) + .wasm_reference_types(simd) // some simd tests assume multiple tables ok .wasm_multi_value(wast.iter().any(|s| s == "multi-value")) .strategy(strategy)? .cranelift_debug_verifier(true); From 2b7d62700746153c357e30d04f5793d23c49efae Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 10 Jan 2020 14:36:31 -0600 Subject: [PATCH 21/28] Remove `HostRef` as a reexport from `wasmtime` (#794) This continues #788 and literally removes the type from the public API of the `wasmtime` crate, making it inaccessible to the outside world. Now it's purely an implementation detail, yay! --- crates/api/src/lib.rs | 2 +- crates/api/src/wasm.rs | 5 ++-- crates/api/tests/name.rs | 50 ++++++++++++++++------------------------ 3 files changed, 24 insertions(+), 33 deletions(-) diff --git a/crates/api/src/lib.rs b/crates/api/src/lib.rs index 49622c94fe..e5196e7e1e 100644 --- a/crates/api/src/lib.rs +++ b/crates/api/src/lib.rs @@ -26,7 +26,7 @@ pub use crate::callable::Callable; pub use crate::externals::*; pub use crate::instance::Instance; pub use crate::module::Module; -pub use crate::r#ref::{AnyRef, HostInfo, HostRef}; +pub use crate::r#ref::AnyRef; pub use crate::runtime::{Config, Engine, OptLevel, Store, Strategy}; pub use crate::trap::{FrameInfo, Trap}; pub use crate::types::*; diff --git a/crates/api/src/wasm.rs b/crates/api/src/wasm.rs index f5591ece5b..f87ca77b8e 100644 --- a/crates/api/src/wasm.rs +++ b/crates/api/src/wasm.rs @@ -7,9 +7,10 @@ use super::{ AnyRef, Callable, Engine, ExportType, Extern, ExternType, Func, FuncType, Global, GlobalType, - HostInfo, HostRef, ImportType, Instance, Limits, Memory, MemoryType, Module, Store, Table, - TableType, Trap, Val, ValType, + ImportType, Instance, Limits, Memory, MemoryType, Module, Store, Table, TableType, Trap, Val, + ValType, }; +use crate::r#ref::{HostInfo, HostRef}; use std::cell::RefCell; use std::rc::Rc; use std::{mem, ptr, slice}; diff --git a/crates/api/tests/name.rs b/crates/api/tests/name.rs index 69276af4ee..24c86caeea 100644 --- a/crates/api/tests/name.rs +++ b/crates/api/tests/name.rs @@ -1,48 +1,38 @@ use wasmtime::*; -use wat::parse_str; #[test] -fn test_module_no_name() -> Result<(), String> { +fn test_module_no_name() -> anyhow::Result<()> { let store = Store::default(); - let binary = parse_str( + let binary = wat::parse_str( r#" - (module - (func (export "run") (nop)) - ) - "#, - ) - .map_err(|e| format!("failed to parse WebAssembly text source: {}", e))?; + (module + (func (export "run") (nop)) + ) + "#, + )?; - let module = HostRef::new( - Module::new(&store, &binary).map_err(|e| format!("failed to compile module: {}", e))?, - ); - assert_eq!(module.borrow().name(), None); + let module = Module::new(&store, &binary)?; + assert_eq!(module.name(), None); Ok(()) } #[test] -fn test_module_name() -> Result<(), String> { +fn test_module_name() -> anyhow::Result<()> { let store = Store::default(); - let binary = parse_str( + let binary = wat::parse_str( r#" - (module $from_name_section - (func (export "run") (nop)) - ) - "#, - ) - .map_err(|e| format!("failed to parse WebAssembly text source: {}", e))?; + (module $from_name_section + (func (export "run") (nop)) + ) + "#, + )?; - let module = HostRef::new( - Module::new(&store, &binary).map_err(|e| format!("failed to compile module: {}", e))?, - ); - assert_eq!(module.borrow().name(), Some("from_name_section")); + let module = Module::new(&store, &binary)?; + assert_eq!(module.name(), Some("from_name_section")); - let module = HostRef::new( - Module::new_with_name(&store, &binary, "override") - .map_err(|e| format!("failed to compile module: {}", e))?, - ); - assert_eq!(module.borrow().name(), Some("override")); + let module = Module::new_with_name(&store, &binary, "override")?; + assert_eq!(module.name(), Some("override")); Ok(()) } From 28a938a62f2ae1a64145080c0014928c901b404f Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 10 Jan 2020 14:41:49 -0600 Subject: [PATCH 22/28] Remove `allow(improper_ctypes)` (#797) This was a bug on nightly a month or so ago but has since been fixed! --- crates/api/src/lib.rs | 2 -- crates/misc/py/src/lib.rs | 2 -- crates/runtime/src/lib.rs | 1 - crates/wasi/src/lib.rs | 2 -- crates/wasi/src/old/snapshot_0/mod.rs | 2 -- crates/wast/src/spectest.rs | 2 -- 6 files changed, 11 deletions(-) diff --git a/crates/api/src/lib.rs b/crates/api/src/lib.rs index e5196e7e1e..7ccf342ca5 100644 --- a/crates/api/src/lib.rs +++ b/crates/api/src/lib.rs @@ -6,8 +6,6 @@ //! and there to implement Rust idioms. This crate also defines the actual C API //! itself for consumption from other languages. -#![allow(improper_ctypes)] - mod callable; mod context; mod externals; diff --git a/crates/misc/py/src/lib.rs b/crates/misc/py/src/lib.rs index 2bb164ddd2..1c7584a40c 100644 --- a/crates/misc/py/src/lib.rs +++ b/crates/misc/py/src/lib.rs @@ -1,5 +1,3 @@ -#![allow(improper_ctypes)] - use crate::function::{wrap_into_pyfunction, Function}; use crate::instance::Instance; use crate::memory::Memory; diff --git a/crates/runtime/src/lib.rs b/crates/runtime/src/lib.rs index 4a1f06d66c..5a48273e12 100644 --- a/crates/runtime/src/lib.rs +++ b/crates/runtime/src/lib.rs @@ -1,6 +1,5 @@ //! Runtime library support for Wasmtime. -#![allow(improper_ctypes)] #![deny(missing_docs, trivial_numeric_casts, unused_extern_crates)] #![warn(unused_import_braces)] #![cfg_attr(feature = "clippy", plugin(clippy(conf_file = "../../clippy.toml")))] diff --git a/crates/wasi/src/lib.rs b/crates/wasi/src/lib.rs index c152b34132..565958f9e8 100644 --- a/crates/wasi/src/lib.rs +++ b/crates/wasi/src/lib.rs @@ -1,5 +1,3 @@ -#![allow(improper_ctypes)] - mod instantiate; pub mod old; diff --git a/crates/wasi/src/old/snapshot_0/mod.rs b/crates/wasi/src/old/snapshot_0/mod.rs index ef699ce0b6..b4ffd25440 100644 --- a/crates/wasi/src/old/snapshot_0/mod.rs +++ b/crates/wasi/src/old/snapshot_0/mod.rs @@ -1,5 +1,3 @@ -#![allow(improper_ctypes)] - extern crate alloc; mod instantiate; diff --git a/crates/wast/src/spectest.rs b/crates/wast/src/spectest.rs index fb2cb96de6..c180a7689c 100644 --- a/crates/wast/src/spectest.rs +++ b/crates/wast/src/spectest.rs @@ -1,5 +1,3 @@ -#![allow(improper_ctypes)] - use anyhow::Result; use std::collections::HashMap; use std::rc::Rc; From ef2177ed3a153b9f7d5767ac77e999f06ab1e503 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Fri, 10 Jan 2020 13:57:38 -0800 Subject: [PATCH 23/28] Update to the latest spec_testsuite and dependencies. (#803) * Update to the latest spec_testsuite and dependencies. Update to target-lexicon 0.10, cranelift 0.54, wast 0.6, faerie 0.14, and the latest spec_testsuite. For wast and cranelift-wasm, update the code for API changes. * Factor out the code for matching f32, f64, and v128. This takes the idea from #802 to split out `f32_matches`, `f64_matches`, and `v128_matches` functions, which better factor out the matching functionality between scalar and vector. --- Cargo.lock | 116 ++++++++----------- Cargo.toml | 4 +- build.rs | 2 + crates/api/Cargo.toml | 4 +- crates/api/c-examples/wasm-c-api | 2 +- crates/debug/Cargo.toml | 6 +- crates/environ/Cargo.toml | 12 +- crates/environ/src/func_environ.rs | 4 + crates/fuzzing/Cargo.toml | 2 +- crates/interface-types/Cargo.toml | 2 +- crates/jit/Cargo.toml | 14 +-- crates/lightbeam/Cargo.toml | 4 +- crates/misc/py/Cargo.toml | 4 +- crates/obj/Cargo.toml | 2 +- crates/test-programs/Cargo.toml | 2 +- crates/wasi-c/Cargo.toml | 10 +- crates/wasi-common/wig/WASI | 2 +- crates/wasi/Cargo.toml | 8 +- crates/wast/Cargo.toml | 2 +- crates/wast/src/wast.rs | 175 ++++++++++++----------------- scripts/cranelift-version.sh | 8 +- tests/spec_testsuite | 2 +- 22 files changed, 167 insertions(+), 220 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index da9a3565fd..01553a79ad 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -126,7 +126,7 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "440d600bca1c3b3982dd2533518e15ba73d051b532768804aa3c06ae52f4ce44" dependencies = [ - "bindgen 0.52.0", + "bindgen", "cc", "cmake", "heck", @@ -143,29 +143,6 @@ dependencies = [ "serde", ] -[[package]] -name = "bindgen" -version = "0.51.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebd71393f1ec0509b553aa012b9b58e81dadbdff7130bd3b8cba576e69b32f75" -dependencies = [ - "bitflags", - "cexpr", - "cfg-if", - "clang-sys", - "clap", - "env_logger 0.6.2", - "lazy_static", - "log", - "peeking_take_while", - "proc-macro2", - "quote", - "regex", - "rustc-hash", - "shlex", - "which", -] - [[package]] name = "bindgen" version = "0.52.0" @@ -364,18 +341,18 @@ dependencies = [ [[package]] name = "cranelift-bforest" -version = "0.52.0" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56aa72ef104c5d634f2f9e84ef2c47e116c1d185fae13f196b97ca84b0a514f1" +checksum = "3b065d5992ea22903200c56dd2b3a7062a1311b49739ffd2be9215f882204f73" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-codegen" -version = "0.52.0" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "460b9d20793543599308d22f5a1172c196e63a780c4e9aacb0b3f4f63d63ffe1" +checksum = "6ae646133a3dda0af636eb4e2928d282a976c836392e0de57a5750ca9eb132e1" dependencies = [ "byteorder", "cranelift-bforest", @@ -391,9 +368,9 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.52.0" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc70e4e8ccebd53a4f925147def857c9e9f7fe0fdbef4bb645a420473e012f50" +checksum = "883a636641a34034d16d1986557fdf815245140c4bb9e6561a6cb8ebacd7b9d4" dependencies = [ "cranelift-codegen-shared", "cranelift-entity", @@ -401,24 +378,24 @@ dependencies = [ [[package]] name = "cranelift-codegen-shared" -version = "0.52.0" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3992000be4d18df0fe332b7c42c120de896e8ec54cd7b6cfa050910a8c9f6e2f" +checksum = "a3467bb48aa1b6a4c0da0fa0b5fea7f78f96bbf4bbf054eeb053b5e2e8794387" [[package]] name = "cranelift-entity" -version = "0.52.0" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "722957e05064d97a3157bf0976deed0f3e8ee4f8a4ce167a7c724ca63a4e8bd9" +checksum = "03578fa46b2009c4575494b0ecf8319a79bc913a6c1be3a2cb55ee7089c59989" dependencies = [ "serde", ] [[package]] name = "cranelift-frontend" -version = "0.52.0" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13051964302dc7948e8869735de42591559ea55e319b9b92da5b38f8e6a75cb7" +checksum = "54859b486e505c03d5d8982216509eb99782ef5a3f7f8cbe86cd73967975c49b" dependencies = [ "cranelift-codegen", "log", @@ -428,9 +405,9 @@ dependencies = [ [[package]] name = "cranelift-native" -version = "0.52.0" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21398a0bc6ba389ea86964ac4a495426dd61080f2ddd306184777a8560fe9976" +checksum = "b245d7376b7200a5dcce955761f4f7396019beda4a788d9cbe555308f1869cd2" dependencies = [ "cranelift-codegen", "raw-cpuid", @@ -439,9 +416,9 @@ dependencies = [ [[package]] name = "cranelift-wasm" -version = "0.52.0" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b72b7b10c09f70a604122fab76e6c4411255cf35403b68c3285566cc9d21c486" +checksum = "115e207912c5841c3932b366be979b34a62ee32c839c2ddbc1c81877cd8ec03c" dependencies = [ "cranelift-codegen", "cranelift-entity", @@ -637,9 +614,9 @@ dependencies = [ [[package]] name = "faerie" -version = "0.13.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f902f2af041f6c7177a2a04f805687cdc71e69c7cbef059a2755d8923f4cd7a8" +checksum = "74b9ed6159e4a6212c61d9c6a86bee01876b192a64accecf58d5b5ae3b667b52" dependencies = [ "anyhow", "goblin", @@ -953,7 +930,7 @@ dependencies = [ "smallvec", "thiserror", "typemap", - "wasmparser 0.45.2", + "wasmparser 0.47.0", "wat", ] @@ -1030,9 +1007,9 @@ dependencies = [ [[package]] name = "num" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4825417e1e1406b3782a8ce92f4d53f26ec055e3622e1881ca8e9f5f9e08db" +checksum = "b8536030f9fea7127f841b45bb6243b27255787fb4eb83958aa1ef9d2fdc0c36" dependencies = [ "num-complex", "num-integer", @@ -1043,11 +1020,11 @@ dependencies = [ [[package]] name = "num-complex" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb0cf31fb3ff77e6d2a6ebd6800df7fdcd106f2ad89113c9130bcd07f93dffc" +checksum = "b6b19411a9719e753aff12e5187b74d60d3dc449ec3f4dc21e3989c3f554bc95" dependencies = [ - "autocfg 0.1.7", + "autocfg 1.0.0", "num-traits", ] @@ -1074,11 +1051,11 @@ dependencies = [ [[package]] name = "num-rational" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2885278d5fe2adc2f75ced642d52d879bffaceb5a2e0b1d4309ffdfb239b454" +checksum = "da4dc79f9e6c81bef96148c8f6b8e72ad4541caa4a24373e900a36da07de03a3" dependencies = [ - "autocfg 0.1.7", + "autocfg 1.0.0", "num-integer", "num-traits", ] @@ -1710,9 +1687,9 @@ dependencies = [ [[package]] name = "target-lexicon" -version = "0.9.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f4c118a7a38378f305a9e111fcb2f7f838c0be324bfb31a77ea04f7f6e684b4" +checksum = "ab0e7238dcc7b40a7be719a25365910f6807bd864f4cce6b2e6b873658e2b19d" [[package]] name = "tempfile" @@ -1993,6 +1970,12 @@ version = "0.45.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b4eab1d9971d0803729cba3617b56eb04fcb4bd25361cb63880ed41a42f20d5" +[[package]] +name = "wasmparser" +version = "0.47.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1add8db5a53a2f64f13418b241982c4ab533d7a9e1e8a5dcadccce633d8d393b" + [[package]] name = "wasmprinter" version = "0.2.0" @@ -2016,7 +1999,7 @@ dependencies = [ "region", "target-lexicon", "wasi-common", - "wasmparser 0.45.2", + "wasmparser 0.47.0", "wasmtime-environ", "wasmtime-jit", "wasmtime-runtime", @@ -2063,7 +2046,7 @@ dependencies = [ "more-asserts", "target-lexicon", "thiserror", - "wasmparser 0.45.2", + "wasmparser 0.47.0", "wasmtime-environ", ] @@ -2097,7 +2080,7 @@ dependencies = [ "tempfile", "thiserror", "toml", - "wasmparser 0.45.2", + "wasmparser 0.47.0", "winapi", "zstd", ] @@ -2124,7 +2107,7 @@ dependencies = [ "binaryen", "env_logger 0.7.1", "log", - "wasmparser 0.45.2", + "wasmparser 0.47.0", "wasmprinter", "wasmtime", "wasmtime-environ", @@ -2139,7 +2122,7 @@ dependencies = [ "anyhow", "walrus", "wasm-webidl-bindings", - "wasmparser 0.45.2", + "wasmparser 0.47.0", "wasmtime", "wasmtime-environ", "wasmtime-jit", @@ -2161,7 +2144,7 @@ dependencies = [ "region", "target-lexicon", "thiserror", - "wasmparser 0.45.2", + "wasmparser 0.47.0", "wasmtime-debug", "wasmtime-environ", "wasmtime-runtime", @@ -2186,7 +2169,7 @@ dependencies = [ "pyo3", "region", "target-lexicon", - "wasmparser 0.45.2", + "wasmparser 0.47.0", "wasmtime", "wasmtime-environ", "wasmtime-interface-types", @@ -2252,7 +2235,7 @@ dependencies = [ name = "wasmtime-wasi-c" version = "0.9.0" dependencies = [ - "bindgen 0.51.1", + "bindgen", "cmake", "cranelift-codegen", "cranelift-entity", @@ -2272,7 +2255,7 @@ version = "0.9.0" dependencies = [ "anyhow", "wasmtime", - "wast 5.0.1", + "wast 6.0.0", ] [[package]] @@ -2284,15 +2267,6 @@ dependencies = [ "leb128", ] -[[package]] -name = "wast" -version = "5.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d1de68310854a9840d39487701a8c1acccb5c9f9f2650d5fce3cdfe6650c372" -dependencies = [ - "leb128", -] - [[package]] name = "wast" version = "6.0.0" diff --git a/Cargo.toml b/Cargo.toml index 9eaba429dd..378189e3c2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,9 +29,9 @@ wasmtime-wasi = { path = "crates/wasi" } wasmtime-wasi-c = { path = "crates/wasi-c", optional = true } wasi-common = { path = "crates/wasi-common" } structopt = { version = "0.3.5", features = ["color", "suggestions"] } -faerie = "0.13.0" +faerie = "0.14.0" anyhow = "1.0.19" -target-lexicon = { version = "0.9.0", default-features = false } +target-lexicon = { version = "0.10.0", default-features = false } pretty_env_logger = "0.3.0" file-per-thread-logger = "0.1.1" wat = "1.0.2" diff --git a/build.rs b/build.rs index 44428b3e3c..3e5598926e 100644 --- a/build.rs +++ b/build.rs @@ -166,6 +166,8 @@ fn ignore(testsuite: &str, testname: &str, strategy: &str) -> bool { "Lightbeam" => match (testsuite, testname) { (_, _) if testname.starts_with("simd") => return true, (_, _) if testsuite.ends_with("multi_value") => return true, + // Lightbeam doesn't support float arguments on the stack. + ("spec_testsuite", "call.wast") => return true, _ => (), }, "Cranelift" => match (testsuite, testname) { diff --git a/crates/api/Cargo.toml b/crates/api/Cargo.toml index b441217640..67961e0299 100644 --- a/crates/api/Cargo.toml +++ b/crates/api/Cargo.toml @@ -16,8 +16,8 @@ crate-type = ["lib", "staticlib", "cdylib"] wasmtime-runtime = { path = "../runtime", version = "0.9.0" } wasmtime-environ = { path = "../environ", version = "0.9.0" } wasmtime-jit = { path = "../jit", version = "0.9.0" } -wasmparser = { version = "0.45.1", default-features = false } -target-lexicon = { version = "0.9.0", default-features = false } +wasmparser = { version = "0.47.0", default-features = false } +target-lexicon = { version = "0.10.0", default-features = false } anyhow = "1.0.19" region = "2.0.0" libc = "0.2" diff --git a/crates/api/c-examples/wasm-c-api b/crates/api/c-examples/wasm-c-api index 8782d5b456..d9a80099d4 160000 --- a/crates/api/c-examples/wasm-c-api +++ b/crates/api/c-examples/wasm-c-api @@ -1 +1 @@ -Subproject commit 8782d5b456f39e5ebf86bbbfa88d0ac13743edfa +Subproject commit d9a80099d496b5cdba6f3fe8fc77586e0e505ddc diff --git a/crates/debug/Cargo.toml b/crates/debug/Cargo.toml index a85387c326..f7ac2cc8c0 100644 --- a/crates/debug/Cargo.toml +++ b/crates/debug/Cargo.toml @@ -13,10 +13,10 @@ edition = "2018" [dependencies] gimli = "0.19.0" -wasmparser = "0.45.1" -faerie = "0.13.0" +wasmparser = "0.47.0" +faerie = "0.14.0" wasmtime-environ = { path = "../environ", version = "0.9.0" } -target-lexicon = { version = "0.9.0", default-features = false } +target-lexicon = { version = "0.10.0", default-features = false } anyhow = "1.0" thiserror = "1.0.4" more-asserts = "0.2.1" diff --git a/crates/environ/Cargo.toml b/crates/environ/Cargo.toml index 260b8a468f..596a413db1 100644 --- a/crates/environ/Cargo.toml +++ b/crates/environ/Cargo.toml @@ -13,10 +13,10 @@ edition = "2018" [dependencies] anyhow = "1.0" -cranelift-codegen = { version = "0.52.0", features = ["enable-serde"] } -cranelift-entity = { version = "0.52.0", features = ["enable-serde"] } -cranelift-wasm = { version = "0.52.0", features = ["enable-serde"] } -wasmparser = "0.45.1" +cranelift-codegen = { version = "0.53", features = ["enable-serde"] } +cranelift-entity = { version = "0.53", features = ["enable-serde"] } +cranelift-wasm = { version = "0.53", features = ["enable-serde"] } +wasmparser = "0.47.0" lightbeam = { path = "../lightbeam", optional = true, version = "0.9.0" } indexmap = "1.0.2" rayon = "1.2.1" @@ -43,10 +43,10 @@ errno = "0.2.4" [dev-dependencies] tempfile = "3" -target-lexicon = { version = "0.9.0", default-features = false } +target-lexicon = { version = "0.10.0", default-features = false } pretty_env_logger = "0.3.0" rand = { version = "0.7.0", default-features = false, features = ["small_rng"] } -cranelift-codegen = { version = "0.52.0", features = ["enable-serde", "all-arch"] } +cranelift-codegen = { version = "0.53", features = ["enable-serde", "all-arch"] } filetime = "0.2.7" [badges] diff --git a/crates/environ/src/func_environ.rs b/crates/environ/src/func_environ.rs index 6daa016b69..b218641877 100644 --- a/crates/environ/src/func_environ.rs +++ b/crates/environ/src/func_environ.rs @@ -362,6 +362,10 @@ impl<'module_environment> TargetEnvironment for FuncEnvironment<'module_environm } impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'module_environment> { + fn is_wasm_parameter(&self, func: &ir::Function, index: usize) -> bool { + func.signature.params[index].purpose == ir::ArgumentPurpose::Normal + } + fn make_table(&mut self, func: &mut ir::Function, index: TableIndex) -> WasmResult { let pointer_type = self.pointer_type(); diff --git a/crates/fuzzing/Cargo.toml b/crates/fuzzing/Cargo.toml index 76d65fc05e..e6eefeafe7 100644 --- a/crates/fuzzing/Cargo.toml +++ b/crates/fuzzing/Cargo.toml @@ -14,7 +14,7 @@ arbitrary = "0.2.0" binaryen = "0.8.2" env_logger = { version = "0.7.1", optional = true } log = "0.4.8" -wasmparser = "0.45.1" +wasmparser = "0.47.0" wasmprinter = "0.2.0" wasmtime = { path = "../api", version = "0.9.0" } wasmtime-environ = { path = "../environ", version = "0.9.0" } diff --git a/crates/interface-types/Cargo.toml b/crates/interface-types/Cargo.toml index 72572c59b0..380d466766 100644 --- a/crates/interface-types/Cargo.toml +++ b/crates/interface-types/Cargo.toml @@ -13,7 +13,7 @@ edition = "2018" [dependencies] anyhow = "1.0.19" walrus = "0.13" -wasmparser = { version = "0.45.1", default-features = false } +wasmparser = { version = "0.47.0", default-features = false } wasm-webidl-bindings = "0.6" wasmtime = { path = "../api", version = "0.9.0" } wasmtime-jit = { path = "../jit", version = "0.9.0" } diff --git a/crates/jit/Cargo.toml b/crates/jit/Cargo.toml index a4a1c59a4c..950c714988 100644 --- a/crates/jit/Cargo.toml +++ b/crates/jit/Cargo.toml @@ -11,18 +11,18 @@ readme = "README.md" edition = "2018" [dependencies] -cranelift-codegen = { version = "0.52.0", features = ["enable-serde"] } -cranelift-entity = { version = "0.52.0", features = ["enable-serde"] } -cranelift-wasm = { version = "0.52.0", features = ["enable-serde"] } -cranelift-native = "0.52.0" -cranelift-frontend = "0.52.0" +cranelift-codegen = { version = "0.53", features = ["enable-serde"] } +cranelift-entity = { version = "0.53", features = ["enable-serde"] } +cranelift-wasm = { version = "0.53", features = ["enable-serde"] } +cranelift-native = "0.53" +cranelift-frontend = "0.53" wasmtime-environ = { path = "../environ", version = "0.9.0" } wasmtime-runtime = { path = "../runtime", version = "0.9.0" } wasmtime-debug = { path = "../debug", version = "0.9.0" } region = "2.0.0" thiserror = "1.0.4" -target-lexicon = { version = "0.9.0", default-features = false } -wasmparser = { version = "0.45.1", default-features = false } +target-lexicon = { version = "0.10.0", default-features = false } +wasmparser = { version = "0.47.0", default-features = false } more-asserts = "0.2.1" anyhow = "1.0" diff --git a/crates/lightbeam/Cargo.toml b/crates/lightbeam/Cargo.toml index b5af145c84..51fb19ed5c 100644 --- a/crates/lightbeam/Cargo.toml +++ b/crates/lightbeam/Cargo.toml @@ -14,12 +14,12 @@ edition = "2018" smallvec = "1.0.0" dynasm = "0.5.2" dynasmrt = "0.5.2" -wasmparser = "0.45.1" +wasmparser = "0.47.0" memoffset = "0.5.3" itertools = "0.8.2" capstone = "0.6.0" thiserror = "1.0.9" -cranelift-codegen = "0.52.0" +cranelift-codegen = "0.53" multi_mut = "0.1" either = "1.5" typemap = "0.3" diff --git a/crates/misc/py/Cargo.toml b/crates/misc/py/Cargo.toml index 335e843794..633cab3adb 100644 --- a/crates/misc/py/Cargo.toml +++ b/crates/misc/py/Cargo.toml @@ -22,10 +22,10 @@ wasmtime-environ = { path = "../../environ", version = "0.9.0" } wasmtime-interface-types = { path = "../../interface-types", version = "0.9.0" } wasmtime-runtime = { path = "../../runtime", version = "0.9.0" } wasmtime-wasi = { path = "../../wasi", version = "0.9.0" } -target-lexicon = { version = "0.9.0", default-features = false } +target-lexicon = { version = "0.10.0", default-features = false } anyhow = "1.0.19" region = "2.0.0" -wasmparser = "0.45.1" +wasmparser = "0.47.0" pyo3 = { version = "0.8.0", features = ["extension-module"] } [badges] diff --git a/crates/obj/Cargo.toml b/crates/obj/Cargo.toml index 15056b8245..66843b6cbc 100644 --- a/crates/obj/Cargo.toml +++ b/crates/obj/Cargo.toml @@ -13,7 +13,7 @@ edition = "2018" [dependencies] anyhow = "1.0" wasmtime-environ = { path = "../environ", version = "0.9.0" } -faerie = "0.13.0" +faerie = "0.14.0" more-asserts = "0.2.1" [badges] diff --git a/crates/test-programs/Cargo.toml b/crates/test-programs/Cargo.toml index 50f2254757..28833c37ab 100644 --- a/crates/test-programs/Cargo.toml +++ b/crates/test-programs/Cargo.toml @@ -16,7 +16,7 @@ wasmtime-environ = { path = "../environ", version = "0.9.0" } wasmtime-jit = { path = "../jit", version = "0.9.0" } wasmtime-wasi = { path = "../wasi", version = "0.9.0" } wasmtime = { path = "../api", version = "0.9.0" } -target-lexicon = "0.9.0" +target-lexicon = "0.10.0" pretty_env_logger = "0.3.0" tempfile = "3.1.0" os_pipe = "0.9" diff --git a/crates/wasi-c/Cargo.toml b/crates/wasi-c/Cargo.toml index 423fb4d346..560edb2a23 100644 --- a/crates/wasi-c/Cargo.toml +++ b/crates/wasi-c/Cargo.toml @@ -14,17 +14,17 @@ edition = "2018" wasmtime-runtime = { path = "../runtime", version = "0.9.0" } wasmtime-environ = { path = "../environ", version = "0.9.0" } wasmtime-jit = { path = "../jit", version = "0.9.0" } -cranelift-codegen = { version = "0.52.0", features = ["enable-serde"] } -cranelift-entity = { version = "0.52.0", features = ["enable-serde"] } -cranelift-wasm = { version = "0.52.0", features = ["enable-serde"] } -target-lexicon = "0.9.0" +cranelift-codegen = { version = "0.53", features = ["enable-serde"] } +cranelift-entity = { version = "0.53", features = ["enable-serde"] } +cranelift-wasm = { version = "0.53", features = ["enable-serde"] } +target-lexicon = "0.10.0" log = { version = "0.4.8", default-features = false } libc = "0.2.60" more-asserts = "0.2.1" [build-dependencies] cmake = "0.1.35" -bindgen = "0.51.0" +bindgen = "0.52.0" [badges] maintenance = { status = "actively-developed" } diff --git a/crates/wasi-common/wig/WASI b/crates/wasi-common/wig/WASI index 9150e66a34..04d4eba571 160000 --- a/crates/wasi-common/wig/WASI +++ b/crates/wasi-common/wig/WASI @@ -1 +1 @@ -Subproject commit 9150e66a349dff6215b0290ee8f66794fbfa5ea8 +Subproject commit 04d4eba571dc1d6fe9ab129ea9343911bcc256dc diff --git a/crates/wasi/Cargo.toml b/crates/wasi/Cargo.toml index fa3607dfc5..c35a3464ff 100644 --- a/crates/wasi/Cargo.toml +++ b/crates/wasi/Cargo.toml @@ -16,10 +16,10 @@ wasmtime-runtime = { path = "../runtime", version = "0.9.0" } wasmtime-environ = { path = "../environ", version = "0.9.0" } wasmtime-jit = { path = "../jit", version = "0.9.0" } wasi-common = { path = "../wasi-common", version = "0.9.0" } -cranelift-codegen = { version = "0.52.0", features = ["enable-serde"] } -cranelift-entity = { version = "0.52.0", features = ["enable-serde"] } -cranelift-wasm = { version = "0.52.0", features = ["enable-serde"] } -target-lexicon = "0.9.0" +cranelift-codegen = { version = "0.53", features = ["enable-serde"] } +cranelift-entity = { version = "0.53", features = ["enable-serde"] } +cranelift-wasm = { version = "0.53", features = ["enable-serde"] } +target-lexicon = "0.10.0" log = { version = "0.4.8", default-features = false } wig = { path = "../wasi-common/wig", version = "0.9.2" } diff --git a/crates/wast/Cargo.toml b/crates/wast/Cargo.toml index f3baca6e2e..3213febf42 100644 --- a/crates/wast/Cargo.toml +++ b/crates/wast/Cargo.toml @@ -13,7 +13,7 @@ edition = "2018" [dependencies] anyhow = "1.0.19" wasmtime = { path = "../api", version = "0.9.0" } -wast = "5.0.1" +wast = "6.0.0" [badges] maintenance = { status = "actively-developed" } diff --git a/crates/wast/src/wast.rs b/crates/wast/src/wast.rs index 480e64fce5..2564bac34e 100644 --- a/crates/wast/src/wast.rs +++ b/crates/wast/src/wast.rs @@ -191,10 +191,10 @@ impl WastContext { Ok(Outcome::Ok(vec![global.get()])) } - fn assert_return(&self, result: Outcome, results: &[Val]) -> Result<()> { + fn assert_return(&self, result: Outcome, results: &[wast::AssertExpression]) -> Result<()> { let values = result.into_result()?; for (v, e) in values.iter().zip(results) { - if values_equal(v, e)? { + if val_matches(v, e)? { continue; } bail!("expected {:?}, got {:?}", e, v) @@ -263,10 +263,6 @@ impl WastContext { exec, results, } => { - let results = results - .iter() - .map(runtime_value) - .collect::>>()?; let result = self.perform_execute(exec)?; self.assert_return(result, &results)?; } @@ -286,92 +282,6 @@ impl WastContext { let result = self.perform_invoke(call)?; self.assert_trap(result, message)?; } - AssertReturnCanonicalNan { span: _, invoke } => { - for v in self.perform_invoke(invoke)?.into_result()? { - match v { - Val::F32(x) => { - if !is_canonical_f32_nan(x) { - bail!("expected canonical NaN"); - } - } - Val::F64(x) => { - if !is_canonical_f64_nan(x) { - bail!("expected canonical NaN"); - } - } - other => bail!("expected float, got {:?}", other), - }; - } - } - AssertReturnCanonicalNanF32x4 { span: _, invoke } => { - for v in self.perform_invoke(invoke)?.into_result()? { - let val = match v { - Val::V128(x) => x, - other => bail!("expected v128, got {:?}", other), - }; - for l in 0..4 { - if !is_canonical_f32_nan(extract_lane_as_u32(val, l)?) { - bail!("expected f32x4 canonical NaN in lane {}", l) - } - } - } - } - AssertReturnCanonicalNanF64x2 { span: _, invoke } => { - for v in self.perform_invoke(invoke)?.into_result()? { - let val = match v { - Val::V128(x) => x, - other => bail!("expected v128, got {:?}", other), - }; - for l in 0..4 { - if !is_canonical_f64_nan(extract_lane_as_u64(val, l)?) { - bail!("expected f64x2 canonical NaN in lane {}", l) - } - } - } - } - AssertReturnArithmeticNan { span: _, invoke } => { - for v in self.perform_invoke(invoke)?.into_result()? { - match v { - Val::F32(x) => { - if !is_arithmetic_f32_nan(x) { - bail!("expected arithmetic NaN"); - } - } - Val::F64(x) => { - if !is_arithmetic_f64_nan(x) { - bail!("expected arithmetic NaN"); - } - } - other => bail!("expected float, got {:?}", other), - } - } - } - AssertReturnArithmeticNanF32x4 { span: _, invoke } => { - for v in self.perform_invoke(invoke)?.into_result()? { - let val = match v { - Val::V128(x) => x, - other => bail!("expected v128, got {:?}", other), - }; - for l in 0..4 { - if !is_arithmetic_f32_nan(extract_lane_as_u32(val, l)?) { - bail!("expected f32x4 arithmetic NaN in lane {}", l) - } - } - } - } - AssertReturnArithmeticNanF64x2 { span: _, invoke } => { - for v in self.perform_invoke(invoke)?.into_result()? { - let val = match v { - Val::V128(x) => x, - other => bail!("expected v128, got {:?}", other), - }; - for l in 0..4 { - if !is_arithmetic_f64_nan(extract_lane_as_u64(val, l)?) { - bail!("expected f64x2 arithmetic NaN in lane {}", l) - } - } - } - } AssertInvalid { span: _, mut module, @@ -449,12 +359,20 @@ impl WastContext { } } -fn extract_lane_as_u32(bytes: u128, lane: usize) -> Result { - Ok((bytes >> (lane * 32)) as u32) +fn extract_lane_as_i8(bytes: u128, lane: usize) -> i8 { + (bytes >> (lane * 8)) as i8 } -fn extract_lane_as_u64(bytes: u128, lane: usize) -> Result { - Ok((bytes >> (lane * 64)) as u64) +fn extract_lane_as_i16(bytes: u128, lane: usize) -> i16 { + (bytes >> (lane * 16)) as i16 +} + +fn extract_lane_as_i32(bytes: u128, lane: usize) -> i32 { + (bytes >> (lane * 32)) as i32 +} + +fn extract_lane_as_i64(bytes: u128, lane: usize) -> i64 { + (bytes >> (lane * 64)) as i64 } fn is_canonical_f32_nan(bits: u32) -> bool { @@ -475,15 +393,64 @@ fn is_arithmetic_f64_nan(bits: u64) -> bool { (bits & AF64_NAN) == AF64_NAN } -fn values_equal(v1: &Val, v2: &Val) -> Result { - Ok(match (v1, v2) { - (Val::I32(a), Val::I32(b)) => a == b, - (Val::I64(a), Val::I64(b)) => a == b, +fn val_matches(actual: &Val, expected: &wast::AssertExpression) -> Result { + Ok(match (actual, expected) { + (Val::I32(a), wast::AssertExpression::I32(b)) => a == b, + (Val::I64(a), wast::AssertExpression::I64(b)) => a == b, // Note that these float comparisons are comparing bits, not float // values, so we're testing for bit-for-bit equivalence - (Val::F32(a), Val::F32(b)) => a == b, - (Val::F64(a), Val::F64(b)) => a == b, - (Val::V128(a), Val::V128(b)) => a == b, - _ => bail!("don't know how to compare {:?} and {:?} yet", v1, v2), + (Val::F32(a), wast::AssertExpression::F32(b)) => f32_matches(*a, b), + (Val::F64(a), wast::AssertExpression::F64(b)) => f64_matches(*a, b), + (Val::V128(a), wast::AssertExpression::V128(b)) => v128_matches(*a, b), + _ => bail!( + "don't know how to compare {:?} and {:?} yet", + actual, + expected + ), }) } + +fn f32_matches(actual: u32, expected: &wast::NanPattern) -> bool { + match expected { + wast::NanPattern::CanonicalNan => is_canonical_f32_nan(actual), + wast::NanPattern::ArithmeticNan => is_arithmetic_f32_nan(actual), + wast::NanPattern::Value(expected_value) => actual == expected_value.bits, + } +} + +fn f64_matches(actual: u64, expected: &wast::NanPattern) -> bool { + match expected { + wast::NanPattern::CanonicalNan => is_canonical_f64_nan(actual), + wast::NanPattern::ArithmeticNan => is_arithmetic_f64_nan(actual), + wast::NanPattern::Value(expected_value) => actual == expected_value.bits, + } +} + +fn v128_matches(actual: u128, expected: &wast::V128Pattern) -> bool { + match expected { + wast::V128Pattern::I8x16(b) => b + .iter() + .enumerate() + .all(|(i, b)| *b == extract_lane_as_i8(actual, i)), + wast::V128Pattern::I16x8(b) => b + .iter() + .enumerate() + .all(|(i, b)| *b == extract_lane_as_i16(actual, i)), + wast::V128Pattern::I32x4(b) => b + .iter() + .enumerate() + .all(|(i, b)| *b == extract_lane_as_i32(actual, i)), + wast::V128Pattern::I64x2(b) => b + .iter() + .enumerate() + .all(|(i, b)| *b == extract_lane_as_i64(actual, i)), + wast::V128Pattern::F32x4(b) => b.iter().enumerate().all(|(i, b)| { + let a = extract_lane_as_i32(actual, i) as u32; + f32_matches(a, b) + }), + wast::V128Pattern::F64x2(b) => b.iter().enumerate().all(|(i, b)| { + let a = extract_lane_as_i64(actual, i) as u64; + f64_matches(a, b) + }), + } +} diff --git a/scripts/cranelift-version.sh b/scripts/cranelift-version.sh index db34f24b8b..7af91d26cd 100755 --- a/scripts/cranelift-version.sh +++ b/scripts/cranelift-version.sh @@ -9,16 +9,16 @@ topdir=$(dirname "$0")/.. cd "$topdir" # All the cranelift-* crates have the same version number -version="0.49" +version="0.53" # Update all of the Cargo.toml files. echo "Updating crate versions to $version" -for crate in . crates/* crates/misc/* fuzz; do +for toml in Cargo.toml crates/*/Cargo.toml crates/misc/*/Cargo.toml fuzz/Cargo.toml; do # Update the version number of this crate to $version. sed -i.bk -e "/^cranelift-/s/\"[^\"]*\"/\"$version\"/" \ - "$crate/Cargo.toml" + "$toml" # Update the required version number of any cranelift* dependencies. sed -i.bk -e "/^cranelift-/s/version = \"[^\"]*\"/version = \"$version\"/" \ - "$crate/Cargo.toml" + "$toml" done diff --git a/tests/spec_testsuite b/tests/spec_testsuite index ab59e3a7cb..c70c3c8b13 160000 --- a/tests/spec_testsuite +++ b/tests/spec_testsuite @@ -1 +1 @@ -Subproject commit ab59e3a7cb039f9a50d4e24da7634dd4dd472ce3 +Subproject commit c70c3c8b136e5e7193135d40ec3960f4ef1cb20a From a45b037bfceffce45e290691b22315bd7f6b1f37 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 10 Jan 2020 16:27:52 -0600 Subject: [PATCH 24/28] Move around some panics in `wasmtime` (#804) In preparation for eventual support for wasm interface types this commit moves around a few panics internally inside of conversions between the `wasmtime` crate and the underlying jit support crates. This should have any immediately-visible user changes, but the goal is that this'll help support interface types which means `wasmtime` will have types that are not supported by wasmtime itself and we'll be able to more gracefully support that with error messages instead of accidental panics. --- crates/api/src/externals.rs | 11 ++- crates/api/src/instance.rs | 9 ++- crates/api/src/trampoline/func.rs | 7 +- crates/api/src/trampoline/global.rs | 7 +- crates/api/src/trampoline/table.rs | 7 +- crates/api/src/types.rs | 115 ++++++++++++++++------------ 6 files changed, 99 insertions(+), 57 deletions(-) diff --git a/crates/api/src/externals.rs b/crates/api/src/externals.rs index 98afc5a691..0062b60b1d 100644 --- a/crates/api/src/externals.rs +++ b/crates/api/src/externals.rs @@ -163,8 +163,12 @@ impl Func { store: &Store, instance_handle: InstanceHandle, ) -> Self { + // This is only called with `Export::Function`, and since it's coming + // from wasmtime_runtime itself we should support all the types coming + // out of it, so assert such here. let ty = if let wasmtime_runtime::Export::Function { signature, .. } = &export { FuncType::from_wasmtime_signature(signature.clone()) + .expect("core wasm signature should be supported") } else { panic!("expected function export") }; @@ -258,9 +262,12 @@ impl Global { let global = if let wasmtime_runtime::Export::Global { ref global, .. } = export { global } else { - panic!("wasmtime export is not memory") + panic!("wasmtime export is not global") }; - let ty = GlobalType::from_wasmtime_global(&global); + // The original export is coming from wasmtime_runtime itself we should + // support all the types coming out of it, so assert such here. + let ty = GlobalType::from_wasmtime_global(&global) + .expect("core wasm global type should be supported"); Global { inner: Rc::new(GlobalInner { _store: store.clone(), diff --git a/crates/api/src/instance.rs b/crates/api/src/instance.rs index 49a51ba588..145e25f2c2 100644 --- a/crates/api/src/instance.rs +++ b/crates/api/src/instance.rs @@ -132,7 +132,14 @@ impl Instance { // imported into this store using the from_handle() method. let _ = store.register_wasmtime_signature(signature); } - let extern_type = ExternType::from_wasmtime_export(&export); + + // We should support everything supported by wasmtime_runtime, or + // otherwise we've got a bug in this crate, so panic if anything + // fails to convert here. + let extern_type = match ExternType::from_wasmtime_export(&export) { + Some(ty) => ty, + None => panic!("unsupported core wasm external type {:?}", export), + }; exports_types.push(ExportType::new(name, extern_type)); exports.push(Extern::from_wasmtime_export( store, diff --git a/crates/api/src/trampoline/func.rs b/crates/api/src/trampoline/func.rs index 8ace580382..328a325490 100644 --- a/crates/api/src/trampoline/func.rs +++ b/crates/api/src/trampoline/func.rs @@ -3,7 +3,7 @@ use super::create_handle::create_handle; use super::trap::{record_api_trap, TrapSink, API_TRAP_CODE}; use crate::{Callable, FuncType, Store, Val}; -use anyhow::Result; +use anyhow::{bail, Result}; use std::cmp; use std::convert::TryFrom; use std::rc::Rc; @@ -234,7 +234,10 @@ pub fn create_handle_with_function( func: &Rc, store: &Store, ) -> Result { - let sig = ft.get_wasmtime_signature().clone(); + let sig = match ft.get_wasmtime_signature() { + Some(sig) => sig.clone(), + None => bail!("not a supported core wasm signature {:?}", ft), + }; let isa = { let isa_builder = native::builder(); diff --git a/crates/api/src/trampoline/global.rs b/crates/api/src/trampoline/global.rs index f1b610559d..f53701f167 100644 --- a/crates/api/src/trampoline/global.rs +++ b/crates/api/src/trampoline/global.rs @@ -1,6 +1,6 @@ use super::create_handle::create_handle; use crate::{GlobalType, Mutability, Val}; -use anyhow::Result; +use anyhow::{bail, Result}; use wasmtime_environ::entity::PrimaryMap; use wasmtime_environ::{wasm, Module}; use wasmtime_runtime::{InstanceHandle, VMGlobalDefinition}; @@ -24,7 +24,10 @@ pub fn create_global(gt: &GlobalType, val: Val) -> Result<(wasmtime_runtime::Exp } let global = wasm::Global { - ty: gt.content().get_wasmtime_type(), + ty: match gt.content().get_wasmtime_type() { + Some(t) => t, + None => bail!("cannot support {:?} as a wasm global type", gt.content()), + }, mutability: match gt.mutability() { Mutability::Const => false, Mutability::Var => true, diff --git a/crates/api/src/trampoline/table.rs b/crates/api/src/trampoline/table.rs index 5d2441bf92..713de1b43a 100644 --- a/crates/api/src/trampoline/table.rs +++ b/crates/api/src/trampoline/table.rs @@ -1,6 +1,6 @@ use super::create_handle::create_handle; use crate::{TableType, ValType}; -use anyhow::Result; +use anyhow::{bail, Result}; use wasmtime_environ::entity::PrimaryMap; use wasmtime_environ::{wasm, Module}; use wasmtime_runtime::InstanceHandle; @@ -13,7 +13,10 @@ pub fn create_handle_with_table(table: &TableType) -> Result { maximum: table.limits().max(), ty: match table.element() { ValType::FuncRef => wasm::TableElementType::Func, - _ => wasm::TableElementType::Val(table.element().get_wasmtime_type()), + _ => match table.element().get_wasmtime_type() { + Some(t) => wasm::TableElementType::Val(t), + None => bail!("cannot support {:?} as a table element", table.element()), + }, }, }; let tunable = Default::default(); diff --git a/crates/api/src/types.rs b/crates/api/src/types.rs index 36fde8ff20..5162c49c54 100644 --- a/crates/api/src/types.rs +++ b/crates/api/src/types.rs @@ -84,25 +84,25 @@ impl ValType { } } - pub(crate) fn get_wasmtime_type(&self) -> ir::Type { + pub(crate) fn get_wasmtime_type(&self) -> Option { match self { - ValType::I32 => ir::types::I32, - ValType::I64 => ir::types::I64, - ValType::F32 => ir::types::F32, - ValType::F64 => ir::types::F64, - ValType::V128 => ir::types::I8X16, - _ => unimplemented!("get_wasmtime_type other"), + ValType::I32 => Some(ir::types::I32), + ValType::I64 => Some(ir::types::I64), + ValType::F32 => Some(ir::types::F32), + ValType::F64 => Some(ir::types::F64), + ValType::V128 => Some(ir::types::I8X16), + _ => None, } } - pub(crate) fn from_wasmtime_type(ty: ir::Type) -> ValType { + pub(crate) fn from_wasmtime_type(ty: ir::Type) -> Option { match ty { - ir::types::I32 => ValType::I32, - ir::types::I64 => ValType::I64, - ir::types::F32 => ValType::F32, - ir::types::F64 => ValType::F64, - ir::types::I8X16 => ValType::V128, - _ => unimplemented!("from_wasmtime_type other"), + ir::types::I32 => Some(ValType::I32), + ir::types::I64 => Some(ValType::I64), + ir::types::F32 => Some(ValType::F32), + ir::types::F64 => Some(ValType::F64), + ir::types::I8X16 => Some(ValType::V128), + _ => None, } } } @@ -153,26 +153,29 @@ impl ExternType { (Table(TableType) table unwrap_table) (Memory(MemoryType) memory unwrap_memory) } - pub(crate) fn from_wasmtime_export(export: &wasmtime_runtime::Export) -> Self { - match export { + + /// Returns `None` if the sub-type fails to get converted, see documentation + /// for sub-types about what may fail. + pub(crate) fn from_wasmtime_export(export: &wasmtime_runtime::Export) -> Option { + Some(match export { wasmtime_runtime::Export::Function { signature, .. } => { - ExternType::Func(FuncType::from_wasmtime_signature(signature.clone())) + ExternType::Func(FuncType::from_wasmtime_signature(signature.clone())?) } wasmtime_runtime::Export::Memory { memory, .. } => { ExternType::Memory(MemoryType::from_wasmtime_memory(&memory.memory)) } wasmtime_runtime::Export::Global { global, .. } => { - ExternType::Global(GlobalType::from_wasmtime_global(&global)) + ExternType::Global(GlobalType::from_wasmtime_global(&global)?) } wasmtime_runtime::Export::Table { table, .. } => { ExternType::Table(TableType::from_wasmtime_table(&table.table)) } - } + }) } } // Function Types -fn from_wasmtime_abiparam(param: &ir::AbiParam) -> ValType { +fn from_wasmtime_abiparam(param: &ir::AbiParam) -> Option { assert_eq!(param.purpose, ir::ArgumentPurpose::Normal); ValType::from_wasmtime_type(param.value_type) } @@ -184,7 +187,12 @@ fn from_wasmtime_abiparam(param: &ir::AbiParam) -> ValType { pub struct FuncType { params: Box<[ValType]>, results: Box<[ValType]>, - signature: ir::Signature, + // `None` if params/results aren't wasm-compatible (e.g. use wasm interface + // types), or if they're not implemented (like anyref at the time of this + // writing) + // + // `Some` if they're all wasm-compatible. + signature: Option, } impl FuncType { @@ -196,23 +204,26 @@ impl FuncType { use wasmtime_environ::ir::{types, AbiParam, ArgumentPurpose, Signature}; use wasmtime_jit::native; let call_conv = native::call_conv(); - let signature: Signature = { - let mut params = params - .iter() - .map(|p| AbiParam::new(p.get_wasmtime_type())) - .collect::>(); - let returns = results - .iter() - .map(|p| AbiParam::new(p.get_wasmtime_type())) - .collect::>(); - params.insert(0, AbiParam::special(types::I64, ArgumentPurpose::VMContext)); + let signature = params + .iter() + .map(|p| p.get_wasmtime_type().map(AbiParam::new)) + .collect::>>() + .and_then(|params| { + results + .iter() + .map(|p| p.get_wasmtime_type().map(AbiParam::new)) + .collect::>>() + .map(|results| (params, results)) + }) + .map(|(mut params, returns)| { + params.insert(0, AbiParam::special(types::I64, ArgumentPurpose::VMContext)); - Signature { - params, - returns, - call_conv, - } - }; + Signature { + params, + returns, + call_conv, + } + }); FuncType { params, results, @@ -230,27 +241,33 @@ impl FuncType { &self.results } - pub(crate) fn get_wasmtime_signature(&self) -> &ir::Signature { - &self.signature + /// Returns `Some` if this function signature was compatible with cranelift, + /// or `None` if one of the types/results wasn't supported or compatible + /// with cranelift. + pub(crate) fn get_wasmtime_signature(&self) -> Option<&ir::Signature> { + self.signature.as_ref() } - pub(crate) fn from_wasmtime_signature(signature: ir::Signature) -> FuncType { + /// Returns `None` if any types in the signature can't be converted to the + /// types in this crate, but that should very rarely happen and largely only + /// indicate a bug in our cranelift integration. + pub(crate) fn from_wasmtime_signature(signature: ir::Signature) -> Option { let params = signature .params .iter() .filter(|p| p.purpose == ir::ArgumentPurpose::Normal) .map(|p| from_wasmtime_abiparam(p)) - .collect::>(); + .collect::>>()?; let results = signature .returns .iter() .map(|p| from_wasmtime_abiparam(p)) - .collect::>(); - FuncType { + .collect::>>()?; + Some(FuncType { params: params.into_boxed_slice(), results: results.into_boxed_slice(), - signature, - } + signature: Some(signature), + }) } } @@ -287,14 +304,16 @@ impl GlobalType { self.mutability } - pub(crate) fn from_wasmtime_global(global: &wasm::Global) -> GlobalType { - let ty = ValType::from_wasmtime_type(global.ty); + /// Returns `None` if the wasmtime global has a type that we can't + /// represent, but that should only very rarely happen and indicate a bug. + pub(crate) fn from_wasmtime_global(global: &wasm::Global) -> Option { + let ty = ValType::from_wasmtime_type(global.ty)?; let mutability = if global.mutability { Mutability::Var } else { Mutability::Const }; - GlobalType::new(ty, mutability) + Some(GlobalType::new(ty, mutability)) } } From ad2e94fce3b884527465be2988843a7d381cb357 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 10 Jan 2020 16:40:28 -0600 Subject: [PATCH 25/28] Don't use webidl bindings in custom tests (#801) It's not necessary and we can go straight to the general `wasmtime` crate APIs instead. --- tests/custom_signal_handler.rs | 46 ++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/tests/custom_signal_handler.rs b/tests/custom_signal_handler.rs index 66a449fb22..8f0e1c83e4 100644 --- a/tests/custom_signal_handler.rs +++ b/tests/custom_signal_handler.rs @@ -1,9 +1,9 @@ #[cfg(not(target_os = "windows"))] mod tests { + use anyhow::Result; use std::rc::Rc; use std::sync::atomic::{AtomicBool, Ordering}; use wasmtime::*; - use wasmtime_interface_types::{ModuleData, Value}; const WAT1: &str = r#" (module @@ -36,12 +36,14 @@ mod tests { ) "#; - fn invoke_export( - instance: &Instance, - data: &[u8], - func_name: &str, - ) -> Result, anyhow::Error> { - ModuleData::new(&data)?.invoke_export(instance, func_name, &[]) + fn invoke_export(instance: &Instance, func_name: &str) -> Result, Trap> { + let ret = instance + .find_export_by_name(func_name) + .unwrap() + .func() + .unwrap() + .call(&[])?; + Ok(ret) } // Locate "memory" export, get base address and size and set memory protection to PROT_NONE @@ -101,7 +103,7 @@ mod tests { } #[test] - fn test_custom_signal_handler_single_instance() -> anyhow::Result<()> { + fn test_custom_signal_handler_single_instance() -> Result<()> { let engine = Engine::new(&Config::default()); let store = Store::new(&engine); let data = wat::parse_str(WAT1)?; @@ -119,16 +121,16 @@ mod tests { // these invoke wasmtime_call_trampoline from action.rs { println!("calling read..."); - let result = invoke_export(&instance, &data, "read").expect("read succeeded"); - assert_eq!("123", result[0].clone().to_string()); + let result = invoke_export(&instance, "read").expect("read succeeded"); + assert_eq!(123, result[0].unwrap_i32()); } { println!("calling read_out_of_bounds..."); - let trap = invoke_export(&instance, &data, "read_out_of_bounds").unwrap_err(); - assert!(trap.root_cause().to_string().starts_with( - "trapped: Trap { message: \"call error: wasm trap: out of bounds memory access" - )); + let trap = invoke_export(&instance, "read_out_of_bounds").unwrap_err(); + assert!(trap + .message() + .starts_with("call error: wasm trap: out of bounds memory access")); } // these invoke wasmtime_call_trampoline from callable.rs @@ -155,7 +157,7 @@ mod tests { } #[test] - fn test_custom_signal_handler_multiple_instances() -> anyhow::Result<()> { + fn test_custom_signal_handler_multiple_instances() -> Result<()> { let engine = Engine::new(&Config::default()); let store = Store::new(&engine); let data = wat::parse_str(WAT1)?; @@ -225,8 +227,8 @@ mod tests { assert!(!exports1.is_empty()); println!("calling instance1.read..."); - let result = invoke_export(&instance1, &data, "read").expect("read succeeded"); - assert_eq!("123", result[0].clone().to_string()); + let result = invoke_export(&instance1, "read").expect("read succeeded"); + assert_eq!(123, result[0].unwrap_i32()); assert_eq!( instance1_handler_triggered.load(Ordering::SeqCst), true, @@ -240,8 +242,8 @@ mod tests { assert!(!exports2.is_empty()); println!("calling instance2.read..."); - let result = invoke_export(&instance2, &data, "read").expect("read succeeded"); - assert_eq!("123", result[0].clone().to_string()); + let result = invoke_export(&instance2, "read").expect("read succeeded"); + assert_eq!(123, result[0].unwrap_i32()); assert_eq!( instance2_handler_triggered.load(Ordering::SeqCst), true, @@ -252,7 +254,7 @@ mod tests { } #[test] - fn test_custom_signal_handler_instance_calling_another_instance() -> anyhow::Result<()> { + fn test_custom_signal_handler_instance_calling_another_instance() -> Result<()> { let engine = Engine::new(&Config::default()); let store = Store::new(&engine); @@ -281,8 +283,8 @@ mod tests { }); println!("calling instance2.run"); - let result = invoke_export(&instance2, &data2, "run")?; - assert_eq!("123", result[0].clone().to_string()); + let result = invoke_export(&instance2, "run")?; + assert_eq!(123, result[0].unwrap_i32()); Ok(()) } } From f592811c9aac88e589eab207a6c63719423ffe01 Mon Sep 17 00:00:00 2001 From: Andrew Brown Date: Fri, 10 Jan 2020 17:02:42 -0800 Subject: [PATCH 26/28] Update cranelifte and enable more SIMD spec tests (#806) * Update cranelift to 0.54 * Enable entire SIMD spec test directory and skip failing tests --- Cargo.lock | 32 +++++++++++++++---------------- build.rs | 38 +++++++++++++++---------------------- crates/environ/Cargo.toml | 8 ++++---- crates/jit/Cargo.toml | 10 +++++----- crates/lightbeam/Cargo.toml | 2 +- crates/wasi-c/Cargo.toml | 6 +++--- crates/wasi/Cargo.toml | 6 +++--- 7 files changed, 47 insertions(+), 55 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 01553a79ad..d8b036cd0f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -341,18 +341,18 @@ dependencies = [ [[package]] name = "cranelift-bforest" -version = "0.53.0" +version = "0.54.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b065d5992ea22903200c56dd2b3a7062a1311b49739ffd2be9215f882204f73" +checksum = "bd3225fff1be118941c5fb66f1fb1f7f3e86468fac0e7364713c4fb99b72632b" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-codegen" -version = "0.53.0" +version = "0.54.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ae646133a3dda0af636eb4e2928d282a976c836392e0de57a5750ca9eb132e1" +checksum = "f3e3e6679892029f76a99b9059d2b74e77ac03637d573bb014bc21579ec1b7da" dependencies = [ "byteorder", "cranelift-bforest", @@ -368,9 +368,9 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.53.0" +version = "0.54.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "883a636641a34034d16d1986557fdf815245140c4bb9e6561a6cb8ebacd7b9d4" +checksum = "3cabe691548e28ca82ebd218f2fe76eec4c5629b64ef3db8b58443b7d9047275" dependencies = [ "cranelift-codegen-shared", "cranelift-entity", @@ -378,24 +378,24 @@ dependencies = [ [[package]] name = "cranelift-codegen-shared" -version = "0.53.0" +version = "0.54.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3467bb48aa1b6a4c0da0fa0b5fea7f78f96bbf4bbf054eeb053b5e2e8794387" +checksum = "d173252ffade4aa6e929090977b9a4cd5ac28e15a42626f878be3844b3000ad9" [[package]] name = "cranelift-entity" -version = "0.53.0" +version = "0.54.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03578fa46b2009c4575494b0ecf8319a79bc913a6c1be3a2cb55ee7089c59989" +checksum = "3498ad9ba021715716a1c52e2b31d7829a149913fb0d88493e4b07d3b772b656" dependencies = [ "serde", ] [[package]] name = "cranelift-frontend" -version = "0.53.0" +version = "0.54.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54859b486e505c03d5d8982216509eb99782ef5a3f7f8cbe86cd73967975c49b" +checksum = "521a30773b8de74345c807a38853f055aca8fecaa39a0fc7698bfebc5a3da515" dependencies = [ "cranelift-codegen", "log", @@ -405,9 +405,9 @@ dependencies = [ [[package]] name = "cranelift-native" -version = "0.53.0" +version = "0.54.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b245d7376b7200a5dcce955761f4f7396019beda4a788d9cbe555308f1869cd2" +checksum = "624e755cbe984e437308968239736e7f9aa3193e99928fb76eec7a1946627b34" dependencies = [ "cranelift-codegen", "raw-cpuid", @@ -416,9 +416,9 @@ dependencies = [ [[package]] name = "cranelift-wasm" -version = "0.53.0" +version = "0.54.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "115e207912c5841c3932b366be979b34a62ee32c839c2ddbc1c81877cd8ec03c" +checksum = "0320733e518ab9e0e2d1a22034d40e2851fb403ed14db5220cf9b86576b9cfd4" dependencies = [ "cranelift-codegen", "cranelift-entity", diff --git a/build.rs b/build.rs index 3e5598926e..ea89c70031 100644 --- a/build.rs +++ b/build.rs @@ -30,28 +30,8 @@ fn main() -> anyhow::Result<()> { // Skip running spec_testsuite tests if the submodule isn't checked // out. if spec_tests > 0 { - start_test_module(&mut out, "simd")?; - write_testsuite_tests( - &mut out, - "tests/spec_testsuite/proposals/simd/simd_address.wast", - "simd", - strategy, - )?; - write_testsuite_tests( - &mut out, - "tests/spec_testsuite/proposals/simd/simd_align.wast", - "simd", - strategy, - )?; - // FIXME this uses some features from the reference types proposal - // (multi-table) which aren't fully implemented yet - // write_testsuite_tests( - // &mut out, - // "tests/spec_testsuite/proposals/simd/simd_const.wast", - // "simd", - // strategy, - // )?; - finish_test_module(&mut out)?; + test_directory(&mut out, "tests/spec_testsuite/proposals/simd", strategy) + .expect("generating tests"); test_directory( &mut out, @@ -167,10 +147,22 @@ fn ignore(testsuite: &str, testname: &str, strategy: &str) -> bool { (_, _) if testname.starts_with("simd") => return true, (_, _) if testsuite.ends_with("multi_value") => return true, // Lightbeam doesn't support float arguments on the stack. - ("spec_testsuite", "call.wast") => return true, + ("spec_testsuite", "call") => return true, _ => (), }, "Cranelift" => match (testsuite, testname) { + ("simd", "simd_bit_shift") => return true, // FIXME Unsupported feature: proposed SIMD operator I8x16Shl + ("simd", "simd_const") => return true, // FIXME Invalid input WebAssembly code at offset 474: Unexpected data at the end of the section + ("simd", "simd_conversions") => return true, // FIXME Unsupported feature: proposed SIMD operator I16x8NarrowI32x4S + ("simd", "simd_f32x4") => return true, // FIXME expected V128(F32x4([CanonicalNan, CanonicalNan, Value(Float32 { bits: 0 }), Value(Float32 { bits: 0 })])), got V128(18428729675200069632) + ("simd", "simd_f64x2") => return true, // FIXME expected V128(F64x2([Value(Float64 { bits: 9221120237041090560 }), Value(Float64 { bits: 0 })])), got V128(0) + ("simd", "simd_f64x2_arith") => return true, // FIXME expected V128(F64x2([Value(Float64 { bits: 9221120237041090560 }), Value(Float64 { bits: 13835058055282163712 })])), got V128(255211775190703847615975447847722024960) + ("simd", "simd_i64x2_arith") => return true, // FIXME Unsupported feature: proposed SIMD operator I64x2Mul + ("simd", "simd_lane") => return true, // FIXME invalid u8 number: constant out of range: (v8x16.shuffle -1 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14... + ("simd", "simd_load") => return true, // FIXME Unsupported feature: proposed SIMD operator I8x16Shl + ("simd", "simd_load_extend") => return true, // FIXME Unsupported feature: proposed SIMD operator I16x8Load8x8S { memarg: MemoryImmediate { flags: 0, offset: 0 } } + ("simd", "simd_load_splat") => return true, // FIXME Unsupported feature: proposed SIMD operator V8x16LoadSplat { memarg: MemoryImmediate { flags: 0, offset: 0 } } + ("simd", "simd_splat") => return true, // FIXME Unsupported feature: proposed SIMD operator I8x16ShrS _ => {} }, _ => panic!("unrecognized strategy"), diff --git a/crates/environ/Cargo.toml b/crates/environ/Cargo.toml index 596a413db1..0f3d3e52ac 100644 --- a/crates/environ/Cargo.toml +++ b/crates/environ/Cargo.toml @@ -13,9 +13,9 @@ edition = "2018" [dependencies] anyhow = "1.0" -cranelift-codegen = { version = "0.53", features = ["enable-serde"] } -cranelift-entity = { version = "0.53", features = ["enable-serde"] } -cranelift-wasm = { version = "0.53", features = ["enable-serde"] } +cranelift-codegen = { version = "0.54", features = ["enable-serde"] } +cranelift-entity = { version = "0.54", features = ["enable-serde"] } +cranelift-wasm = { version = "0.54", features = ["enable-serde"] } wasmparser = "0.47.0" lightbeam = { path = "../lightbeam", optional = true, version = "0.9.0" } indexmap = "1.0.2" @@ -46,7 +46,7 @@ tempfile = "3" target-lexicon = { version = "0.10.0", default-features = false } pretty_env_logger = "0.3.0" rand = { version = "0.7.0", default-features = false, features = ["small_rng"] } -cranelift-codegen = { version = "0.53", features = ["enable-serde", "all-arch"] } +cranelift-codegen = { version = "0.54", features = ["enable-serde", "all-arch"] } filetime = "0.2.7" [badges] diff --git a/crates/jit/Cargo.toml b/crates/jit/Cargo.toml index 950c714988..368b9eb4ad 100644 --- a/crates/jit/Cargo.toml +++ b/crates/jit/Cargo.toml @@ -11,11 +11,11 @@ readme = "README.md" edition = "2018" [dependencies] -cranelift-codegen = { version = "0.53", features = ["enable-serde"] } -cranelift-entity = { version = "0.53", features = ["enable-serde"] } -cranelift-wasm = { version = "0.53", features = ["enable-serde"] } -cranelift-native = "0.53" -cranelift-frontend = "0.53" +cranelift-codegen = { version = "0.54", features = ["enable-serde"] } +cranelift-entity = { version = "0.54", features = ["enable-serde"] } +cranelift-wasm = { version = "0.54", features = ["enable-serde"] } +cranelift-native = "0.54" +cranelift-frontend = "0.54" wasmtime-environ = { path = "../environ", version = "0.9.0" } wasmtime-runtime = { path = "../runtime", version = "0.9.0" } wasmtime-debug = { path = "../debug", version = "0.9.0" } diff --git a/crates/lightbeam/Cargo.toml b/crates/lightbeam/Cargo.toml index 51fb19ed5c..225a73c311 100644 --- a/crates/lightbeam/Cargo.toml +++ b/crates/lightbeam/Cargo.toml @@ -19,7 +19,7 @@ memoffset = "0.5.3" itertools = "0.8.2" capstone = "0.6.0" thiserror = "1.0.9" -cranelift-codegen = "0.53" +cranelift-codegen = "0.54" multi_mut = "0.1" either = "1.5" typemap = "0.3" diff --git a/crates/wasi-c/Cargo.toml b/crates/wasi-c/Cargo.toml index 560edb2a23..d169491a89 100644 --- a/crates/wasi-c/Cargo.toml +++ b/crates/wasi-c/Cargo.toml @@ -14,9 +14,9 @@ edition = "2018" wasmtime-runtime = { path = "../runtime", version = "0.9.0" } wasmtime-environ = { path = "../environ", version = "0.9.0" } wasmtime-jit = { path = "../jit", version = "0.9.0" } -cranelift-codegen = { version = "0.53", features = ["enable-serde"] } -cranelift-entity = { version = "0.53", features = ["enable-serde"] } -cranelift-wasm = { version = "0.53", features = ["enable-serde"] } +cranelift-codegen = { version = "0.54", features = ["enable-serde"] } +cranelift-entity = { version = "0.54", features = ["enable-serde"] } +cranelift-wasm = { version = "0.54", features = ["enable-serde"] } target-lexicon = "0.10.0" log = { version = "0.4.8", default-features = false } libc = "0.2.60" diff --git a/crates/wasi/Cargo.toml b/crates/wasi/Cargo.toml index c35a3464ff..4aaca18c0b 100644 --- a/crates/wasi/Cargo.toml +++ b/crates/wasi/Cargo.toml @@ -16,9 +16,9 @@ wasmtime-runtime = { path = "../runtime", version = "0.9.0" } wasmtime-environ = { path = "../environ", version = "0.9.0" } wasmtime-jit = { path = "../jit", version = "0.9.0" } wasi-common = { path = "../wasi-common", version = "0.9.0" } -cranelift-codegen = { version = "0.53", features = ["enable-serde"] } -cranelift-entity = { version = "0.53", features = ["enable-serde"] } -cranelift-wasm = { version = "0.53", features = ["enable-serde"] } +cranelift-codegen = { version = "0.54", features = ["enable-serde"] } +cranelift-entity = { version = "0.54", features = ["enable-serde"] } +cranelift-wasm = { version = "0.54", features = ["enable-serde"] } target-lexicon = "0.10.0" log = { version = "0.4.8", default-features = false } wig = { path = "../wasi-common/wig", version = "0.9.2" } From 420dcd76fd0d684291901c7a6afeb481481dea7e Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 13 Jan 2020 17:50:57 -0600 Subject: [PATCH 27/28] Don't require `Store` in `Instance` constructor (#810) * Don't require `Store` in `Instance` constructor This can be inferred from the `Module` argument. Additionally add a `store` accessor to an `Instance` in case it's needed to instantiate another `Module`. cc #708 * Update more constructors * Fix a doctest * Don't ignore store in `wasm_instance_new` * Run rustfmt --- crates/api/examples/gcd.rs | 2 +- crates/api/examples/hello.rs | 3 +-- crates/api/examples/memory.rs | 2 +- crates/api/examples/multi.rs | 4 ++-- crates/api/src/callable.rs | 1 - crates/api/src/instance.rs | 20 ++++++++++++++++--- crates/api/src/runtime.rs | 4 ++++ crates/api/src/wasm.rs | 16 +++++++++++++-- crates/api/tests/import-indexes.rs | 2 +- crates/api/tests/import_calling_export.rs | 2 +- crates/api/tests/traps.rs | 2 +- crates/fuzzing/src/oracles.rs | 4 ++-- crates/misc/py/src/lib.rs | 2 +- crates/misc/rust/macro/src/lib.rs | 2 +- .../test-programs/tests/wasm_tests/runtime.rs | 2 +- crates/test-programs/wasi-tests/Cargo.lock | 2 +- crates/wast/src/wast.rs | 2 +- src/commands/run.rs | 2 +- tests/custom_signal_handler.rs | 10 +++++----- 19 files changed, 56 insertions(+), 28 deletions(-) diff --git a/crates/api/examples/gcd.rs b/crates/api/examples/gcd.rs index c510a176ca..43a29fcf01 100644 --- a/crates/api/examples/gcd.rs +++ b/crates/api/examples/gcd.rs @@ -50,7 +50,7 @@ fn main() -> anyhow::Result<()> { .0; // Instantiate the module. - let instance = Instance::new(&store, &module, &[])?; + let instance = Instance::new(&module, &[])?; // Invoke `gcd` export let gcd = instance.exports()[gcd_index].func().expect("gcd"); diff --git a/crates/api/examples/hello.rs b/crates/api/examples/hello.rs index 8924dfcb7d..c33b2c4495 100644 --- a/crates/api/examples/hello.rs +++ b/crates/api/examples/hello.rs @@ -48,8 +48,7 @@ fn main() -> Result<()> { // Note that this is where the wasm `start` function, if any, would run. println!("Instantiating module..."); let imports = vec![hello_func.into()]; - let instance = - Instance::new(&store, &module, &imports).context("> Error instantiating module!")?; + let instance = Instance::new(&module, &imports).context("> Error instantiating module!")?; // Next we poke around a bit to extract the `run` function from the module. println!("Extracting export..."); diff --git a/crates/api/examples/memory.rs b/crates/api/examples/memory.rs index f9df469669..a167e6f1ac 100644 --- a/crates/api/examples/memory.rs +++ b/crates/api/examples/memory.rs @@ -90,7 +90,7 @@ fn main() -> Result<(), Error> { // Instantiate. println!("Instantiating module..."); - let instance = Instance::new(&store, &module, &[]).context("> Error instantiating module!")?; + let instance = Instance::new(&module, &[]).context("> Error instantiating module!")?; // Extract export. println!("Extracting export..."); diff --git a/crates/api/examples/multi.rs b/crates/api/examples/multi.rs index d3236501cb..830d899138 100644 --- a/crates/api/examples/multi.rs +++ b/crates/api/examples/multi.rs @@ -67,8 +67,8 @@ fn main() -> Result<()> { // Instantiate. println!("Instantiating module..."); let imports = vec![callback_func.into()]; - let instance = Instance::new(&store, &module, imports.as_slice()) - .context("Error instantiating module!")?; + let instance = + Instance::new(&module, imports.as_slice()).context("Error instantiating module!")?; // Extract exports. println!("Extracting export..."); diff --git a/crates/api/src/callable.rs b/crates/api/src/callable.rs index 4aefa8b206..139959f359 100644 --- a/crates/api/src/callable.rs +++ b/crates/api/src/callable.rs @@ -59,7 +59,6 @@ use wasmtime_runtime::Export; /// /// // Create module instance that imports our function /// let instance = wasmtime::Instance::new( -/// &store, /// &module, /// &[times_two_function.into()] /// )?; diff --git a/crates/api/src/instance.rs b/crates/api/src/instance.rs index 145e25f2c2..7d1d8c18e3 100644 --- a/crates/api/src/instance.rs +++ b/crates/api/src/instance.rs @@ -68,7 +68,8 @@ pub struct Instance { } impl Instance { - pub fn new(store: &Store, module: &Module, externs: &[Extern]) -> Result { + pub fn new(module: &Module, externs: &[Extern]) -> Result { + let store = module.store(); let context = store.context().clone(); let exports = store.global_exports().clone(); let (mut instance_handle, contexts) = instantiate_in_context( @@ -100,14 +101,27 @@ impl Instance { }) } - pub fn exports(&self) -> &[Extern] { - &self.exports + /// Returns the associated [`Store`] that this `Instance` is compiled into. + /// + /// This is the [`Store`] that generally serves as a sort of global cache + /// for various instance-related things. + pub fn store(&self) -> &Store { + self.module.store() } + /// Returns the associated [`Module`] that this `Instance` instantiated. + /// + /// The corresponding [`Module`] here is a static version of this `Instance` + /// which can be used to learn information such as naming information about + /// various functions. pub fn module(&self) -> &Module { &self.module } + pub fn exports(&self) -> &[Extern] { + &self.exports + } + pub fn find_export_by_name(&self, name: &str) -> Option<&Extern> { let (i, _) = self .module diff --git a/crates/api/src/runtime.rs b/crates/api/src/runtime.rs index d2a4117950..7476bc44c9 100644 --- a/crates/api/src/runtime.rs +++ b/crates/api/src/runtime.rs @@ -397,6 +397,10 @@ impl Store { .get(&type_index) .cloned() } + + pub(crate) fn ptr_eq(a: &Store, b: &Store) -> bool { + Rc::ptr_eq(&a.inner, &b.inner) + } } impl Default for Store { diff --git a/crates/api/src/wasm.rs b/crates/api/src/wasm.rs index f87ca77b8e..083671406f 100644 --- a/crates/api/src/wasm.rs +++ b/crates/api/src/wasm.rs @@ -686,7 +686,6 @@ pub unsafe extern "C" fn wasm_instance_new( imports: *const *const wasm_extern_t, result: *mut *mut wasm_trap_t, ) -> *mut wasm_instance_t { - let store = &(*store).store.borrow(); let mut externs: Vec = Vec::with_capacity((*module).imports.len()); for i in 0..(*module).imports.len() { let import = *imports.add(i); @@ -697,8 +696,21 @@ pub unsafe extern "C" fn wasm_instance_new( ExternHost::Memory(e) => Extern::Memory(e.borrow().clone()), }); } + let store = &(*store).store.borrow(); let module = &(*module).module.borrow(); - match Instance::new(store, module, &externs) { + // FIXME(WebAssembly/wasm-c-api#126) what else can we do with the `store` + // argument? + if !Store::ptr_eq(&store, module.store()) { + if !result.is_null() { + let trap = Trap::new("wasm_store_t must match store in wasm_module_t"); + let trap = Box::new(wasm_trap_t { + trap: HostRef::new(trap), + }); + (*result) = Box::into_raw(trap); + } + return ptr::null_mut(); + } + match Instance::new(module, &externs) { Ok(instance) => { let instance = Box::new(wasm_instance_t { instance: HostRef::new(instance), diff --git a/crates/api/tests/import-indexes.rs b/crates/api/tests/import-indexes.rs index 18847da8e6..8406a8b63a 100644 --- a/crates/api/tests/import-indexes.rs +++ b/crates/api/tests/import-indexes.rs @@ -55,7 +55,7 @@ fn same_import_names_still_distinct() -> anyhow::Result<()> { ) .into(), ]; - let instance = Instance::new(&store, &module, &imports)?; + let instance = Instance::new(&module, &imports)?; let func = instance.find_export_by_name("foo").unwrap().func().unwrap(); let results = func.call(&[])?; diff --git a/crates/api/tests/import_calling_export.rs b/crates/api/tests/import_calling_export.rs index 71991ae09b..aad031d173 100644 --- a/crates/api/tests/import_calling_export.rs +++ b/crates/api/tests/import_calling_export.rs @@ -47,7 +47,7 @@ fn test_import_calling_export() { let imports = vec![callback_func.into()]; let instance = - Instance::new(&store, &module, imports.as_slice()).expect("failed to instantiate module"); + Instance::new(&module, imports.as_slice()).expect("failed to instantiate module"); let exports = instance.exports(); assert!(!exports.is_empty()); diff --git a/crates/api/tests/traps.rs b/crates/api/tests/traps.rs index 9973236578..aea6404a9b 100644 --- a/crates/api/tests/traps.rs +++ b/crates/api/tests/traps.rs @@ -29,7 +29,7 @@ fn test_trap_return() -> Result<(), String> { let hello_func = Func::new(&store, hello_type, Rc::new(HelloCallback)); let imports = vec![hello_func.into()]; - let instance = Instance::new(&store, &module, &imports) + let instance = Instance::new(&module, &imports) .map_err(|e| format!("failed to instantiate module: {:?}", e))?; let run_func = instance.exports()[0] .func() diff --git a/crates/fuzzing/src/oracles.rs b/crates/fuzzing/src/oracles.rs index 2dab05f457..bb5860c9a1 100644 --- a/crates/fuzzing/src/oracles.rs +++ b/crates/fuzzing/src/oracles.rs @@ -60,7 +60,7 @@ pub fn instantiate(wasm: &[u8], strategy: Strategy) { // aren't caught during validation or compilation. For example, an imported // table might not have room for an element segment that we want to // initialize into it. - let _result = Instance::new(&store, &module, &imports); + let _result = Instance::new(&module, &imports); } /// Compile the Wasm buffer, and implicitly fail if we have an unexpected @@ -152,7 +152,7 @@ pub fn make_api_calls(api: crate::generators::api::ApiCalls) { // aren't caught during validation or compilation. For example, an imported // table might not have room for an element segment that we want to // initialize into it. - if let Ok(instance) = Instance::new(store.as_ref().unwrap(), &module, &imports) { + if let Ok(instance) = Instance::new(&module, &imports) { instances.insert(id, instance); } } diff --git a/crates/misc/py/src/lib.rs b/crates/misc/py/src/lib.rs index 1c7584a40c..61a6132c53 100644 --- a/crates/misc/py/src/lib.rs +++ b/crates/misc/py/src/lib.rs @@ -120,7 +120,7 @@ pub fn instantiate( } } - let instance = wasmtime::Instance::new(&store, &module, &imports) + let instance = wasmtime::Instance::new(&module, &imports) .map_err(|t| PyErr::new::(format!("instantiated with trap {:?}", t)))?; let module = Py::new(py, Module { module })?; diff --git a/crates/misc/rust/macro/src/lib.rs b/crates/misc/rust/macro/src/lib.rs index 2d91664dd5..0cbc1e027c 100644 --- a/crates/misc/rust/macro/src/lib.rs +++ b/crates/misc/rust/macro/src/lib.rs @@ -75,7 +75,7 @@ fn generate_load(item: &syn::ItemTrait) -> syn::Result { } } let instance = - Instance::new(&store, &module, &imports).map_err(|t| format_err!("instantiation trap: {:?}", t))?; + Instance::new(&module, &imports).map_err(|t| format_err!("instantiation trap: {:?}", t))?; Ok(#name { instance, data }) } diff --git a/crates/test-programs/tests/wasm_tests/runtime.rs b/crates/test-programs/tests/wasm_tests/runtime.rs index c24ce862c3..28eef2878d 100644 --- a/crates/test-programs/tests/wasm_tests/runtime.rs +++ b/crates/test-programs/tests/wasm_tests/runtime.rs @@ -61,7 +61,7 @@ pub fn instantiate(data: &[u8], bin_name: &str, workspace: Option<&Path>) -> any }) .collect::, _>>()?; - let instance = Instance::new(&store, &module, &imports).context(format!( + let instance = Instance::new(&module, &imports).context(format!( "error while instantiating Wasm module '{}'", bin_name, ))?; diff --git a/crates/test-programs/wasi-tests/Cargo.lock b/crates/test-programs/wasi-tests/Cargo.lock index 83b94cc7b8..b1962b4c0e 100644 --- a/crates/test-programs/wasi-tests/Cargo.lock +++ b/crates/test-programs/wasi-tests/Cargo.lock @@ -17,7 +17,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "wasi-tests" -version = "0.7.0" +version = "0.9.0" dependencies = [ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "more-asserts 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/crates/wast/src/wast.rs b/crates/wast/src/wast.rs index 2564bac34e..fc71896ac9 100644 --- a/crates/wast/src/wast.rs +++ b/crates/wast/src/wast.rs @@ -99,7 +99,7 @@ impl WastContext { .clone(); imports.push(export); } - let instance = match Instance::new(&self.store, &module, &imports) { + let instance = match Instance::new(&module, &imports) { Ok(i) => i, Err(e) => return e.downcast::().map(Outcome::Trap), }; diff --git a/src/commands/run.rs b/src/commands/run.rs index 3dd9a48033..4426245c71 100644 --- a/src/commands/run.rs +++ b/src/commands/run.rs @@ -259,7 +259,7 @@ impl RunCommand { }) .collect::, _>>()?; - let instance = Instance::new(store, &module, &imports) + let instance = Instance::new(&module, &imports) .context(format!("failed to instantiate {:?}", path))?; Ok((instance, module, data)) diff --git a/tests/custom_signal_handler.rs b/tests/custom_signal_handler.rs index 8f0e1c83e4..40f9080998 100644 --- a/tests/custom_signal_handler.rs +++ b/tests/custom_signal_handler.rs @@ -108,7 +108,7 @@ mod tests { let store = Store::new(&engine); let data = wat::parse_str(WAT1)?; let module = Module::new(&store, &data)?; - let instance = Instance::new(&store, &module, &[])?; + let instance = Instance::new(&module, &[])?; let (base, length) = set_up_memory(&instance); instance.set_signal_handler(move |signum, siginfo, _| { @@ -165,7 +165,7 @@ mod tests { // Set up multiple instances - let instance1 = Instance::new(&store, &module, &[])?; + let instance1 = Instance::new(&module, &[])?; let instance1_handler_triggered = Rc::new(AtomicBool::new(false)); { @@ -192,7 +192,7 @@ mod tests { }); } - let instance2 = Instance::new(&store, &module, &[]).expect("failed to instantiate module"); + let instance2 = Instance::new(&module, &[]).expect("failed to instantiate module"); let instance2_handler_triggered = Rc::new(AtomicBool::new(false)); { @@ -261,7 +261,7 @@ mod tests { // instance1 which defines 'read' let data1 = wat::parse_str(WAT1)?; let module1 = Module::new(&store, &data1)?; - let instance1 = Instance::new(&store, &module1, &[])?; + let instance1 = Instance::new(&module1, &[])?; let (base1, length1) = set_up_memory(&instance1); instance1.set_signal_handler(move |signum, siginfo, _| { println!("instance1"); @@ -275,7 +275,7 @@ mod tests { // instance2 wich calls 'instance1.read' let data2 = wat::parse_str(WAT2)?; let module2 = Module::new(&store, &data2)?; - let instance2 = Instance::new(&store, &module2, &[instance1_read])?; + let instance2 = Instance::new(&module2, &[instance1_read])?; // since 'instance2.run' calls 'instance1.read' we need to set up the signal handler to handle // SIGSEGV originating from within the memory of instance1 instance2.set_signal_handler(move |signum, siginfo, _| { From 0cf12b3f93f0e1518d7f367d899c30bb41c51ad8 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Tue, 14 Jan 2020 08:08:41 -0600 Subject: [PATCH 28/28] Register module signatures (#811) --- crates/api/src/instance.rs | 20 +++++++++----- crates/api/tests/invoke_func_via_table.rs | 33 +++++++++++++++++++++++ 2 files changed, 47 insertions(+), 6 deletions(-) create mode 100644 crates/api/tests/invoke_func_via_table.rs diff --git a/crates/api/src/instance.rs b/crates/api/src/instance.rs index 7d1d8c18e3..48b080528b 100644 --- a/crates/api/src/instance.rs +++ b/crates/api/src/instance.rs @@ -9,7 +9,7 @@ use anyhow::{Error, Result}; use std::cell::RefCell; use std::collections::{HashMap, HashSet}; use std::rc::Rc; -use wasmtime_jit::{instantiate, Resolver, SetupError}; +use wasmtime_jit::{CompiledModule, Resolver}; use wasmtime_runtime::{Export, InstanceHandle, InstantiationError}; struct SimpleResolver<'a> { @@ -24,7 +24,8 @@ impl Resolver for SimpleResolver<'_> { } } -pub fn instantiate_in_context( +fn instantiate_in_context( + store: &Store, data: &[u8], imports: &[Extern], module_name: Option<&str>, @@ -34,18 +35,24 @@ pub fn instantiate_in_context( let mut contexts = HashSet::new(); let debug_info = context.debug_info(); let mut resolver = SimpleResolver { imports }; - let instance = instantiate( + let mut compiled_module = CompiledModule::new( &mut context.compiler(), data, module_name, &mut resolver, exports, debug_info, - ) - .map_err(|e| -> Error { + )?; + + // Register all module signatures + for signature in compiled_module.module().signatures.values() { + store.register_wasmtime_signature(signature); + } + + let instance = compiled_module.instantiate().map_err(|e| -> Error { if let Some(trap) = take_api_trap() { trap.into() - } else if let SetupError::Instantiate(InstantiationError::StartTrap(msg)) = e { + } else if let InstantiationError::StartTrap(msg) = e { Trap::new(msg).into() } else { e.into() @@ -73,6 +80,7 @@ impl Instance { let context = store.context().clone(); let exports = store.global_exports().clone(); let (mut instance_handle, contexts) = instantiate_in_context( + module.store(), module.binary().expect("binary"), externs, module.name(), diff --git a/crates/api/tests/invoke_func_via_table.rs b/crates/api/tests/invoke_func_via_table.rs new file mode 100644 index 0000000000..c10d696ef2 --- /dev/null +++ b/crates/api/tests/invoke_func_via_table.rs @@ -0,0 +1,33 @@ +use anyhow::{Context as _, Result}; +use wasmtime::*; + +#[test] +fn test_invoke_func_via_table() -> Result<()> { + let store = Store::default(); + + let binary = wat::parse_str( + r#" + (module + (func $f (result i64) (i64.const 42)) + + (table (export "table") 1 1 anyfunc) + (elem (i32.const 0) $f) + ) + "#, + )?; + let module = Module::new(&store, &binary).context("> Error compiling module!")?; + let instance = Instance::new(&store, &module, &[]).context("> Error instantiating module!")?; + + let f = instance + .find_export_by_name("table") + .unwrap() + .table() + .unwrap() + .get(0) + .funcref() + .unwrap() + .clone(); + let result = f.call(&[]).unwrap(); + assert_eq!(result[0].unwrap_i64(), 42); + Ok(()) +}