From ad70caff8389fe7d7018603de58e421cb7f2c07f Mon Sep 17 00:00:00 2001 From: Johan Andersson Date: Sun, 15 Sep 2019 03:21:04 +0200 Subject: [PATCH 01/14] Remove colored CLI output from runtime-core lib. When the colored output was originally added in https://github.com/wasmerio/wasmer/pull/489 and there was a discussion then about that it should ideally be in a higher-level crate rather than in the runtime-core library crate. I agree with that, users of the library shouldn't be required to bring in the colored crate dependency and ideally also not have stdout/stderr output either, that should be controlled by the application that uses wasmer-runtime-core, not the library. Disabling stdout/stderr output would be more intrusive but I wanted to at least not have colored output and another crate dependency so this change removes the colored output and the "colored" crate. --- Cargo.lock | 69 ------------------------------- lib/runtime-core/Cargo.toml | 1 - lib/runtime-core/src/fault.rs | 3 -- lib/runtime-core/src/state.rs | 22 ++++------ lib/singlepass-backend/Cargo.toml | 1 - src/bin/wasmer.rs | 2 +- 6 files changed, 10 insertions(+), 88 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 11c8633e3..9f2bdaf5a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -16,11 +16,6 @@ dependencies = [ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "approx" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "arrayref" version = "0.3.5" @@ -205,16 +200,6 @@ name = "cfg-if" version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "cgmath" -version = "0.16.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "approx 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "clang-sys" version = "0.28.1" @@ -255,15 +240,6 @@ dependencies = [ "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "colored" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winconsole 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "constant_time_eq" version = "0.1.4" @@ -810,14 +786,6 @@ dependencies = [ "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "num-traits" -version = "0.1.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "num-traits" version = "0.2.8" @@ -947,18 +915,6 @@ dependencies = [ "proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "rand" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "rand" version = "0.7.0" @@ -1108,11 +1064,6 @@ dependencies = [ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "rgb" -version = "0.8.14" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "rustc-demangle" version = "0.1.16" @@ -1691,7 +1642,6 @@ dependencies = [ "bincode 1.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "blake2b_simd 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", - "colored 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "errno 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "field-offset 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1717,7 +1667,6 @@ name = "wasmer-singlepass-backend" version = "0.7.0" dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "colored 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "dynasm 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "dynasmrt 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1843,21 +1792,9 @@ dependencies = [ "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "winconsole" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cgmath 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rgb 0.8.14 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - [metadata] "checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" -"checksum approx 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08abcc3b4e9339e33a3d0a5ed15d84a687350c05689d825e0f6655eef9e76a94" "checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" "checksum arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b8d73f9beda665eaa98ab9e4f7442bd4e7de6652587de55b2525e52e29c1b0ba" "checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" @@ -1879,12 +1816,10 @@ dependencies = [ "checksum cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)" = "4fc9a35e1f4290eb9e5fc54ba6cf40671ed2a2514c3eeb2b2a908dda2ea5a1be" "checksum cexpr 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a7fa24eb00d5ffab90eaeaf1092ac85c04c64aaf358ea6f84505b8116d24c6af" "checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33" -"checksum cgmath 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)" = "64a4b57c8f4e3a2e9ac07e0f6abc9c24b6fc9e1b54c3478cfb598f3d0023e51c" "checksum clang-sys 0.28.1 (registry+https://github.com/rust-lang/crates.io-index)" = "81de550971c976f176130da4b2978d3b524eaa0fd9ac31f3ceb5ae1231fb4853" "checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum cmake 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "81fb25b677f8bf1eb325017cb6bb8452f87969db0fedb4f757b297bee78a7c62" -"checksum colored 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6cdb90b60f2927f8d76139c72dbde7e10c3a2bc47c8594c9c7a66529f2687c03" "checksum constant_time_eq 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "995a44c877f9212528ccc74b21a232f66ad69001e40ede5bcee2ac9ef2657120" "checksum cranelift-bforest 0.31.0 (registry+https://github.com/rust-lang/crates.io-index)" = "409f92af3dd276e112b72873a3ef02613e3c5f55b81d5d5d04f3157d4f8b8c54" "checksum cranelift-codegen 0.31.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b303542a56fba4cbaeea099fb30ed078b50de0e765fd69f7f5f410adbe31d95b" @@ -1946,7 +1881,6 @@ dependencies = [ "checksum nix 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3b2e0b4f3320ed72aaedb9a5ac838690a8047c7b275da22711fddff4f8a14229" "checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" "checksum nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6" -"checksum num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31" "checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32" "checksum num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273" "checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37" @@ -1963,7 +1897,6 @@ dependencies = [ "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" "checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" "checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" -"checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" "checksum rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d47eab0e83d9693d40f825f86948aa16eff6750ead4bdffc4ab95b8b3a7f052c" "checksum rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853" "checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" @@ -1981,7 +1914,6 @@ dependencies = [ "checksum regex-automata 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "92b73c2a1770c255c240eaa4ee600df1704a38dc3feaa6e949e7fcd4f8dc09f9" "checksum regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716" "checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" -"checksum rgb 0.8.14 (registry+https://github.com/rust-lang/crates.io-index)" = "2089e4031214d129e201f8c3c8c2fe97cd7322478a0d1cdf78e7029b0042efdb" "checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997" @@ -2043,4 +1975,3 @@ dependencies = [ "checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" "checksum wincolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "96f5016b18804d24db43cebf3c77269e7569b8954a8464501c216cc5e070eaa9" -"checksum winconsole 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ef84b96d10db72dd980056666d7f1e7663ce93d82fa33b63e71c966f4cf5032" diff --git a/lib/runtime-core/Cargo.toml b/lib/runtime-core/Cargo.toml index 8ce52ebe0..9349a7c64 100644 --- a/lib/runtime-core/Cargo.toml +++ b/lib/runtime-core/Cargo.toml @@ -18,7 +18,6 @@ libc = "0.2.60" hex = "0.3.2" smallvec = "0.6.10" bincode = "1.1" -colored = "1.8" [dependencies.indexmap] version = "1.2.0" diff --git a/lib/runtime-core/src/fault.rs b/lib/runtime-core/src/fault.rs index 2d46d8ca2..a1a1f58c2 100644 --- a/lib/runtime-core/src/fault.rs +++ b/lib/runtime-core/src/fault.rs @@ -283,13 +283,10 @@ extern "C" fn signal_trap_handler( let image = build_instance_image(ctx, es_image); unwind_result = Box::new(image); } else { - use colored::*; if es_image.frames.len() > 0 { eprintln!( "\n{}", "Wasmer encountered an error while running your WebAssembly program." - .bold() - .red() ); es_image.print_backtrace_if_needed(); } diff --git a/lib/runtime-core/src/state.rs b/lib/runtime-core/src/state.rs index b6bbb95f5..4da5283d7 100644 --- a/lib/runtime-core/src/state.rs +++ b/lib/runtime-core/src/state.rs @@ -303,7 +303,7 @@ impl ExecutionStateImage { if let Ok(x) = env::var("WASMER_BACKTRACE") { if x == "1" { - eprintln!("{}", self.colored_output()); + eprintln!("{}", self.output()); return; } } @@ -311,9 +311,7 @@ impl ExecutionStateImage { eprintln!("Run with `WASMER_BACKTRACE=1` environment variable to display a backtrace."); } - pub fn colored_output(&self) -> String { - use colored::*; - + pub fn output(&self) -> String { fn join_strings(x: impl Iterator, sep: &str) -> String { let mut ret = String::new(); let mut first = true; @@ -341,8 +339,6 @@ impl ExecutionStateImage { i, x.map(|x| format!("{}", x)) .unwrap_or_else(|| "?".to_string()) - .bold() - .cyan() ) }), ", ", @@ -353,27 +349,27 @@ impl ExecutionStateImage { let mut ret = String::new(); if self.frames.len() == 0 { - ret += &"Unknown fault address, cannot read stack.".yellow(); + ret += &"Unknown fault address, cannot read stack."; ret += "\n"; } else { - ret += &"Backtrace:".bold(); + ret += &"Backtrace:"; ret += "\n"; for (i, f) in self.frames.iter().enumerate() { - ret += &format!("* Frame {} @ Local function {}", i, f.local_function_id).bold(); + ret += &format!("* Frame {} @ Local function {}", i, f.local_function_id); ret += "\n"; ret += &format!( " {} {}\n", - "Offset:".bold().yellow(), - format!("{}", f.wasm_inst_offset).bold().cyan(), + "Offset:", + format!("{}", f.wasm_inst_offset), ); ret += &format!( " {} {}\n", - "Locals:".bold().yellow(), + "Locals:", format_optional_u64_sequence(&f.locals) ); ret += &format!( " {} {}\n\n", - "Stack:".bold().yellow(), + "Stack:", format_optional_u64_sequence(&f.stack) ); } diff --git a/lib/singlepass-backend/Cargo.toml b/lib/singlepass-backend/Cargo.toml index fd6494569..65bfd54bc 100644 --- a/lib/singlepass-backend/Cargo.toml +++ b/lib/singlepass-backend/Cargo.toml @@ -18,4 +18,3 @@ byteorder = "1.3.2" nix = "0.15.0" libc = "0.2.60" smallvec = "0.6.10" -colored = "1.8" diff --git a/src/bin/wasmer.rs b/src/bin/wasmer.rs index f9cffd1ae..659f53c71 100644 --- a/src/bin/wasmer.rs +++ b/src/bin/wasmer.rs @@ -732,7 +732,7 @@ fn interactive_shell(mut ctx: InteractiveShellContext) -> ShellExitOperation { } "backtrace" | "bt" => { if let Some(ref image) = ctx.image { - println!("{}", image.execution_state.colored_output()); + println!("{}", image.execution_state.output()); } else { println!("State not available"); } From 21bcac21591366b2a1fbe39d53d9863b1ad4d6f7 Mon Sep 17 00:00:00 2001 From: Johan Andersson Date: Sun, 15 Sep 2019 03:31:05 +0200 Subject: [PATCH 02/14] Rustfmt --- lib/runtime-core/src/state.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/lib/runtime-core/src/state.rs b/lib/runtime-core/src/state.rs index 4da5283d7..7b8dcd2b1 100644 --- a/lib/runtime-core/src/state.rs +++ b/lib/runtime-core/src/state.rs @@ -357,11 +357,7 @@ impl ExecutionStateImage { for (i, f) in self.frames.iter().enumerate() { ret += &format!("* Frame {} @ Local function {}", i, f.local_function_id); ret += "\n"; - ret += &format!( - " {} {}\n", - "Offset:", - format!("{}", f.wasm_inst_offset), - ); + ret += &format!(" {} {}\n", "Offset:", format!("{}", f.wasm_inst_offset),); ret += &format!( " {} {}\n", "Locals:", From 05816e3221e13577d48892630e62d9773e6bf7a7 Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Mon, 16 Sep 2019 13:12:31 -0700 Subject: [PATCH 03/14] This is no longer referring to the correct line. It's supposed to be 352 which is already there. --- lib/spectests/tests/excludes.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/spectests/tests/excludes.txt b/lib/spectests/tests/excludes.txt index 118e2520a..19a1c51a8 100644 --- a/lib/spectests/tests/excludes.txt +++ b/lib/spectests/tests/excludes.txt @@ -863,7 +863,6 @@ llvm:skip:unwind.wast:*:windows # LLVM Linux after OSR - https://github.com/wasmerio/wasmer/pull/567 llvm:skip:simd.wast:352:unix # Module - caught panic Any -llvm:skip:simd.wast:355:unix # Module - caught panic Any llvm:skip:simd_binaryen.wast:*:unix # Module - caught panic Any From b35a522d28628ab0fd1b4a978358f898096d8aee Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Mon, 16 Sep 2019 15:01:18 -0700 Subject: [PATCH 04/14] Add method to call function at index on Ctx --- lib/runtime-core/src/instance.rs | 2 +- lib/runtime-core/src/vm.rs | 25 ++++++++++++++++++++++++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/lib/runtime-core/src/instance.rs b/lib/runtime-core/src/instance.rs index e6ba365f6..97b2d3629 100644 --- a/lib/runtime-core/src/instance.rs +++ b/lib/runtime-core/src/instance.rs @@ -518,7 +518,7 @@ impl LikeNamespace for Rc { } #[must_use] -fn call_func_with_index( +pub(crate) fn call_func_with_index( info: &ModuleInfo, runnable: &dyn RunnableModule, import_backing: &ImportBacking, diff --git a/lib/runtime-core/src/vm.rs b/lib/runtime-core/src/vm.rs index 51f883318..7c811e36e 100644 --- a/lib/runtime-core/src/vm.rs +++ b/lib/runtime-core/src/vm.rs @@ -1,9 +1,11 @@ pub use crate::backing::{ImportBacking, LocalBacking, INTERNALS_SIZE}; use crate::{ + error::{CallError, CallResult, RuntimeError}, + instance::call_func_with_index, memory::{Memory, MemoryType}, module::{ModuleInfo, ModuleInner}, structures::TypedIndex, - types::{LocalOrImport, MemoryIndex}, + types::{FuncIndex, LocalOrImport, MemoryIndex, Value}, vmcalls, }; use std::{ @@ -393,6 +395,27 @@ impl Ctx { (*self.internal.internals)[field.index()] = value; } } + + /// Calls a host or Wasm function at the given index + pub fn call_with_index(&mut self, index: FuncIndex, args: &[Value]) -> CallResult> { + let module = unsafe { &(*self.module) }; + if module.info.func_assoc.get(index).is_none() { + return Err(CallError::Runtime(RuntimeError::Trap { + msg: format!("Index out of bounds: {}", index.index()).into_boxed_str(), + })); + } + let mut output = vec![]; + call_func_with_index( + &module.info, + module.runnable_module.as_ref(), + unsafe { &*self.import_backing }, + self as *mut Ctx, + index, + args, + &mut output, + )?; + Ok(output) + } } #[doc(hidden)] From 4190f011957c8f73d6c8c14ef8d9bfecb0b81fd5 Mon Sep 17 00:00:00 2001 From: Patrick Ventuzelo Date: Tue, 17 Sep 2019 12:03:03 +0200 Subject: [PATCH 05/14] remove panic and unimplemented in llvm-backend and runtime-core --- lib/llvm-backend/src/code.rs | 28 +++++++++++++++++++++++----- lib/llvm-backend/src/trampolines.rs | 14 +++++++++----- lib/runtime-core/src/parse.rs | 21 +++++++++++++-------- 3 files changed, 45 insertions(+), 18 deletions(-) diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index 2696d2896..8ac76fe26 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -1176,7 +1176,11 @@ impl FunctionCodeGenerator for LLVMFunctionCodeGenerator { BasicTypeEnum::FloatType(float_ty) => { float_ty.const_float(0.0).as_basic_value_enum() } - _ => unimplemented!(), + _ => { + return Err(CodegenError { + message: "Operator::End phi type unimplemented".to_string(), + }); + } }; state.push1(placeholder_value); phi.as_instruction().erase_from_basic_block(); @@ -1741,7 +1745,12 @@ impl FunctionCodeGenerator for LLVMFunctionCodeGenerator { _ => value, }); } - _ => unimplemented!("multi-value returns"), + _ => { + return Err(CodegenError { + message: "Operator::CallIndirect multi-value returns unimplemented" + .to_string(), + }); + } } } @@ -6853,7 +6862,9 @@ impl FunctionCodeGenerator for LLVMFunctionCodeGenerator { state.push1(result.try_as_basic_value().left().unwrap()); } _ => { - unimplemented!("{:?}", op); + return Err(CodegenError { + message: format!("Operator {:?} unimplemented", op), + }); } } @@ -6876,7 +6887,11 @@ impl FunctionCodeGenerator for LLVMFunctionCodeGenerator { "return", ))); } - _ => unimplemented!("multi-value returns not yet implemented"), + _ => { + return Err(CodegenError { + message: "multi-value returns not yet implemented".to_string(), + }); + } } Ok(()) } @@ -7051,7 +7066,10 @@ impl ModuleCodeGenerator self.context.as_ref().unwrap(), self.builder.as_ref().unwrap(), self.intrinsics.as_ref().unwrap(), - ); + ) + .map_err(|e| CodegenError { + message: format!("trampolines generation error: {:?}", e), + })?; if let Some(path) = unsafe { &crate::GLOBAL_OPTIONS.pre_opt_ir } { self.module.print_to_file(path).unwrap(); diff --git a/lib/llvm-backend/src/trampolines.rs b/lib/llvm-backend/src/trampolines.rs index cebfa9d46..c75438d23 100644 --- a/lib/llvm-backend/src/trampolines.rs +++ b/lib/llvm-backend/src/trampolines.rs @@ -20,7 +20,7 @@ pub fn generate_trampolines( context: &Context, builder: &Builder, intrinsics: &Intrinsics, -) { +) -> Result<(), String> { for (sig_index, sig) in info.signatures.iter() { let func_type = signatures[sig_index]; @@ -42,8 +42,9 @@ pub fn generate_trampolines( Some(Linkage::External), ); - generate_trampoline(trampoline_func, sig, context, builder, intrinsics); + generate_trampoline(trampoline_func, sig, context, builder, intrinsics)?; } + Ok(()) } fn generate_trampoline( @@ -52,7 +53,7 @@ fn generate_trampoline( context: &Context, builder: &Builder, intrinsics: &Intrinsics, -) { +) -> Result<(), String> { let entry_block = context.append_basic_block(&trampoline_func, "entry"); builder.position_at_end(&entry_block); @@ -64,7 +65,7 @@ fn generate_trampoline( args_ptr.into_pointer_value(), returns_ptr.into_pointer_value(), ), - _ => unimplemented!(), + _ => return Err("trampoline function unimplemented".to_string()), }; let cast_ptr_ty = |wasmer_ty| match wasmer_ty { @@ -108,8 +109,11 @@ fn generate_trampoline( call_site.try_as_basic_value().left().unwrap(), ); } - _ => unimplemented!("multi-value returns"), + _ => { + return Err("trampoline function multi-value returns".to_string()); + } } builder.build_return(None); + Ok(()) } diff --git a/lib/runtime-core/src/parse.rs b/lib/runtime-core/src/parse.rs index 259a628dd..b2ad3051e 100644 --- a/lib/runtime-core/src/parse.rs +++ b/lib/runtime-core/src/parse.rs @@ -392,14 +392,19 @@ pub fn read_module< } pub fn wp_type_to_type(ty: WpType) -> Result { - Ok(match ty { - WpType::I32 => Type::I32, - WpType::I64 => Type::I64, - WpType::F32 => Type::F32, - WpType::F64 => Type::F64, - WpType::V128 => Type::V128, - _ => panic!("broken invariant, invalid type"), - }) + match ty { + WpType::I32 => Ok(Type::I32), + WpType::I64 => Ok(Type::I64), + WpType::F32 => Ok(Type::F32), + WpType::F64 => Ok(Type::F64), + WpType::V128 => Ok(Type::V128), + _ => { + return Err(BinaryReaderError { + message: "broken invariant, invalid type", + offset: -1isize as usize, + }); + } + } } pub fn type_to_wp_type(ty: Type) -> WpType { From 726269a52cf709d1953fd25a6e2ff918b167237e Mon Sep 17 00:00:00 2001 From: Patrick Ventuzelo Date: Tue, 17 Sep 2019 12:05:00 +0200 Subject: [PATCH 06/14] fix missing info error --- lib/llvm-backend/src/trampolines.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/llvm-backend/src/trampolines.rs b/lib/llvm-backend/src/trampolines.rs index c75438d23..c9bd50e1b 100644 --- a/lib/llvm-backend/src/trampolines.rs +++ b/lib/llvm-backend/src/trampolines.rs @@ -110,7 +110,7 @@ fn generate_trampoline( ); } _ => { - return Err("trampoline function multi-value returns".to_string()); + return Err("trampoline function multi-value returns unimplemented".to_string()); } } From 71b865aa1144dd181a61821ebb5b196f8cc8d8df Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Tue, 17 Sep 2019 22:16:38 +0000 Subject: [PATCH 07/14] Bump rand from 0.7.0 to 0.7.2 Bumps [rand](https://github.com/rust-random/rand) from 0.7.0 to 0.7.2. - [Release notes](https://github.com/rust-random/rand/releases) - [Changelog](https://github.com/rust-random/rand/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-random/rand/compare/0.7.0...0.7.2) Signed-off-by: dependabot-preview[bot] --- Cargo.lock | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 11c8633e3..b26948e68 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -961,7 +961,7 @@ dependencies = [ [[package]] name = "rand" -version = "0.7.0" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1333,7 +1333,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1590,7 +1590,7 @@ dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-runtime-core 0.7.0", ] @@ -1749,7 +1749,7 @@ dependencies = [ "generational-arena 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "typetag 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1964,7 +1964,7 @@ dependencies = [ "checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" "checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" "checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" -"checksum rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d47eab0e83d9693d40f825f86948aa16eff6750ead4bdffc4ab95b8b3a7f052c" +"checksum rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3ae1b169243eaf61759b8475a998f0a385e42042370f3a7dbaf35246eacc8412" "checksum rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853" "checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" "checksum rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" From e8a918e2e5f37e0d9d57d876eb036800b96ed56d Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Wed, 18 Sep 2019 23:25:35 +0200 Subject: [PATCH 08/14] %lld -> %ld fixes cargo test compile error --- lib/runtime-c-api/tests/test-exports.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/runtime-c-api/tests/test-exports.c b/lib/runtime-c-api/tests/test-exports.c index 3af813d0e..893174908 100644 --- a/lib/runtime-c-api/tests/test-exports.c +++ b/lib/runtime-c-api/tests/test-exports.c @@ -242,7 +242,7 @@ int main() wasmer_result_t call_result = wasmer_export_func_call(exported_function, inputs, inputs_arity, outputs, outputs_arity); - printf("Result: %lld\n", outputs[0].value.I64); + printf("Result: %ld\n", outputs[0].value.I64); assert(outputs[0].value.I64 == 7); assert(call_result == WASMER_OK); From 5741a2cf7004afa3e341c49294d374254495ada9 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Wed, 18 Sep 2019 16:06:46 -0700 Subject: [PATCH 09/14] Implement function lookups using the table --- lib/runtime-core/src/instance.rs | 56 +++++++++++++++++---------- lib/runtime-core/src/table/anyfunc.rs | 2 +- lib/runtime-core/src/table/mod.rs | 3 +- lib/runtime-core/src/vm.rs | 54 ++++++++++++++++---------- 4 files changed, 71 insertions(+), 44 deletions(-) diff --git a/lib/runtime-core/src/instance.rs b/lib/runtime-core/src/instance.rs index 97b2d3629..f1ce0a193 100644 --- a/lib/runtime-core/src/instance.rs +++ b/lib/runtime-core/src/instance.rs @@ -518,7 +518,7 @@ impl LikeNamespace for Rc { } #[must_use] -pub(crate) fn call_func_with_index( +fn call_func_with_index( info: &ModuleInfo, runnable: &dyn RunnableModule, import_backing: &ImportBacking, @@ -527,29 +527,12 @@ pub(crate) fn call_func_with_index( args: &[Value], rets: &mut Vec, ) -> CallResult<()> { - rets.clear(); - let sig_index = *info .func_assoc .get(func_index) .expect("broken invariant, incorrect func index"); let signature = &info.signatures[sig_index]; - let num_results = signature.returns().len(); - let num_results = num_results - + signature - .returns() - .iter() - .filter(|&&ty| ty == Type::V128) - .count(); - rets.reserve(num_results); - - if !signature.check_param_value_types(args) { - Err(ResolveError::Signature { - expected: signature.clone(), - found: args.iter().map(|val| val.ty()).collect(), - })? - } let func_ptr = match func_index.local_or_import(info) { LocalOrImport::Local(local_func_index) => { @@ -567,6 +550,39 @@ pub(crate) fn call_func_with_index( } }; + let wasm = runnable + .get_trampoline(info, sig_index) + .expect("wasm trampoline"); + + call_func_with_index_inner(ctx_ptr, func_ptr, signature, wasm, args, rets) +} + +pub(crate) fn call_func_with_index_inner( + ctx_ptr: *mut vm::Ctx, + func_ptr: NonNull, + signature: &FuncSig, + wasm: Wasm, + args: &[Value], + rets: &mut Vec, +) -> CallResult<()> { + rets.clear(); + + let num_results = signature.returns().len(); + let num_results = num_results + + signature + .returns() + .iter() + .filter(|&&ty| ty == Type::V128) + .count(); + rets.reserve(num_results); + + if !signature.check_param_value_types(args) { + Err(ResolveError::Signature { + expected: signature.clone(), + found: args.iter().map(|val| val.ty()).collect(), + })? + } + let mut raw_args: SmallVec<[u64; 8]> = SmallVec::new(); for v in args { match v { @@ -598,9 +614,7 @@ pub(crate) fn call_func_with_index( trampoline, invoke, invoke_env, - } = runnable - .get_trampoline(info, sig_index) - .expect("wasm trampoline"); + } = wasm; let run_wasm = |result_space: *mut u64| unsafe { let mut trap_info = WasmTrapInfo::Unknown; diff --git a/lib/runtime-core/src/table/anyfunc.rs b/lib/runtime-core/src/table/anyfunc.rs index 789f67ada..8336b5028 100644 --- a/lib/runtime-core/src/table/anyfunc.rs +++ b/lib/runtime-core/src/table/anyfunc.rs @@ -44,7 +44,7 @@ impl<'a> From> for Anyfunc<'a> { } pub struct AnyfuncTable { - backing: Vec, + pub backing: Vec, max: Option, } diff --git a/lib/runtime-core/src/table/mod.rs b/lib/runtime-core/src/table/mod.rs index 2e11507b1..8fb321501 100644 --- a/lib/runtime-core/src/table/mod.rs +++ b/lib/runtime-core/src/table/mod.rs @@ -9,8 +9,7 @@ use std::{cell::RefCell, fmt, ptr, rc::Rc}; mod anyfunc; -pub use self::anyfunc::Anyfunc; -use self::anyfunc::AnyfuncTable; +pub use self::anyfunc::{Anyfunc, AnyfuncTable}; use crate::error::GrowError; pub enum Element<'a> { diff --git a/lib/runtime-core/src/vm.rs b/lib/runtime-core/src/vm.rs index 7c811e36e..a4abc7b02 100644 --- a/lib/runtime-core/src/vm.rs +++ b/lib/runtime-core/src/vm.rs @@ -1,17 +1,19 @@ pub use crate::backing::{ImportBacking, LocalBacking, INTERNALS_SIZE}; use crate::{ - error::{CallError, CallResult, RuntimeError}, - instance::call_func_with_index, + error::CallResult, + instance::call_func_with_index_inner, memory::{Memory, MemoryType}, module::{ModuleInfo, ModuleInner}, + sig_registry::SigRegistry, structures::TypedIndex, - types::{FuncIndex, LocalOrImport, MemoryIndex, Value}, + types::{LocalOrImport, MemoryIndex, TableIndex, Value}, vmcalls, }; use std::{ cell::UnsafeCell, ffi::c_void, - mem, ptr, + mem, + ptr::{self, NonNull}, sync::atomic::{AtomicUsize, Ordering}, sync::Once, }; @@ -397,24 +399,36 @@ impl Ctx { } /// Calls a host or Wasm function at the given index - pub fn call_with_index(&mut self, index: FuncIndex, args: &[Value]) -> CallResult> { - let module = unsafe { &(*self.module) }; - if module.info.func_assoc.get(index).is_none() { - return Err(CallError::Runtime(RuntimeError::Trap { - msg: format!("Index out of bounds: {}", index.index()).into_boxed_str(), - })); - } - let mut output = vec![]; - call_func_with_index( - &module.info, - module.runnable_module.as_ref(), - unsafe { &*self.import_backing }, - self as *mut Ctx, - index, + pub fn call_with_index(&mut self, index: TableIndex, args: &[Value]) -> CallResult> { + let anyfunc_table = + unsafe { &*((**self.internal.tables).table as *mut crate::table::AnyfuncTable) }; + let entry = anyfunc_table.backing[index.index()]; + + let fn_ptr = entry.func; + let sig_id = entry.sig_id; + let signature = SigRegistry.lookup_signature(unsafe { std::mem::transmute(sig_id.0) }); + let mut rets = vec![]; + + let wasm = { + let module = unsafe { &*self.module }; + let runnable = &module.runnable_module; + + let sig_index = SigRegistry.lookup_sig_index(signature.clone()); + runnable + .get_trampoline(&module.info, sig_index) + .expect("wasm trampoline") + }; + + call_func_with_index_inner( + self as *mut Ctx, /* doesn't handle all cases */ + NonNull::new(fn_ptr as *mut _).unwrap(), + &signature, + wasm, args, - &mut output, + &mut rets, )?; - Ok(output) + + Ok(rets) } } From ccd369ff0c4b2510babee32caf81a281c1b3c9c7 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Wed, 18 Sep 2019 16:43:47 -0700 Subject: [PATCH 10/14] Add example, rename Ctx fn, make things pub(crate), misc changes --- .github/pull_request_template.md | 2 +- CHANGELOG.md | 2 ++ Cargo.toml | 6 +++- examples/callback-guest.rs | 24 ++++++++++++++ examples/callback-guest.wasm | Bin 0 -> 31667 bytes examples/callback.rs | 46 ++++++++++++++++++++++++++ lib/runtime-core/src/table/anyfunc.rs | 2 +- lib/runtime-core/src/table/mod.rs | 3 +- lib/runtime-core/src/vm.rs | 16 +++++---- 9 files changed, 90 insertions(+), 11 deletions(-) create mode 100644 examples/callback-guest.rs create mode 100755 examples/callback-guest.wasm create mode 100644 examples/callback.rs diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 609e0c83f..b29669d33 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -12,4 +12,4 @@ links to related issues, and the context of the PR. # Review -- [ ] Create a short description of the the change in the CHANGELOG.md file +- [ ] Add a short description of the the change to the CHANGELOG.md file diff --git a/CHANGELOG.md b/CHANGELOG.md index 4672f8d70..ed517016d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ Blocks of changes will separated by version increments. ## **[Unreleased]** +- [#803](https://github.com/wasmerio/wasmer/issues/803) Add method to `Ctx` to invoke functions by their `TableIndex` + ## 0.7.0 - 2019-09-12 Special thanks to @YaronWittenstein @penberg for their contributions. diff --git a/Cargo.toml b/Cargo.toml index 31ba526bd..06b2c2854 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -58,7 +58,7 @@ members = [ "lib/wasi-tests", "lib/emscripten-tests", "lib/middleware-common-tests", - "examples/plugin-for-example" + "examples/plugin-for-example", ] [build-dependencies] @@ -105,3 +105,7 @@ managed = ["backend-singlepass", "wasmer-runtime-core/managed"] [[example]] name = "plugin" crate-type = ["bin"] + +[[example]] +name = "callback" +crate-type = ["bin"] diff --git a/examples/callback-guest.rs b/examples/callback-guest.rs new file mode 100644 index 000000000..129ad05c8 --- /dev/null +++ b/examples/callback-guest.rs @@ -0,0 +1,24 @@ +extern "C" { + fn call_guest_fn(f: u32) -> u32; + fn call_guest_fn2(f: u32) -> u32; + fn host_callback() -> u32; +} + +#[no_mangle] +fn test_callback() -> u32 { + 42 +} + +#[no_mangle] +fn test_callback2() -> u32 { + 45 +} + +fn main() { + unsafe { call_guest_fn(test_callback as usize as u32) }; + unsafe { call_guest_fn(host_callback as usize as u32) }; + unsafe { call_guest_fn(test_callback2 as usize as u32) }; + unsafe { call_guest_fn2(test_callback2 as usize as u32) }; + unsafe { call_guest_fn2(test_callback as usize as u32) }; + unsafe { call_guest_fn2(host_callback as usize as u32) }; +} diff --git a/examples/callback-guest.wasm b/examples/callback-guest.wasm new file mode 100755 index 0000000000000000000000000000000000000000..05558297595555751c3b484fce3f763f1828c182 GIT binary patch literal 31667 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 literal 0 HcmV?d00001 diff --git a/examples/callback.rs b/examples/callback.rs new file mode 100644 index 000000000..732a6a1a4 --- /dev/null +++ b/examples/callback.rs @@ -0,0 +1,46 @@ +/// This example demonstrates the use of callbacks: calling functions (Host and Wasm) +/// passed to us from the Wasm via hostcall +use wasmer_runtime::{compile_with, compiler_for_backend, func, imports, Backend, Ctx}; +use wasmer_runtime_core::{structures::TypedIndex, types::TableIndex}; + +static WASM: &'static str = "examples/callback-guest.wasm"; + +/// This function matches our arbitrarily decided callback signature +/// in this example we'll only call functions that take no arguments and return one value +fn host_callback(_ctx: &mut Ctx) -> u32 { + 55 +} + +fn call_guest_fn(ctx: &mut Ctx, guest_fn: u32) -> u32 { + // We get a TableIndex from our raw value passed in + let guest_fn_typed = TableIndex::new(guest_fn as usize); + // and use it to call the corresponding function + let result = ctx.call_with_table_index(guest_fn_typed, &[]).unwrap(); + + println!("Guest fn {} returned {:?}", guest_fn, result); + + 0 +} + +fn main() { + let wasm_bytes = + std::fs::read(WASM).expect(&format!("Could not read in WASM plugin at {}", WASM)); + + let imports = imports! { + "env" => { + "call_guest_fn" => func!(call_guest_fn), + "call_guest_fn2" => func!(call_guest_fn), + "host_callback" => func!(host_callback), + }, + }; + + let compiler = compiler_for_backend(Backend::default()).unwrap(); + let module = compile_with(&wasm_bytes[..], compiler.as_ref()).unwrap(); + let instance = module + .instantiate(&imports) + .expect("failed to instantiate wasm module"); + + let entry_point = instance.func::<(u32, u32), u32>("main").unwrap(); + + entry_point.call(0, 0).expect("START"); +} diff --git a/lib/runtime-core/src/table/anyfunc.rs b/lib/runtime-core/src/table/anyfunc.rs index 8336b5028..4a63c8f62 100644 --- a/lib/runtime-core/src/table/anyfunc.rs +++ b/lib/runtime-core/src/table/anyfunc.rs @@ -44,7 +44,7 @@ impl<'a> From> for Anyfunc<'a> { } pub struct AnyfuncTable { - pub backing: Vec, + pub(crate) backing: Vec, max: Option, } diff --git a/lib/runtime-core/src/table/mod.rs b/lib/runtime-core/src/table/mod.rs index 8fb321501..1b61cd754 100644 --- a/lib/runtime-core/src/table/mod.rs +++ b/lib/runtime-core/src/table/mod.rs @@ -9,7 +9,8 @@ use std::{cell::RefCell, fmt, ptr, rc::Rc}; mod anyfunc; -pub use self::anyfunc::{Anyfunc, AnyfuncTable}; +pub use self::anyfunc::Anyfunc; +pub(crate) use self::anyfunc::AnyfuncTable; use crate::error::GrowError; pub enum Element<'a> { diff --git a/lib/runtime-core/src/vm.rs b/lib/runtime-core/src/vm.rs index a4abc7b02..e3084a9c5 100644 --- a/lib/runtime-core/src/vm.rs +++ b/lib/runtime-core/src/vm.rs @@ -398,14 +398,16 @@ impl Ctx { } } - /// Calls a host or Wasm function at the given index - pub fn call_with_index(&mut self, index: TableIndex, args: &[Value]) -> CallResult> { + /// Calls a host or Wasm function at the given table index + pub fn call_with_table_index( + &mut self, + index: TableIndex, + args: &[Value], + ) -> CallResult> { let anyfunc_table = unsafe { &*((**self.internal.tables).table as *mut crate::table::AnyfuncTable) }; - let entry = anyfunc_table.backing[index.index()]; + let Anyfunc { func, ctx, sig_id } = anyfunc_table.backing[index.index()]; - let fn_ptr = entry.func; - let sig_id = entry.sig_id; let signature = SigRegistry.lookup_signature(unsafe { std::mem::transmute(sig_id.0) }); let mut rets = vec![]; @@ -420,8 +422,8 @@ impl Ctx { }; call_func_with_index_inner( - self as *mut Ctx, /* doesn't handle all cases */ - NonNull::new(fn_ptr as *mut _).unwrap(), + ctx, + NonNull::new(func as *mut _).unwrap(), &signature, wasm, args, From a090bec49081bae2b79d9ce8926333d90153def7 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Wed, 18 Sep 2019 17:12:48 -0700 Subject: [PATCH 11/14] Add examples step in Makefile and add it to integration-tests --- Makefile | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 007e89853..5eb9c9aa2 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: spectests emtests clean build install lint precommit docs +.PHONY: spectests emtests clean build install lint precommit docs examples # Generate files generate-spectests: @@ -111,12 +111,16 @@ test: spectests emtests middleware wasitests circleci-clean test-rest # Integration tests -integration-tests: release-clif +integration-tests: release-clif examples echo "Running Integration Tests" ./integration_tests/lua/test.sh ./integration_tests/nginx/test.sh ./integration_tests/cowsay/test.sh +examples: + cargo run --example plugin + cargo run --example callback + # Utils lint: From 3b200fa4d3e1f798583c7cdf8f0e81b24d02f686 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Thu, 19 Sep 2019 13:53:07 -0700 Subject: [PATCH 12/14] Move callback guest out of direct examples dir --- examples/callback-guest/README.md | 5 +++++ examples/{ => callback-guest}/callback-guest.rs | 0 examples/{ => callback-guest}/callback-guest.wasm | Bin examples/callback.rs | 2 +- 4 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 examples/callback-guest/README.md rename examples/{ => callback-guest}/callback-guest.rs (100%) rename examples/{ => callback-guest}/callback-guest.wasm (100%) diff --git a/examples/callback-guest/README.md b/examples/callback-guest/README.md new file mode 100644 index 000000000..6439ef00d --- /dev/null +++ b/examples/callback-guest/README.md @@ -0,0 +1,5 @@ +# Call back guest + +This is part of the `callback` example. This Wasm module passes host imports and its own functions to the Wasm host to execute. + +See `examples/callback.rs` for the host diff --git a/examples/callback-guest.rs b/examples/callback-guest/callback-guest.rs similarity index 100% rename from examples/callback-guest.rs rename to examples/callback-guest/callback-guest.rs diff --git a/examples/callback-guest.wasm b/examples/callback-guest/callback-guest.wasm similarity index 100% rename from examples/callback-guest.wasm rename to examples/callback-guest/callback-guest.wasm diff --git a/examples/callback.rs b/examples/callback.rs index 732a6a1a4..e5969fec9 100644 --- a/examples/callback.rs +++ b/examples/callback.rs @@ -3,7 +3,7 @@ use wasmer_runtime::{compile_with, compiler_for_backend, func, imports, Backend, Ctx}; use wasmer_runtime_core::{structures::TypedIndex, types::TableIndex}; -static WASM: &'static str = "examples/callback-guest.wasm"; +static WASM: &'static str = "examples/callback-guest/callback-guest.wasm"; /// This function matches our arbitrarily decided callback signature /// in this example we'll only call functions that take no arguments and return one value From 882a77ccf9d7f4d112c000ad05babb90dce90198 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Fri, 20 Sep 2019 11:59:20 -0700 Subject: [PATCH 13/14] Remove null pointer checks generally, re-add them in Emscripten --- CHANGELOG.md | 1 + lib/emscripten/src/env/mod.rs | 12 +-- lib/emscripten/src/env/unix/mod.rs | 6 +- lib/emscripten/src/env/windows/mod.rs | 3 +- lib/emscripten/src/lib.rs | 1 + lib/emscripten/src/ptr.rs | 113 ++++++++++++++++++++++++++ lib/emscripten/src/syscalls/mod.rs | 10 +-- lib/emscripten/src/syscalls/unix.rs | 4 +- lib/runtime-core/src/memory/ptr.rs | 16 +--- 9 files changed, 136 insertions(+), 30 deletions(-) create mode 100644 lib/emscripten/src/ptr.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 6273bc8ef..28f596879 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ Blocks of changes will separated by version increments. ## **[Unreleased]** +- [#820](https://github.com/wasmerio/wasmer/issues/820) Remove null-pointer checks in `WasmPtr` from runtime-core, re-add them in Emscripten - [#803](https://github.com/wasmerio/wasmer/issues/803) Add method to `Ctx` to invoke functions by their `TableIndex` - [#790](https://github.com/wasmerio/wasmer/pull/790) Fix flaky test failure with LLVM, switch to large code model. - [#788](https://github.com/wasmerio/wasmer/pull/788) Use union merge on the changelog file. diff --git a/lib/emscripten/src/env/mod.rs b/lib/emscripten/src/env/mod.rs index 88fba54a6..a61a2bb9f 100644 --- a/lib/emscripten/src/env/mod.rs +++ b/lib/emscripten/src/env/mod.rs @@ -12,14 +12,14 @@ pub use self::windows::*; use libc::c_char; -use crate::{allocate_on_stack, EmscriptenData}; +use crate::{ + allocate_on_stack, + ptr::{Array, WasmPtr}, + EmscriptenData, +}; use std::os::raw::c_int; -use wasmer_runtime_core::{ - memory::ptr::{Array, WasmPtr}, - types::ValueType, - vm::Ctx, -}; +use wasmer_runtime_core::{types::ValueType, vm::Ctx}; pub fn call_malloc(ctx: &mut Ctx, size: u32) -> u32 { get_emscripten_data(ctx) diff --git a/lib/emscripten/src/env/unix/mod.rs b/lib/emscripten/src/env/unix/mod.rs index 0e62e8e2f..951650495 100644 --- a/lib/emscripten/src/env/unix/mod.rs +++ b/lib/emscripten/src/env/unix/mod.rs @@ -9,11 +9,9 @@ use std::mem; use std::os::raw::c_char; use crate::env::{call_malloc, call_malloc_with_cast, EmAddrInfo, EmSockAddr}; +use crate::ptr::{Array, WasmPtr}; use crate::utils::{copy_cstr_into_wasm, copy_terminated_array_of_cstrs}; -use wasmer_runtime_core::{ - memory::ptr::{Array, WasmPtr}, - vm::Ctx, -}; +use wasmer_runtime_core::vm::Ctx; // #[no_mangle] /// emscripten: _getenv // (name: *const char) -> *const c_char; diff --git a/lib/emscripten/src/env/windows/mod.rs b/lib/emscripten/src/env/windows/mod.rs index d6ba0b0da..025a01bd7 100644 --- a/lib/emscripten/src/env/windows/mod.rs +++ b/lib/emscripten/src/env/windows/mod.rs @@ -6,8 +6,9 @@ use std::mem; use std::os::raw::c_char; use crate::env::{call_malloc, EmAddrInfo}; +use crate::ptr::WasmPtr; use crate::utils::{copy_cstr_into_wasm, read_string_from_wasm}; -use wasmer_runtime_core::{memory::ptr::WasmPtr, vm::Ctx}; +use wasmer_runtime_core::vm::Ctx; extern "C" { #[link_name = "_putenv"] diff --git a/lib/emscripten/src/lib.rs b/lib/emscripten/src/lib.rs index ba25b4be8..727405381 100644 --- a/lib/emscripten/src/lib.rs +++ b/lib/emscripten/src/lib.rs @@ -62,6 +62,7 @@ mod math; mod memory; mod process; mod pthread; +mod ptr; mod signal; mod storage; mod syscalls; diff --git a/lib/emscripten/src/ptr.rs b/lib/emscripten/src/ptr.rs new file mode 100644 index 000000000..3c383c3a1 --- /dev/null +++ b/lib/emscripten/src/ptr.rs @@ -0,0 +1,113 @@ +//! This is a wrapper around the `WasmPtr` abstraction that does not allow deref of address 0 +//! This is a common assumption in Emscripten code + +use std::{cell::Cell, fmt}; +pub use wasmer_runtime_core::memory::ptr::Array; +use wasmer_runtime_core::{ + memory::{ptr, Memory}, + types::{ValueType, WasmExternType}, +}; + +#[repr(transparent)] +pub struct WasmPtr(ptr::WasmPtr); + +unsafe impl ValueType for WasmPtr {} +impl Copy for WasmPtr {} + +impl Clone for WasmPtr { + fn clone(&self) -> Self { + Self(self.0.clone()) + } +} + +impl fmt::Debug for WasmPtr { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{:?}", self.0) + } +} + +unsafe impl WasmExternType for WasmPtr { + type Native = as WasmExternType>::Native; + + fn to_native(self) -> Self::Native { + self.0.to_native() + } + fn from_native(n: Self::Native) -> Self { + Self(ptr::WasmPtr::from_native(n)) + } +} + +impl PartialEq for WasmPtr { + fn eq(&self, other: &Self) -> bool { + self.0 == other.0 + } +} + +impl Eq for WasmPtr {} + +impl WasmPtr { + #[inline(always)] + pub fn new(offset: u32) -> Self { + Self(ptr::WasmPtr::new(offset)) + } + + #[inline(always)] + pub fn offset(self) -> u32 { + self.0.offset() + } +} + +impl WasmPtr { + #[inline(always)] + pub fn deref<'a>(self, memory: &'a Memory) -> Option<&'a Cell> { + if self.0.offset() == 0 { + None + } else { + self.0.deref(memory) + } + } + + #[inline(always)] + pub unsafe fn deref_mut<'a>(self, memory: &'a Memory) -> Option<&'a mut Cell> { + if self.0.offset() == 0 { + None + } else { + self.0.deref_mut(memory) + } + } +} + +impl WasmPtr { + #[inline(always)] + pub fn deref<'a>(self, memory: &'a Memory, index: u32, length: u32) -> Option<&'a [Cell]> { + if self.0.offset() == 0 { + None + } else { + self.0.deref(memory, index, length) + } + } + + #[inline] + pub unsafe fn deref_mut<'a>( + self, + memory: &'a Memory, + index: u32, + length: u32, + ) -> Option<&'a mut [Cell]> { + if self.0.offset() == 0 { + None + } else { + self.0.deref_mut(memory, index, length) + } + } + + #[allow(dead_code)] + #[inline(always)] + pub fn get_utf8_string<'a>(self, memory: &'a Memory, str_len: u32) -> Option<&'a str> { + if self.0.offset() == 0 { + None + } else { + self.0.get_utf8_string(memory, str_len) + } + } +} diff --git a/lib/emscripten/src/syscalls/mod.rs b/lib/emscripten/src/syscalls/mod.rs index b098bd152..ba5965fde 100644 --- a/lib/emscripten/src/syscalls/mod.rs +++ b/lib/emscripten/src/syscalls/mod.rs @@ -10,7 +10,10 @@ pub use self::unix::*; #[cfg(windows)] pub use self::windows::*; -use crate::utils::{copy_stat_into_wasm, get_cstr_path, get_current_directory}; +use crate::{ + ptr::{Array, WasmPtr}, + utils::{copy_stat_into_wasm, get_cstr_path, get_current_directory}, +}; use super::varargs::VarArgs; use byteorder::{ByteOrder, LittleEndian}; @@ -40,10 +43,7 @@ use libc::{ write, // ENOTTY, }; -use wasmer_runtime_core::{ - memory::ptr::{Array, WasmPtr}, - vm::Ctx, -}; +use wasmer_runtime_core::vm::Ctx; use super::env; use std::cell::Cell; diff --git a/lib/emscripten/src/syscalls/unix.rs b/lib/emscripten/src/syscalls/unix.rs index 000a3e319..efcff0a5e 100644 --- a/lib/emscripten/src/syscalls/unix.rs +++ b/lib/emscripten/src/syscalls/unix.rs @@ -1,4 +1,4 @@ -use crate::varargs::VarArgs; +use crate::{ptr::WasmPtr, varargs::VarArgs}; #[cfg(target_os = "macos")] use libc::size_t; /// NOTE: TODO: These syscalls only support wasm_32 for now because they assume offsets are u32 @@ -111,7 +111,7 @@ fn translate_ioctl(wasm_ioctl: u32) -> c_ulong { #[allow(unused_imports)] use std::ffi::CStr; -use wasmer_runtime_core::{memory::ptr::WasmPtr, vm::Ctx}; +use wasmer_runtime_core::vm::Ctx; use crate::env::EmSockAddr; use crate::utils::{self, get_cstr_path}; diff --git a/lib/runtime-core/src/memory/ptr.rs b/lib/runtime-core/src/memory/ptr.rs index 0a9454acc..abed45bfb 100644 --- a/lib/runtime-core/src/memory/ptr.rs +++ b/lib/runtime-core/src/memory/ptr.rs @@ -46,9 +46,7 @@ fn align_pointer(ptr: usize, align: usize) -> usize { impl WasmPtr { #[inline] pub fn deref<'a>(self, memory: &'a Memory) -> Option<&'a Cell> { - if self.offset == 0 - || (self.offset as usize) + mem::size_of::() >= memory.size().bytes().0 - { + if (self.offset as usize) + mem::size_of::() >= memory.size().bytes().0 { return None; } unsafe { @@ -62,9 +60,7 @@ impl WasmPtr { #[inline] pub unsafe fn deref_mut<'a>(self, memory: &'a Memory) -> Option<&'a mut Cell> { - if self.offset == 0 - || (self.offset as usize) + mem::size_of::() >= memory.size().bytes().0 - { + if (self.offset as usize) + mem::size_of::() >= memory.size().bytes().0 { return None; } let cell_ptr = align_pointer( @@ -83,9 +79,7 @@ impl WasmPtr { let item_size = mem::size_of::() + (mem::size_of::() % mem::align_of::()); let slice_full_len = index as usize + length as usize; - if self.offset == 0 - || (self.offset as usize) + (item_size * slice_full_len) >= memory.size().bytes().0 - { + if (self.offset as usize) + (item_size * slice_full_len) >= memory.size().bytes().0 { return None; } @@ -112,9 +106,7 @@ impl WasmPtr { let item_size = mem::size_of::() + (mem::size_of::() % mem::align_of::()); let slice_full_len = index as usize + length as usize; - if self.offset == 0 - || (self.offset as usize) + (item_size * slice_full_len) >= memory.size().bytes().0 - { + if (self.offset as usize) + (item_size * slice_full_len) >= memory.size().bytes().0 { return None; } From 7f2c5325949a1fc771f4390e3af3800637a437cc Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Fri, 20 Sep 2019 13:19:31 -0700 Subject: [PATCH 14/14] Allow dead code in emscripten WasmPtr --- lib/emscripten/src/ptr.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/emscripten/src/ptr.rs b/lib/emscripten/src/ptr.rs index 3c383c3a1..34cd68364 100644 --- a/lib/emscripten/src/ptr.rs +++ b/lib/emscripten/src/ptr.rs @@ -1,6 +1,10 @@ //! This is a wrapper around the `WasmPtr` abstraction that does not allow deref of address 0 //! This is a common assumption in Emscripten code +// this is a wrapper with extra logic around the runtime-core `WasmPtr`, so we +// don't want to warn about unusued code here +#![allow(dead_code)] + use std::{cell::Cell, fmt}; pub use wasmer_runtime_core::memory::ptr::Array; use wasmer_runtime_core::{ @@ -101,7 +105,6 @@ impl WasmPtr { } } - #[allow(dead_code)] #[inline(always)] pub fn get_utf8_string<'a>(self, memory: &'a Memory, str_len: u32) -> Option<&'a str> { if self.0.offset() == 0 {