From 5ebea9672c7341e95fa2c3e466d80f432079f892 Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Thu, 31 Jan 2019 23:51:34 -0600 Subject: [PATCH 001/262] Initial commit of C API library --- Cargo.lock | 7 +++++ Cargo.toml | 2 +- lib/runtime-c-api/Cargo.toml | 13 ++++++++++ lib/runtime-c-api/README.md | 6 +++++ lib/runtime-c-api/src/lib.rs | 50 ++++++++++++++++++++++++++++++++++++ lib/runtime-c-api/wasmer.h | 24 +++++++++++++++++ 6 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 lib/runtime-c-api/Cargo.toml create mode 100644 lib/runtime-c-api/README.md create mode 100644 lib/runtime-c-api/src/lib.rs create mode 100644 lib/runtime-c-api/wasmer.h diff --git a/Cargo.lock b/Cargo.lock index 9d4912143..aab4ff843 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -728,6 +728,13 @@ dependencies = [ "wasmer-runtime-core 0.1.2", ] +[[package]] +name = "wasmer-runtime-c-api" +version = "0.1.4" +dependencies = [ + "wasmer-runtime 0.1.4", +] + [[package]] name = "wasmer-runtime-core" version = "0.1.2" diff --git a/Cargo.toml b/Cargo.toml index b570c9b09..d84cd66d3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,7 +27,7 @@ wasmer-runtime-core = { path = "lib/runtime-core" } wasmer-emscripten = { path = "lib/emscripten" } [workspace] -members = ["lib/clif-backend", "lib/runtime", "lib/runtime-core", "lib/emscripten", "lib/spectests"] +members = ["lib/clif-backend", "lib/runtime", "lib/runtime-core", "lib/emscripten", "lib/spectests", "lib/runtime-c-api"] [build-dependencies] wabt = "0.7.2" diff --git a/lib/runtime-c-api/Cargo.toml b/lib/runtime-c-api/Cargo.toml new file mode 100644 index 000000000..938233964 --- /dev/null +++ b/lib/runtime-c-api/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "wasmer-runtime-c-api" +version = "0.1.4" +description = "Wasmer c-api library" +license = "MIT" +authors = ["The Wasmer Engineering Team "] +repository = "https://github.com/wasmerio/wasmer" +edition = "2018" +readme = "README.md" + +[dependencies] +wasmer-runtime = { path = "../runtime", version = "0.1.2" } + diff --git a/lib/runtime-c-api/README.md b/lib/runtime-c-api/README.md new file mode 100644 index 000000000..d5df888e4 --- /dev/null +++ b/lib/runtime-c-api/README.md @@ -0,0 +1,6 @@ +# Wasmer Runtime C API + + +## Generating header files +1. `cargo install cbindgen` +2. `cbindgen lib/runtime-c-api/ -o lib/runtime-c-api/wasmer.h` \ No newline at end of file diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs new file mode 100644 index 000000000..ca9f68c53 --- /dev/null +++ b/lib/runtime-c-api/src/lib.rs @@ -0,0 +1,50 @@ +extern crate wasmer_runtime; + +use std::os::raw::c_char; + +use wasmer_runtime::ImportObject; + +#[allow(non_camel_case_types)] +#[no_mangle] +pub enum wasmer_import_object_t {} + +#[allow(non_camel_case_types)] +#[no_mangle] +pub enum wasmer_instance_t {} + +#[allow(non_camel_case_types)] +#[no_mangle] +#[repr(C)] +pub enum wasmer_compile_result_t { + WASMER_COMPILE_OK = 1, + WASMER_COMPILE_ERROR = 2, +} + +#[no_mangle] +pub extern "C" fn wasmer_import_object_new() -> *mut wasmer_import_object_t { + Box::into_raw(Box::new(ImportObject::new())) as *mut wasmer_import_object_t +} + +#[no_mangle] +pub extern "C" fn wasmer_import_object_destroy(import_object: *mut wasmer_import_object_t) { + if !import_object.is_null() { + drop(unsafe { Box::from_raw(import_object as *mut ImportObject) }); + } +} + +#[no_mangle] +pub extern "C" fn wasmer_instantiate( + mut instance: *mut wasmer_instance_t, + bytes: *const c_char, + import_object: *mut wasmer_import_object_t, +) -> wasmer_compile_result_t { + let import_object = unsafe { Box::from_raw(import_object as *mut ImportObject) }; + let bytes = &[]; + let result = wasmer_runtime::instantiate(bytes, *import_object); + let new_instance = match result { + Ok(instance) => instance, + Err(error) => return wasmer_compile_result_t::WASMER_COMPILE_ERROR, + }; + instance = Box::into_raw(Box::new(new_instance)) as *mut wasmer_instance_t; + wasmer_compile_result_t::WASMER_COMPILE_OK +} diff --git a/lib/runtime-c-api/wasmer.h b/lib/runtime-c-api/wasmer.h new file mode 100644 index 000000000..3d57c81ea --- /dev/null +++ b/lib/runtime-c-api/wasmer.h @@ -0,0 +1,24 @@ +#include +#include +#include + +enum class wasmer_compile_result_t { + WASMER_COMPILE_OK = 1, + WASMER_COMPILE_ERROR = 2, +}; + +struct wasmer_import_object_t; + +struct wasmer_instance_t; + +extern "C" { + +void wasmer_import_object_destroy(wasmer_import_object_t *import_object); + +wasmer_import_object_t *wasmer_import_object_new(); + +wasmer_compile_result_t wasmer_instantiate(wasmer_instance_t *instance, + const char *bytes, + wasmer_import_object_t *import_object); + +} // extern "C" From 6f051467371550f0e990a27632179508c7f1942b Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Fri, 1 Feb 2019 18:52:22 -0600 Subject: [PATCH 002/262] Use build script to run cbinden behind feature flag --- Cargo.lock | 93 +++++++++++++++++++++++++++++++++--- Makefile | 3 ++ lib/runtime-c-api/Cargo.toml | 10 ++++ lib/runtime-c-api/README.md | 4 +- lib/runtime-c-api/build.rs | 28 +++++++++++ lib/runtime-c-api/src/lib.rs | 6 +-- 6 files changed, 131 insertions(+), 13 deletions(-) create mode 100644 lib/runtime-c-api/build.rs diff --git a/Cargo.lock b/Cargo.lock index aab4ff843..9bdf7ccfa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -36,6 +36,21 @@ name = "cast" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "cbindgen" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "cc" version = "1.0.28" @@ -327,6 +342,14 @@ dependencies = [ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "proc-macro2" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "proc-macro2" version = "0.4.26" @@ -335,6 +358,14 @@ dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "quote" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "quote" version = "0.6.11" @@ -470,6 +501,14 @@ dependencies = [ "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "remove_dir_all" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rustc_version" version = "0.2.3" @@ -505,15 +544,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "serde" version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "serde_derive" -version = "1.0.85" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.13.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -564,6 +606,16 @@ dependencies = [ "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "syn" +version = "0.13.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "syn" version = "0.15.26" @@ -595,6 +647,19 @@ dependencies = [ "serde_json 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "tempfile" +version = "3.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", + "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "termion" version = "1.5.1" @@ -623,6 +688,14 @@ dependencies = [ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "toml" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "unicode-segmentation" version = "1.2.1" @@ -662,7 +735,7 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", "wabt-sys 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -732,6 +805,7 @@ dependencies = [ name = "wasmer-runtime-c-api" version = "0.1.4" dependencies = [ + "cbindgen 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-runtime 0.1.4", ] @@ -806,6 +880,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" "checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" "checksum cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "926013f2860c46252efceabb19f4a6b308197505082c609025aa6706c011d427" +"checksum cbindgen 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "32e01024aaf5390d6a8145047371a4f5b0063a14c1e411bc731353bd2278ca44" "checksum cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4a8b715cb4597106ea87c7c84b2f1d452c7492033765df7f32651e66fcf749" "checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" "checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e" @@ -841,7 +916,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum page_size 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f89ef58b3d32420dbd1a43d2f38ae92f6239ef12bb556ab09ca55445f5a67242" "checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" "checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" +"checksum proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1b06e2f335f48d24442b35a19df506a835fb3547bc3c06ef27340da9acf5cae7" "checksum proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)" = "38fddd23d98b2144d197c0eca5705632d4fe2667d14a6be5df8934f8d74f1978" +"checksum quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9949cfe66888ffe1d53e6ec9d9f3b70714083854be20fd5e271b232a017401e8" "checksum quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cdd8e04bd9c52e0342b406469d494fcb033be4bdbe5c606016defbb1681411e1" "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" "checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" @@ -857,25 +934,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" "checksum redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)" = "423e376fffca3dfa06c9e9790a9ccd282fafb3cc6e6397d01dbf64f9bacc6b85" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" +"checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" "checksum serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)" = "534b8b91a95e0f71bca3ed5824752d558da048d4248c91af873b63bd60519752" -"checksum serde_derive 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)" = "a915306b0f1ac5607797697148c223bedeaa36bcc2e28a01441cd638cc6567b4" +"checksum serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)" = "ac38f51a52a556cd17545798e29536885fb1a3fa63d6399f5ef650f4a7d35901" "checksum serde_json 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)" = "4b90a9fbe1211e57d3e1c15670f1cb00802988fb23a1a4aad7a2b63544f1920e" "checksum smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "88aea073965ab29f6edb5493faf96ad662fb18aa9eeb186a3b7057951605ed15" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" "checksum structopt 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "670ad348dc73012fcf78c71f06f9d942232cdd4c859d4b6975e27836c3efc0c3" "checksum structopt-derive 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "ef98172b1a00b0bec738508d3726540edcbd186d50dfd326f2b1febbb3559f04" +"checksum syn 0.13.11 (registry+https://github.com/rust-lang/crates.io-index)" = "14f9bf6292f3a61d2c716723fdb789a41bbe104168e6f496dc6497e531ea1b9b" "checksum syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)" = "f92e629aa1d9c827b2bb8297046c1ccffc57c99b947a680d3ccff1f136a3bee9" "checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" "checksum target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4af5e2227f0b887d591d3724b796a96eff04226104d872f5b3883fcd427d64b9" +"checksum tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "7e91405c14320e5c79b3d148e1c86f40749a36e490642202a31689cb1a3452b2" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" "checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6" "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" +"checksum toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "758664fc71a3a69038656bee8b6be6477d2a6c315a6b81f7081f591bffa4111f" "checksum unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa6024fc12ddfd1c6dbc14a80fa2324d4568849869b779f6bd37e5e4c03344d1" "checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" diff --git a/Makefile b/Makefile index 44d2f6037..4a700f222 100644 --- a/Makefile +++ b/Makefile @@ -12,6 +12,9 @@ spectests: emtests: WASM_EMSCRIPTEN_GENERATE_EMTESTS=1 cargo build -p wasmer-emscripten +capi: + WASM_EMSCRIPTEN_GENERATE_C_API_HEADERS=1 cargo build --manifest-path lib/runtime-c-api/Cargo.toml --features generate-c-api-headers + # clean: # rm -rf artifacts diff --git a/lib/runtime-c-api/Cargo.toml b/lib/runtime-c-api/Cargo.toml index 938233964..d1e2b7cff 100644 --- a/lib/runtime-c-api/Cargo.toml +++ b/lib/runtime-c-api/Cargo.toml @@ -11,3 +11,13 @@ readme = "README.md" [dependencies] wasmer-runtime = { path = "../runtime", version = "0.1.2" } +[lib] +crate-type = ["cdylib"] + +[build-dependencies] +cbindgen = { version = "0.7.1", optional = true } + +[features] +generate-c-api-headers = ["cbindgen"] + + diff --git a/lib/runtime-c-api/README.md b/lib/runtime-c-api/README.md index d5df888e4..954d2e0cf 100644 --- a/lib/runtime-c-api/README.md +++ b/lib/runtime-c-api/README.md @@ -1,6 +1,4 @@ # Wasmer Runtime C API - ## Generating header files -1. `cargo install cbindgen` -2. `cbindgen lib/runtime-c-api/ -o lib/runtime-c-api/wasmer.h` \ No newline at end of file +Run `make capi` \ No newline at end of file diff --git a/lib/runtime-c-api/build.rs b/lib/runtime-c-api/build.rs new file mode 100644 index 000000000..c1d68e431 --- /dev/null +++ b/lib/runtime-c-api/build.rs @@ -0,0 +1,28 @@ +#[cfg(feature = "generate-c-api-headers")] +extern crate cbindgen; + +use std::env; + +static CAPI_ENV_VAR: &str = "WASM_EMSCRIPTEN_GENERATE_C_API_HEADERS"; + +fn main() { + if env::var(CAPI_ENV_VAR).unwrap_or("0".to_string()) == "1" { + build(); + } +} + +#[cfg(feature = "generate-c-api-headers")] +fn build() { + let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap(); + + cbindgen::Builder::new() + .with_crate(crate_dir) + .generate() + .expect("Unable to generate bindings") + .write_to_file("wasmer.h"); +} + +#[cfg(not(feature = "generate-c-api-headers"))] +fn build() { + panic!("environment var set to generate wasmer c API headers but generate-c-api-headers feature not enabled") +} diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index ca9f68c53..8f95e8331 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -5,12 +5,10 @@ use std::os::raw::c_char; use wasmer_runtime::ImportObject; #[allow(non_camel_case_types)] -#[no_mangle] -pub enum wasmer_import_object_t {} +pub struct wasmer_import_object_t(); #[allow(non_camel_case_types)] -#[no_mangle] -pub enum wasmer_instance_t {} +pub struct wasmer_instance_t(); #[allow(non_camel_case_types)] #[no_mangle] From 62f7bb607e48d852884108d1e45d020bed7ec38a Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Fri, 1 Feb 2019 22:10:36 -0600 Subject: [PATCH 003/262] Add first c test to test the C api --- lib/runtime-c-api/README.md | 6 +++++- lib/runtime-c-api/build.rs | 2 ++ lib/runtime-c-api/src/lib.rs | 2 ++ lib/runtime-c-api/tests/.gitignore | 12 +++++++++++ lib/runtime-c-api/tests/CMakeLists.txt | 11 ++++++++++ .../tests/runtime_c_api_tests.rs | 4 ++++ lib/runtime-c-api/tests/test-instantiate.c | 9 ++++++++ lib/runtime-c-api/wasmer.h | 21 ++++++++----------- 8 files changed, 54 insertions(+), 13 deletions(-) create mode 100644 lib/runtime-c-api/tests/.gitignore create mode 100644 lib/runtime-c-api/tests/CMakeLists.txt create mode 100644 lib/runtime-c-api/tests/runtime_c_api_tests.rs create mode 100644 lib/runtime-c-api/tests/test-instantiate.c diff --git a/lib/runtime-c-api/README.md b/lib/runtime-c-api/README.md index 954d2e0cf..7792a8c17 100644 --- a/lib/runtime-c-api/README.md +++ b/lib/runtime-c-api/README.md @@ -1,4 +1,8 @@ # Wasmer Runtime C API ## Generating header files -Run `make capi` \ No newline at end of file +Run `make capi` from wasmer project root directory + +## Running tests +`cmake . && make && make test` from runtime-c-api/tests directory +(TODO run this within a rust test) \ No newline at end of file diff --git a/lib/runtime-c-api/build.rs b/lib/runtime-c-api/build.rs index c1d68e431..40398c2f9 100644 --- a/lib/runtime-c-api/build.rs +++ b/lib/runtime-c-api/build.rs @@ -15,8 +15,10 @@ fn main() { fn build() { let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap(); + use cbindgen::Language; cbindgen::Builder::new() .with_crate(crate_dir) + .with_language(Language::C) .generate() .expect("Unable to generate bindings") .write_to_file("wasmer.h"); diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index 8f95e8331..5decf8d75 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -23,6 +23,7 @@ pub extern "C" fn wasmer_import_object_new() -> *mut wasmer_import_object_t { Box::into_raw(Box::new(ImportObject::new())) as *mut wasmer_import_object_t } +#[allow(clippy::cast_ptr_alignment)] #[no_mangle] pub extern "C" fn wasmer_import_object_destroy(import_object: *mut wasmer_import_object_t) { if !import_object.is_null() { @@ -30,6 +31,7 @@ pub extern "C" fn wasmer_import_object_destroy(import_object: *mut wasmer_import } } +#[allow(clippy::cast_ptr_alignment)] #[no_mangle] pub extern "C" fn wasmer_instantiate( mut instance: *mut wasmer_instance_t, diff --git a/lib/runtime-c-api/tests/.gitignore b/lib/runtime-c-api/tests/.gitignore new file mode 100644 index 000000000..4e3d6fb5d --- /dev/null +++ b/lib/runtime-c-api/tests/.gitignore @@ -0,0 +1,12 @@ +CMakeLists.txt.user +CMakeCache.txt +CMakeFiles +CMakeScripts +Testing +Makefile +cmake_install.cmake +install_manifest.txt +compile_commands.json +CTestTestfile.cmake +_deps +test-instantiate \ No newline at end of file diff --git a/lib/runtime-c-api/tests/CMakeLists.txt b/lib/runtime-c-api/tests/CMakeLists.txt new file mode 100644 index 000000000..4687b27da --- /dev/null +++ b/lib/runtime-c-api/tests/CMakeLists.txt @@ -0,0 +1,11 @@ +cmake_minimum_required (VERSION 2.6) +project (WasmerCApiTests) + +add_executable(test-instantiate test-instantiate.c) + +target_link_libraries(test-instantiate + general "${CMAKE_SOURCE_DIR}/../../../target/debug/libwasmer_runtime_c_api.dylib") + +enable_testing() +add_test(test-instantiate test-instantiate) + diff --git a/lib/runtime-c-api/tests/runtime_c_api_tests.rs b/lib/runtime-c-api/tests/runtime_c_api_tests.rs new file mode 100644 index 000000000..f9112c83c --- /dev/null +++ b/lib/runtime-c-api/tests/runtime_c_api_tests.rs @@ -0,0 +1,4 @@ +#[test] +fn test_c_api() { + // TODO run `cmake . && make && make test` +} diff --git a/lib/runtime-c-api/tests/test-instantiate.c b/lib/runtime-c-api/tests/test-instantiate.c new file mode 100644 index 000000000..f801fa044 --- /dev/null +++ b/lib/runtime-c-api/tests/test-instantiate.c @@ -0,0 +1,9 @@ +#include +#include "../wasmer.h" + +int main() +{ + wasmer_import_object_t *import_object = wasmer_import_object_new(); + wasmer_import_object_destroy(import_object); + return 0; +} \ No newline at end of file diff --git a/lib/runtime-c-api/wasmer.h b/lib/runtime-c-api/wasmer.h index 3d57c81ea..6fd391dec 100644 --- a/lib/runtime-c-api/wasmer.h +++ b/lib/runtime-c-api/wasmer.h @@ -1,24 +1,21 @@ -#include -#include -#include +#include +#include +#include +#include -enum class wasmer_compile_result_t { +typedef enum { WASMER_COMPILE_OK = 1, WASMER_COMPILE_ERROR = 2, -}; +} wasmer_compile_result_t; -struct wasmer_import_object_t; +typedef struct wasmer_import_object_t wasmer_import_object_t; -struct wasmer_instance_t; - -extern "C" { +typedef struct wasmer_instance_t wasmer_instance_t; void wasmer_import_object_destroy(wasmer_import_object_t *import_object); -wasmer_import_object_t *wasmer_import_object_new(); +wasmer_import_object_t *wasmer_import_object_new(void); wasmer_compile_result_t wasmer_instantiate(wasmer_instance_t *instance, const char *bytes, wasmer_import_object_t *import_object); - -} // extern "C" From be19e9666967f80251023be57e8c1d62271a0938 Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Sat, 2 Feb 2019 00:26:10 -0600 Subject: [PATCH 004/262] Implementing instantiate and call --- Cargo.lock | 1 + lib/runtime-c-api/Cargo.toml | 1 + lib/runtime-c-api/src/lib.rs | 66 +++++++++++++++++++-- lib/runtime-c-api/tests/sum.wasm | Bin 0 -> 71 bytes lib/runtime-c-api/tests/test-instantiate.c | 26 +++++++- lib/runtime-c-api/wasmer.h | 12 +++- 6 files changed, 98 insertions(+), 8 deletions(-) create mode 100644 lib/runtime-c-api/tests/sum.wasm diff --git a/Cargo.lock b/Cargo.lock index 9bdf7ccfa..091154677 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -806,6 +806,7 @@ name = "wasmer-runtime-c-api" version = "0.1.4" dependencies = [ "cbindgen 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-runtime 0.1.4", ] diff --git a/lib/runtime-c-api/Cargo.toml b/lib/runtime-c-api/Cargo.toml index d1e2b7cff..4d049ad1a 100644 --- a/lib/runtime-c-api/Cargo.toml +++ b/lib/runtime-c-api/Cargo.toml @@ -10,6 +10,7 @@ readme = "README.md" [dependencies] wasmer-runtime = { path = "../runtime", version = "0.1.2" } +libc = "0.2" [lib] crate-type = ["cdylib"] diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index 5decf8d75..3235e4196 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -1,8 +1,9 @@ extern crate wasmer_runtime; -use std::os::raw::c_char; - -use wasmer_runtime::ImportObject; +use libc::{c_char, c_int, uint32_t, uint8_t}; +use std::ffi::CStr; +use std::str; +use wasmer_runtime::{Instance, ImportObject, Value}; #[allow(non_camel_case_types)] pub struct wasmer_import_object_t(); @@ -18,6 +19,14 @@ pub enum wasmer_compile_result_t { WASMER_COMPILE_ERROR = 2, } +#[allow(non_camel_case_types)] +#[no_mangle] +#[repr(C)] +pub enum wasmer_call_result_t { + WASMER_CALL_OK = 1, + WASMER_CALL_ERROR = 2, +} + #[no_mangle] pub extern "C" fn wasmer_import_object_new() -> *mut wasmer_import_object_t { Box::into_raw(Box::new(ImportObject::new())) as *mut wasmer_import_object_t @@ -35,16 +44,61 @@ pub extern "C" fn wasmer_import_object_destroy(import_object: *mut wasmer_import #[no_mangle] pub extern "C" fn wasmer_instantiate( mut instance: *mut wasmer_instance_t, - bytes: *const c_char, + wasm_bytes: *mut uint8_t, + wasm_bytes_len: uint32_t, import_object: *mut wasmer_import_object_t, ) -> wasmer_compile_result_t { let import_object = unsafe { Box::from_raw(import_object as *mut ImportObject) }; - let bytes = &[]; + if wasm_bytes.is_null() { + return wasmer_compile_result_t::WASMER_COMPILE_ERROR + } + let bytes: &[u8] = unsafe { ::std::slice::from_raw_parts_mut(wasm_bytes, wasm_bytes_len as usize) }; let result = wasmer_runtime::instantiate(bytes, *import_object); let new_instance = match result { Ok(instance) => instance, - Err(error) => return wasmer_compile_result_t::WASMER_COMPILE_ERROR, + Err(error) => { + println!("Err: {:?}", error); + return wasmer_compile_result_t::WASMER_COMPILE_ERROR + }, }; instance = Box::into_raw(Box::new(new_instance)) as *mut wasmer_instance_t; wasmer_compile_result_t::WASMER_COMPILE_OK } + +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub extern "C" fn wasmer_instance_call(instance: *mut wasmer_instance_t, + name: *const c_char) -> wasmer_call_result_t { + // TODO handle params and results + if instance.is_null(){ + println!("Instance null"); + return wasmer_call_result_t::WASMER_CALL_ERROR; + } + if name.is_null(){ + println!("Name null"); + return wasmer_call_result_t::WASMER_CALL_ERROR; + } + let func_name_c = unsafe { + CStr::from_ptr(name) + }; + let func_name_r = func_name_c.to_str().unwrap(); + let instance = unsafe { Box::from_raw(instance as *mut Instance) }; + let result = instance.call(func_name_r, &[Value::I32(1), Value::I32(2)]); + match result { + Ok(res) => { + wasmer_call_result_t::WASMER_CALL_OK + }, + Err(err) => { + println!("Err: {:?}", err); + wasmer_call_result_t::WASMER_CALL_ERROR + } + } +} + +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub extern "C" fn wasmer_instance_destroy(instance: *mut wasmer_instance_t) { + if !instance.is_null() { + drop(unsafe { Box::from_raw(instance as *mut Instance) }); + } +} \ No newline at end of file diff --git a/lib/runtime-c-api/tests/sum.wasm b/lib/runtime-c-api/tests/sum.wasm new file mode 100644 index 0000000000000000000000000000000000000000..135da2604ae37187b5a44036332649df14822496 GIT binary patch literal 71 zcmWm3F$#b%5JkcFcg3LM4J>jrQwTwfg^P8rE>1g?Xabb9Tkq;_A|-je4dzLSOxC%u T4R>jWM)9Am!tkqx{HgH)a(xRp literal 0 HcmV?d00001 diff --git a/lib/runtime-c-api/tests/test-instantiate.c b/lib/runtime-c-api/tests/test-instantiate.c index f801fa044..aeaad9f8b 100644 --- a/lib/runtime-c-api/tests/test-instantiate.c +++ b/lib/runtime-c-api/tests/test-instantiate.c @@ -1,9 +1,33 @@ #include #include "../wasmer.h" +#include +#include int main() { wasmer_import_object_t *import_object = wasmer_import_object_new(); - wasmer_import_object_destroy(import_object); + + // Read the wasm file bytes + FILE *file = fopen("sum.wasm", "r"); + fseek(file, 0, SEEK_END); + long len = ftell(file); + uint8_t *bytes = malloc(len); + fseek(file, 0, SEEK_SET); + fread(bytes, 1, len, file); + fclose(file); + + wasmer_instance_t *instance = NULL; + wasmer_compile_result_t compile_result = wasmer_instantiate(instance, bytes, len, import_object); + printf("Compile result: %d\n", compile_result); + assert(compile_result == WASMER_COMPILE_OK); + + wasmer_call_result_t call_result = wasmer_instance_call(instance, "sum"); + printf("Call result: %d\n", call_result); + assert(call_result == WASMER_CALL_OK); + + printf("Destroy instance\n"); + wasmer_instance_destroy(instance); + printf("Destroy import object\n"); + //wasmer_import_object_destroy(import_object); // error here return 0; } \ No newline at end of file diff --git a/lib/runtime-c-api/wasmer.h b/lib/runtime-c-api/wasmer.h index 6fd391dec..5951a82a7 100644 --- a/lib/runtime-c-api/wasmer.h +++ b/lib/runtime-c-api/wasmer.h @@ -3,6 +3,11 @@ #include #include +typedef enum { + WASMER_CALL_OK = 1, + WASMER_CALL_ERROR = 2, +} wasmer_call_result_t; + typedef enum { WASMER_COMPILE_OK = 1, WASMER_COMPILE_ERROR = 2, @@ -16,6 +21,11 @@ void wasmer_import_object_destroy(wasmer_import_object_t *import_object); wasmer_import_object_t *wasmer_import_object_new(void); +wasmer_call_result_t wasmer_instance_call(wasmer_instance_t *instance, const char *name); + +void wasmer_instance_destroy(wasmer_instance_t *instance); + wasmer_compile_result_t wasmer_instantiate(wasmer_instance_t *instance, - const char *bytes, + uint8_t *wasm_bytes, + uint32_t wasm_bytes_len, wasmer_import_object_t *import_object); From 3c7ad109bc4a17ebb077c9a8bdfe9f166f77ce42 Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Sat, 2 Feb 2019 08:43:29 -0600 Subject: [PATCH 005/262] Fix instance null ptr bug --- lib/runtime-c-api/src/lib.rs | 38 +++++++++++----------- lib/runtime-c-api/tests/test-instantiate.c | 4 +-- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index 3235e4196..af63b88c9 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -3,7 +3,7 @@ extern crate wasmer_runtime; use libc::{c_char, c_int, uint32_t, uint8_t}; use std::ffi::CStr; use std::str; -use wasmer_runtime::{Instance, ImportObject, Value}; +use wasmer_runtime::{ImportObject, Instance, Value}; #[allow(non_camel_case_types)] pub struct wasmer_import_object_t(); @@ -42,52 +42,52 @@ pub extern "C" fn wasmer_import_object_destroy(import_object: *mut wasmer_import #[allow(clippy::cast_ptr_alignment)] #[no_mangle] -pub extern "C" fn wasmer_instantiate( - mut instance: *mut wasmer_instance_t, +pub unsafe extern "C" fn wasmer_instantiate( + mut instance: *mut *mut wasmer_instance_t, wasm_bytes: *mut uint8_t, wasm_bytes_len: uint32_t, import_object: *mut wasmer_import_object_t, ) -> wasmer_compile_result_t { let import_object = unsafe { Box::from_raw(import_object as *mut ImportObject) }; if wasm_bytes.is_null() { - return wasmer_compile_result_t::WASMER_COMPILE_ERROR + return wasmer_compile_result_t::WASMER_COMPILE_ERROR; } - let bytes: &[u8] = unsafe { ::std::slice::from_raw_parts_mut(wasm_bytes, wasm_bytes_len as usize) }; + let bytes: &[u8] = + unsafe { ::std::slice::from_raw_parts_mut(wasm_bytes, wasm_bytes_len as usize) }; let result = wasmer_runtime::instantiate(bytes, *import_object); let new_instance = match result { Ok(instance) => instance, Err(error) => { println!("Err: {:?}", error); - return wasmer_compile_result_t::WASMER_COMPILE_ERROR - }, + return wasmer_compile_result_t::WASMER_COMPILE_ERROR; + } }; - instance = Box::into_raw(Box::new(new_instance)) as *mut wasmer_instance_t; + unsafe { *instance = Box::into_raw(Box::new(new_instance)) as *mut wasmer_instance_t }; wasmer_compile_result_t::WASMER_COMPILE_OK } #[allow(clippy::cast_ptr_alignment)] #[no_mangle] -pub extern "C" fn wasmer_instance_call(instance: *mut wasmer_instance_t, - name: *const c_char) -> wasmer_call_result_t { +pub unsafe extern "C" fn wasmer_instance_call( + instance: *mut wasmer_instance_t, + name: *const c_char, +) -> wasmer_call_result_t { // TODO handle params and results - if instance.is_null(){ - println!("Instance null"); + if instance.is_null() { return wasmer_call_result_t::WASMER_CALL_ERROR; } - if name.is_null(){ - println!("Name null"); + if name.is_null() { return wasmer_call_result_t::WASMER_CALL_ERROR; } - let func_name_c = unsafe { - CStr::from_ptr(name) - }; + let func_name_c = unsafe { CStr::from_ptr(name) }; let func_name_r = func_name_c.to_str().unwrap(); let instance = unsafe { Box::from_raw(instance as *mut Instance) }; let result = instance.call(func_name_r, &[Value::I32(1), Value::I32(2)]); match result { Ok(res) => { + println!("Res: {:?}", res); wasmer_call_result_t::WASMER_CALL_OK - }, + } Err(err) => { println!("Err: {:?}", err); wasmer_call_result_t::WASMER_CALL_ERROR @@ -101,4 +101,4 @@ pub extern "C" fn wasmer_instance_destroy(instance: *mut wasmer_instance_t) { if !instance.is_null() { drop(unsafe { Box::from_raw(instance as *mut Instance) }); } -} \ No newline at end of file +} diff --git a/lib/runtime-c-api/tests/test-instantiate.c b/lib/runtime-c-api/tests/test-instantiate.c index aeaad9f8b..52a095593 100644 --- a/lib/runtime-c-api/tests/test-instantiate.c +++ b/lib/runtime-c-api/tests/test-instantiate.c @@ -17,7 +17,7 @@ int main() fclose(file); wasmer_instance_t *instance = NULL; - wasmer_compile_result_t compile_result = wasmer_instantiate(instance, bytes, len, import_object); + wasmer_compile_result_t compile_result = wasmer_instantiate(&instance, bytes, len, import_object); printf("Compile result: %d\n", compile_result); assert(compile_result == WASMER_COMPILE_OK); @@ -26,7 +26,7 @@ int main() assert(call_result == WASMER_CALL_OK); printf("Destroy instance\n"); - wasmer_instance_destroy(instance); + //wasmer_instance_destroy(instance); // error here printf("Destroy import object\n"); //wasmer_import_object_destroy(import_object); // error here return 0; From 3633ab8ef4c988e1f47d6400007d26272e4a4e95 Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Sat, 2 Feb 2019 10:44:08 -0600 Subject: [PATCH 006/262] Add parameters and results --- lib/runtime-c-api/src/lib.rs | 28 ++++++++++++++++++++-- lib/runtime-c-api/tests/test-instantiate.c | 6 ++++- lib/runtime-c-api/wasmer.h | 9 +++++-- 3 files changed, 38 insertions(+), 5 deletions(-) diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index af63b88c9..2d6d3a4b4 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -1,7 +1,8 @@ extern crate wasmer_runtime; -use libc::{c_char, c_int, uint32_t, uint8_t}; +use libc::{c_char, c_int, int32_t, uint32_t, uint8_t}; use std::ffi::CStr; +use std::slice; use std::str; use wasmer_runtime::{ImportObject, Instance, Value}; @@ -71,6 +72,10 @@ pub unsafe extern "C" fn wasmer_instantiate( pub unsafe extern "C" fn wasmer_instance_call( instance: *mut wasmer_instance_t, name: *const c_char, + params: *const uint32_t, + params_len: c_int, + results: *mut uint32_t, + results_len: c_int, ) -> wasmer_call_result_t { // TODO handle params and results if instance.is_null() { @@ -79,13 +84,32 @@ pub unsafe extern "C" fn wasmer_instance_call( if name.is_null() { return wasmer_call_result_t::WASMER_CALL_ERROR; } + + if params.is_null() { + return wasmer_call_result_t::WASMER_CALL_ERROR; + } + + let params: &[uint32_t] = slice::from_raw_parts(params, params_len as usize); + // TODO Fix this conversion and params + let params: Vec = params + .iter() + .cloned() + .map(|x| Value::I32(x as i32)) + .collect(); + // let params= &[Value::I32(3), Value::I32(4)]; + let func_name_c = unsafe { CStr::from_ptr(name) }; let func_name_r = func_name_c.to_str().unwrap(); let instance = unsafe { Box::from_raw(instance as *mut Instance) }; - let result = instance.call(func_name_r, &[Value::I32(1), Value::I32(2)]); + + let results: &mut [uint32_t] = slice::from_raw_parts_mut(results, results_len as usize); + let result = instance.call(func_name_r, ¶ms[..]); match result { Ok(res) => { println!("Res: {:?}", res); + if let Value::I32(x) = res[0] { + results[0] = x as u32; + } wasmer_call_result_t::WASMER_CALL_OK } Err(err) => { diff --git a/lib/runtime-c-api/tests/test-instantiate.c b/lib/runtime-c-api/tests/test-instantiate.c index 52a095593..3347c5cc9 100644 --- a/lib/runtime-c-api/tests/test-instantiate.c +++ b/lib/runtime-c-api/tests/test-instantiate.c @@ -21,8 +21,12 @@ int main() printf("Compile result: %d\n", compile_result); assert(compile_result == WASMER_COMPILE_OK); - wasmer_call_result_t call_result = wasmer_instance_call(instance, "sum"); + uint32_t params[] = {7, 8}; + uint32_t results[] = {0}; + wasmer_call_result_t call_result = wasmer_instance_call(instance, "sum", params, 2, results, 1); printf("Call result: %d\n", call_result); + printf("Result: %d\n", results[0]); + assert(results[0] == 15); assert(call_result == WASMER_CALL_OK); printf("Destroy instance\n"); diff --git a/lib/runtime-c-api/wasmer.h b/lib/runtime-c-api/wasmer.h index 5951a82a7..86f5a539b 100644 --- a/lib/runtime-c-api/wasmer.h +++ b/lib/runtime-c-api/wasmer.h @@ -21,11 +21,16 @@ void wasmer_import_object_destroy(wasmer_import_object_t *import_object); wasmer_import_object_t *wasmer_import_object_new(void); -wasmer_call_result_t wasmer_instance_call(wasmer_instance_t *instance, const char *name); +wasmer_call_result_t wasmer_instance_call(wasmer_instance_t *instance, + const char *name, + const uint32_t *params, + int params_len, + uint32_t *results, + int results_len); void wasmer_instance_destroy(wasmer_instance_t *instance); -wasmer_compile_result_t wasmer_instantiate(wasmer_instance_t *instance, +wasmer_compile_result_t wasmer_instantiate(wasmer_instance_t **instance, uint8_t *wasm_bytes, uint32_t wasm_bytes_len, wasmer_import_object_t *import_object); From 9120a9d1f8f325738bb4d701b15bc58947af3064 Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Sat, 2 Feb 2019 14:53:07 -0600 Subject: [PATCH 007/262] Implement tagged enum for params/results --- lib/runtime-c-api/src/lib.rs | 95 ++++++++++++++++++---- lib/runtime-c-api/tests/test-instantiate.c | 17 +++- lib/runtime-c-api/wasmer.h | 24 +++++- 3 files changed, 115 insertions(+), 21 deletions(-) diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index 2d6d3a4b4..41d4e0383 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -1,6 +1,6 @@ extern crate wasmer_runtime; -use libc::{c_char, c_int, int32_t, uint32_t, uint8_t}; +use libc::{c_char, c_int, int32_t, int64_t, uint32_t, uint8_t}; use std::ffi::CStr; use std::slice; use std::str; @@ -28,6 +28,31 @@ pub enum wasmer_call_result_t { WASMER_CALL_ERROR = 2, } +#[repr(u32)] +#[derive(Clone)] +pub enum wasmer_value_tag { + WASM_I32, + WASM_I64, + WASM_F32, + WASM_F64, +} + +#[repr(C)] +#[derive(Clone, Copy)] +pub union wasmer_value { + I32: int32_t, + I64: int64_t, + F32: f32, + F64: f64, +} + +#[repr(C)] +#[derive(Clone)] +pub struct wasmer_value_t { + tag: wasmer_value_tag, + value: wasmer_value, +} + #[no_mangle] pub extern "C" fn wasmer_import_object_new() -> *mut wasmer_import_object_t { Box::into_raw(Box::new(ImportObject::new())) as *mut wasmer_import_object_t @@ -72,9 +97,9 @@ pub unsafe extern "C" fn wasmer_instantiate( pub unsafe extern "C" fn wasmer_instance_call( instance: *mut wasmer_instance_t, name: *const c_char, - params: *const uint32_t, + params: *const wasmer_value_t, params_len: c_int, - results: *mut uint32_t, + results: *mut wasmer_value_t, results_len: c_int, ) -> wasmer_call_result_t { // TODO handle params and results @@ -89,31 +114,45 @@ pub unsafe extern "C" fn wasmer_instance_call( return wasmer_call_result_t::WASMER_CALL_ERROR; } - let params: &[uint32_t] = slice::from_raw_parts(params, params_len as usize); + let params: &[wasmer_value_t] = slice::from_raw_parts(params, params_len as usize); // TODO Fix this conversion and params - let params: Vec = params - .iter() - .cloned() - .map(|x| Value::I32(x as i32)) - .collect(); + let params: Vec = params.iter().cloned().map(|x| x.into()).collect(); // let params= &[Value::I32(3), Value::I32(4)]; let func_name_c = unsafe { CStr::from_ptr(name) }; let func_name_r = func_name_c.to_str().unwrap(); let instance = unsafe { Box::from_raw(instance as *mut Instance) }; - let results: &mut [uint32_t] = slice::from_raw_parts_mut(results, results_len as usize); + let results: &mut [wasmer_value_t] = slice::from_raw_parts_mut(results, results_len as usize); let result = instance.call(func_name_r, ¶ms[..]); match result { - Ok(res) => { - println!("Res: {:?}", res); - if let Value::I32(x) = res[0] { - results[0] = x as u32; + Ok(results_vec) => { + println!("Call Res: {:?}", results_vec); + if results_vec.len() > 0 { + let ret = match results_vec[0] { + Value::I32(x) => wasmer_value_t { + tag: wasmer_value_tag::WASM_I32, + value: wasmer_value { I32: x }, + }, + Value::I64(x) => wasmer_value_t { + tag: wasmer_value_tag::WASM_I64, + value: wasmer_value { I64: x }, + }, + Value::F32(x) => wasmer_value_t { + tag: wasmer_value_tag::WASM_F32, + value: wasmer_value { F32: x }, + }, + Value::F64(x) => wasmer_value_t { + tag: wasmer_value_tag::WASM_F64, + value: wasmer_value { F64: x }, + }, + }; + results[0] = ret; } wasmer_call_result_t::WASMER_CALL_OK } Err(err) => { - println!("Err: {:?}", err); + println!("Call Err: {:?}", err); wasmer_call_result_t::WASMER_CALL_ERROR } } @@ -126,3 +165,29 @@ pub extern "C" fn wasmer_instance_destroy(instance: *mut wasmer_instance_t) { drop(unsafe { Box::from_raw(instance as *mut Instance) }); } } + +impl From for Value { + fn from(v: wasmer_value_t) -> Self { + unsafe { + match v { + wasmer_value_t { + tag: WASM_I32, + value: wasmer_value { I32 }, + } => Value::I32(I32), + wasmer_value_t { + tag: WASM_I64, + value: wasmer_value { I64 }, + } => Value::I64(I64), + wasmer_value_t { + tag: WASM_F32, + value: wasmer_value { F32 }, + } => Value::F32(F32), + wasmer_value_t { + tag: WASM_F64, + value: wasmer_value { F64 }, + } => Value::F64(F64), + _ => panic!("not implemented"), + } + } + } +} diff --git a/lib/runtime-c-api/tests/test-instantiate.c b/lib/runtime-c-api/tests/test-instantiate.c index 3347c5cc9..4ad4c1ec7 100644 --- a/lib/runtime-c-api/tests/test-instantiate.c +++ b/lib/runtime-c-api/tests/test-instantiate.c @@ -21,12 +21,21 @@ int main() printf("Compile result: %d\n", compile_result); assert(compile_result == WASMER_COMPILE_OK); - uint32_t params[] = {7, 8}; - uint32_t results[] = {0}; + wasmer_value_t param_one; + param_one.tag = WASM_I32; + param_one.value.I32 = 7; + wasmer_value_t param_two; + param_two.tag = WASM_I32; + param_two.value.I32 = 8; + wasmer_value_t params[] = {param_one, param_two}; + + wasmer_value_t result_one; + wasmer_value_t results[] = {result_one}; + wasmer_call_result_t call_result = wasmer_instance_call(instance, "sum", params, 2, results, 1); printf("Call result: %d\n", call_result); - printf("Result: %d\n", results[0]); - assert(results[0] == 15); + printf("Result: %d\n", results[0].value.I32); + assert(results[0].value.I32 == 15); assert(call_result == WASMER_CALL_OK); printf("Destroy instance\n"); diff --git a/lib/runtime-c-api/wasmer.h b/lib/runtime-c-api/wasmer.h index 86f5a539b..d2c9e2f15 100644 --- a/lib/runtime-c-api/wasmer.h +++ b/lib/runtime-c-api/wasmer.h @@ -13,19 +13,39 @@ typedef enum { WASMER_COMPILE_ERROR = 2, } wasmer_compile_result_t; +enum wasmer_value_tag { + WASM_I32, + WASM_I64, + WASM_F32, + WASM_F64, +}; +typedef uint32_t wasmer_value_tag; + typedef struct wasmer_import_object_t wasmer_import_object_t; typedef struct wasmer_instance_t wasmer_instance_t; +typedef union { + int32_t I32; + int64_t I64; + float F32; + double F64; +} wasmer_value; + +typedef struct { + wasmer_value_tag tag; + wasmer_value value; +} wasmer_value_t; + void wasmer_import_object_destroy(wasmer_import_object_t *import_object); wasmer_import_object_t *wasmer_import_object_new(void); wasmer_call_result_t wasmer_instance_call(wasmer_instance_t *instance, const char *name, - const uint32_t *params, + const wasmer_value_t *params, int params_len, - uint32_t *results, + wasmer_value_t *results, int results_len); void wasmer_instance_destroy(wasmer_instance_t *instance); From ffb3dc083ad23a05be87777fd96dd0d042f76cee Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Sat, 2 Feb 2019 17:43:59 -0600 Subject: [PATCH 008/262] Add test to import function and call it --- Cargo.lock | 1 + lib/runtime-c-api/Cargo.toml | 1 + lib/runtime-c-api/src/lib.rs | 65 ++++++++++++++++++ lib/runtime-c-api/tests/.gitignore | 3 +- lib/runtime-c-api/tests/CMakeLists.txt | 5 ++ .../tests/test-import-function.c | 46 +++++++++++++ lib/runtime-c-api/tests/wasm_sample_app.wasm | Bin 0 -> 1356630 bytes lib/runtime-c-api/wasmer.h | 9 +++ 8 files changed, 129 insertions(+), 1 deletion(-) create mode 100644 lib/runtime-c-api/tests/test-import-function.c create mode 100755 lib/runtime-c-api/tests/wasm_sample_app.wasm diff --git a/Cargo.lock b/Cargo.lock index 091154677..3c96a0a46 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -808,6 +808,7 @@ dependencies = [ "cbindgen 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-runtime 0.1.4", + "wasmer-runtime-core 0.1.2", ] [[package]] diff --git a/lib/runtime-c-api/Cargo.toml b/lib/runtime-c-api/Cargo.toml index 4d049ad1a..692c03cd7 100644 --- a/lib/runtime-c-api/Cargo.toml +++ b/lib/runtime-c-api/Cargo.toml @@ -10,6 +10,7 @@ readme = "README.md" [dependencies] wasmer-runtime = { path = "../runtime", version = "0.1.2" } +wasmer-runtime-core = { path = "../runtime-core", version = "0.1.2" } libc = "0.2" [lib] diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index 41d4e0383..db01f7fe6 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -1,10 +1,16 @@ extern crate wasmer_runtime; +extern crate wasmer_runtime_core; use libc::{c_char, c_int, int32_t, int64_t, uint32_t, uint8_t}; use std::ffi::CStr; use std::slice; use std::str; +use std::sync::Arc; +use std::{ffi::c_void, mem, ptr}; use wasmer_runtime::{ImportObject, Instance, Value}; +use wasmer_runtime_core::export::{Context, Export, FuncPointer}; +use wasmer_runtime_core::import::{LikeNamespace, Namespace}; +use wasmer_runtime_core::types::{FuncSig, Type}; #[allow(non_camel_case_types)] pub struct wasmer_import_object_t(); @@ -12,6 +18,9 @@ pub struct wasmer_import_object_t(); #[allow(non_camel_case_types)] pub struct wasmer_instance_t(); +#[allow(non_camel_case_types)] +pub struct wasmer_instance_context_t(); + #[allow(non_camel_case_types)] #[no_mangle] #[repr(C)] @@ -53,6 +62,13 @@ pub struct wasmer_value_t { value: wasmer_value, } +#[repr(C)] +#[derive(Clone)] +pub struct wasmer_memory_t { + pub ptr: *mut uint8_t, + pub len: uint32_t, +} + #[no_mangle] pub extern "C" fn wasmer_import_object_new() -> *mut wasmer_import_object_t { Box::into_raw(Box::new(ImportObject::new())) as *mut wasmer_import_object_t @@ -89,6 +105,7 @@ pub unsafe extern "C" fn wasmer_instantiate( } }; unsafe { *instance = Box::into_raw(Box::new(new_instance)) as *mut wasmer_instance_t }; + // Box::into_raw(import_object); // TODO Review is this the correct way not to drop wasmer_compile_result_t::WASMER_COMPILE_OK } @@ -125,6 +142,7 @@ pub unsafe extern "C" fn wasmer_instance_call( let results: &mut [wasmer_value_t] = slice::from_raw_parts_mut(results, results_len as usize); let result = instance.call(func_name_r, ¶ms[..]); + Box::into_raw(instance); match result { Ok(results_vec) => { println!("Call Res: {:?}", results_vec); @@ -158,6 +176,53 @@ pub unsafe extern "C" fn wasmer_instance_call( } } +#[no_mangle] +pub extern "C" fn wasmer_imports_set_import_func( + import_object: *mut wasmer_import_object_t, + namespace: *const c_char, + name: *const c_char, + func: extern "C" fn(data: *mut c_void), +) { + let mut import_object = unsafe { Box::from_raw(import_object as *mut ImportObject) }; + let namespace_c = unsafe { CStr::from_ptr(namespace) }; + let namespace_r = namespace_c.to_str().unwrap(); + let name_c = unsafe { CStr::from_ptr(name) }; + let name_r = name_c.to_str().unwrap(); + + let export = Export::Function { + func: unsafe { FuncPointer::new(func as _) }, + ctx: Context::Internal, + signature: Arc::new(FuncSig::new(vec![Type::I32, Type::I32], vec![])), + }; + + // TODO handle existing namespace + // let maybe_namespace = import_object.get_namespace(namespace_r); + // if let Some(n) = maybe_namespace { + // n.insert(name_r, export); + // } else { + let mut namespace = Namespace::new(); + namespace.insert(name_r, export); + import_object.register(namespace_r, namespace); + Box::into_raw(import_object); + // }; +} + +//#[no_mangle] +//pub extern "C" fn wasmer_debug_print(kind: uint8_t, thing: *mut c_void) { +// match kind { +// 1 => { +// println!("wasmer import object:"); +// let import_object = unsafe { Box::from_raw(thing as *mut ImportObject) }; +// println!("after import object"); +// Box::into_raw(import_object); +// }, +// _ => panic!("unknown kind {:?}", kind) +// } +//} + +#[no_mangle] +pub extern "C" fn wasmer_instance_context_memory(instance: *mut wasmer_instance_context_t) {} + #[allow(clippy::cast_ptr_alignment)] #[no_mangle] pub extern "C" fn wasmer_instance_destroy(instance: *mut wasmer_instance_t) { diff --git a/lib/runtime-c-api/tests/.gitignore b/lib/runtime-c-api/tests/.gitignore index 4e3d6fb5d..30324d55c 100644 --- a/lib/runtime-c-api/tests/.gitignore +++ b/lib/runtime-c-api/tests/.gitignore @@ -9,4 +9,5 @@ install_manifest.txt compile_commands.json CTestTestfile.cmake _deps -test-instantiate \ No newline at end of file +test-instantiate +test-import-function \ No newline at end of file diff --git a/lib/runtime-c-api/tests/CMakeLists.txt b/lib/runtime-c-api/tests/CMakeLists.txt index 4687b27da..7d47da19c 100644 --- a/lib/runtime-c-api/tests/CMakeLists.txt +++ b/lib/runtime-c-api/tests/CMakeLists.txt @@ -2,10 +2,15 @@ cmake_minimum_required (VERSION 2.6) project (WasmerCApiTests) add_executable(test-instantiate test-instantiate.c) +add_executable(test-import-function test-import-function.c) target_link_libraries(test-instantiate general "${CMAKE_SOURCE_DIR}/../../../target/debug/libwasmer_runtime_c_api.dylib") +target_link_libraries(test-import-function + general "${CMAKE_SOURCE_DIR}/../../../target/debug/libwasmer_runtime_c_api.dylib") + enable_testing() add_test(test-instantiate test-instantiate) +add_test(test-import-function test-import-function) diff --git a/lib/runtime-c-api/tests/test-import-function.c b/lib/runtime-c-api/tests/test-import-function.c new file mode 100644 index 000000000..eecacc347 --- /dev/null +++ b/lib/runtime-c-api/tests/test-import-function.c @@ -0,0 +1,46 @@ +#include +#include "../wasmer.h" +#include +#include + +static print_str_called = false; + +void print_str(int32_t ptr, int32_t len, wasmer_instance_context_t *ctx) { + printf("In print_str\n"); + print_str_called = true; +} + +int main() +{ + wasmer_import_object_t *import_object = wasmer_import_object_new(); + wasmer_imports_set_import_func(import_object, "env", "print_str", print_str); + + // Read the wasm file bytes + FILE *file = fopen("wasm_sample_app.wasm", "r"); + fseek(file, 0, SEEK_END); + long len = ftell(file); + uint8_t *bytes = malloc(len); + fseek(file, 0, SEEK_SET); + fread(bytes, 1, len, file); + fclose(file); + + wasmer_instance_t *instance = NULL; + wasmer_compile_result_t compile_result = wasmer_instantiate(&instance, bytes, len, import_object); + printf("Compile result: %d\n", compile_result); + assert(compile_result == WASMER_COMPILE_OK); + + wasmer_value_t params[] = {}; + wasmer_value_t results[] = {}; + wasmer_call_result_t call_result = wasmer_instance_call(instance, "hello_wasm", params, 0, results, 0); + printf("Call result: %d\n", call_result); + assert(call_result == WASMER_CALL_OK); + + assert(print_str_called); + + // TODO review import object ownership, instantiate moves it + printf("Destroy instance\n"); + //wasmer_instance_destroy(instance); // TODO error here + printf("Destroy import object\n"); + //wasmer_import_object_destroy(import_object); // TODO error here + return 0; +} \ No newline at end of file diff --git a/lib/runtime-c-api/tests/wasm_sample_app.wasm b/lib/runtime-c-api/tests/wasm_sample_app.wasm new file mode 100755 index 0000000000000000000000000000000000000000..7c8c4b72abe90b282fd6ba5ef053c845f2c109f5 GIT binary patch literal 1356630 zcmeFa2Y40L*8jg}&N*o(=OjQT1cQ)JBQ+pRKntanp}gDiU!WCmM4q9mk199MveTS!9kgpt^dM ziqBC4&JEww_lc!V89!y(vB$fr*~pQTrjDC*?D()25D`K6=dL@s5g* z9653P=*p2}Mjtmm;$)2+Id1gy(IdxC9T#!4CXSyxdD_TX$fn#Z&vjKiS4nQwYCs~l znoGsw`Hpr{@kF_V?o@Qhv|}faD^@iN^Wt5`jUO}PNb;UA?ZT<9ic&zOqEb%PTm%bs`L%qet}i7 z>a@UbkA9MOdfExTUw%CBTVVV;2YzR!{1zRq<6X47YtoEflC4yRq@DvkHXx#o=oL|g zuV;$W(G+XXff4lrRQP(IK3DipB8mCdKPLR5G!>t=FNjNYCIQBT_}oS5Dsk=s+F$7y zpGH*T+eyaZW^V2JMB{U<2wg4z>nfGo0!y6L@#B?@3Bk06R>KCVx9asY=0}qKRL!v>j@t z(dLqEN|dU>4;*g_mP_*LG&2$}?5tVCUl2(Qwf-Ver_TH)4$LS9wA@7!nON7@91?bIq3KQzpr@5GxI zorz)WRa)Mx-6HCrJp+54j?=F=-6G0+EB7}fUrhFeZyVi;_uSnhs@?P2I}3%csN)^m zBciS`-uZa1t>b+b-rpGSR(Nj;dGAQ#i9r#y04jV{*Op3<&uhB2ihzD?l?mQTZB^j+ zH`i7cf`w~K_)u*bHmEIO!?mUPP;F^GR9nJ_YfJOBYD>&Vcav|TnURAtM_82an`KYO`Z3ySMS3ZQ0(2omz{{d44xn)sRc> zv$GSS3Iy9us1*FCJ0a5DYA0j|18H10 z(Xe#mTGkj&N%NKNNSii=_dB9dK;N{h1aHN(=i~P`n>Nj_mT3zgGHt^KrY&sPv^5_x zZOw;FTllbPYrd9gYlFCoKDPs7rXDw!HS&j{=ZRf-cb1s7T-QK_cmJnNdkH$Wro9Td z?WWyCWIP6vZY^M>0}UAIF7tkQR+*t`nUgpBIc0jkji- zN5!(cDpe3o+qn}7jg@IgS`9g#+@0!P>2NIiI?8dp^pwiMAJray9~)ltP1#nzzh|e2F{4)-vHY*d4%Lupwf=Sag7eE3Y@gb za4#B8H50FlXiVHP%;al(nMBbHVxQpFJeoF#+ZZGDS->`QbWTCqGN4XBnzj;Hjw@w( z--o$syN!KabrZbf6rRsb6<#Dv;br`~h1c*KQL(qVA?<<0PD%S1ju%OKD9uTG67ELJ zxoOYB-DkN-+G}u+7*53`TJ0jlByMe|W|BZgw3)=rkhUIsri%{qB33isl=5CGWRbuq zzS)F9WjK9Ac^s8?EHL{p9ErOpaeG8lx=<-)MbiRhm1?!TX=+=PrD1MbAv2OAnO8*% z(%vD_`D1}aDRU@MvDa|Uh&E5qCI3e5QPo`L&*`RuqB4QiMk+Gy2-=>zs)pvaji{%g z!rAGG2l|MsQU^isCQvh&?+CDSI~^$gcBz>^NqWQ5Rp zod-CKB(62dB<>$&g2|ju^757($vjM$z8Q{=AsIYI=y-c0U5Uuf)d&it+XJQv0S+^P zvfrR=6{M__95zv@g%FHMQpz%pkT-m!9TO+mByCw#3;gvQ|5gHhYm(G%)VRtoiKr0} zsReFx;GZ&XT4oVv6MX3oI$ZXLh*M?7(E+X^z)pD1H31TzTJ0T+yO#OrNlHBo6|PHn zyr+C7%j)EQg562fA5HXR{{$s8>1THZFBP1Xp;9Hu=nzrEAQBHGJPQ6$7EHKhe~pBz z!xBmn?jnE|f&jk}U{g52?gaRW00TRkdU@>|9JpFRQUsliXnFzx22ItD@%P%31eb3$ zuUTHKq~$^<{&bkHapKX>b#SHqPj<4#*@cPlMaR@$JDex;5tZ0%lc4mHq*C6NDar`Y z-KuXcUbiFF_eS*i2}y~mluVisJw7l`vubDIcg#pWMLWyDgj?O@#6Q74<)S63;@0s* zKbALgY5p6LE2Q;;P7yT<^0odXp0nT|Hg3sgzd5Rigz-;igZqG6&vFxOe>Q58-`16G z_967W!^E%Bjd!=j}gpGUI#3Jm@o z1lysr7TBvfj!8X)aH(cfj%UsUqo%uZOl-e0SKGEMnkQ1NnrME%1!FQueh3DCla;f6-Vja1-{PUC)?5hG6=kP$Q*vDgHS zCcdY1rCdWG0>t;V=HClm%>Nb4KNr!&{CAirAyejG-hlb1n*NW7bOy6J5hLBs{(Wot z$xi>J$+SB-C8p+MDKTUCiau9_V?oE^w1Flx90HHfCIM)xY8*uPG0!9;Y2Rh$YM%ig^O%iA(_|Z^ zlBtm+HWn3+n9Nj|UM?fcrZOFMR6!)|dwgEgLa3H$vk39CVN^_f>~zsg_R{4hJCNz0 z(Jp6*Da0g(4J3|iMb;1GT~p?$%~0nylrEQT!%FsKtdZxOBih+kkZrhM>?Z9r%*Cf zg_02>Wu2yV_EActmRe<5`BGR}O-R75hO4Es{-lOFy3Y`+hd~I{4PyXrsrxs?uU!RWJarTreTa4 z9YpvKtjH(0Gi^Y0Ncg5{vp_v^Swbs7Wv z&2UDJY_kq5zlV+?nl3k8o%7>PNDdoF92*SeeM-*#-b9YJBF7Q$(zitOcP^+a$7ozq za-3l}BS)T*<3iRRWFa>#$MHLb<*N0O-t zQW-gNjU4;-!!4RFw+0%V4P+Z!{XpIXa();x^-@X_^h`s^$J9&Iw6aQ*v2A4+hsCg+ z&fCX}Xz6m(VziR>pd8+J9WKu_{i1>N`$SJK~OdXN&z1`@{x19{o>g-1YIs40yc^$;YCiap2=6*iMh zYYTN*EukI`3uWt~u27R&hYiOD634JmK_Kr3avqHB8UsG2rIzEjdUCWX3@c}_;c6L9 zT{*sHY)UD|${~(nIf6jmt>pYGWb`qsts@Qk4DzY1kDF`B@j_S*+g87m?VxD7+_dFP zI3g^E4J3{Y2J$W==MSOI>_>V1_H)$PkRIS}0sJfs1Du&gc$btoDr*Oveu_F?U%(y0 zY=(KH)KR^|xST45yEB--#>kYpw2HLX>1E9Na&wiPiU{(>yEMB4qY5I6EX>P?5ZoJkeQ%A&rrIv z-xZfs?>5eG#yG6L^^C!Tyn(AskBi%Uu$ z(+yWkA9dyUBYgzI27$bL$vN`?8a{HHJ z)DPs1pHCx#j2Qp8Sc~zzh+(G2MvSkl7*Rbx$uFv}jT`lJIbCi>jH|=ls#V!o92tP> z2l9R<;{z{24CW_Z62r$sfkfBDAGt^T~fjI4BSDf637)JGuGEi~!i zrV{F3Y*kr5p=;TasFTn>M7dMg`msGpn+i<2`Z$*x05Gd8Z*g)bK zmLmw{l}&clJjlp#&*>q>UhL;K%MDtr)Cl%4kB3%u6x;j^S51P9Vuzg>O6cvaCp3LQ zy%FG4qP`00o~9k!Tvd=+)%Cj3l`*$+;%2bYwZjx$`X?(f3oW**B;3w~=ulWuWD zO%k?tAn!eL-f;P>9pHC$4w%byKr`d5LxU&(o&$B;u02lGA@E$8=b6X?VAHAmne>M%X;DTXs**ly&-F1jA&rp4F- zNQq$si6ia0ejx8xG9LO7V#ty*7X4I<@km`U-mfJ_W?L;(EivLiUlTYo&JlW)I8}ov&9CjY?g**g`rprysan6{qI&2_uY%q}5*o&y~ zke)24=tB_#KE_Y%Lw;CTuHp7-dr_u$`s=J#Aa5d*y_?=r>V3$ofyq3_RY$%EqZna_ z!CVS?&q>GmFuNI?;F4r6*g-Vr?ZqL4b0F`FnB%o1mX0|c=9V{=`VjIO!|by=TRxEY zJj}_r*fjgXbiU6ua=gR@arQdb$nmXA1G|cXOl~tubZ)DD4+UPy^F=MR4&0aHMFein z?Ya&UI9NJ+vwn2dlaM!!0ckCu#ZNHvVcG*`2s2d7=eyD%zg0R3G92%r zwX`fzOgk9$hElyC?_2iTKBb(+|AbNaj7E_QMVTMtlTM-gOTiQPEJ2ZD@vqMhp@ z@u67HiWRIgR`4P>Gb2csn@%=%9PO0m_A`FnwX)MB*a9H)!5(LrcHu3j+l^Io*kA$L z8w6M&%nZ@qb|gS~B$lbI^htKA=`|wOeo!aQLwXm_Rq70=(@L1v0nJWp4ZwW zBrbL6C&8GF9~Lahi!^ixzECQ5i*$AMWdB);5ltUVRY(!N-$yxW;Als6x(K`8c$A~M z9t|S}IUn$bFuEZ7k{ZL6%DL} z56~f9=9vQ>wH(sgXj$&4k&scq_Czc_g;v2VUB&j!4Mcv&h%7f# zu?H0fVkJz&$Y!#kH8SpYwhC^uVr_poOLRz!wf|U0T>u%eu9da7DVfAYEI$bqOB4rw zlTGq1{N%S>tJFkDm-@(Aj=B-j$^USIqk5m{CqKI=NJ8S0yq^Tgqe&jmOR4K@o2ghk z)8xhP1!geBlbb2^2cMRv+>M$6|@=e zlUF&3^BTq}ebV>qF)v74YF|dh*^tr344G(}%Ik8p7@2npE?M*gol0Wlu%AcZ z)DoxI%2NZ0dg~~<>N90=m+DGY>}P^u+Fx@srmbSf=@qQ5=$GonO!Y!f=@q69rkFBw zKuDBsGYFZ+4u@zYYtK#pJh+c{%yX&Gbp zH{&-PGpb!RV{y?{(~tRs_x1*6=^L@3Ij$4yucxS58OQ3w?OJEo$>^H0PR2HZ)v1&R zKM6!QAr;eVJFr6)eUS$Pv3L35sle_`B>jydH%%TH9Epn~PX*qBsWOa;iI3xihBEQB zPXOu;b9rMA<_RR!^byDFI+N`wsA-lAoJ|-TTqpm&P_9bn`nJi48K)%tWjI^c361{Z z>zbz%dS(#vQ?cQ##86o-i?pq@MNm>33w*3A>@N%@{Xp7q&kxfhLCrMEhpnaVqN6-xxD=?&Cfnd_#QUg;s`^HwQF#dgIY zSuh??jla!rZz34U7mxB%;ZgHb%o(fz6BZSTWE19bFv#0;>a#W;Kxfw%tz$;pQIk_kW1hSldi+N>j|_jEYPMp z0v*6!QL407AaO*Xz|XrN%T;eeB9Mw*tS6fJEzoc6q7TF+rPu=u7nJ>pT8gz) z{8a1#J?YFpv0my|oAgW*SQ<{81a2G}R;=x;#gTFZe%`9*T@_=BYc$qOPhs;vtd~=k zo;~^oQfN3+4qDre%wtn3v#m`W5hL(Zv4iwXHGg+v*VfXJCOuP*s&L{Yu(@#q+X|m#jDua1GMFQ zQBTsweZuwG+HgUA%8Bcg9&CMzBgF{(RBZluamnAC*tPXA&7^1aP#sR31lls`O(kyY zQykGl;Maum=po}KVte1Q$I;)R@G>Nt6Ha%Kw;XzGdXDTN6uG@Cm3yLc7C~HdR{abmtZKY zFpN=JQ8azKe&PDHPbGwUUOb2#z)>mc;z&+`pLa89e*u}CzWGd# z@Q0C9ZH1j2&guMcPV_l)R3X(IY@eggGq5w}`+1lDuG9udTg1FfCty@8zbPgb&3~z0 zw%>)bP3x~q8`M+RBN|YpI8wmC&uc~66Cj=K2MJg0kTh1QVvpj?7`!Lx)-LT7lan2T zPY&nH7~F4mxNEUvusC8nfuHvQiFYb6gCTFjfGFYJ^|D%L5;y(Krf^QAc6+TVw3aB2 zlrZq~E+y@al9L|)-YwTTwV->gU8n)l<@+|jzhMGhrVnaBm*PlHfuA>aPefQ??ck=Jl@Y~;}o6K*Y$Gp7$k!-wKGgmrl%Xy zo;Z?I;ODiN>ZtLMS*tw8ZXfk@I7!vk-kfkw^XugF(4GyHNgT;3@biYAK1~t9db@H~b%~AFu41>Wa?n?wS7@YViXVM|luUzr~pA~TOmx(-POP^cb^;OE^#;=e#zo=4v0sKt9)9`EGO9Q7z< zWElFWJ`2*jtgcQD!zHDY$%ZpB(7CPnB`kyO+{6)`1b*JJB)%Ndy-c6Yj+z6BKuj?n za}-1I9rf~kxmLdKhx27DZo&&0zbG!f{7xH>8oN;CsWF ztqx~KIpl4=R2gmmW?u12`FW?3{Iif=a18r~Sq`KNynTyEz;J5gC2jNt15*VyGW5qK zRl!3I7Z`nN!#%XopqFIP)MmVQ6^XwK>3oNOm||3H=s&e#%@6X8whD^B++=3D_ou=+ zV_Jo5il&NhO-meU%z>YGJjp)@NzOcbdS9Q7{58l-r7~;1Tc~1t7{(N{Aez2=t<3C6 zNO2^yz%Q>S$)5yCbH0W9H-guZ?;{kMGnq3;)ml?3-^;`K-dZQ$DGlW-j^rEod7qPf zw~zcnw)@=oR zYc2ji2a5#O{o3kM#X53s03F>B zlFzI_pEeSiF7b`9cRBko2@vKZQ!S3 zr(CTSwys{{Kb!Pyg=X)mOK1v(#%>OtPlbjraiqY3pSO&}e}GI!(E3qVwl)WnRPC+J z3Akhgwlm9cCM&i!{X+&^A!hp1<2tL`>Sgs}t*qXylhyUUA?ewV z%}N~EMGgGC)=%)z0Wzh!;YnRP1w-l@ML%2uquARpfl+jBsCLAW+6nwrY^U`)@fr0J zUl>mOraFo5-%#S>NaBGXpQUwCp0-!0=BeFD4J9s)Bp&#AJCSxZWGr~a z_pU5?`;(O4b47K>Jklg?T4iN8Csw@s9u@8)?TS|%$tm#j){}P2AIM2R>pL7o6TKmn zlbMY@9nR^Ea88uzw1&zgj^q^hd2>m7jpQU-(62BF^cfZVDjJb&x8FNeK$C45E`bs3 zXPCeU&TS}LaU|Qo&r9;K;1EbJv{kfQIvwBf{LrM?S5TK$NDgU-;&Sn!(l3S{T+V46 z1Y4$qrH`=dU~f65|1*?(eBANQ+DED9q1>r)8c&OYAl3^e);zn?^e!I8(FRDz8bNl~ zLMGNRErM8|npoq9m>$U6;c%s-azeWMaMDI*64%9B2yix+%yH`}$qj<{g4y zt#z>UW_#Pje=aq?uQ7*U7?R3s2!Q6p-lTJMJA$HMrLqN*xV}`yJfhw>WVomJDefa=*sn4czl;jQarY zGYw|Ms4XP<~V8OnV&FL5?WK$65M-0w9wQ-XGYRuJrS9W-kZ%~-Ayh;JudZ`o#s zt)VxN%d#idW+x1ke0|^eFf`+{$=BV)X_glWlP|dO<99Ru)W1rub%T#=37>PV#FQ&2 zPxqZ7>PU$4yo3Dt=jih2GV~|h$#^Z(-dU6O(=ioonb0{OlF#~xK>d-g%|QJnBpvlg z!u&+Eu6-rt9QoFmoT#MefAeR?igc=4f@oy09R#v_2A zg^?In-=Wkikiq3onsHv!)NN*!Itk>Gk$MUjvb!GjNJ?vCQj-hL*ASgj=CEX(V7-JYHvvJ z(k_nr022HUUdvhs30`xcqke}3&pC*=kl?E)IqDTi@QFt`>P|@TF_n(G0TMj84kXcgUF@i%A;AR;9W@jZ zJpM9AT?Ppr)r9jzkl-h{|73B~j;`7p!acU4yG*+DSo%y#o!1+6et57Q#Jw&(U3DNN z66QV9i-&WN#Q&0W*0tiN2a)m?Fo}2)BAl0GQ0f8cA|80Ct7b!*xf8I?GI<}K$afu1 z(oymb;Xcpef6jGPqf<;$2Xmh-_~lF|@A7%BS_?@To1RO#Adzdg^8>j)(&b9Odmn#B zl7DgF7hwcu#+C?XE5j}g{8}2n34!0kmj!p%9etK4S3=^F2DZ{+P zHLe;6iMS_mzsq1R@(&&}L0Th|0XGOEO=sOrtnP2tF}$B|aaHlHHq;(~Il@SDIq(j2 z0_ph60G|sZKEK`Nsy54vPu?E)5Db#+AL0JJ#kb$AAphUwqN6_Lm1NgeeicS!ACZWt(;&?(2D~8*a>Tw#M*K3s%h$Dtro{KkyfkoL)H!U-iv7xEllWmyFwoQn2LXH_tmAKDRpv6^W%c;xmAEGv{o zf#1s`F+r6sH{&<4Y2fFL(tdI?es63a__a5Fax;EswhsJ$9IfNY&G;?fA@F-}jP{e8 z@tf2)@O#f}B+AYB{j`&wmtTR*vnCNtrOVCu6^stzH8&5RYoAG<*qQLKY<0m)c7c=eu3d*q2_{q)q z%{1*_{Ju7Rax;F*_5PBszo=OS%FXy~Fs3B&CXdy6k(>5Y(J@l{llWmXEcMb#QqF=n z>384l?>{|PpdD6b`3_D??NA;#+)a%VCAIKc+QFm|)Lm=iFz`x0jdMHe5Lb@!Ybmpf zcDR46FS?u@B+*@hdc2*1EDvI|R?uV?R;7L`*bX!s98&Kz z^k%Y;L*t(zO{k*%%-EV#EM?cPqVvaa*ak}M|IVov24?cxzHFfoV1?6M0a3D+7LWH zKOC5yH=5Ir5_4)_C+};HBX*+GnYtU>0iy}S=F0)x%t6Mq3ZUMA&PY4Lhs2CNo*=*V z{P2#*)7;EUmuW8nP4K)g-&U&q2BmgB&GF8Age{_M-mRETm;WdmcIiLiaUdJ{D*9uR zlv?EIuHaX&X|`#ZxZF;TPEP0kx&9~n=ms;DAwdYU3l@evcJ31 zrk0WRu@AG;z60tffVpYE_^x?rX~Zt0hjC~((OXvd`P~KDk5D}iX31w|7zuxaxb2q7 zdX*OU6V!8Bj^hoy&r#KoW|}?Zs6!yljOBfUYoVS!5{|bMFBsen^<2Zb?e>_)c*w;0 zlF<-?Ou3{}={Y!>yd1uO1wzmAXtF=;w-312Y$v-b zxB^^U#OL?LL#`~S*LhAtJmnHz0wgPOsFIlHJK1Bw^Cf0sriwptv<|304~J*mvoV|C z++<56krCpHGjNR`Y+Xn}^{RH_dxrSpVNU#@eNBquUwlz!!vDCN@VSLC@r*YfAva77 z>NzZ$_{|nt^SdLKA3$qiNGgEl381`((N{C6suocyOrXV3YlgQD6c<1v!K#1 zoJ>EZ^9gL+8vQm(9L-m=OTSQgD+u~cC^$zd)n^1ZZjCyR)}a-h1SzV#b+5BM^M)g- z=k4=m3V#y9KfaxE@A^&(pYd)AFL^J8Px&B)TYQ+p|M-nhu0WF4q)g_3kl;aaSIvb4 zPi@Y3d?B!kPAK;q{FzT;m`@?{_Egj{`Fx`W(#*|YyQ~?}F=Z`+6tBpb`;mFo}BoJzL zoOYsPSC7Ib+SGDt342t^Nh013`=fTsJB%}@E1_mL@hNET9bNDZu}=0S#^UD(+yzMa8g5MZ7#Vjhv@bj(okh4`ETcv+aC_G&ZX?0SGM_2VSag+??ND!!ZT*d3o?w+SkK8lTsFW_uEt z`Yb+BvAmH#>1(7K2J!FonfAorxrd`xLd9+InckQ0 z6GECf>T*Xt59vyL9k4$=ovy@3nNs$@0Y>a&5a4NHq(WZt87bT0H#+J?NXnM?J7CBX z7^E3@v!fn|iciJ}UIcW%1x765_uCy+eh18Hl%|s5<6cPD;rlP!Y(%+7y~2SfNNa8G zt85NIT2XV^rf#$jMif;7xI-8z^+SNZ>tUpzm;BD>7JZAzqn3S(@VqD|nxNvjlQ%17nRV>b6PRQ$E${gb=4`I8W1mxRj- z84t1fVcVxN^InGu#HeWDs!yTf=P)0qC1?1>%*Qf2Iuqs>sQ4+E9g3_^&!iJ=oQXxc zzD#SyK93vds*R9tR5NyC{|J&s#Rn%@XxNUztP*ucp`qz0hMA7SUuSs75aC&<_%qf> zu{A79Y;?20*3mUI(MOx;{u<1CnFw8u_oMHLJ=y4)lY?$bLlgZX6McqVU3do&;dV&p zuA*0TV@!C3nS1Q;9hsSCq^$=po`_5;ugfOd6tvqt$l2R?Z@}Bm!Qb^^M%q3JJ4Ni1 z_EZV;fJwy9P5aglP@485P)}L<>%Oy#5lWVCJxMoj=|?vHrEyOlYfeY`#9DDuPU?xt+NMs)?vuuh9~sQkIG{zG>s&+kCIBZj zrV?be<=iwW!kdKBwB7XCgJ^zW!&V8{}QQ=lf<-6?$L-R@|}YlM+Z;f zW=>9OQSYPfoQ$-SaMcDx$mk6uxSe;jt5yLVr}b^ze&@<*eHTczULnrmnbqWSUJ`_w z+=n`UK1Zo@=fV6Avj)(W!MMo^m@((G;v#O7M`3QBA7V0@eSb;3CU@a8`2vOtsL4+- znT*I2p(aV5>E*MGyAon~;doP8JL+3VGxOVUkgcs{N;=ZHLfU6ccdFT!piv**GKQKg zCxMd|Q;2J9uv`AYe!VZ-?l(E=8AvD4j}hQ9NK4S@)=;p~KR9X=q=S9BCFC>sM<-RD z`Gp)nU^*(n(C#ZJ%3IHmvnM6tb$zcp;vFU;?kqC`ZVn+o78dPPw=Wx z2~(Kh*DcKFmm?CoC7m&t(*{uE6Btgaj%5M^H9m-O;weD-aWH4XjQ^2I2h{i!MuSxV z*&k?}!GOCQ;QS2pAU=%%6~dI_^EC@9opdG@d@vtj3zEJJWgQ?i z9?QGNU-Ge=HBBQ%wrlA?k_8bX&Z{u{z-V!rQGfGbbP*)j+HkPkW}#sFzyu||z-J`R zYcRT`l63xdsW>WDjneGS=N-d={7vnN5$igd3rg#Sx;8YD9_j=jFaAsaY`?~!qV4Bm zdL8-M59)F>(jEagLzo+2W?ZJ!<&gGidAa$-i}pGGDy6Q5x};%-^ZvodtRWq2*K28? zkPbFv2_qV$gWY#4Q*}rOn|GV}GK&s&#-02-DM$xPuHyqZkPbExus|3QXWn}9fwa#< z0QsVY_Q`l3ASB{kb~Y~%KswlWfEMS#NCJ_0EZQOMa~9w(Ven~lMpsw4ZrT)XMmhRB z3O$)MQ2YK^u42j8yY@zua zFK?oK;#b)qnXt`&brK6ge3NBVSiE{C9a1OKZDeMn=^?%;txcDZ)rnd{={86SXJ#hf zrG#6^r&~>C;x#K(QnJW$ledsXE_-oO;&<^Y0W*&0WR%n0a&7uo)m$X8jhbs|6)mUAAT`r%*HjsVmontVKjs7w)a@lFuf-Qi z9S(uLPrqbxwHdq|Gj*pAD8vOs#l%cCeMJ`BrYQl`Fj7%1vHJ zjE%%5bn;S(jThS-iCw0Exjd-&<*ej#{EEcypm=<<%|)!Ccvd{o>Q@PAH>;OtV?PpF zuEtRD!KoMt;X^SrUq8kne>z6RHpI|n=p$t~ES{7y3==#no-OiE6fBaccpuhka*3gc zDju_i(T1}G?I+{om8zBqE3=co;k#IHVW!@gUnN-fh?Ct3wNbeHvXgDWxi}IkIhGh@ zf?H=Lcg4L@@T-|YWyK`lCsO_VYdflFIBIfaLFybIiCV=@Wc4BY8-H@W#RPO!(pr#d;)d7@V&_@?BN0j}x;OjJ5K zSAd6slb7UP-V`kf9GP|cZZv%^(oxBy8r>XXbC{ms;r}aH>5z81Irt}z!tzfX>;7|B ziJ~tr^BbBQ)Vl}G?SUqa+9{7uy7i_xoDInGU=}eA-4pPDFkNGg*=X~cIch1?duPHv zc@^hnu69-L3uukM{otxaTVTXz`<8suz%t4^oVI*F)O#^=ypaX2dK&6|E6k%;vKS?m z-U~=!->7-HWNJ2<0_v&I1BJ*d;JQu+f}<_Ji4n zW6NT!44&X8Mqe=aPP!d0-BE`^gI|;mLr*N(995$sJ}oc(f$WECkG$hqNyT<@)V^;y z-tH?Iwgu~_fw2!L4{ylGcv<(o92H%((eHPz0euaXJxS58-i|FkNHe={@2HC*&3xC* zQG-~~ls!+d9459$LS^f{&QVxp&3R*{c4Yu~R=~r2mSJVDHiBV;o3! zBKJSS$*Z8f%GNU2yPnmf>?7_UWgj7%)u8s6D$1P6CPeBHMc#?9??H#Kp1bgS)~bTp zxa4ZPVYX5%PE>R;T=Y8mnI}IN@DsyoWO08ZcwJwaBc^=_)E~a)UGvZU2mJ+%TQ=A} z{ptoQKEn@oJMGH`yR2TYz5QUuIvzQZeWjB)t9m5sxARV?$G~40>4H@$B>xRr|7YDk z`1=2Tv_kM!{{3hret+}7AC(T{zxbbZwJx4O2KgVO|LOlMT7&xhf0_&2=F_Y#kPpjI z>caCmOFBOywa7U9z{yH|3U%l}1%I`xql(HL!|VyD5@rNG9gcI*=kTBaz zvdyv2T}XBcL_&#zYH{Uc0o0*1n)m`i;GS2%Z?dl zLhosO|MmYBE;%(&Q5mqdie!Wf{a;~WbpWhbM%D@o$SRk_ z3y-cciiby6;r-Dy`P&=@b4j>!G`aM6PJM%iM4aT!?3J$tmp$bq@85$H?cnmMPI3UF zsX9%mcGqU;LAC(A=UP3;mID1jwp_3sWJd`$gKQPhA7tl)la~Y|D;-35WEHl~$hrqk zp^;VC@W`t92~s$@lIJk6EFlXK`r`xHQWU(0lhb#1W(MGrDZwbN^IB!1#jBaF<1IQU zJc!xC>EH|#tq9z3G!^}j=rNfUFdF;@ZZ=m;+FQv;vI!cZ9H-sBEgaSIUD8W~$?wDl zKjDY)xj@}YuOgP@uCtxUddSaK)=CX!+ipQWN4)?I>E}3N&-z5f4|7R}u96ssI@)a)+)syJA#Nw8+*ZMVBW{nG+=dYDXZYvF z;P!zNf5T3S#QuhS;?zF6|B{hT^}rd#sW)MpKN zNO^}B`}0pC1s-53;8zmvKG%9@x$%2+{qpcs!ZdQ@?Xh3EgqMGtx7R6}RmX8F>4abM z&L7zi5L3%_b5_&Jmx6aF&<%byu-yq6y1{Q0Y#aO*ux;=%5%(K>iD28{%LJPSUjg(R zd?ol#HFz1rLk(WoaD&&pZSakrqgl%(D%f+apm_K-6$+U3x4fqkBjs&;Yr+gNs#8R% zv;10W<|caBTG@`2hO~4O8Man3gfBAx1G5HIfpz^X5!~F=&nmF3pY=e$el`oX^^?&r zsGlOBUq5{W+xi(M*woKNpkF`L;Qzt;(f{0aA$bnj-VN%iP?XRjRae3@?D}uGSk`~T z#jwE}F2aW2aH(5Y(lKrIog&?Veol*ekGeXjB@MN`n=L)nihhW+L!Els!8QG-G^IUG ziKzTZ^nqR6ytK>s4=>EVhm3Y~V>}aoX?D6f^T8GMHB)%qhDX!TIk%x=pCcxH)Qw<| zF3j(uN&$3H?YODJj>4$esmvyA&@)WX=(#ycb-a+D>)xjSTFtwkT=E|Y^Nt`4J`?ndr+@$=M`>_6RU0;lyB8FVk!Zm*MhBNB2)x=v?tW_Lh6e0oGZI)H?R zHmd$i94Qs#4pllxF1X-~h>176(Lfsn;gvgFwOb&)^FG8L$S7Jd%u!E5?rx45sAQ;n zg~*~~x4F~qTVvx4wk?ibcA4?+d(5-020Yf^l_Ht`eROtH>0ZoD$YXYTA|U3yi@KXY@|*&#OmdvYwH zE66wA(`ochC!LQzHkbKT*3Xt@XG3Lv9seT4cH%hYs%a*)cz3$bi7yNBU2b#}Hy)7k z?=r<`C4Q~VJsrPzZzq0(jihC=#U+MFqi}A|Oa`Xn%3NTaRU>YntFX3sh^akN+u<-sgIOn2w`LD*3*wpKj{RCiMcnp zm#(trorxcpS^`OHvH10ElrV#kfkr7*>uLR=MEKIbu|!fbrksVo-8P0}dON@R?t!zyic< z!WN+UkOc@IwgAmrGr}wDi?;l7WkdbCCi=D4oMyeV5h30v+Xx~(UEimiMjJjeA%x!% zS-EtaEr3&K+#4acgK6AV_`4lbjXRw%p~fw2xN&PfXxvLAvT5A%6x}xN%|IG=jx_F! zJ*8nMrD2x}Tw?TH0q)mE>$@80>w5{<*Y{e%M&Db2wgDG0#SZIQtSs}Z9BIJA@XGu; zDUG)ZNW)D^!(A-+J|`)Sb~PAHXG??KEcidrSQF20LME;p2+bzNIt%s!cXD#XGW&pe zg;uPxLc^q3WEIf2#`$1tjZ1*Oc2!@T<0znSjaA}otZ}|TYmH05)*4pEI3* zyYV;d>OdNFhXb6%Q1<@i629H!m`Z$Z%~+-n9S(Goi*{wpLn0sKB<26eXY4~CKO-&p zAM!GI$UkS-8#6`5Q*X?af&Gn{QG!DoGZ{n*k4VyEg-0ae{SisUlgz~ANm?Uv3K za6_9U2o$eIt;38CWJ{++u-(!r12-H^1xAuB6>yjn?_mepEa68uSu?E72%r0G;!tZ- z+M5RwT)|kq2aMY_HC78B8mkT4;8%XBj$+>77At&s ztk(X2eYUo>v056(pBt-7F#Vx55p^@QP0D4<{*Nc+^p}5aQcfqbY&`QCa_I29o4f&B3NCJ!nOp=e z7hIAR9}bpFI*j6XGUL7!3}r2 zy0>16x4!|uTCnY{H*Pgr(9;e^r*8LDPb++=r!{QQ)3TQt%tN=3xb10k>FNERwgl|= zv@)T!J#7W>zu(h}rEPOh+nB&A!N4R7?8N1EotTFs4OutpN(!}=m39qYe#2f2{;LgJ zue4W4V%xORUQ5V7Zq)y|mA2NGEV=g!>nm6EHPDIsyAk6IueT#Mg_M+WkXDjD?@}T- zbl&9;Cw@BH&ZIgboUPO}n_O{!gQ3Xs{%(cLEw^olL6s0xKN7l!(Y8j?DNpU4?RA!Q zd)RD|J&ONzxam#2C!OTg&(WTS6Nl%5pRfnnNAOA~=T`7UaK}S(Wcj;L;CXttVKvaM zH#P(Pc2#g_s9gy*Gnk1$yZW6ku;KN_3W;D=zw3eidSi=VyWS``EVbU~BlvG#Z)ELf zcUEF(s9)Pg@3iI4rP-c>;-A;R6kpESIk|+FsY}{W%^F^&E-E<=3#vd`ceRrv zT}&mI<#Psk)fgzt=f%K|*J|yq0NP$_EzsBQCa~XYslx;9763!NRwh}7H7tC1ei#@3 z(EL#I|NdT%s7Uu(+*P|?JYhSBr~59)YTAp-X6RQ;PCGvB#Kq*~+5>Xe7_%#-Aimj^ zgRR+(5@^h>3TVx4KG0Xp60onBRf3J#tp{4O+bpo2+5IoyHT^5LR(vJoRiI%5eF@vCRZ3r)59v$uA$4G@iD3HcB|yKwUM<-6*PFop{!qrK|4aRK3DUaHoBp~CZ2Rj91Es&N z1ls<(259^1#Xw)XE5N>X*9tb>(k9^lvi@3k(H!hn4`N{#D2o1qu`)Fpyw+G*iC}AG z6<}*+H3E&5tpHjp+X(dakTE8uhf={t4;4UbWz_;3wz4G>!C2X9pl@ZH1Y0Z17@M-P z62bo`W(A{9V(Emms5jo34oa>JsKcyiqA0}cZ9!R3Ruj0xY;&S(A=qC~E(QAw%GF?h zLAep^FDSQw{R19MZv6#iiD3VLhhTfa1L!X(<%=zUYC+kWGK9AOgbi>1X}#dnEX8o5z%x)bu>24D8QiDvZ0H$5aZo z^O(dvC9c+NbAI#Bi|DsLY9zp-h`GHkKtMl7G1| zmeqo-v1}3?G8T#P*C)LhlXPm@Sc<^DvGg(STD8LjTVv7HK2aR5iv-myx(ipc)}>Ul zR7Q;i-pfr&MJxtW3CUl1wzdMitrf6V!rBVh1okUH9hItp0>QQdO2L1+0^*dyuK+oC zT}~pDQa|4tC5hWtnyLibSDNMv4sG$oNF)4gPk8^?o>tuwNpwD|sqhkITU*R3iTqbu zOwcNJmYNE+iXQOcRw4YhR?2#$@hfGs=)ty%jHAJ}RTK%fmC^_NZ&XUq>eHkQw$%?K zO)x{2zZjE!G7d}?tf zxvASBS#$>@m}JU|TaRE9DL{DjU5HG#}EJ@L_#v-q#niNWAr?>gmi>YQXM>)TV0ldDd-DH}C9fM|}#p zW6f^Yv4ow0zusUS#=FBWvg^kViMyYhJf2O}`GR+IbNYc-fbCLhqd>Ei%BT#MQl&tD zmRAAxXL;3v%`9&T&@QFc3T${OwM8PBrBuN&D9Ro$>Lb`Lr7FNEL?17z68twWrO-<} zI@FArqHL59A2KAx%MPmi^9;GfKhNx-{&ohlLBtXLwV_s42_EIfo9Y^3NF`{vT}jji zcC~1w2Xbast_(=;K;Wi})>yS*bSm3o3&EmO*%DhSIAvg}UG`kNQ96dt13{pC>0dCfA$M`ej>5X=RLpCI;IS$5YJtwf=B3T;54vq_exYt#^MAD)s%NtC zLl9T4W)NaFYHQ6xvT-M?xR|b7S&%!<{crAEqDa;LT)T65a2*Ri#8~iJ(YEajH-W7M ztLcFS7XaMUg>4_ouLcb0)=X-gZOvMk~M$3|s)6j-(^Ps6k>5Gx;U#@NkL)I*I~70duzvnmH$ zv#JtkI>seHYgTK4zFBPn`({-%Gcc=ipf#&Xf%VKvZ;CIJ2xg330rbb%^@8mfy9Mlz zu?4eI<3VuRTC^E{LZ|sZu?h39A7cK6K5{A+)(2@(@3w7MRub6XuB-w3+m(yK{&wXG zu)kfo7VK|VZUWowN_o-E->xhWY_}^*1)J^4a-hFmISTwA-ma`73xB(EzF@muxdi+N z+m);E_O~n73%1*po3|ECZ&zj<{~y_|EFxLEUD*e??c0@dWMmjI+{4_Q6T#Iwp`0SN z@8nHmW=OJKxe;i$D|2Vl$jo~QB|yKCm4W?6Rw3BVK7jwrwksRc8dWz)`qjiQ%-H3U z`6HdG?qF*WI^4lZd;NGZZtXWk#@89zLmjXT^`Q>fu)(rO*zmGQ^P%~O z=0nRO;ls-!&8KFqS|c*Yka<&Wjf^!KSu7d}O`x_D0sd<{w{_?I|2HO3%tOuM^Bo4c z8n8Qwe~}}O^7(`5ybdR?3A#_^tdV_awtn1aa$>wjvliH62mQL*Cg6@e^y_MB7kx@r zH9BkuNy4nIdUVKo%pPai9;Y6q!5eY1vz7N=>Ww(fvlff*+fE{zS3@K~dHWRay+E*> z*ASbuKY5W~kM23WsM9ha-L#u`>qn2B&%FG@Tb4qk88;TaLT}8NB-_jX8AWTG;TBYt08ot}DsS z9=Vcjr%Ha-Hm(c?nxtfoTd5j z<18^}3E)5I&;iCV@u@BDw+)LspDcZGmk74vt`f2AbB6VTt+<;7TX8e6%)e1wIgcw> z3#h}7(cmbq@NzWwFC4{X_9kzd6(Okqrdb(yt8bcB7*G8qstW8siCQT5-+t3fR{P;M z&4kxSN)}PX6=WfAnjJ(tSPPbIc{ysbN!;z5W^zQ+U%M56{k2;u*k8MqgZ;JJD6n0- zRRR6A+kC-x?Y2a)S-Y(Q`fIoK;6Jr?JD9SBj+zK7kGK5yw>4k;sL5us@Yik`gHmg^ zB5*_V5d?}?v+%{+U%L$xY}alRw;C<=rkV5)@}`;px}rP@4!^D_yu7aX@4SjuP8x30 z)C&^AvmDrl*T$Rh2@#pZ0IzJu-p8CgvuMv$06p) z2O>@|!?kkxa4ScV3z-PI^LeLq14exi_##J7phto21iA`nC(!c+c46A}b?piCTeT<9 z{&DaaGRpkeKMt<>ZJR)Q$g@Ob=#l9Uf-P89sSqraG04ffmPLh!b3$GmWqvYe znuv=zLozKtHpI*PMBZ|eOZ@#=q@I=+ke{8Fmjdmyyd0>f<%#v-Y57Hb;AQH>U|v3- zwThjWA45w7ZH>JCk;|SBRH(*K2F-u1c~t%i;Mz+wPVC zO}o2w7gI+$+^AL+djMe9!w=CLh1#7wN7c{aR}tHPMz9HN+gbiQS(39C1eifE&IpBGUQ);+;ZzR!1R zR?ODHbJl^^gHdiTDsPLxp1i=^krD0$g3NK_$AaZbK;gYc&0i47mN#7b5SF)F2y}N# z9XNFk;3Kp=%p{e316&EF29nnt$caC}Q{3!}z)Qio$0DkV-w!Jn%O2%c|CgSIB{!p* zjR?gPqoh-bZUnOn@hyeOJ<*ua?MPZ8*mmE^<9agZ!GWqs?uJ4uz)h>%#BJ~D66r7Q zxpUp%J+;Vf|Cn zH0+fNu&BrQ(H3#-eIoR%)X_ zYf%{|5#*9>v#27%{((jHF-d8QssQ^IRVCP3)IxAW7Io==)1p=*ly6ZR1zU^SB7$?6 zMJy`!7)`G+5n53r(zn!P~zw4k$_PJEyCdvIS zH?h)o1Tsx^m$^Y-*F^YxQkE%v=)sd=g9DhEB5&vbrshL$$7!BPfgG8VOY=+${I>~( z$J&Co2{mu~Ff`_Oz%tbc3nhF=D8mL%!-Ne#4byx`2+fCt5I!t~=2JpEWk-Qx5#nAq zYsLWpF5wa4COcO&Y`jDkNL)Ek-l|9fb&h=$!J5taVX=X}ZUfjVvap})ON zFC`n>rdI>Ey-j<=X`*LJGo?vuMN7kci$0DrC}y9DY^WH>5J$$OkYIXFntmKbi>?KO@9CRhM6%pXqZL7ZEu(= zx;l-oDm2cZ6EsgOYu;i`r_$1K(f_DEH@ydo+NT-dybU8Abv2aVjsMTqdz7P2gYuh4 z*jjl8fBrM&ji|IwS5{})X@$5fH~(c~6;P*@NTt<@y_1un{FnKU9p!$)&%j*Ef6({_ z;siPgH_8np6FHn*o$v=EWf_?k$5a1fkc_m`$V0oY-{s_Uw!FyhT{GEHnNz^~5M=;BGdJ@;7v%u3 z*Lj+wmO-4#hpV3MsE?uiGtkO`Gb}RzFBQFl(Iqz9VC~@-I@8PJUp&mWafP9&*e)Kga`btj0{6bOl1|8<8vml8+ zZ3OZ`I{IadclD$1z-9osm;2H0nCYmmq5sF;pTI{|-T(jiy|ZO9lbHmVNR*KT)DS=c z1tbb8DkzFeTmex;M2R92*WyyeJyzS&y5UmAS`}@z)Rnq5bt~?1sYcw;x}dd+Tg9sQ zd%n&&_s)%ig0}s9KL7vsJ|1W0^*-zSZ11z5Bj+a^=X-xb$+=0w#OD_hf_IVUO+gLW z+%MG46CYd_-6C|F7MhW z?v=0exDvYSX>o6tjWd(ql|Q!C-eu!Xw;4B$u-zEbml=lj>*Qoe<}l}k0uI?_mk8Ok zRm92TSl62vyA12HJ$-F`#z~{`(0iWz9d$Z)`^(CR%002tJ{%vnSiMboOR*bl%Jbkf zT-X7J3p?O&VFw&8?0|!X9bmYyBOEO32)l(HU@(!~0bZSnzc3j-kJ{ zutN~x!p;_vg&pupW~uPdF6>|&F6;;g3p=ZF7LJG~<3;owu^JcpQo)GWk->;~7i;?6 zBjVWv?D{%$ft^LF3PR*95s}6M|6buuq{zM0=3TC3tb#ny*^^y(l%nv!&v<`|*_K_7 z^9whe?|U0u0A_B+OH8Ax^^xO4QN4Z~_x42bPImVF!=!6V-p(;UdtHRq6~~`Vx8_Jc zdy|vBN{u?WGf!;jDz!#%aFyD4;f9PkR5?pHa*djLye#d8*Qkkh%e!9wRqE{=>uHr1 z_2z?jc|W|&IfLC@{t@24EHb#vxec4+qa{fcFv$;4O2 zJD24 za8RFG!9jhR2M+4fLa?h(?ZBWuEfse4$r~2dry5{Tp9X=~s6NdizLEMQGFqPu-MK!E zA&8(pO%`^WTxWs5r9REUIH*tagP1RvJS`Dvju%(uAwu>K)5-oy?u9fO@!-xe91C zk4AUMuG^fkOiTrbKsN&ihd_mcL!jU_-kebmqXfbgi+dHBgT)J~VD9eY(B_jVwCxf! z1Uhr5xat(`+}AgH)flXGl09&@^MI1xb%EZdR!_dI&*Lk`EfwEOoPx+S-HpETyDRDr zn%7qTcRMlE>cZm&M(c)9>ySX}S-Pm@?ED&n>i2rWPwWFoXfIgxVf@@F?e}>Erg|g# zeUniA{x0e@^t*}L)%O$Y?vBm?etwK%Lxx{{_kNlBw=kEYZM4ZDc zm@c-iUYj2i3np24Lwq0K8-eQgu&5KT8N{M`-HUnc57qB*-@emzAJwHRBW>gPp?-d? zw`mwofye2k+nUS8^O1gqb`mwo>{#DyX=)Zep2mcFGF$irE z3|=JMpf(^pxSo{P$NAy?1ftFT1oCr<{5+Wxdf?^O&u>T+6JXV;r2reiL8~@WxFM69 zK;Zf$6sV+v=3>?Hm=i#FC!j8&((#&VS}A5bs9?(O#m3WJz+t8iO5U9s~WTBH`ud^19ScUUI`cCVr~G zUw169TDRSWo>?>Bq^Dna_9Du#Y;Hg%B(A3=N&bN!_lTn%UiYh{c^iYOYw-*F;lm}U zx}*KV#5yplZYRG`-P`xZqU!eW3%l|E6XEf^M#=vp!n|$yH2+=K15aUq$N&Dq)BM5! zp19rsRrh1R-{Bk!zaCXL%Syhr6y<-A4Z6mC{<&J0h&SstCHp-EMy#1l5AgaA-jv z(5pKx+(jvp*3gKYHarTpC3Xl0Egv{+`91>&EuV1E@`2a5+)AYm`Uu&!N{B=}+( z`etfl>ApOq?iGfS8!f21OZ`Hko)=V6byxU>as2;S zSe@A|e5qOF(9xOfUc1WB8uyC4)GTu=oihKNWo&rdG$tS3j*z@Rn~xvI@c|Ni*oaJi z#n$Z75avzjep9ToQ~2Xy;OwrBFVQ>>oEf4q44-JcZHSNqeZNZ&N2f6!_;hA#N3JdM znJz==@9R^A8F-f$8h01{+}Dj|)5{+3Qes=*GPv_(qwk3xIy{zr=0HoY&)?AHeztG3 zr6nwSt(OfSu~yRb`Y3~sfs1wI!jFBoi`+hwvC1bu<)V`hsWtW?70XSVEdT7;;h|+E zA8XJXT2b;5epeog&OBAbD&*rBGI3~5LMV6cSbq7G5xixbjqhYga}gzUZuTrot8>Hp zp@^z+Y6@99FbptaJFCkeHG3xCb5o7&OjBXG77*eUQ=D=dz(65IWdN1bchKAl7vgEx= zg!SIYZZ*E$%M#{E#=6ZBd=HY{$#&(rZ{AA0=tD_x^d2#K1H8ojIjC3psY)9g#r>4v zg@tV~?^D#&jS#zZ&T8)mZ|W;6OpJG;^|<22xHq-0mmGKx8;Lr(9)`}bsHr{t!m0e< zD_rXrcK8#|y`!eCSMq7Cz^Cq34D}mNu&o3$HSZ_HLgB$b$IO6y>Oe%&Zy#``UF-{M z6R^3-NAya>nTRF`V%|WhNcLCJ=oIthkZ)>D9rATsYoBejlAoEsLRCMWgG2TF$cf5+ z&m77sEv|a@_WKPy#^D~e0hMGpJeDx;!1X-A@HGmp*8(O*JS!%XchP2bVz01&gYW$U z)$?vz@W1!{nz5Js@*7(9+imE3N1n5==oLU?!XRU{ys(?9Xj!E*yn`EatwNf_9;pQHYR8qT!Mj4AD7~Jx5KHd>JnI%X zIsu}Oh)v0|Q?PlXZ1bwkOJr0lhCK)RCe!ADU8XG*w3*fp3^HvgILI{blTxPDfP+jM z1a_G=1{h@8WMP+SvxIG?%>f3PHXr;S&a^gy2r{ih*k#%>@V8`I`k$pts}pva)(Bp? zGm<-Tj|ApDy@8#@#yOjzW3|jek?l*DVQ)z~;jLSq@cNwNt+RwjX1Co|HhXNupVwok zh#s5s%W{wwd-@%8yp$z80w|R!cUH+#W+7x~049p!UC7 zNV4?D%cK^BJip&*Otn6U+H!px1ND5iV8D>RGUjbrXJR0&rxXJ(aa?~~p1}|MD`)d} z3>72c6`H?{nQ7-48~cTqz&%&QycuKt!pU9ibBr^Jexb1|ix;RF+ffM;XAb5Xle76@ zeafU{`H40q`wsH^ok>F~dE9q%TcNsw5B|(ms4XG(f$$1XF6H-atkEuwewU-MsJ?sq zg@53@=lkG;{lZzit#mi4Z+CxS&Dk+;G^+2RrKoN||92l$-wiZi@D$a9A(cmccTWde zzeH>C?s2d0lu+wFv_6!>!@We)Fk&>0pX5}2s{GWx{Pmuu&bybqK!%Cb&-lylr)5N* zJ8ty6Vj^`PS}J3HCiMjH7#zgXsh5Ct{~}$oskcHmsZRo!@RFJ_WQlD!f5v$#wH?qn zPo#DQ4#qj*c**l1I+YUB?^na|PbARByr8_tp_OkVgqo;EdrUVns2S*F&}=~~gXRJQ z8MFW#$e=~wpy5~o4rI`Bu#-VmpO$1$gRql9BZaLD8V?L)Pz(4!EQ4AJB9KAzgq;jp z2wu4`F>6Nc7zYiYlAL)WzlO>V*DtbSy&Mo)=aMBT>c zZ$+&?B<5B0vM;^9I1&@p#lmg>qKk-?ih93r(&sVnFZ843as&chPZvG>HDJO?XmnbS+Oy^8xOqHEkNgO z=s~)0D)x*APm)g4s1${}&=DBj-N~cJs1-`E(Hr{x)=Bu@(@2ET1O0x(Q@s3*r=y4Z z{pO~b!6^5=(ZlKAZOK|Y(tXx1s7)hHl)9mF+C=i(D{Koq88uoHD}@`Yd~Y$Tagty7 zGrh)7QH@Q0p^U!bW~j!U{KQvTEI!?zMS2o=r%L?j_yYt53De|Lt%Q(BJ;tAjoj34h zpo!A&eQ)57NV$_yjnn+ZV;kVn@86AiZ=()b%P%bBzyCkLgjCpbow#=<3Qr5a=l@lQ zKjeS?9#(&0ZQOeYCAQ+UQpt&=OQ%w7#LE6eZGD;bx z2nS;2^Hn+H@!@f*^0ZN?mUS|_kFvwn9*}ObvIf^?veL*48BZi{E<&}`g^k!e$TQmU zVuMhsJdaiv25~K0xV;JLv)+fsC#c4qOkNJcZ21Q8_iB4L-vOTgcf$jdPf61j>dEJ)-A@XDRp;fyv+-AV$#uS9N1ZdeyrtGE__ zwxLQD1DHsyAHa0#sa&w1uBYllcT}8Fh-uN(!|)Ps@{`;FLAJ`>Ue_k=<}@$KVhs&c zQ4^20A5c6IjWTTyWbIRZoPXINUE?fB67+ep+jy75j!okQ0m|Ms4& z+Sit{X#sd;>0Q4^g>QzLV}`j^VR`X_ypTVOK#<`c9 z=HTDSV@~n&ThnP91P;W^7_h4WlYv1Em?i9Lz#L&)1LgyR8qfyL zUs!c1Io=_-f94F6dv>}de`t80PsXD`yPTiWl8#a?GG!z(I%Q<&(v*?XW?7x(UrAKe ztCU28gk8lL172B*yE&Ze31x=~E?KVg^YV7GoL}#ol%E~(c3#BWg{$<|bkbGaHryxf z?N!UZ(A(|glJtHS=(SnBVd#Aj=si@jxBo=vw!NhHK%n>6lH2-yoxK-Jdglase=E8D zFwlFaWN*LyoZAmd_8trLmY4K4Ww*VF$5$o2d4XOo7RI;B{?1-)N$>DLufC-BRG_y} zNpG{s&g~GZr*!#kpf@~LzeUj%=NT-4B~+wLuSc!zlD&9H`m3>p%<%pSnM5Rv`743~>?IE1C;3a}?HP|B0v=~~ARmp+kLm9FiLwt6CN$q( zq321y_fu5=a~Uk$fT(f%mnT~%3vfMHPAXFW1j<<=;<^Ku8=s8py>MMlU2p+j^^E{; zAbCxI&mP2h<6swHf{54I4bxu_uxJ95GXe}<{~nj=X*NJRDm>)JNK;h*OZ>t$&Fp(Q z1k)>-Y%%6f z(f5+?T*FJ>iImLFyUm#C&zPAAnQWDem_ZmXp@v@o&t?JLt&(4c;hz~c!t;q2dfp#V zg9rG9d->Py>cN9qcYTRjz?Z>eN<2UEn&o+LPdA>fo=b!$VTldXeZ`w%7AM3?O4Z;! zyu?SnN!G9U(T44KF-zijUTWi>gL+?)SP!Eu`B`>A%!{vUhwA68Pl0;q#+Y{#xfX|w zv)f~yc1_3o_$uLEo9}sxUyXZPKZM?n_IkMIfIHdi;ef&Qa2>z_NY=SDCp8f9oz0zR zg9Q7A!dH!0Wt&$uY)fu)Ge%zJDDY(Ard+RWY}?4V*vq{c&+mp&D@M7u;`!|{TOiEi zE}Mfp!1;gj^pSJZ12_50ICMD!z$ZDMzs1iT6rsCP;urs<4W{)JNlV(o&Pf5?(^Kq5wh#XVj?@kHAE^X`Kx1H z_Knb$H+Z?~NUZa}j%7PFT-V0J#FJ;VT)Drj4G>1b5x?2D*o34{nU;Gep4-!TX=vTM zbmll??yVyWf2YL!eRm`W6(+uyxgc&3kP)9Qh-(7sM0_|nR5vERcQ`my=x%V>f>pbL zIPo||Dbc~tCSUcor9Cn9Wk@g4gWB4^4?m~ZLtSJ`-f(Ect*4G&fs#HIl{lkIVW^FX zBA00O3ZH)!^W;O~LOY?-7k%#r)TX{&bWPM7ttn_-5@?-^ea$c=PF2|F^0O9UCyO@h zISP9tly3g;ws<}6$y%~U<`69D!=;y8H+P95&L^_^>4aDLzz~WfQBL-%{3CE4a8!F` zmw~)iBKS;Y64);IZso>6GfIOr}-*J^AfHlCz4=O()%LWPFo$n4D1I)dV z%-^y#wL$n_$;!*Xv%vYwGQV(TMinUE++{o0X%ty`6F+2E>n`TsoL_JJOXkD~$^NB- zU5QXJt$H-ugxC5+=AVyck8}PTx;++dMG{?km23uI=2(|X%AsU^?pl{hBC9`1@N1@u zjA%?OCSf;uogWFL)HUxZuPPU=U@aZFn!2O%Lav{f4?Lv1 zkxXsCm37ZD`x1t}E~wOf*`X1#ddp<4;NmOe>f@3m{QZQXuOBM)m(2aHs#QQ9vQg$x zmsKJod+$ZsszYofe*53S&th7ZvSVy9eFgstso&dG?y_TPc_QmAW~}kZa?_?f{fb?B z*=mGcKUYrtjM}87m#tVD>9pFSwkS#2bgM?nueeLWX=@j*bPF)kXbbwUunRELcJvFk zy9JnOz5K%IZUJVRHmW4n*@B;X{an8>k+_MUuYTow*+1AwjM|C-yyT9ukVtL9-yOrm zbV}9pIZjrx>hrhVj;ZdcROjYzZ9FfS~kC{G0Z$X0Pu3g{il<|jauW}x78ie!a9#!W9n}FRryvo^x z&?4<({wUxa1#oQK9L!!I9C-o2c(qZ|ya~}Rvw`+ah-Jd=O^B)&!QAhmWY&RD(zjI`7NaR4*UHRv8WU4cH>P}WHSku)z$(vc|LeL^#b6xma zfJg!ip4PGCf9Yg*MoF))64l%*tK`=wGJ3a%p??|ge6%}q9$tfTT{_c!rd(5mP^*7} zw5s=53IMs&+^cdJg|OAaD=GH#1pDM0cc$$C`XdtGeV;6O8zgl#d^GnClUigXsVx~M zwJErfL-eMsMGny$Iuc1kM~=ygj-FpPbXeZ#gi+PniG&WdzHZXw zWu!(paF^)&HWhj!eoTcPh+GNqAXY8aUyt;Y8%tLAYHFpirCR>py2fZV!~X7B1` zL07G38ylut&jSY4dZF;QRBMx^E3MWURcn0`HO&LNsA}sIN%eLS7Y9Mag@cIGyr_bj zhzq-jSN2t8&}bf1SyW_zM5ds~2of2U-C4#)SZ*bzDYv=c)n!BfGVbLDs72*d-x3R@ z5~56M9vqesk&zN&$*|aqjNWKq=mec zLwk0)BtkYe(+}U0?(Y$(Lz#w1to0tZQuW}6XxznggxyG8SPz|pQPbbF8@jYMIPlH5 zcQR`Fb6q|@#Dw5I&foMGJMCkh{?bbKF{kNJ1pAolgxx;oMsTo?xk=dVV{R69`g`cEo#1Y?=tTj6Xe{W5c=%T2aTj(Oh2 zxKmC{pU=@MiqKp*oqn^Qf962Oxx(X1yHiyGdaZ0rXt+bRi+tL*PT^PF4u3WV> z)AwH!7fP0>i&b)!Q5^J{FuZVQ>nfS*5;!o?DD50p%Q5}1)!?z>dQxzSQtg0PUe6&e z7v4K&E}^YjLRz@z5F3Oem(WUhMsGVd^aJJLZf4QJF%-|-ojejBrr+-851i_GljU2F z^4wO0sLw?3uedSSiOgPtO*%;8XRh#{e8bNIaKO(ZVfQ@a65+`6j42N~!i(sT7Y3tL z)AA2voCW1a;%oYEsf6pI?Nz|Yr<5-lPruI3Mt8Ym>w9c-&pt6r9JlZvyWZ--0xWzalm&9ihb_c=stJ(`~Nn&5B*=X(Y=9O zT*XHBf6|%MSA)_<_oG~aP@Q)h-R* z<3{i{6Xx_P1eNLBOvFZ!9#-a!g}z*Po1@B(t?YnYip?pn=FLpo-++7g6`E$N0c(nl zuW%1NM@@*79qlJ}??G>IKYp%7&8+eh`Y+tYk0kBPuD%h-g|*hT{mGdOviK6$(5bh_ z&Ta+KTe=qA58*uF^}EKiN6l)l^83oN=8%$y**T=zADalYp>+ZgsH~#Hw+vggzo}|t z8Yj(+Ox-b+yRO5`k%1Kp-eXlC$Z>uqj1KF8L%!aq+TYlo(!I?4FsewjjDY;^CE!-WZjSvpgeIIVT5 zi-7351M_W6XSOQ=-}m$TftM=Pt|^_|&0sBmK`giB3;-WRRdhHtFP@@P^P-uW|E{Tc zY`I7&fQA`ybNH}!V?Q_E@vHo(-Gr@~(-=owkE-P;UE$Vz%zFn_d#hjgg#Uh(7B8Y0 zbw#1y@8Uwt9DS_)8)KIxN*sHb??8&2OQgNgynklg9O|pBh~n?K~sx!G9%R2Q}+b5Pg1CLVo)oL!nA|u_ zIkFi?+x-n=-lnM9W8!Y6vU<0}n42DnpFifz{R zwmhD%o=S<6etEni4Q>MWN^9EBt8ZA}w{fU+5o<*EFG0kv{#wMY`5qC=zcQU(kAlC( z&o6^59V-x9VsWnYt1OEPgdK~Ez>Y=RbrM^f9PZNlcVA=chVRSP5(RmKWotP&V5@4w z5?c+zj;)d4PHd?d+!nBP^VitA<@>Ou6dJD}Z(%+e+!A4>HNwig5-WXR!V@QhkRql) zGDp~{K;HR%Ia#O>@3fq>M>ts;;Y7`;OBBP&K5$Yz!tS4`JtLOC_&qcR;Ln+{%Bzk; z5Q6Kj%YU*b%WOdHy_-+VFb3T4sBhNRCWD=rnkD$%Vk*2GB~M@tkD1D6xS0d}Lcq;s zvHXWj!pyv#J0CTNep$umpBg$M;sZGk`Wqw*| zxmdK?q+sbzL-#yS;s#516`~_cccM#6cSZ_I4E*fKxOdi0NW4#DM&u7dPbDC$`m3)O zijtU99o8q>Bz$OHg(oXFfiZRKyPew_rr$`zos;+?(ezB=9*iK4_S?9K#+Thr|>1&!4Hd#*W%7z z(^tI#qWoY~&0u7I?^iueBkyhY8|%J&ERT&`A(CKlKvS?UwSAGNMAze{?5bytQS{;XyMeTYbqS zyBn#dh3YYjdZMmR&G9k6{xv`=&T3A9Skdf=B=;04J*(I2YA=(hd4W!rNs|JWUnbn_ zll`f27M*#WM2FOL#6hj)C zNx$4y8{2e~Ig@_;<}Ptg(sIJR35hMNlb)8&O>j(UR>V#xg^AdJR?VfZC#}31bf9fR zYOajc7kb#+Lux)x*goqpEL<5_xIUJDgyB!CQsH;8yc*_t!e1mz%e)XAw9M_`pk-bP zUXA_iVRI}&6K#&wIY>>lor9XTmrq+y$8{bdB zaMZ!BgzszTUFOSoHqIIglgZ{^V?jI8Yo^7`J8W&T&>S~s_O&@HIE}Cj9Gpf-Z@{L< z!|h(|I&iQTyAka6VmASUz1YpdZZGz1VLSYr3k-&T3&5+9d!-H78puY*d?KS`K0^m% zKDRHOAcE5fON8B~>*e5;rmMZKv#P#y8bLRy2d5E6f>-J+TeT<5@Tr>A92yUIS&3#r zHP~h4$Y7V1CBv?oNOoD}PInEdDt7*fQrFGUk*=HQu z)sti{LK~6#Yg-5pLT}Nbw)a-^dcug+M%bu%!@fq@B<#d$GdK{dvxV)BOG)Cn5hn{G zP8LO+ED4=->RJ-gH+!a7<*> z(h_mf8gVkO!xj#D3b^^vU90Ia~i{#V5jzDS0I<-8P{W=P6)KVGBxF5wEj*v zf|O$OJ?izqoFQ3q&)2B7kxq@58c2GZh4h4RQHF~>5WRCyHKS}z(D>q4(0`TQ?(E%v z;|+A|blk<$bv(cN9dvrWNpkGxTES7+IEC7Ct7_Dv@y>nD$DGJM4@>u8VTCMx6wm2# zSABF;yqZs(rT!3IsdKuztL7KBT+dR4zR;HIIl`{a%?AhNx=q-WYnz+$XB7Tu0raQ=K5YG27V#%dy$SrO6Sn@C6jEn%HvZg!s(F!n1P(wPxkCu&(O+Ym=9^eKct3h; zY2!jA`YJ@!QdG@PY??~%6X-^yPR*P+lsT%LJQahw#9H+ng)a3{(`X)zP6BTI)D)<* z92H9)3iUHb#ZyN>UEruh>IA6EEafHT2}c*ypM6+*32$xrRF_y=UhpTkb%~@LIeV|r z`^KIrS104{F5K03`xm=*P{mE?d?t6tHg_;+2fnfGrMdyDM)*PGH^kleo7s&?))w#Z z!vy&`dd8c3@kP895^EK4*4^C2z$#yA9W-ajBNOZOpw4krEHxPFI!DD*BcbkcR3fzl z)DwEcE5?{!*N{dj%>(YMxot)cSiYm@4_v;ria;h9jO72(Y z*WX%3r|K6Fk6>*p=F#`~3Tvaw{OU&->3@PM-jMR^kE)7!SD}iRmKS=9XzGM`j(uQs^2GWXeYH^YdJ88ELnxh$7Iz=l`{ZMy0vfES@=L<2Zn z)~{Hd0IqQXXmSP@xkHY$0i=Tf5CNX|do*7mMYdjxNK?i%)l>C-5hfsUI)sRI=5r9PpGZH-zuv+xeVL4fKJ_pIO@9Mh9-J_J`dl02C`k!r+XR?G1^v~R& zjty~Maj>5)x{`Av_J{q(&wkY?*PQ7`6%USe>FdnLKzF}}pWLO+2Nkj65N@M&bQeo! z_dE>1w+E^?)X#3?d=Sk%cUG$f`Zh!r>v%$qX~PDREm$!a2@dAH$Ag1;Z!dQU39PRi zMOc16 z?g1F_?GH^E%rv@07d_~`>pNe%Rm}eEe`{7|{R-}!5{-kNl z75o|3)BOAq;8t+2P4oGw;CaH2a3bDUd4pPkL^=ptii-4WQ?#f@w1;`eLfA}g*Ilw24(!j+-LRbKH} zra0b`%_|P+d%_(z3g5Nz7Elp6VhDIi+L`Em53|*R_nnFv^N)W}J)A?WTNnC^%CbHe9;f`+| zRPpXa=B*iq^vd|_^-*qdgzUO*#;Y8J{SMsr`Z&KHaG7A8pWR`qb(WN~+2x%lqR%gF zrImTG(~_bO2d$T*3T*(1Ddo9y9O#J+6)z>tyTb{X=@THlD49QgVIfe{qIj# zaTHBg(b04@bR=C39eK}0^w-l>T?d!0pgt&X9%_AL&P2(bW-E7^iBRznD|coKJGnC# z9LSvoU?+DL0fX7_CBjzjEC&X1r)m+&X>TTJ5L^?vqoj_=9g$JFW9UHc*?Qa)9N;-RhweI>+nBK&Jb`cxa~k?>VK%|?2>u#0pHIEZvB*hP9CFo^U*VH@do zU=Zo0U>9lcq5o>6Pjr!12ex>6+77;FLuhpM-GeZRa&uH>yXa7Q9Gb;PS7Quk3)WDq z-$eSpqckor&z^dV%?Oh-neyD>A1f5Q%sF;xGPkg3X-yVGyW%P8b9~Tk&Bb-gvp;vf zn5ML6c}~{>>k~cp$&_=YZs@@K|&RG*hFWIV^?R~nbhiBob9nT6a8C>zPcWH?Esv8C(*w<(Rm-o&r)7q9g?}$Fzk$| zq((X;BE!ze0_?iZ$Rfc=XGG0bv@>GpNM}U!zo9eI4R4B(&WNESoe@K?v@;U!c{bAU ziPD~D(a}B6wq#K`)qBy`A4Lx)qaKVt(Y3dQ8&*X|9t0678Ljt-^i_$TTGr`}rQmSg z5)zR%DX;#+awVvH9;@muusdAWAnXp;jRddp;X0+fYxuJ2Q0UtjMW-T+lITd3L`I?{ zG8!e5VylSKcvuXg)FRehlv;&dl;#P$C@lo9ag?%R$hCW>xaWx01r+z}IM=OJsu!0f zvXfmW*3eHRvq!oOC5FB+74BaYU3)=1+)!)i$aYvmpX7%xE{KjC{X~qq7Z(6tR`b02 zeuokl!Ni_A_|YlfRhHIp%D1;%M5cVzg4kK9U0M&pA5g{j6U?mxewl-~GvQai4xxSN#oOKL)_#=j4ep_lK^1F~ zos)g-SPZl!i|l{M7TPXHrZ9m^gWL%u2YJ+aS|C8)m7%iH;UHLq`gnp(6!O^miAytHsq1DsY-uj}|ypug(Qdn;F)mz!~`yDR8DG zcoa{vzjtZ5Kt8UU%&NiCXXu3q({{BZA6D6REwzTL)pmJzBXsOQx<>H-wOyq24`{mv zk%)nyAEN|yf_}2F6ZEr$ouHosUSmQ3-)+0*!(tGnHnHxa)FJGmv`pAVDSglPh*Gre z;?Ucdh}EIp5Uquz-$#Z2ctqIx@C6DrqJh zM}mVf@MN$X1J4EqW8ithb_~1_7>t42!EOw^RB%lO{^Bt*@D~{!_!~MH_?u}q?@zG2 zL()vM)qveJ(IB9kW*Y;K&` z*t9fLmR_4lM>AzvBkZOu2Z5v0Z0d-8-)Xin__cb|Yy=WcPnwb)nVuAlObe$c4gLM6 z(JC_gkXCS3+$ov;RK?glzQ$z%N8>o@8&0xo@l$50X36 z*LM5e_n2fZabAg*v2Wz`8}wD?+-7&96mp#OVv!24)HJv^SW|tYa z4qvS4qFc~EHJ*Lu00rcETcKD#>Z09F0X^tF16jS%;(Ru-0-%oNwFEcVYYy_E#AT5Bd3B*_2TA8v=OP zuhfQwF~V1yy$H>~U@yXKaIhC)F4!)|8y5@Y;u_p_%#D#ZtCl@u4#mkI~Mqm&| z6F3N?xwDJea&fD1F)!j`VZ=pyXBSK5;%?(2eN8EhI&ct1BRCR|CdlGF#zjlSMQg;x zywC-kYEB?!byl_LQg$xAlg)04TfKHaf87+{TPQ!D^eYb~WgD&qU!DJwRl703ZeAk) z`GMTq0XL6?t=6L0>^H(T4IHSs2DqRxvKpY!vB5B9xTa@pZmE+i$F z3SXV?&VH-(Z}BCc$ZM~99hl?gruH?0qkGlUN{h%|bO=TO)za z`@w-m60A$Kf)&pRZ2$&=jsypR zjtBp+Kr2cyH7VVqK<{(QR>xr2JNHNjISFl%~$5C@^6J-{uXqdh>;rUz*J zm-DH2;#WDHwAOfMU(PP|Bfs63Ym=V$D!!PwogdFHYo*H|E-#2z{F?o9&BFJ@a>Dvl z4xqjK%_pbu=9SnSmG4om~VbB2^x}=p|qi3A6QYxoq7Q zH(USeZl#dA`|8FByQ`F1gd;h;LUd?#g`tfDL^Y*^WmEXVElGmY-7TJ=wOgK{V zw9CSjyo)J$={q1Ej%WQD=t5#|vXw6=8kn z$?WP_Sd7)+2F18Zb}x=)RgCqWgi@VUQ4VM~Dl^&FEc>sOs)VU8u1d68zf6^w4-T@k z4Q%`{Dc>Pmyt<%rxJ>vtTMpA&nRL4b>x5Mfv$Ca65iY(Q&#J`g6OHZMfl=C&T)Ak( zeeqH2Z&SqI=D^?1^@xK~Mq)ifoS!)wi4|;Mf0El|Y+W8sGOT|`GV zw2y>lLwjy0BSC#8rCVaTo1A+?bCfF#pbbmk7684jP5}&oUY!7J5mbDhrwE#%Rh+eG z$Cim!BJm%N*0%)k!=ttH-L6lX`C7EH|LJIbO8`GCTI-Noe;`_>soF4+O>9bL^R=Oh z0}|OK2Z-V+0u*aynPB->G@GS^x$+|*qpQE&MXzkHLb&?7k!(a(f9s&lVjTYot($ke<>(WR;R z?4rq$%F8AsT>zucRNgyjcn$AbC^;YAbqv4wVluba{?-=zWW3@_E`q}#KEjf2fhqP+ zWlwhd0+h4G4O3a&p{EZ?$Bjbq@H#z1m#)(j8M#hRWb`^cLr0cAMZ4?tvYKetw;`(b zta!K;!_cMOB_bnRF+?(nU$GCnOJ=u$4=T%RH|ktrx07T6I9R$`B+mMu|$NZV=s6K}79&K(GZj)5!O#*{c|3jMug4$>rZny}J z@7acYCCB&v&+@GXQ{OmLad0XZG&1XprtSP1?W)fZ9Q~GDGfmUBU(2;o|I@iPQ@q2) z8s^&n9los$Qzqm&YH22ScKliS z-)Z$oqoosC)yMN=Yz;-L{v?)~Ow)Qn(q0Xwo~atHu(ism2-8}H4eh1uxowr^;_~cG zYNhy$GC38d+2yRiH!!~-92Lgw@G&H;b1#sRO6 zi&DV%5wNLPu}tTHD)#^|Ih4u3>GWZ@fBA=>DWW`YAsgU z*gcN@JA>G5n+X>|S#|e{(1E|EWsCT`%5uuW6i!WP-(-=iZNJJGJ#}?|iJmUiDgGv- zN@1Qo+~^Bu?|frz9@;+-v`+L*Jvs}$JE=Fu!p9J=1s1-vcMBYV-u7QQe|jg3y$R_3 zF3>wG<*lPT5#HN`8xZ^+x(34Qu{Wa?zsLUk#(GTUH||w8v1WQYs<@lGpicGn_M3QC z1yx+v&*cwAgRcx#>{&X_r2+$OUnzJsMyD4Cb*v~92b4~Ozbi|F{czOTLv&;?y_@LB zV0v5V)fwx4ufySsuA-v2>tvUJgN4lH;P7yGauhSNT+;CsUDBNywsYr54LT!7>CTaq zQp&svQ%r4!ZUq-K`0J*&3SiIbU4dt!ioLmXcMjko5d$DD{KEI1K^1S{QoGjy>wO7v z6~qOA$3<}GoT#8>WHv1h zv(Z^Y(ZO_`7jjUeD7_TRp9=?r@S*rJ_pyS<2oEexmKl3DmL|)LP+ZAmSyq!}`hF{q zS98K_vI1MZ3A4`0v$37>nkDx`?9|j8a4_XHU)Z#mUiG?P`Sy~L*C`SELS%F?$-Oaq zc4Rl0ZlOfnh$?;%%Pl;`#-gWU@nOtN)3qs-PfAmM6yR{mZ<);8tZT#Xsbg;DdOWx^ zbKMGs4`$Z24IJ>fTv!KsbHU>-8lM&a84GDs7@!|;d?_=F%RAp}h|ir5l=hB=Z?nih zoB7qJ$70??sNxC|VhNyU9O73lA?O2n_mBu$Dk)aP!>bcbNzKQ@07UnS1R&Z3kiCsr z41F)6inzGW(N9D7I<|DJfh0cH8syuVZ5*@!yjM2=XQpDu2>&Qsp{Py<;|EidvZc?s z+S}Tk6|p&I(aVk=Y?(BP zLsVaKOpB&OFfh<%zO z*4)#*TrPA^clL2y=rh&Si&toMrRFAFT^_5b9ZdpToI4w=FM-0$%gTFwX;jfKUE(X6 zV8S~tMBAVO7u9l+D7g?Fbs^eG{dIvJPi}iY%V%0~D|U}tDI>Pl{^3%_)X&NCEHWie zeG2R6ESW_l%uLLpQ}UvNDR~LpIkLZw6}a=kfxvAOUN4gkUNKUm9TmEUj=V!8IuN>H zT}q;f=V4tE9j!~EZC$$0)twKmi%#c$P2It~Lo7wEQZVVxbs?`gw^j0;>q4G!%N&O0 zVvazR7}2th>R8}Hf~^{qxu{~#cvzn{ z5$%;~hv;bS5WVWEJ5Q{-s=LtQ|Dmc|{dsxJ8>%IxyJH+#Jf0pCowsY@erp=~gjatu zI;J0WXxw(Khhe5=aIdKv5Z_RYdHbS@6IqBCs9sR#M&Aef*tYKkKCf=H zy-@754?%41?5?8HS!?n)weIO{Y+c6hEuYF^1Bm`NH_Sc3P0Fn?Z^Ccg^~Zf>A_4d> z#tynu5~iM^%hwemk=Trt@H4D<4%O3W6^mF|5&o{xXCNuAqJ6Aq7Mr>$+P(Mx2)gqg8S z&%Ko!p7$(&`<#^Db}uC`mtAcbtK1l)C18#aZ;G})iM)w(GFv!DqYaro$dSE7a?)+V zIO}Jn=-RT}^UhrD#J;0Ri0qM0XMNdNJDHb@(|6o_- zjPUv86|aNGgRR651CTs70eF?qwb0MR#>6@K=`i049FU4vjw9fCa`7n-#<=}x$S=$ zLnd|j$sa~7SWc=<+#s1BM!~LnoXlwTtL}y224RX-Sar6;#l*h0>Wq}3t2*N??p&x> zQgy-_qG^hW{cR0tk>d~jyq+Fu75>OK7a7b0mkwmOsmh@^Y(qkSC@KAZEO&>iRw{)P zmbpE8s^QDA(4R(ZLPb2ZB&jeV7th7l1MuZh&{qD-=S^^MkQ{BmMmH=igoO$9B@a~g zq3Htbcvg(6mD-lSvuQ(oFZI((irXLqd$9aH#KK34M94tXKH=26k9O=s)P!U*)cX|L zr+uHWPDyY5cJ6t-l3v2FlHMNZor#*Te@XA>(2q#(^rV;Ec3U{`&7G|OD0Mm{akrvL zor#+8>r#t;4D@fL_io%9f*mt4@gjbW<^;)vzb3PHeG7n_yqf6$$nPjHu+0BMW!lp^)Uw4((E~wMaXN2vtheDwNl6mz+(<$@_A)tnv+3l!e6t#4L z%l85Z`xIXYv@;MRD^P}uY=qTHUd4Ar?GJpM5JgXY)r8e$4sP`3{ zpuK4`KNn8Y_2UUYX$)J?sh;^N8+-;LQ?_MGP~wc&(Yojjr}db$9&13W&znx`A+$^y zy@&62jI~kqpHAfa{EAt0Du(|IJ(WwsanqU%=6Y6|vmK zI~&rN7dVy&*u?5c9^)ea+~#y#-K@u`;>d(C-x)X?7;RSQp62Y78ASuNmym5zfB_l&|o@A z-N4%>^83R2Jg`{5i9JYd(jS$mxbQew2iNT6=k>6ZUTpwZ=!W<@;mG?^>M^bKeJQWv zx5T~?>v&1qc^*01Bx;95K3PHT3da+bpHaZ(f(H+&diq@&Yrz5ZA^yHQKJ%$R>sKZ+ zo8l&*892Ry-GCgtFDO5pr-zry)3FKj%8ABQo8R({S5ER-icbw@{`QId=A(F^4P5Bw zf5W1cNw4Ac5LgdOomvF{xKgPT9W8Z+R;kNwQ;!iJ4ZU3C2AGm=yAjphk|i%qQ9GyP zrRb=ahL)H4fy8l)ct6J`T#MrPrb)O~APHA_I9BFK`>p(FlD187zF&FOmAcmkc-jdOC1O=8%;yd50Hb4aX;7H*>4w^2&Xd)|lA67S0{UbtNbTs7*y-FcJo&cheQ)3ww@}i?cUbGYP z_1)j%uneu0zla-&UcZ~^K6)blk+fLJDP(U$IwjNJY>d=Rr^B#VZ`_gdLq|IdI zi~Ur<%a-%^1zdW`yEi3at-K%99|vC9PW)N3BSv7^nq6nj9th3;z9j<>Yu24wi@U-6 zS$D5*9lE>Tnmrhp*^U96^NrrRa*&oA`6Qw0-c zfuGgqV(TSTb|cPF=bmAr43+)TuU_;Vb+rQ=_et)_XOgg%;}=SveP}%kB3*qWw!T6c z&rUzf_nt(_v+AGnz#dATRrmNs#MWUDfvszP>3g4|pe- zX(n>S{w097M0^Ry7hZrw@>3t4MhA)=77)o%i^ypkiQ2=>rU9kMrhD7F2+GP7sTv?C#aGMQyXRsR)I>riOvfY-9!a- zfl`WkgTi4-crV+xy#l?$j!adnhHZ_kZ<0;>`i#GgpSjx6v?H34Y2C$`dX5ZUzH(%6 zg@Yx-D;z{dU%pC;j=X$TA$pZpIvCc6VPzC-Dn|Zz_hO*hmkVi6D^8@2j#0HeI_A~y z+m7Hy`Ej=exg2XJ;PzUS|9UJp4k!Ag@6*NW77#M1KL@9`$@x(%YA>T6{1|rqhuwaU z$7mZC;7^DA+9#e@@RJqt#JJ&Nmg6Ej6v?AcargI+=L)X%6J5;?`%thNE~duA-m~ba zU^R5u>6jz`r^ZchZ2{PIIu-$gPR9~y+fK)FLD%W1LI%1{M*}eEbc_TCosRLsw$sr9 zbe)b?!BuoRyk%yP^ zNpv)y46S_X+}}Jr{*C@-h2EtcsqkmIm)R^1i-Za4nAHhtG%cAv4eR}5;$5DltE4ZD z8u5&mRX0lC7?giPJfp5uK+~Pt&vn=shIyMmXgjB~U}pFL(>a|ZzFg;YJ~${RZNj#k zbO5toWz{*=C(ff~MRfTG|GpmPd#dt$k{H7W=7#q%lp(8s0t?^WLCkjD)w+>bQIe!0 zGy?8aH>i~{DHM!pC9(=_@o-FQXmUHN2L$y|%#DRI$CBvk_hrpZQS<`5gw*JwZt2hB zxy{@}mlDqZxtq*vr~LH7!tSzkrxh>DlnZxR@sg%kO2~CCwtp@a+m(x#`%7i%+r>+r z{J-Cdmyuv6Ud96h@zNq~D_&X!op_lCcH(6rFeo%~ZY6Mp z!hhI`m!%eW7BA1NPEfl!@v@$ndnTUiBwl{yXLs&ut3BgcZ^RXTm#3Bk_(X5D1^L=Z z{w!WC`J+upPX5#ZgM!ou4hm9}uq{ZRNc zIYvuj&(mo7iR0s5;)J+2cB);CmtGEfd+D8?u(Qe1T+DoD{unfuB=6$D0Rdc#Zt-IU z5c<{|3%khD%YLZ0H}q-JTUOFL7y8fAV@=6SfQGi8M7I@>$BwrzTPx^Z$Hu*TxAwiU z`1|N_t(PjoTlU^k$-G+@4y}dmO!Uwjzu(N_rd3a{ird z^_W)khO)szn=Hm2W0z?d=6NTOhKA>DY#J&ur;vU|@2I3mdg*K_Khe3ZOZSzYrWCjT z#MwJN)Vd_lx;xbRAkca!)Ee_o=kO_`bvk}s7HB>1CC?s$hAjlQm2#YB$NLGf(#T-! zWu;i%f!>Fxv2N?gKr;AC=z)sq;qm+cvbkm;Zf3?SC#_&P7u@rn%H4rufQ>s>t~lBA zCJXLn-XER?4Bj7}0}kFFo(~S*A8rE&?+U;u=Glx*elj z4nvJyY|ESz^)hTAbf)%2Fy7Y`V8q zAB)~!aUt!ouiLKC`sigS@LQn9dg{;rD(Mr=Ubyfq$Pv)1b!I6SoF3_8U69uSBVu}NE?rSGn;ziC;L3DXj|k{%MvbjX zoA(47Fk97o0wd*aRqqLmw+_vF0xjU+J%LuRdrx4VfouL+f@Z9$9yQDG?ZDN4PawZ# z6O+X_8QV3T(bEn3c0kc3*7FVe966;k`Q1-AXw}CtRRdgIrt&&LKL`h7yQTBWt}$Sa z&gXUFaI)~X9-FU)J25*Fyi#YKYx&x?mXF8ws%m))W~;2_t=6Hb<@3NnEnf(BwY=TH zHLvAMjXP7zy`igLqDX14de(+4OQFU-z%8i%XyD97-mPsSAmVE7Ew%L7K5+63eB=Mw2eYaXraW&ftzRg9ebRs^VyN444hY=i!I|^{8sOOJ°k#uMFX@t8OxCdk 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

8#ym*SA{Z76>Skn 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

bN^v>pXI}bo|Yvn5vyIAJLvH@YQ=e|EWy6 zYzgez^y9*nHdC*xyCwYSQi60OZgm(oX&6OukTwy)aL|v*Cmi0gS@k^DSbv1j@ITB! z_0@=}QZqpeCqo-bWl2S^A{cqG(wyrb%y9nY$HA`NEW!WsXr#%ReQI!jK*ga-_F=mX}IwssHvyg8TZ=&<=C z#7SquTPqTb0WdwXEUY}RgN3(ES&_#|ws{k^&ha6Hz++@t5R{os!P#bPfC9(I z>i%ZaK|lPv*8KY|`cMHSEL1qe!ON23 zMy#ye&+8-cKTB>{4Q0Jq%0s=b@cq|VasO4_nqkyt0Qd%BRioX+f>I~7BltYmH-=pZ zT6Nv1LO-KP(aB9Q0bkCwNxdsHC7|RLZAeKdCELGC*XB!)UauQgDNvqCozw-&H8eWE zU)^vphJLD1CRTN|f2MwDTihL#i#lQ&7BIa6xD5OoknDiA{g2Lec4lRu9moIC*|eTM z8JG9b+aSUVSbfNdq9|H1PyR=5(=|+wUv{gO*6&$w>xSjOhr_Px?gj(UZp{DcPCFo% z8$fHzjHFTE(n)&#Jv;5X8Ggnfv;D?n^MQ^HGHP#l01*upB{CMl$B3K7UxY;&+5Hc4~&Ald-G8Pb^RYuI1_URexeVj%* z)hWdBBOi3eGzvhdm3nAZo$@m6a9JVZKi_=wa1Sy3)zt+lnQU3lC+8{gK>m$9C<*aZ z+KZn&b7j=4XRf=lrDh6GQ`YHP!P+W7a?yBc3AYod`LLr)M%3T`Zm|6S@sIyT6>UHlotF{ybmCB% z+-7iDx1&D}zpR;V6cZ;%`a;SPWGR&vpxm$OXmW^)0=zj#jOPwr8g5 zkt9u0!1ovXx8Qx&7lMZ>G7IURHdM3MkuaKyMLxJ?bH^T)DESf!#I(=C^I5?u=S5*w zMS|%)>htQf+XMVVi9yS>pPv}i!jsn;ZqRZNSe@YPOn{j|vc0?|rRh`fy*c^KqGOlP z29Tso{r)FU)nGN`WAt$i`qtqHfByFJsuohQC;Dg)6h8dK`N>;_pLC)=Xs1TCaCqaB z4ztT)&}L-;jzS2D7gbmu*&dPxsF=^^nz3c@zJ0jAeYk&R*?%6j65J+wA)W@ZMLjrF zvZ%m?_TEkW^0&+TH^BWr?E7X`92F<(!n^(FNEvCjfM9nd0lx2CO>bd6-`!n{m~Np& zf`+ZgYS@ZHhH(63u-iuspXBBQaGkt~%CLs9ttq)#E=-;PpAR@~fS*m`pFA0oCo61} zphZMMD*3X5Thu!=#)dhH_U~@0)6-AyDxCqxAtRQoAx#Cyoq8C8_Yr{Qc}eD5N9-)m z5y!sW^KVIV=+9td3*3r;Ekx3Y1l*PDOGq0& zRX;!5?XLU;sB*#bhMl5f%PZi@2w$3j$pVW7vv8ovnKr&gcEJAELO@f?3eLPTr*;8K z_(~vT?YHbrvN9&`C48=$CqTI4mbD(7XJJ@l0OU~XB7hg}RqV-cE`I_u?EBr%jpAh) zVvug1m05@f;mvL68-V{wRd;v?N(`+n)2@tUL47R*N+E@e6+HWrim+Mr)ubDQ8lipzU7;^!ybudts8TD|$PyF2+8OkbO(+rLEL zb$0ef-K}=D0DLv|$!$^n+}xl1;kEvG_uI+0H_iSn*!*l(_49|DebF|bH-KQy>XcNz zo}WD2{&ZI$OaHpNe~aXJ1AzSr|I|P1`NqHPez-mP=G_nao=>Dy)_Lh1_tM)>dM^_W-8qpUyXRpPlFV2VEOC2sZc@({YCFuRgx$Lq~K zM&0!Z#2WGg*z|`6Zq9vmp??)@yoc-N4tGlRmKuU9gaOkmVDBg2z{ybH`;$rj_Eu1t zr*ov=%l!8Dp6hqjCt7~K?lE1RMclRE?98?CoI6y5hcDKS@{NsH*gcQ>u)D^e^1bIL z_r>Lv@Mr&GCZOCs+|*_OFK$q2_OiJzW$>9p%=0~_h@P@f?ccj!?3GO;)R`O8F}Lrr zFFrr{RIQ7Mo^zTyn7eaFmQ)0sV{E$1hw*7ZZhnpOU3J%rWn_T5Q^q@oP_ z*W%~q{(lz;0 z^r6sD4|G$pFGN8=Ev!~umAW`&NkY$Ha1bkbrZV%S@?>)9M*sKwn7K!U$9A?%*1g>- zGMN$KyPKPvz4qD*QSz-MS1~H0dRagXZ(4~vIl52(3TdF4=b~U=s-|0yQln_kw+&Kk zk48aW`ue`uBH2`z*~nex(8|%SzkKNq$C)cb9AM{#`ObJw7y_76gl0 z2%Ps0h--cI30rRV{bc^8H?$Q^-gM1r$NAfB+LG}KnJM108dtX3wAdFvTo)h6ygL!F zv+{@6Bv{sL2>s|^X0MJOTcFpvsPArw&WrA4@z8y(`_y^=Ps%Mz3NtQ&dOx++F}0OM zBJUIPRbrm2`x3iG)8x5VHdW9z5IG8DYczx0lLp;?>O#Ex zM1H|mG6ltXNFGnWA_;pEHW{7T);im>QOP>No2Yyi>YFMh$z+;EB_^HP$B=16_g;s@ zu(OH$y1Fv-yRUBLN{7IZW<4cqyqA#X7HdBCWvDjQ#`vjEK;_&Ubo9G}d9N0f)Hn}j zdHA)=JT~`aU>UQ3k6V^rD>4WIc8K@7GG!#jyi_3Agufp)JPpg1R!IBa$W7S zeQcJgGf?*IT~@xjw}*YKBYSG9W9yB<{8pz4N$-QOHKr=@#++K?AAbM1Cy(tPes}5z zJ>jrf1&I=fxQp`_Zf8$imyzFOX%qNj=`BI*EQpqV6Xm^qEfOihW-3a*sKcC;yitma z5(Zg$Aj{~O#W5|(oeGf+nZ(G|9xpr0XOrHocuaPKrS&8$V^zSv+Qwl@#%c0h19~~j zL2nK)5sqitQWo#_bLz@VdCW z!_K%t6=ZfuI-M0w6}FAvmL#Sn5A*W7&($8mKUq^eSwrcit)JF@i%69RbFFcGA)i`f z@_764UcDY((SS9K;}Y^sU$H0V(aE)z#r^%38^pT?w^kwcF;P*zHNREO)-~EW%hY~I z5>PofkC1+hr+U=mI;frrTUW;Zian`L=#yO5JS9agN z>zc}`(;E=U^@}-Orn+IirP_DT~*%BXY`lkD_TvGS?D_ivBI{m4|f z@-pMPplUhess;6W){Q)wsalBLMVM?$m`v9zq@^Pe~(`7tOYH_cId>0 z_QW<%E2cN5IVpX$jVK4t*H$BT&xLUeyEG4ALhxhX3vgNoDN5_YE_D{giDS5sqVG%f zT{Mr7Z4^xM0;yIbu53RLiKGWmfo=^PAoQw&RPnM#xMMf=}Kk43%af z7d<4_t>%00L>#E0kD(UQfgGxh2DudAA10Sg|Jbd4y`O#gDMq83l;kOX2l=~G_Bdza z8mM*c`4wjzHz!f{PAL3ab2^CjXjl8nei&qofivHJ4gR zanL{Q70wapz&EzlzlqX4pbk1D0AmJ-(huZfT{a0yC|h#WuE{W1f#_!usk{6nkE*n- z3Irk_^=qWp`{D@Jju?W;8dA4F2(jtMvOdE7Z2x%QIH^MfUVlij^Qw}&Qc)*B0sOGG z%GH7rcyfh~<`%$i7IPO6z(XGSs4(lA+d|VR$x+SXy5f+IFb8OU3R-H_wi8-*swULw zUTvOKaoD17b3JP!tR$*?b!{A{fnT&ycCU`pz8`s2rr&d}W()x8%aDkEq{R3hFeXxv z3V=vdiN*ud;Y;eFFrnG3>HhIEj?i!lwZyb$+`NDj2B2wyv)EIp>w32Zd~ZmO;`_w| zXq_z>ted-365rlF3f#sk+qi6zISu(o1B=>`eeHhSy?^xnALnHYin=U8Jhr6}NiJZ&duD-Nq%V zt^j0(VSspVsdDWa^`urfThQ~PtSOVc<@y%+1=2&e;8Tlt_GOb*z`7#Xt-=5S;#`@Y zR0(n`Gzv8<AD;tNQb;F>(r9 zC&|}kdtY7Y)|OYk>C{96zWwSktiO6AJv7VlF(~_=gqZ%#YlVWE5{t|x;bUDUYI(3&^}joC&m#FE(e-0Vyz?Cce^U{Hru zi0v?K(zoE;q+z! z)ono3WSRR_kvA=>Quoj~wsfbBu)g=j$Bham<6AYm-x8#MqsyL^>cjV<4cnCJETuZm z&aBO&xbzuLwBMf9*1mFZ(R8t+wzHj|7KxdSQv4oo+)RQVSW`%(5>PT^c({L3VXZm3 zrq&yJY_dIkW~{ZCoN8IoS`B_>q1kS}d}-$3@X&QxuEt|$)R9YOwtBq32UoheEB8oEW5RJ3uZV^h?~d@))5re&bqaQ=sx`W=?a;; zJ>z@DhI?i`_3DI?&E}Y0ILKr<5sRSG+!5ni79_Y*V_DuEf4)zYXBM`^ z1JrV@cf@#q%8hTC9Hl_qxreL4-)q{?%NYz((&6W0jXKZ2R#VBKd5#NmuB(_DwKS~v zK@s4Zi2`y1rKp~+PP`(f;;2m8CQbmZXCaXEBq*8659m3 zM1X34=;nT8s>iqZAjyL?VNr!1{v2QPLL76jEG?sRZ}bWDWF^pt%qs~IC@^Xb-jqrC zvN29Aez*?DVExI-E{8b`77}~l8fBNNVB8Y(`{WnhAQVQ-i1-D(DoSwm1xZ5WQmPRXMVgILweOHRM$6 zY`KUI&yN&^%cS1akH)=2Suh)ic-#p(%5ebu91`veQdnk)M`+#Em9$E(Guo0BRk^s| zKD;N!s;)%`F~Zk;_r0yQ(?;x_j1wx#^IG({pbDisG~rk`q{mJ-+Bk2Dpf0L7i{Uen zz2&^{gl@cjERS}Bs$^Cgtoj8GboP0k$Fl1l%dQ*a`HZ@jZ}wYrYXBXC{_Nr)T!dj_jbQ- zB;)e+UM3}M;f1cDqH5Z_O%jH1cx-KmjKkrN_Zm?yF(#sd&Yd1<~a3oFeP9SD?dPO8e^XOfcxp7p0&g~yj7E9M<{Y=lp_9* z^Iz~*I@JimF0_AIlW~d8e(PGe6LZm87OBJfnV)ovQnke)RKay5oIgofasmuR=n{PK zFJ=LPO}>8l(gBT{U+**^?Bz>4lJ2|f@rC9s46YJ`U;^jNuO5p1uQD{hB42(Yoz3+> z`0-vW-hJrV{~^sGK2n1yf5#5h-MBa$|Hm|T+)6W-&pAIYbhiG|e70im`D-we+EFKr zCVO>-A+@-^y6PHWj7S{Wa%^W0_n$W((d`gDZ1@^edhUk-)<@AFx`$t^%^fR2XF-k5 zY<^^$j^7L3AxubBnl&iDc(3WxZ`W*D+sFL6O_Uc+-ISbyX_3cg`*o>;^iV2fo^xTk zHURg!Sz_MzBF}HJd1C@X8(f9>nVtQ`o91}9N_^L4>f`d37b?b94$ilhH`BMlz(~Qb`l& z>`pEt+&8kR6Tb3@ae#yoMLHC@*>rn)Q58IUBGGGI2*wD%0o%EXmL>;5lwec_D&y6m zxd4O)j;D6}C4aYA5`f#vB_s#IAGZ~-Hz<=Dj#Gi*T7&<(d+&q_qPxev=o%3+r_MtF zL}^e(J~haL<5i5wsgHZ0q)(LssY7gPO+vI%p4N4hiQ|Op#-TnPa4%ip%E^iwBJDw| z)f)yA8xgoQ>`N(BPfY?j4sN=v5i{BBwcoIj2^j^O`wxxF#{|S5!#oKx{V)cLjwG1A z^xHL%jjHXF6_i9_TclxFCLp#$HmZGgVQWrUyiV=4m;=M0jK$~{#)^N?mL05pID(D8 zE%`~^dNB~n;xm21`s9Q%pJ1TLQ9cOrAvI(X-!S&4a+zy1n12^o-sGHqH*kqi1N zsxz`|dnCk;Q$%$C^k6%O*^{ouA2Er`7LGxy6=8}BMGR7&V>i_&M~b?}Te-pF?r@*! zX@ztT?jQVo;rZe7@90l3y;j|&ksok6s@{Sa-y0?SKnkzw!P?8hYp7bh?A zznhy?PSRn+9N6GbOgXA^UqEW^ z3nx2MAuj<_Bk z+q?HfPd|OftDHQoRY~62%KnMDy1W*KWB zDADd`wz21G=UDU*!?E9p0*4zLX_00Dt~8JMmN4xUJs9Bz! zS@UTU&W{GcYBldL&N14?MGgl9wnnUc<5!+6@y)YabsyS7yQ?ARLMsj(vUA zh>q^SS57MJcI*PoR9C#ZGCJej;JaF9Tf&uHVj_#%7!Vlpq60gd3RMm=8|&IlH2&bI za#IH>9N_?mpwu9QieB1VGHQAsI-ZcBi>u&k?JL0KTbl@LT;J2zQ zYkfv)xH1(p8w~(&t$&-PWJ3~OiLFKcOPWu2Q0H;xl(1T*oOQ&Zl?B;Tga=+8*#XVRZK?Ot1qujA;R6i3O?eTWPs*#O)x!~&796&WZ;`=PCVQn4XqHH3BJ(#kR% z$OaU6F6h8r9exmDP-{vr_A`m8Gse?1ms@v(4n2-u0hM{Ixv=0UREfWM$2m&?J;Ql9 zMh^Dd_8CfE5lwsRmmOjtXjky3C^&*TljNBf@>O|`UAA1Ts zYwqw;?i*p1;$?u?FJtvPG&ln^&KMpQ-a{@O37CY+t~Oc+>!XML`hhtvg-)WlPAZ}+ z)N<|T1Q&WlF659HU|8XJ)koc4TPYxgZ2RGUCk_iT{hiz&iz zTnB(cL!!J2*0~c?)UE0s{db^?$5iUJsp(tf1#MnrjpU11h$@-;|4wbfpI&@?XtNjp z;14)TyCHKmkw{)h?F(d0+{{W2zkK;>j|aI?6u#~`n@CJb>j);L7nC?@ztxt0xV$5P!3z@PK&k*n3-Y;9N1TRR znKW%~cV-*qPF{+nOX*GX@P1eCgK1bE&!nw^*ha{CareHtkqj@)51u}m+PEekY6;h1 z@PnZ3jMI8>bO1F1%&9h!e@dCcV0ntvbK*EJ2OcZRi$$R7+}UX$@AJ zcrYYzE#A6rLjt17y7=~30xb8IRbUcqsbHJ##d#pS8*=&8n;&|z2VJ}45cw3xMFV$Q z3Q?cNFF7Idvbx5Em#5;9ELglkZlpde4?gCzN~mrHEH1^aZOK0v-Kh(FU|_Pjl$q|$ zCv3^I4f2#sJ48uVM5-X(G-Q8u2eRp2zI3;$(^BgRIbloskzJpUw_6e5EMam8!Nyg4 zWq_XpPj|nB?JL6?S&HTf1KH_*D9lU}$@8Dh{Z5&6YoN7>m&n;oG!|CN(HlddbjgqP z*wF)p@VHyWMFk<3D3V|ay;Cb*gULJg=A_3XNw^Tkl5|NW)QGi~@@4AV zpvm(+cFKuBn0y%ftSrbC+eidyzk{SBzOlSWKn}rNFrwz-;A%m9pzR0^g!6p-W%kIv z-xO7aU5@ze^0R7O+=NMk#Y!PABaS@oAM@A9k%z|}wslR^R=s%NeA?98cS6upe|qss zQf}Tp9(Q0K48b$F`^OVs}WPSO>7M67hd=;df41#&oU59D? zqw$n{eW{{(x+WF+%H%HE$|UgB0=3k%SApw zbtLpJ$VONwWprA^1Wq+&D-3FIAcY*{!)eheTe_iK%agHR8kh*Ns9kamV}cS9z<&cC zB*O#(ewDa#812M@ph%I9N<2EZ;Ewy22z5BueNr28ByoYVE% ziXMn;pIs#ny4Gg(^^IOtvhVE=iTO8^!Q~CuGFOP0=m(-r(h0$% zESsw<{o?A%aD99upQ}9W*cMn5{W~W7Nyl2hq6tve0mUQWzJe(_mLT{IYMTnB&Goh< zTbA5BQOl)G^S(ruB!wtJ@DE<;)eY8<6#tYw`11YWLfiGE^x7!R>K67r$&P5iaPt=9 zY3;rscAijc{J_MpbG(`OR9XICZrq*PqXLnTBwp-6wjDK?j21^2F)dTTRN+vE-8_Zs zoVeyzfVbw+mmg(rz|scQC{&7YSq+;eN#Q7qITeleIvTm;{v%)fn!NePPyE#*?r>ew zS+1p_59+R1HV&?QTjiK5$})ftAZXgiOz?q9h4vJgx_P{nmN0+_tCqM8FfOn`r2*T` zeW4ph*A6gl$-F?{&)^6Gmn>WOL>dtE;h<_EGVuyO1}u7_apQ;EuYYeH8g~U6hA`~& zm%w<0Hcwi=X0^fKP_%F$gaOcU@^m{^o5Q6p4N3I)u)W3t0wP+56w@5x)G&3xj8uy1 ztWV@aqX~=P@3M_TSLjl*lr^^>LX|QP0^X`bFLj=Oy%m_Xc59&^bAbFPuXL0wwWsm^ zTwwwj3&s6O8)S93^O*zJ`4tv84o3fa$JO+4l zKkHG%A1=2W(AkG=)e*d*pinti9?+-&U%+bs^+%cCI%E0_)j*HC`*>Rw`-jba0|`9A z?KmgfC`#e@16L+cV&{cnK65jWCwI~G-(+~dB39{GAOuIFzuuVt zEz?1)3z-8N2pIE>;3~7j@b$QE0q&d(7&ESa>zo%e+QKbXH%RnDi6VdWfvC{(yaqAcL31-Qnv6+XY*9S;9kb?LZa@+NnQC3 zIggO7!)0uto<9hdd}OE;Ih?Bikwo3B2CHGd-|c=qdUql(4_XfZOOjUL;YYtdL%!wx zHJ>4j$PwcaciI9>!05w4*gqXM{F8i&S?VQ_j7d~W(Adm9=N8!c6kB+(fKlXC4ii?A z7zOc3BMI7(X@nq~MTDv@%KqsmMHgPkF$;YiU<)!{d1b{q)bK*PWt|YSe~9*FG?P;o zUDBH>IH}Q$(f534JMjXtl7wS2-ks#V;*ws zR=mvTLk3ny;!oY4cq&8y7<2%CHzqAW0+{vAg$SJ9!Y3`asEHevu*5UQjH%J7jMIrI zoD~=w7Cn-+5VPia#Q8L6SPQ;CqmfL2J?p)aWqzz)LO-EkDq51c5uUaJpIfa$YFJah zGg3?tCtL(!0OP9Mje7!7vqeVD>#s_L@h}n)6$PM9tBR$lx0SEAVKAu0g3jyW!AUpc zrLY?LBt9S`0K?75!ENst!(=)yi%~*)=47}JfM2w2+}5OQ(!J5QJy!9a_m>hpPPbTs zZ-F3UM&&?wtgs?b4BUxad`KxDM5)h3u2-P4s*=VU7VaW=#=-0((v94He zJ8)Epj7txE0NR|yV4fk+{On!xAogLH+!}(pEFpy`TwG}gq5?$5c|*pA*=x(%Qn$U$ zIXgb`j`k>Ox7XJU56GV=#ZiKDxnv12%Kg$xjE<2Q6~hhz$(-U4yfwENz;8J>Fd2eN zDnEJ47ex0aA}0ob*~QHQi+n}WA{h6qLGXkUu;X-DuCh3cLtMI~5cFX0SAk_n7}v`= z2T|ffGK#iR;3urJqT#H2SJd}M- z6g|9>floXrbSDTN^XTioz*F!r8QXuiA`^|S(Ia56HjWuLC0PgWKnNW9UIiTxlYjY$n#PW)SER*T3}_EYr9$g6kkMG z#w?Xge7BxC0dz4<4hvf{9sX%ZJ^13wPr+!FxGV3dEN=pm4^GiEXKjI2;+oL z){7v-9B9HboabFx>z$bvm&AZ}G7{CW4{M@hRi@8(NR$Jy#@1cqxNi*mE9bqHI*uYP z`}XwRL1?`2x@7?*5;d2P_1$r_CTC~BLX291H6w0X6gw_6x-(8G!r2vG29p~LmHCp@ zf*|R3#est4Fm%U$6b@;*KLB%;kn>U|);U-v7EaNSn*hrO;}IK1oWKM?r(!7N_o9@| zPJgoi!K4%q)qB*`%4nL~_v-l*1swkB=KykH-G_lC&AE_)%#`bv|+sqh#am@gPl2 zL%T6fH7@tp`Gj-4#NdyDig{Ulq?7CX(HJP{msvgw*q5!Jh`o#vltik6*bt*K=^8NC z!N~!@6^ogR5LquHZSQwC8z}QZQD$f?MP2ydQQIIj2AE@Qh|zlVYcvapzr{hu!2o#C z5#md=TlCJj2ROo0BxaCfbqnyXo>Yd@1Jbd9W5K(KrG}%)n9kOFVA|040B&zst?`uy zRl``?WiNW9rW;&g6CU><4l9qFH8wnaL|Jug3@sz^xD0%LAQd1b!PUl89P5QC!x;sb zGr%qprp?iu0>L;kist)%6cXf7?t2*FQZk!|==WAR>2(9a8totN?r@2zFNtFt-zJK# zAU(4ZW*79gwFllbF~O084OWP z&Mrg}$w}-MLFG6B1`^lX<^j`kb@$U2;%Snj{pp47E;Vv@12Ga@-tasC4IlteZtrGK z>Q`(m43J`nMQN$FQh!b9^R z9vRpxnGMbQ{S6_C7B=838wm)PjeO!!X2GmT{%I%mZ^3O4N-{|?Ee;Hm07?@gKDKfmfTC4lED!lX{?hD~ zv){hu;Vl`Cl(tBg^ttUOqYhjRLDYt+EH!QscNZyU9GpV2$gC)w_q)9u{;l`Zsv;7DtT0)S9qm3i*|9h)CqQ%{*7z%@jR zkYNWU5K+oSZ_E#9OC^S=|>k zhYW{tl_nVTu%iK?88^q?$QNwyr=BAY#X$}4XMjQsp%bC~tP^wl|Js7nQ1*yuynpw2 zgLv4RtG5YCk|30YDO`%Dc@LFG7RQgjMhr?-m_h9L}&m0c&!oRf5AR_ z>C}LdA=waqB68jNbjj3f9c2U~i9UBpca(AfR5`JW5!=WVYu1)YWHQPWbU_V-Z|Cez zqMSp_&Mh-=SxX}lZ-&G)0PACuidep|9D>Oy!Am8vUsT#{u0n9K#<5p?`?$SEPrY<> zqZ9!Z)Csp5a1q|c5+EXOufejz9FZs033Bp;;o4EW3gO=`rV`3o>V{d;w`#Y^Y9Hn|2?_5CQQg#3s*%+ zHfVyootosLfxfzvU@!UWDch1zj4Wtic@C14tV;$sdBH9rb2G>~+$B*_=|=CL8VNyXMyL z(p{`hQ5iPOf*g?;25s4nghDifaXI4lXXXe2;#v5x2|b$~t! zebkyNB;P|6qS8wpR=xeua5I5qx(`0RVEXfv9qx+~O%ee33ojL;So%0JQrrjdGbr=A zG}Ig%6Yzq`J$vb>ml*=o&m;j*CW*(KQFoTn-Tkg=_86L9ecC>JN3ik5)e!}p=2bvm zKgj09lqmgr>>z39YarNV#S9$b7$QBccqmo}YWWs(X-~v`?BPa^v3eAl63;Cc zr2UiXgAlCD&`G^WXiy}4Nye?*?XJyC7~{;ryWVyWlI62F>}>kW&?k&Y$xq05$__WX z?vj!qjR7r%r;F5i0klr;c-!mvD1arpq!K|egy34y&tU)#*>j?6*-)4Rm)yVI-8J`r z2Khhq92ZVY8W23eWKWMf73h2hf66d{nv(zFsJRu=D|~v;&5#W@Cai88jr^E(E_}P= zoHX*rcgT#32QW4P5EEJo9(D;%T?z^u^iIF?lr%lCM+SIfY9b5F5Q==1B@wHI(D#hL zK|;E*6cG{=5^o5!zNxFIW#J8v2b-vV2{v3K|0oJuL|xp0JT&;ZApOU+m|S&qND=p5HA68vxr-;TmUV}M|!8V7UI5H%{- zZ+Y-FlqL1Of-_V2eh{JWN4)?cw6hz=KMAdYFkN@Q|%mXO=4%L;EnUIC}& zo=;v~@KsLX0+L+jLxtTujtCTrih!J{5)Qh6UQx+xEIor^P#5a=;w=4hbB&O2W@x=S zu^^$Vgg~i1q4+#h9g(8OUONX?+dxv+25ENrdd;D@p8@JXP#v>0IJ6f!+L@YkPaP;L zNC5wlIThSG+)i8(7Rs`N*7xG^u7)rJZTt~}j)(Wnt-*Xp79_7K9?AwLD`AFlo*RKX zY4F}8ft~(#n5~tXgXW*q7XV6xcr8xQb&{fFoSJ_=Yc-+i7xCGWo)F*;homQ&_4xf| z6-inq2wwcqV&vLlYXXja(x)^PcYO>u*euvXqc=wWv>7R?%+Y$u1O#yHXkysc@d_Y@ z#wF`!Qfu7QE;3BRYT;lR$eARuGTa0(-A)UamUX!%Za=ICI(Fh7OXTC zXxu`}-D@}$MSDr)@>>7aYPxfN>S_JA$KqZ|Ih@0GwU>lH6CxJ|X@yxCzx4ArL?^+x z)Jif%ZH2(@Tl0gG0ojm#mBg#fY%vyLX9Z$K2tpuM&xP@F?XI1vRVUi2Z$G#WJJtBE zuJryRlwwFyi4yomR5$t0Xa_uIH!?%`7H|gOV)KCYS?z#_`0Yk$*r(P+CVFA6E=tHn zh|f2t@ly+J18k4rI#ELbY*|9t*m&P$mE!W3Sc$iH*V~65Z77qB1;Zu0Rh9|xbvH7( zl41$J07Jvs2%DIs2f?@wpQEY|iCeZY0?ZQ*%*YWPb$Ylqz`MidE;Gr95(FbxRe#n0 z?mfoYx2j|6bbnct3Rf<|<{~h`FrQZ@@8Bobdp4Cdmi*0-2os21L(q?)xd)bW>y~T9*e_i;*duTsDHDARZ_N^caPpH_eUoH*ZBsTv37u z!l8?!tnNYpH*zEDtX?cqb;KLXw$Ai#-p)LNTZELpSpibhx3{_9ycHxI!S~Gq^s5xO zDe{PG`Im1+-mgK?P-1S?Fu}loO&E-|Wc2u?=?Vu<=z;mOIIl0hgGS>(@E>rZ zxB;Oh>dkMpe@1P`T^zPY@kd<7e?xVJ+%x20S&2%Gno- z=Kg*#8T@7|%k%~UPn`9by~vzI7$#O5v-Z#F&0!17Z`>iYSh4>mUK9FUDK6^JfqUO? z+#6sJpeNA?p-3i#c(mA5v0J8hF$h=`(yJ?jBfGi+-c^uo`5Sx~dt)wkl|-W*Eh;9Y zf+2JnsGT3;Bb6H=doDG0!V7DdS&Qiz&KWp7W0KFXwY3g`Gbg6`sdY=+phTb4s1Ye3 z0Bf-ch2fYcExaDx7MkPq8i$szFI#PVv~WxnCoac?YdmWtlYFQp zxGpUP}F3K4TQD84t5BCneTVG zbn2~~N@z+kbjMt@bC#9Z|DEUVhY`eQvS9Oos9bynfXOiPM8o2i(o=cK(4)y^kg$KB zz^61Ii=EP=$ulX`@>glc`RwZI?|e7!o>-j>3A@;yAWO2wCmCbq&8Iy$0ib6AP(Wl} zAKCQ`<>$gE2P9m1k3B*KNEA&*bxCtBVRm#PHc?N&n{tE^AA$}ei4tcy z^rQ0gh2zpd(NF9V4(CV`wP7HWCL7w&agSZp)~A8?p{!ou>z=4*;vXtY{i=F@2k zoe6Q`yn(rZ77O4|jO>-c-S6F4%!)Pr5M;{Lm3b)FHw5awy5DO0J{Aa+DFlk;glRN% zz={(Q`m$iNjYLbbYGox6JC37}=+2}Jd{vh1Lw6teKCE#!JF=^ruK+B2MU}>Q1{yp< zVvrb~%ZILv(Vpl9_qBLm`wQw5xUUr$2v$2I#}35a#`p1s>KyHfNNN<1B_~k{6kS(? z&GkJju+uxcxa3kid;o9&a}v>y5k)IWrmJ}D&OUwN`88M~q5%l=26tz6bz*=ELl4#q zKWX^^8zfRVfuX#{#4A`B)Qp>4UxrA!$)6UZ-WDTkh~mJGgbX8l2^1_JQ>4K~jRH7dxgg)%jW zg<+|l(xLBnkN8kuNzM% z@J3QA1=z^^I~&xe=EJEEAQm!nxH-K zCx3uE3ts`H$aCvKV02wNOpa)k&>buJ*w0|S3@*p2Tdj_ve$F43N!Hv!dzw{ZlMcUd z5)Z4Wm{(UaeI1YIQ1yt+b496v+F$%)1t|wbE8v5v{9LIF?F8}TxT)taG{ zhUw4GHhx+@7g&dhR~2mOyoer2gaR2JNn0SptBoynSiuD6oYa$kn%SKnudcq^eRQ-R z>p|(d_gi-nQqzKCsQ?;_msc`wFhase5)t>~@fu)DBF@J5GZ3M2ghA(dhZV#C;+ z6i$!8vIMPUnbl?R18j{Kj$n@2h#U!VKv;(aiJGn%KZf0!ECfAeWC$-`50ED{Fj5d> z;A0a>jIgu!^5u#!eT%+v_R8~7;8_l^sfhJLw0IdpcTtFI@9N5A>l5>mWD=rhmsS{| z;Cq;Z(g^4esYbNI*sV~HvI~2Y3!#Efn#KZ0v~{o~Mq@M!LXwS2s!S38m(>BkCsDyL z(ZD?r#RSfg$ysrIt^fQduLBIW{&^U%s_59LG;0f@vJ+nUBvYwXO^6mq`;mu z2q$T-s`^ZOr+Ph~lSWC^Zk(!+W-~B_PY7mXj=b@r&duyh?hvyPk@-J(Svc4p$Cu%? zLfVLJg$N_mn5BJ|b+9r&U}J6WcKfY(R9M1ji=Z6w)p1$JDToH_zA)bjeMyEr770Wl z5MIQ9wIDAlYjQ@QuIWDDp)MZBF6a(#*Cu!MoTPpV?LLUGx`Zr;5It+FGAGV#(3Wa3 z(tG8K2saGTWpc#SVG>$k#CV2@Up{GVt~X}7Aob1d?&_)$t;I2$ck3>I6O3dW0kBt` z$O0J^y~Hu{yCeGpYjqa9?GE$70Z2k9%rc3afe{KeqJ?wFkAFlCBE{JJdf1W0P6T7s z3;#l*;+Y`OfLTi}L%SsG3-fg~FVTCHB#$~CEHP3!N32lP^&~0PS7D2 zIR-SM!$e?kxGcQ4Qf6Xw3rg`3T18fn+5!(IX%^PH;0r^bS&?LC-|xj@3txO0Mko^; zbHs@|c6SEXC|RZlp;^#_IzxS^xdayhribJZb#U~CwAyu2xO269-h)`zE11CbU;R@K z8iS!PxDCLd3sXYc!1!Qh$aTD(SoF{LwJH(@F;8+?wj(r`5yUW+b+q%N3bL7?vU;Yw zU98GGwI-f?{yK*!iG|=s^%1gwZ}ZwX{W}qx7#wQWQ2|)20ycJ1nZOU|1-K-gymX>6 zOuz9%Nfodmg?LeI)lv^kqy_rdq8iir@Nku2sQVA$e&A$Fh|s_V<0XSZd#PTCkV#bV zK}_3F591MvQ4T`^{fxEwd3)`Lq~gZ0!RLU6p)sk82KYAIE5|K%6b>!oqZ~tkG6-LlhBwiDbY+mKd=(T})?}k9C^;+UZzTQE`*hWSw{LPG;>n_L(ER~X=2242DOM5=_uPjWQ zDJ#}vl1&Sl3mMqsh}1@POz_cCdkG^vN%fq~-{Qj8op#1WWVFJ&ZQ7}*zH}cXZs(nF^0va!HoM+xd>(cyQjp56niZBT}j_Qw%vH(@ev)ev$a6F0}T#_ zOl+i}owxuEk4@_w(4cBaU70G0+@r0l+;YW$qTL^Dm|Eq#re#p0ckRLn2S6$W+s6{Z zIH|np`mo#ZLAw|G7B_CfG7ZmW2T6@XET)9l<5C91C29K>-gC-{ejqk675I~ZI(U$u zlhy+A$%Nc{0{ybjrr%^Y%>z8?513Hj6ABgxs}OhvLD+DlbPuOr`LPs7wDZk&zZV21 zUqg3R*Z9p~dBMjo`q1PZDa1y8nOz86Lz?Z*fO|ucm}(hVYw!XYhdH5*6R{Z*;-gE? zX8v9+Panwj8TXkgyl!eyyrS-8#eabJg?vU_>{MlTi z@J<;KeRAvGHqEcn)o9NTj3wcjWJ`<$LB;5lMVO zk`_jdwEn=e3!e`MXr7ESIR_Ud{GB5l*b|CxuOIjC86OBdP@Tawa$RgdBI@j2IyBS4 zCq){mN>B_)Cl`>qNedS(M)s@kP&#!N5KV4XK<5J{txGYw^gaqJ!QlkI-!__BNs?h# zgag8d#5|+F4v(D;H>xt;?4XpAy_zG5$upM22+h?+23VfRcZ4T9cQ+P=(`0wA>1uWb zv6XgsVwNOvJ1I$yTmFL--O4=6JW*EUjB0DV^N7DfV%FUkoQ`FGwW7x=S*#ft?6Ndx z49Puc){Gs;{$1kOM^Z=f9T!;rS_0(p%du0O=S!8PW{|}z0?->G23Ty%q9wg16K$W# zch=LUgCt$=8tabW0ck~U7sAL;P04WtY;m}p=puSO^g;M2>fPTTe3E(SOpg$9+@F07NJZgRr z5*-e^S>{`>%ybmGk4_#1kQ#7ra)NQdNRSRA+ieYx!fd=pe%}CN-*5GT9Fnoa1E!F$ zJAmnq_n-4ox-rwGZ6~czhJ%*91gu=7uX(moA4KI02|E!e=LS8IBA`OZTa*Yw-%21Q z+$6@YNJ+5mjd#}219w0!*jP?MYx@d6F!v-_JGcX6AlZho-0l(?JyJCK8k4)x&@TD} z86?JPj46QV$m%CYvS0|z^L}Xh&vS7bcHg1_V<#Z6stwy1IiuC#lopM)?pm9&>O*%3d|q;6m!d>|PKK*p+Ug~~z)CO${?rQ-86QOGp^0;nHnTL^&!kOR$auNcWq$SqA8mV?W9kiA_n$#D*Qc;Vkb_IRUO}x0tr6K;JY~;zK1zzz8zed10lLR2akI z3uTYhWQ`;FK_%cC{7>A7?6X6kvMWStaZciouj2x?N?$Hh@+r?&KJ~{=W{7vh{gB3a z$Qff**w{Jyohf`Niag>{gtfIyxpSDy zqlN7qEm>a}RV&KJBzA-lR~8d_965C2L?}SzBsXr?%WCL7F@)}wUWh3JST43rb79b< zjD;#DfPFG?@AefMvF2J+CMs|zB>y3zsJ~JKS&Qf<0kg!$d!iqz2XvOg!5nN;rgy}wfeAoh~dL`ij?m2TnG7^Cq%k_geKayjLqg2+ib3>KwZHi@g zqs^RHZiKS~Xcmbnpq_*c$dqfadHs?#<-WyraAK*rGb#vK$YzX%sxo-*U-O&EMV(+DDB_4(Pl>?~Y-q?-91R5{A>I@p7fT+ri|!}~$l^nSg|z~nPqJL< zP;`4*%Z%kuxo;6R1tLEs84|?znPb|PrDa}yE3cx-l3nzgR4IH!4s?Pwxk#da!H;BQ z#-TxR+kIeZh)n<;ADj$GMA%%-6gs-8jIuV$4z^n^zb8hM7iJ?}VxWZur^IrV1=gVz zUs|e7jEdt4{61qLX$Z@P0Ip03!vl0t9Vzo%m-fXqsZB>*T*jqKWffp&$&lv5vIO(C znb^y_;%QSm4_wWi8@elx((A0W6neFB&`C$q$zF0N;wLC0RZBK80ux2}z?5^Kk-RjA z^dOel#f7Cxig6*O)S)JJhg|I`SJ0Lmer9=0PQjs7eB`c=1C1aywXI3wO3rrRe?s^t zB59&=tQO1zv+(8{5$ad2yTlzMMPYObR|Qka8s{BFJV51Vl{RLw0o_j~Co6XkX&|q6RuyUvPC#Zt-YA zb>TrzIB>a{b6L4BFn=CLhBYFHFC1rUv#DtfT2d6>Y}T3U zDo}YlnrMh1VEiY21WUg{4Rj>ez-`3x7J{6&1J|)Mz-ApBul+fj8xa;5SJ;LQ;oeDX zZnm8qG8y&Bmp)%!?{;^VVo=gk zM40fntbp9G6od26a=vUl{8RJ=91z`QO$;k$ZQY3eT`3l##~L{S311g;zCz(UIiH2*f`)9u{{R@8e&G~;Sd z*C6Ovf=0tkRygR4TV^FE5k~2ttIRMD)o19N^g0n=F&6YKLE5w- z4&%fx>k1lFkJ|#@&tF?>h#z(D!eeu%3yfQuq}?t;kZEuUBJIboNKvkNgGQoafgUtV zcI_0LS!Mt{Hb_34%`(w8fIN4=tVav(qicS^H!oXX1%&gNnYGT=+Cf9uJ(z1MABzGW z97!%NBIbE3*3>A|iUZJZ30J2o;ckZT)QW8Y)JoH522E0t-oiEdo&2Si8~p{V0F_XT zlHi-cyJneDqg*?!GcF=p=JPbigRL~m+O91cjdd@QOML|iHQxGZ+1f|0~H zv-|}91)O!5%DZ*8yz}(yS%;3-Y8Fek@lCyqBJ?>RFG>LbND>`60hYz!@p@N;;JD(c z7;IPtgw4YN1quOHvqMd=B^~ViN+aAcpEdzR6C|gkr6`D+r7hY7*G}c`@6F=@9ygD+61SpExIn?n08U7=(z9yb^5Cy*wrMryDDji89uJ=-g#3o6T1gH{w89vz zE4&-wsF3TbHzb?n5{sCHxgf!EOL|JcI6w;zf0KxXM86}FN^(=j1UT@cH7Bpum8oTA zcQ2PuZc`utq4DF;MZKrS?xA}q%$n<5D8cgJDaQ1d13}5HFj=kJxle+W7Vn5I1sH=sC+Z}_Pl_jek)>7P4pjtUSyNB~Z9u;D+W8KS?RECmW zEYFC+Dv0SrzR7fTFB~Z?+gAV(O=fs5z)6wFH3YoBm&?4{herxAP3m5zNn|U;MaK?n zP@D*NGEM4UkkUBoCelt;KYp(v)oSG4uP&B(dkU1I0eE+3?nLZ)gwcgHg!)8866|3w z0Krrs%-Y9pM`LyAiQH?zsWRDVU$W9b;X@^=9>YWukm=JXT43jo44~V*6%}|8)wAA3 zU1K^OTQC@vEDm(Xl5(x zMp! zw^4U438Wr*)2VSA?|N!x=AoE`s#uFNh%qo@cX9QOH)FB*zmN8vT{vqd69F|A5r*#) zn-@0;mAo#y#Bvp*t#hP`kof%q{(Bfo0g4C{AmYP5LQ=mIt}~dtB8-~~HrIW@h0xZg1Jtnpu zBf4d)>yWe)Nu&DTw3cB`j9uZW6A1ghM;J{;0tM*RC3hY}ZkgvSOw}MM1U-UNYDD8Q zZQMyiP~||;0|Gor1)dYbHd->_Lv@$`Qr%HkQ{4D567m*e_l~HZbwdg~2$1S1f;R{c zwK3LqTHyHeZ2$fdht)^H>;UYC>XmG-khzOT0_DLzlnyU{@2lRc?jXy?PeB>gV$#p> z*rd<{vqD5Ma$h=7VBo$dogt%ok+nrhn>>BEJmgj`&>%O9N3_Wd!4Tz zZBHCeZFje}%BVR}u|T3w%b)AC{^S+_Oh}M&*~tIK#?A1tzRUks-x)!c%X;0k7?Wi; z#6$~`$N*v;zyX3Q@1Kr_U{r#i{{JMz9{ijebv}}K5N|mIuGn}hNSfhe(ts4o9;} z3~{M;iya3QIh08YNh0NzR1qWjIr-Wk5Y;s)htx(uz!om>?tb@pCr3C*kYTNWn+*LI zY9@0L=mg@VyuLNYapHVH?cpxGL z$WDM#c;c6;wWyZ!tDS1-D4&z+i6Mks72tZbMhh=WmBqNx1gdO}*ls4G6D!f_1V=RD&6&cF2;cl~-M%fCaUH>qp!%-Bma?N&i5=eP7P1Me6FA1c zVLU`~@^J_+D$&uE(mD9PoEXjv<8M8YxSOKoPpLNIJjP|kF_XY9$jA?m4HgCz!uyvm z`vk*>^7TspOatTBgt2Tt^9RB}^}~#oTg1$G3vL8%U}|ifUV2zWL{AiXA%EiBvys0+u6Kf0~%&V1&Xc zK8|spO?W>VN7J?#-{FLA0Ou8!SPmM=sz6c>Gw7CkvLCWZZ_lg>R?Zs$J5KiaV>36r zFJsbCfmTq`2qYWxG2Dbhtg+dv-Y^m=^C(T0O-gQ5y~1O$CO5)?kNg;|_WH3VY5U{7 z&1pgk8JxUCyMTkoC2cfc_nnC-8=4S!dO8pT|LH-oQ-Eg_R>@p~T8~Kk*w%y!m;oOI zmD7trvZd`MjNUC`W6^bfNe1XJ6AC!I*_IN>Qg7;saPFM-{{Hc9IkZGEERqw3)ao43 zoYv;TI*QAGrbe8yWue|AupFXnLKaA(WUW#&>G31y%tgzOz+3=#kZ|Ghg$K}fHZ(rI z$xb=Hl4sf@fZ54;4XpzgJ$S>+Ah^H}Ga;w6?}GIJ`3LM+;ifV#E z1NS$BO<-c$<-m3|=!@zcYb9)UG*PnGL#9BAYpdnWhW49V5|N_(9z7aQna+?zkT@sd z;s@7;w^OIHKO@rD9BmLqK@XsgOSpwLU1re2ugWSDj1kll>iHVIGCHm%<#5V0x59EH zYBACrdP;(EAp4ABSx-_<|B95epqbf*xfVF=r zG~5%`SYpUIRrG)YqT_IN6=&qb)Oh ze&1Y!hF2n&x}+ZADJ7GuWIWW*yXOm^hZ?|nM}&-ANvXdg8!3EbLUjiQL>T$4l}Hs^ zQ)j?O#r?xxvjgxAe8l*c;1b3-Qxs~5bY55}z>@&g{__+sg-1jO9F`<7(JK4L^N;gZ zWDNFcF=gV{0)O3-_JrVgFhL8g&3i$?`&h8aBb-9r5H)zhjV+}YX4<=WBlboai2&ay zs57!@5Xccq+45xGB0n~160~7f_|>3MAS_1-B=8$0n~#+Rw|{577`MHIQ3hD5A=x1> zQq#zq)MEN~7K%yspKmlsqhpezFBs3bH)GuaaB9LzrY|iN6ja6SP9U+@06obtmiTw>B`d!kdT_A4WCUPjr0x4GC~Y4K5R_?rFCHId3~F^W^+m$*i_c%gU-6 z>@gnkYux$CQ-=2gGGcAB)vA}gb;FP?9(iN6UI8ptzn1gWBx8|x*c^b)!Xzfs1!Roe zwb>kU>~7?#><gJ zqkw9VG}b-of@;iI9x7j(am)f808%DdD0F`0P!BpJlFcMxI&!~5i6;8vyZ77c+8s1~ z?4rdEFqYnRrMxyjbZVpnvoNYSVBFOdB>#CuSrKmdRlS_G48`J6VJwRdW};m`(};ET_th1;SR zeyMG6$|d=RG$#eu26Ue?nCTj8BjzV z`E|zr)hBD;C5+RZ@>@ulVggMSwEGbzXcnn?wECqa%Y2jr9jY;I8caO!h8VC9Rq7-8 za&+LnJyvoRYd9|MQbD#NNXa; z4Y4PyT^`6cUE&`dwSFwLO1A^EK|KiWos`p!=$QUm7+|@OqLyQdVLNEY-J~FsQk*G1 zAjL9LSdoN_>q!pjUo`mVyWNan`?P&{tGg$XOo!|))B(J3SqgNhK{^?!D*99RQLG{l z7o(15o)Eag3MEraY{mo%skh~*OZ8KhcjeS!AEj|^LmiQ6&YN~ z(}#LQEW&(EXxSMgs2lqUu3ZU*Zu5vu3_6)8Hv4e7U49}TntM<$p9r~xOoYVH#1It3 zLcv-vd1+c$#JxgVj7b>Uc|s6s7{AD}H*axKn$QXiJrNYZuu^4Qb|nEGtI!>5Gh(98 zvNQsimoU+l_V_feSQe%~x}S^}?=Qkpd#hXkB3Y9A=FU{@1G@q<62cyV!A0Cn=26#z zXirM#=;m(E*n`Q!q5RJG-)`UC7T3S*er;}(z5YyhqmmmwKv0j+JX$B>SRWlIDgOsU zsm1t_j_OVE3Ew>IYLq9*m>6^Tn@OS#&xjrP{*`&Tp#84F8YXY`FCsOBm{|zHU1pZJJfP^=}E;m7#&3OREH8seijt!tBf4 z9SUE4zXQVeJ%7p^MDkDS$wO!(`G4k~Yi*72V)7FQ<0Uh2YCVfCMOa{P=wQ0R{3Cw+ zg(1+vi2v`$<`Mn%_Mh^%4gm-yaF-sQHx5{))IOV!y<0%tbOlIt5G(@rB(jcs?}f3K~CU+zDjKTsZd?M0}!E%^k%JDRoTVE^5LTC3rtv5L_; zLx7-Ywvs~8Y&$mu;NqJ4;esB4kU4;sAo`l7i-@;ba%MYptv6EBI7KuDW>Nuy)5qUx8ged*8DJ+dyDdj=t~bWOkngij5ba_78N28%WA2qE!4{K z99S|j1L7eFez*RL_XRKCnUl4@QbCE!VAuG6V27JiP!~?bK?_){_>Z&+z!!F^;vf<4B;n10PcoTSmu{E=hez6RON;ly$NmL)v6&oR6~hzPKlI zp<-&kA?MD!TNyHQ5}B{Re*_1Cm%20Saa`B+rqFlk0I9ag?*Mr-0kt8RSAre-$4_X^ z+sE?M=IkHKp*e&L;QobJjH?NG8`%)UV`+}-PCa9EXpZzhq%fT{94cPHxx|%<1fME> zT&MVvk{6F6C@r`b*Q9#E)DYPC81)iJX}%b10KbVI(r%efC!aQetq z_2K7Ry^PMRNCyNoUhV|lkTg(0XXt*vgne)DT#zbAU^LiL@UKO8Ce4#r8Um;=2@M8y ztR81$iuQrWyCJZS$OdxfGx^(jj!#Lxg^FUc10x56|?OAdVS zwLNwJunmJh$y$^3>eif2bgNE-1ey$UC)$WaX~1c?*x?w`|K?MyT1cm_Vr@tnD|ln0 zfL(atyO1OmA{|0V^SH_4ph6l6J;FjW6LaQ8KU^2@Y)uWjF~ib@>m!PT%BW>7W`3BM zt1I(4czr!O&89k4ZL$buczZM9`%1`T5Rs<`j*6Ryj=}S`dihcZYkewyX1U}x{!;d*+_(@ns62Ab! zk8=Wlz}nl>V`sUO^MPDG7>Qz#416T8CMUDCNVu~1DWz+k0|8ZSnmw7Tjn)fljr@du zgGhxm#@s|)ulacu&dxWo(L^mcSAbhssEcLcrxQb{wPvGgBtmP`7HYx;oGk8ksM9jJ zI&#`iUy|V;kr=uS?wuXqbI5WRe|7s|aZzJMSMcDs`nRakda@n>QJXJVDPVa?_}$<@ z$^q3&#Hy9Ku>v~+PXM9%qe)e?dB59U+RHEWklpQWD002!AUKHPs!>m51i)hm{Ps{z;|03;kN;(4>r#_EWp=a|SuGbu*%(J@``&j;DD;5>9=5lS$WaNA>`KDQ9VEby$x#4hSLbdX zVODutrkcEQvl7rRq_Ee;=j$D*TG^3EP$3T&opq*eYQ>t=`LE62)Hjj?nchg8rZ`B_ z9ONvx{{m7RGNnncx~I|~*!$erxi8qNkc?imC&Js!u^f?cl>ku3R^u!zi2VA=;S=&o zK$ZfDH2Z*TnurVM`Pct~P*?THW%t!VG2`pJJ0I9@E*et_2PO3#9@T`5lu zFd^e0+S0EPR}z}X4q=doCX9Di;OR~=3svE&cCSlPA%eKsWnzVpRN6}~&R2gBKHiZp znP9jbZby{B#%?H?W)KB1v5{?rL<;c8>Cvzg_v&*A|R^bB{|{b}MjVly<-y zF-$zQksLCO@=az3N;US)JGmR^Cxo^T=$8^dKol;EasHar>;^Yc;C_1puClnVFr?MZ z1D;<*QGpgH#y8Ew4Z3*2rfbg$(M-maVEEgFR6$DA5U;$LHtf4aAP>}4d z#UCyyy`%TV{(T4)z3;yP_O-i_D+@NQ=414iSO4)g-E7!)dgFj>LvRxW07f8i{JFi? zDfQ|~ip4iwh+o@`=AZe^$%6taKdTDKP(^SDi|t|Gm1BBX12` z+_@N4gOb!F*4N)$vRm*mcQDJ)J<{!t9a_( z0w&OvwfX`P5|bDBXNpQKcU+gY4lfFEPF=OFFFsEG(Cf-^vD32_3u+l5uC>R!oZ z=j!U;AFt0TJBRKQ;A2)pPQ_pL8tW`6w``e;Z$CdY`+s1LKeHmJWHRg^&;@yz3}V{} z$1&noB8)W+tF=P$h3LgOG7p=WN9EvnVd$3PTSe z`&bEUY-l%!E8V7!i9qv9&}C5hX}mIwTvU z0x@UsG>!ESgzfzD`R-JQ7QXs|gueg`q4g*Eu4$^Xg{7%Z3g^=XfEXnr=b;n97Kdfu zTqNBkE&Nw6X~% z+`*M%-$L)C0_(J4$S_2fYzVwGf(f;!oU;y;?ZqMFIjz_@XORQ%5gR_q3lvg?!;WnMA;S1TTD6 zqHJ|D?8sNG;;rT8J8^tSAqEo;{+R-lT47m0LeuUodB!JETYtpNsi)?ooK(&;QxcTPV7&l(p<4kkGFt5ECG{<;fplS* zs8FR^Vf$2J)0IOuiz7XAS_Jn59{v=xG6Y$qB|5XDzD1#j-5!@91{v%-&ovGWnbzi{IqwdAw>VRwIXa%yt&8$;6qY|ICBPcX~Dnof1~EG~JV^HA{-$wPJuh)XSk z-qCt+Ds_>HqTH`v7~Ht%SN{~!2Tv^_o+Cf2|^b| z1U_rx2-1XO`uX~px4RdoEyQZbQ) z=JT!0st}_Wa2jI0M*zr!#V=5g1w0B$fuJcaKjFc8y!-RcW&jx7y-nn^ z{JBnNq`<6*d$Z8xQfn_GhQ+bl`~Lp!8X%1v!V>h@0*kDe-U6dA0VB+=^L*CXV7Cvk zcJW<=`vKh%eFYRJyc3I+WnkUzdQv!`juO9wtt$!x10EYM-Q7OHYIvv7T-F7YPX{K0S5}<=tX&f=hIg+Xyo=F9&l)GMXF)j6pDXdNL zLqo*S-E1%3aBm`uZtMA5El=3F44D`oqY%* zEYxANJZ2vj_wQr@QLV=BGTw zOqG$(3-yy@Nj&lL@JQY9{<>*2?NmhSJ+i#UXib3OjQTL@__+4SQr_SQmn=efObP1a zB4D_;XSGJ6b4|e7TvVY=f)ERl7lXZ>cUZq#!0Lin@!>AP)R~iM*?Jd7jn!qf%OFB( zN@6RS9Gu;x4i5>#AUGuz0DAXu)>z*sf%M~@1X3y(2Wu*~SiocCB!StNv2mWetiG?2 zW;RFJH8;$h}cMSPDU2$tWE5fmoG(ydHIrK z?d3~Y`mt1#ykVjAT>L$Fdp7s#MB4n?e3nB=;I;U*O9E3Nq!DVJh4&WP`U|uD_VfNb zq*i*@+~e{P>Luv?NIHn>gdLICLnDPp)3%1ytW(rlc17BdvXC7%Un&Nu=|^uGK!0@N zK|zYi&zpOO(Z91;U{c4Jn4YjF{Gj4PS}x z^mjk~^!LC1?)Tzdt$v3b5>~q3`B!0Z<^AsWP^p8Dh7I|5+-~##;rai=PyY2^U+nLz zKVEN3;{n(3Vfp9P{r<%twVXfp-@)I*+~ZvlptTRWh=4-c0Y)D}|E&Du3#W_@Ig5`6 zkgYzD*%FRqfrOYa<;=osotL1(H&Mi7490QWW~iL3IEh@;CtbNW#pel>X6puyXlKVDtQ|GMA((T>wa1Jf1qVlNf2+Fy`&meBF0k)QRKD5v`uFq?hY zw7cEI3(e^C;yvoW{_=%z*}nMh{Ud7k{{DRSDTI2q!m3M7LZeTh~+iA|uMg7uDxyR94iyHSAZV4p32pLNCi z!M#Kz?;ir`3A-F@Xv=j0-aig9@aS^A8eTY7ny*U$%mY(FVXE~)2TJBKjK<0+eum2K%@PGfeln%$jeG~HA(Ae^NPqE|_W5K9g(MYyr*S4I|RD*4l%WWe` zBe*O`Vk7hD>(zu5u}DL}2^>R|&5 zhe>!GHD$RO75V1yF$;B#?_+{IzZrkf;nDf&m;CTUzjn=PLmq4jSq47obx184M_@hh zSaCRZ0*U8GR&Ee+&S4AKwA*`0MlIrvt;i;mWek@Kp~cX%gY=0`&D)h8@EzJ0jz?ay zi0*#7#z0N5S;j?DLUb0e_vf!2D>;0yN6$5P7wdSc0|+Z5S8mA_{nd-n8!*cNukH3d z{|Jnkv0rj#r^xjzL_l)WdAAW{t>{)UNF4MlLKRy{^oa5>dSfW|JaH1^Q1GBDtgyJ}6SgwS7r}lC>FbWpVZqR^Ftnv6?k3|`mK!zbFp;vf8KI3vL>tMM#z80;Q5Ylf zuF16mBDemPiQkC%h8AA9pHEv&mOSh9`j zhLIqXOsPJXs;cWE**n<(zRx)kK?ZM`Syd`^&u+_7G8l~Oi4*7YzS=8B65lO8MC^%K zwStru4Z)oWT4KJwvJ)twZm$nmmpP)j0Z=2vbjZ(Ui~duCXJnUjUu3>Y)7KaRGmd=p zUvIwYIy+X@fYSn?a|9$ar0JN_F=CkM-~HOI&t`;Xd{97TV7@@LA)y1iClEJGzj-wO zcDIyD%o8Rjg#kd{i`YJ8O*jQG{9H4;r}DQ!Rbo^zNj$uWt&0O6Fiaq-$mLXpL=s!@ z_XKhX>#Igf=BHGDvH@1z8Et&JzK2KvZbiFwp_<((9;s3Qu{T)@gry@~ro zz9vW_;qx2o%K%Lgod|;|Y*qMT*eTOuduvunfHYrYWYh><+2$l|Avee;Z$bp77?-ET z_S7sEO?`>#s)o3iN>H51pvkr%fp0t3>k)?5mAce)(H> zILVwqJ}0cFgm}iJFtQQ{CHB+@d@*h@v6E00SsEn}ZTx}1v=qG4?x|GM?Hs$aO|;r= zcD6azqf=RvSq9fR=_*`uHbA_HMvh@dkdiSdvc=s86ZtLG-z+!H=!=U^LSLvDv7-sK zS``7m@)fx=o75j}4T%_>Xc@-?4qO0$AV z2qHGY?QI8BtVXkY&Iy=OEalK^Tq?H)t}gK934deNv_fIgJ>6YPDo{K!r&u52LMSUp zfdTZ1t*=k!-|jj>RIgq&yF(oaI=u0)fo`(I8e?%GMzgd_;!o@~(WzVq zlT}+HYM?=H@U}|RPur(f8R^!dk^Jh^LLlKU;9gH0u7J9*6Hd;|rDO6IPxt~rA~@a2 z(}w&UTzk%z*{SJ=CB?8OW;*gNPvw3|9qbp@2$;zXP0WcPvUN~qU!6eVH87^=J5nF} zxdzEF2LF@%A30?E=ks-0JuEVcYp;ajpeDeMoFH5`jX1ge0=ud*daa&Lnjh9xiIV!W6Uc!Uv)oavJK2G$ zfyj-UDAbWe*>Lfi7TZ^IPD-rMYfJ8MS24^QoW>+Xl5PC zg(;+#0HCMa(mr z&;}8X&l{`}iP7fau1U$dZJ#v_L8md=MH8jm9N3>bmWLBZ$XNegi1`3rxs@o{hBQ7Z z@e9m1q~E8kfAt&NKM*3KR*-izV}9sG1S06>lz1>aPqZf`N+HUMiW9Yj0YUDH{qsF_6>_b# z^+4Ptmye8aPGTn{2Gu>>Q%MBbuo#VmZ5Tn{os^>6kXMUd1Qajp3J(;cyij(}H*8D@ zk(OW#ZIJxrf^H>=n#4|=ud6+;hnclwt4bv5fwT>3a)fw6>vM3`)c6WvL)d~l* z3i}TN-=wolwJdew5o6*ELt)@xCr?W4sn<4^y0CbOb{diO8UhH%+?potsXziWrD4=S z0M3RWZzh%7u+q5OXM3tBkUTmL)R970L@*u}3Bd0W__V@4+*3&yH-v_rduA6Ll68gU z3g9C2-GZ}wP-0(w?uM%Fi0+IfKnpW62zLM{5UkCJ+v}QFY;Vo>y!T$A=YW6le=Ic; zEaA{&`A&=NshLQsRy`*zF|{NOg7{CYsxa5egW=20J7iZo;nYo9Y&faGJ`5%C@?Oyd z#82p|xN{)I$Lp%*L{m>M@gKo2U^}*ff$Ncf%RbaEz)vBmzCg2Xg8F95b@9_${?64S zP!J=oknm!O=SSV|gr{9yKf(e3Hu&55+28s3>Hl)SaiJ6O&KveWuiq2Ra{l4l>blaa z#!qJ_c+vE)pat0wg(~>3({s8TJP&@XJ`o_u^CyqAamUB@Kc>Vp4(YSNlz0}H)Yagz z1T)xTrZ30G_R;gEy5Q>fboS}9;4!`M632sDggTvV+Ti71U%&nD^^ZUN@OJ&TAHEe2 zpGGk6I){;1yJ zbvp@nc=PK&1^+wvIUwJ=Z3casix?pURN)r}1rHsy*_X{EtWTQXMX0g8#Xb;xtWIy* z;3mw1zgA~A^y&}64}8iG&-jHHANor<^Mk~O4a@!G>p%VZQ5gO@EZqM}^;f}U645`b z9oGjmNOk5DnfNdrEg>Wnm*beUR^Y3#K>+3UGI(q!fem+j?AA4lSUPpm;J3#55om($ zT2}t~h2SR03TlHl=LAUppg)+c1rV7gg9MLd(;pvG&GGS1{jW^k=6!V;d@FDNc=GQ3 z^)~`(82qf`_dQ-J^KZ#o4!!}r?&_4dy5ObadNGCqYo@6z!Hepm+MHbf@dHZy_7srX z=W>AY@!&-V?$G_jZHCO(;D_G=DPS^ff=i|?WK_4;rX|4(j(Nn!PiMaYdV5BNxa~E7 zN1W8tC>11F%#*|>V`3~4C z`b64}7%{fo1oeqdynM|#{0{%xY)3fkGUz*rM98)zg7FcGxlh=kwx6(vgqZzAV2j=F z?N=|p(n;tHfMUI(?RXiWMl3M>0r*NX5yJHPQbfGgHIeW#4+emQxSKBe=CG+?Q(;!d z36A8lX0^c70LoecgeiZ*| z&OURrgBhtY>%`A}4A$o-xQwwRND9v-a^ou4f<>s(LqoH^I}`ZJ!Aau%{w(1GTuXsUV}z@kNh*zZ)soTSs?TObhhSa690b{$Z@|GMF`>hj;VS4 zkJ-|{23=3hjCiH`Cqy3;^r(5q!{QcrMZM0fQ0)oqhHcwdRRwfv)r8W9=t4+fj_nDBMTP#;VB81^NLLS2nnm zKtitoVL~?8$Q&^R55`)4a39p}7#S@M0#-&s+kl1GvGLeWVZuE`3|IoTLh!E~oiS`| zgawH`4W?x-yu%_YrX+UZT6UO(qh6d~T)hee#>_1u{rls8$bWv7_km-Q(^TSOpI-;B z-4AA!2d}Pz*A+>OTEP766$i};$bv5fn9EN3n+ud>x2oKiyajN{=J^;NA9qCti)j4x zSGWClm+H5O=OkvylSKOmR&O*P8Oyf(TVK=~lKYk~NnScYz z$P%cK`n~)R+`yuyP_M3p! z^6LZAl>p>bYt2aLc0tV5}Xs6pmXB7wa;9q z52%hvM5{@@R_T|ELx6*TLelA84y`jp~PN zFmx1LLU8m=xT5vOmA;^zbe(cc4xk8J_}l=qy1;QVEFx_>tVvHSe7|Yh z;M_Urf<*AKT%5soLDxZmB~Ta$;T~X>At~pa4&HM{&o#@o&e_D|95sAL`rznj_Tz3q zV)ZOzebXyEU#-C9AjS)iM4oe##o0F~;TDHEG5kN}n1C3v03`|MqPYBNvFHzjk+5wt zjhzY}`}nyGgiM&Vs&JTrH32J$U{yd9D4yewoTSRs$05OtDja~mZUzvoS`fFT1%p& zia`yG39t@kEVU2Ab9(yf7KWiMQE5n@2wjP>8cd;TT7yZMT_NN9dk7&XF=k*ukdft( zRMF$Oanv=WfEe3Tw6bxb-3#^h&A>sTtzg`_g%B$NE*E)&j1ecieYW$P2h4`|jaE1k zxW0ptk%QC8SoYsA8(no)v27IMo>>cHCL^@gz&;vDxMU0>Ct&CNw~S_%(5;OOSpmWYxnW%Tp{;OZVu|C{mDbdxANH)#PbFu!+D>1d;T*Szj&U7YrsNuFdpk8|uBzTno9aaGe`S2Z4 zsU)rqYdlDk*LYxtnv7Fm9iZ()5@xMNj*E4)tMQB2&o|gFfGC4#6ZSiJ#jXAP3pHX( z5UQS2FxsI{wWOWmcH#V%2RafaiLF=rF=eSeq%gpQvOJECMA>S(z(+7@H3H^m?6f7BkYfAi(C{xH?h zO%si66*J(?2k8m)hZ4_Jw}R}4w}UiTK!iBw_}!Y+6^FvCPdfHZ7q&o+xsKHF~w zE8Wa|Thob@m|ic8Gl>D4v1vm=!%9PzS8^j4XqJ&p+kDy$gt!De`|gY=+shRLQ%p;; z77__;(@cnk{^x(}9Do5Jt4hS&1Fq)1Eey92f~;z4GQO*ousC`xG)9v9FL~uTRe^5I z2@4Bf%_==7sxEsP$Fhf;2{!~lOB-UFfml%K8+><$-K9S#c)f5=w^W}o)8w{eaG?r3 zxr8o**hB;>iCAd!?%~tL&H7}xiM_L9XZCg~K0xu)qmS`*f%2=#T!#XP`y%-SFen*H$ajg?eFulKrd1Floq}18F$w%MVZB`_yZ1xHv?TJbG*xI- ziH?IpqaZk$D~UWfqz1Gux)~rq=W(zQhEJ|U3XYmz>u`W}3ZY2Mfx06NC$nnC0MdXh8AFdP)-bPt zH0;Z`N`$(o$AF=~P&aLG0uc(oDPoLhBR7HT@)v0xi9Qx7i17Ay1!jI!;^`BzX?@}v z^X2?CU5kKA6I2noyXFlSKsAJVE*gvJ+-+2In&@e*O&8h;3*hsr)4CV7Z1>T!fupWU zqF6GDT0x6*!*HnE#%yJdkuVjp<q=ELSe@Fy<2HjY25Rk}XpBo|f*T3@i@9 z&+};vnK{t5WM`1UAc=lXOo6I*DWHSSZ^O{Nuj&%t1nB1g=#ehZ>F+%szFFK5^SG`y z>;DcFpdB!`m=8-E4Qdb|JdRqk$%@07nI% zkAfwjR<@TL!DeIn%yBC7H-;dwb%hc53f(JVDd}#2Rhk+w?!Eg!BF1}gI5yCQ05Mc$ zAv;G*Vv}-%$y)kcMt-lvnyhOgcADx^fTe+G*pf+HlK6!(Dd>~qLW8PzkM{$t1Iu^^ zmRQWq5Xf%gOG{yw;W&|&eID2$`;`(7(wa2iyv{MZBv{z^ij)1G%-sV=W@~HVodBnV zz=;%lrXWt4+T8WJ+u`WchugYPficG9Fzqzt`a5z06C=8Cb(@`*k+vp#E}Wdvqyo_k zd;t;0RfSt|jXp?wa^^H_@I;S59!S*MrqEMWEC^QZ?2d|sb(_kXl^{Qyz$>C!$d<{I zO(h8A`b3rip*b4pWRHdYfprs?h#U<^N6xVG?fDG}BQH5Q8!=_LlcLmfN^t#YPKbdw z;l2xxVnhx(tEGE7?HY+OgHw=bR4z~If(J!{^kn)YexOX~0T;^dI2Fr5_iuSB-lo&= zMJA-Ofz|}FC>Xk4r-`MX3|c2VbSXILQO=YsHM`gv`Cv$DK)8dFiG<%!as#@jZV)7% zUr+uga^*cezq+|>t#Tq$Nvg^DIVic@eN0#_Ysd@v+}oV=a*N6%0+Jv>U?>R(XYoSv z&b?8dOq*fbph`+^T<&Hynw9lq`_Y&{<$zmQeNs}E+DJXIEx|G&;3y$c20+b;QF?zv z2J6B!y}hVmAF6T0l>}6RmBkT!t6uagRQLSh!pumIz0E7h zRS<tf*iLHsZaUHV<9V2|8cGbcbe`tLiRVo2TG|aJfpzt`b7)5QG-1;QOVz-pHnN zl6f_YyECgmSS5C#BroXJ(>O+7!w2G%IM6C05HSLm1jC0@GWNIZHX8nHD+bNCUFvlF z5R4NE1OwknV1se2AKtPD88fF1=N!U>XXN1jGHe{e|KfH{HAhI-VAUf&3ana?3b;!T z>_1(D^&p-)v@l!}P-$F{#3zEeR##CTCqiXslmYen89C%_kvr=G(4$)31c;f ziePF%`a?!~Qj>OXl@d%TT3~X%IpJ|jrDWQW#Ge0#mX|RKDdmf<2Vx| zaJx##djt#2+C>&S`~c@Um@nuTVgkqjT|4MJ?-#|t$yo%XKiNWHqbACMC7yKj$bB0@ zCx7oj5`{H5gV+eNhB&*H)7oFV`@S(;>3cs`0qNbQLTv#j>@+X#B4K}JC}EC?)UC^ zl}xRpBU4B&6`o(cHw4-MZ}QXdwh+k-sA8)WR>LADl*3mo?(s2fi9`=!L`h5NpoIrpj zE_Az(L@TtRclbiyw;x)Yl%$u36i7HQ!X@ zW;ZygSFizh{jo*54@hqJ*fc_}tg+YtUo*fW$1{}|8DPw?6BcR7Wo%GFDlG=#@yN-Y z8ExhU=u8AJyQDCgN4+z$$ni@{{uP}<$ie&s7bG-w*a^6JnMd}pkeBdE>riMKr*~Ei z!@9i~WHN+Ebu1yk+CUsH#%ddb{Lr0&&KHCtaR#By5Nkc^jJf`NcUoP0VLiRJZc}_G zU4G&P`Y;>iG+IikWITnK7Ai+SZtADI-_nHxA=(I2J7nTevd-Mn7rJ3=D_qz0(l_ak zIbMASiCHpsU`Fk?amjZH0PD;RfP}#=Moc+je?q}24`#HH`Q|#c?Abtk$Wl7s@bM+i z-gC0tu7H>X{3yvu->{tU=H51lh7s|1WjAFn3Tge(kzQ|H*bE$KXFr_5!^es+umWO6 z>RfpwX%bAM_Zb~sa8HS^5#m+$WxWc4G!Jnr180U1mGj3wefqUbX=g)w=5lW3SDo8K z&jZk7<)|xHc(3tSY)RaJ%Ng;>?@y(+r4{tVq{`cMrn`E&DOj9?rF4%Klw~mc#UVf! zn3Gd+-FPc#vc7GrdwsHBLF8j!x3CD2zH1>tf(;x)zr)Y?4!{9{W-+qPJ#~_ATM_G{ z#z|Y?Te7(Y7{nFe*z4wDejVRxYJ}O&L|TEFPXKW&4o(tQ5{VVpN6P}*!!ekQjcens zGPi1IAxQVv?=|f-##+{5Aj$AmGG)?K`|##X~&09@hM8xhD2T8F?IKS}W5m`*y z(45+Aj+A@IVI#waN2$f+0vs<@%$)}KG9W=@)tme1*#a3=V~Mpw;%V^ES}a@#_Sxraj#KW>%dUwye*l%id{(61CZF|>5tU7X`D zt~0LiRfQ6K+K?(wQteB3+Rt4CbWCn_)b~0G%&`#?SXk774XC-Z?$Al>hZZ#eGda$H zg3>d454(MHea!?5F!b*gG%Uokf}4DZW};vGx7AI+tYD6-WYdbZox^Zy()$dew)hg7 zhH%RgZcnTbF*jU(K8L1Z_4m7J8j|bQ3S}+WZy{3c{+h<5IsYO}1FKd@pyX<`0u*2Q zqVB0_Ogd&x=;>|nK};lMM3CoAfCcn!AwfoiYZ`S$ycS8xEBHMy{0zF{ zpV1Rd!%cy&Y3#R*xO48tm^b&HbL0X5>LI3xq#^!^J@KzQ=dkr|2;?F^0q@c_H4&z_ zR9M20God9(vjp57P@|m+iyPvJ!t$^h9fUKuFu@Na*uIP^8@e^4(Yf|bysO=su*d6E z5wNe`Q4y$W7y!h`n@15TZ$tttDgxby78C*d+^HqHQ@eG3w};TpqsJI)Ot`1DX=RSt@7$-+mtX*t_DI7 zN92QMaPi0mTOPV)`z$)*NVm*exoPTnRc*zkqzQH&qgy!u&jBN1A9Ssp6MY=%%g$f& z)fhxi;s6J}6A;_E^gwSa3|W!DIM~w^Hz6>m1)$8`&`Nq50N{i53jni z@^J&$AwusS*qsT^^JIhD88wyjd79_!`uasM2B1R+8xRiIlt?FhDppT$ZODDUvsu|M zB%e)TA^UWqTZfERkfK8UK}0yj#;F9c`-TvS-gY>x%)%3G4Plh{O=VRL21ai8M@QzN z;JrzqpRNHAG0pNeht3B;^JHY4luVgsFkmoMH?oqd=H3QcxK%O6aQ^MUonzOtU=C6$;&t z5m=NzriQ&ILmKAw}ToP3j5hzjD_}#@{CPp9G znX&?UuM0KbudfVb*{)XAW?SP3MInm#mKla#(%b=^C)6PI4xbBtKB7G^AH{VB#v;mr z_k20_Lk8{u%+t}wDtM2;Gz6$KN8OJ(Jcb`L^7sy&vfN+>`mFuE()4qnk0YWY$q_6d zQ%{hp-q(nwpwzuPIQ!uisvk~lkdIeM4w~-#hx^0lpm37{I8!}5Sr`!>igpExA3?LQ z#1rf09*XEWU}6%1hNU7no-mvV-V|wy^@}gJsYadX zlferI^(GA4Gm(O>M<50^c+&E=*dS>mhRk~|otpI-8RS{Be0a7{{Xi(1xEA-~{6fk*m8m|m5 zL?Hes#J}Z!pt0GWtu#3tR1P>Faw>Rp>Ij&=S_S4eM|6w zg1zCU*<8Kq&Eu+^iVGIsvtU zxfRH)AzGjVVxYzN%DfiqcE0ySj?(S342IYeECh*bMeEd|J79koTuJq?XHEei789*Gn7A+ohw>b5 z&*~C|UtFwUxNg%lOz_x1$tMopK?!MwOOrd$*E_p$oq};C$b$g(+8o~R*o)5d+ihu} z+(7&z_yt{x=xt->*>6n>O~W-ZjgHmiZivbZ={@UDb5ynK`dqqoz_f+&)q4WneuF{= z-T_TpBIB+k4;{}U-iHl~c~HXb%R}nUw7m-E+pP`U{hJVkKv*zVQMBPe9v5<7n3KO@ z;+G}^oC6}kv;?jku-@RS2zTqSh;G9>9PpEY!A_0Gl{Lg-5@@~Yz&LZWE~DdPA9`0- zhk(R5m>Gg7+ngx6grs&zhPfjO{*2q|w?KRRM)7PxOFk)rZvsUhfqB3Hg-X}cK~$r| zDcON?D|=|ALkP!?27Wd;%wY%JqV@|XGCF_%SOH1(JKAX@r|%DvQm`D|=iv>7WwtKh zLFU}e8F%+^xKbo5CN-XvE?mrRXxHsIcoq>h^x6L+mQU_EWNCmWAaFDN7yF)$EDdJF z^vGpRk{28T;jyYxEDS0{&6?B``LKEXf?`o47h`!L}{ zNK`%azLknS!D&Me7Z`1J9DBl_m)BVZS{VGbLV#x>QF}d8*?krea50TwgaKkK2ZqKF zN$x!QwB0i0TKxmyU6cYLw0_T2G3?OS6S&)eatoCbkudCb_f!@^>01D7PLo(g4jxxy zHR$7qxf;CT15$^}s16ZsxM^0kys6omZ*Z- z%Aw(HChr}hLq*_$;9!+EpkF2=+F&R*oA}M$mN^jXJJeIPaA|^<0`3rWq=F8@=SXWd>+kmM+Em1KfRkCLHOP*V#4Yt% zX|C!QW8AI4J2aT!$1GhHwazMVr09VbYr-ry#AiBU5O zvn&kx9@lI62DKlwE29vdE$4Q#isG2iv{{Apu^VDN)u_5llQg%APW&33=)Ng`i!dmA zjWeKD0GumSK!C!5HmAz0(aHT*f9d4Tz3oP^L-$Sy?ngfW4XAH7W`DuM3uBwDvaQHi zmka}rW(<`fRN&YUS1EecpoCpyECnC^t~AG`nI@iDj-I2Vj$-HN$kJnWf^GfP?gOK* zMiyl_r21*Hbj6(vWGk+VnGkB5FNwL*Z8T{0z0!HmqbL`#JaMwoy zZBP0yDH;OJ?*|ht=Df)W=n<6LTR}*uu;JxcJIqcxR;3tIA;SPZzuW*%fEi|7N_t7I zgU@{B6yw?Zz~X{Yov_C|eSQTdlhG)LI)$r1zS9g|u zEX}mOjFI~OIa)bw%L*z3Ft^JZSXl^vkV)N;i@uVPNdg!+jb4?IH@?SRA<*ax z($%})J)8+fE(v^R+hhfpUSSN6XGBbbwWtZf#`*A*;3EJnF(Crhve_n38Ewdh z#d|nt`L1d@;4K;k_%{ybEr{1_PGS-CUepyhu+A=A6rGSd>lptox!Yti3nl{>;e(py z0&99Pm2;}J+>*8+4`E+md)=y{n=S#dq>h*%+h!YamKKBczyL1{mgkQLu^AwJ(n~RY z0Y@b&l(_2q_Kfb1Y44>b@Zn0}$DjrwNhp=PYfs0=jd?Vm9m~{XEyj;UsL(ROKqToV>4IB9`0GGq6jDKXQ zRf+W3VE>fRv200cy}}3px|yQmI!``n%GXUW#Gdx2!NW7JLpXq zf9G4y#mMPus^CaOa0rwR37E<*VINK!Gpfa!S6oHFJ6Bxr2}A&ES)*pVg=-heH!~^I8Y}n(73q#eF-uTx2M1t0Dn%0l4{9 zX!gdC#(4CBFjKJQgTH|HyG=;b<^RVGmNwnS*}#b9zVJr7GOc-0y&%~;Ya7%V^4!Qd zFtX-;bvw~5+lsjWshzY&a8W=gCRCpzLK~wTXfhY}+CH*(+hcBDzj%H(3%J0M!;;Av z2k3U08h3~_(v7|ih3QqhFk_43ngP(8aIYmwa05!OT@~j3eT(|dnj6^)LPQ|eZSMC~ z0@|~QLd<3Zrgyge1AZF{T%S~@FaIeTZq)vh2@8SHj`A3{dR3*ZAZWDz)QK9XN&9AI zVqEDI7kKO@3OFB^1~~J|3Rhwl3uH3EhnU`tjGhXSm1)xGa=rBFQIqAHep>9l2D-+< z;{$ye0HY-26V`9sL18#Mw{MpAS7#5y!>#_uQ4Al#7 z2e>BYBeNUfppWb@?B;~85y*gP7gY4jD!N0uyj%6h*gECUDT?2~=n7K^ZbP#1$+ZB< z&TRJKU0`M=CPv4}p6KMQVe0kPmRsj?6Tw(d26Tk|PjYSK5FQ8tyK0v>3TLI4#O;94 z!?8dF(Ngd33^k#qMWM4#KbIW`ADnr_Mt zI{8OZ7*Lo7hFIY*poI%f}w0$j3XF-?4$3$|M{RWZtFZi!Rrnua_NPAuSC^arJUyw!JSP7=y1WYhQ!Dt-?gh3=3F{P; zTv?TeQ48lFj<4UU>eAdfAvD=Dso#z;i||?6{%LiXpp=QF%u+P6||+L z#G<|Z&kZKb;96*-qG3I0J#T*?9`um9%C0z-A-B>9&=|Pp0IL=x zJNr~ReLx3YWpGS$VI=Vp-0KSd#T9eTQn8g~$*n4bMvW08_y^ov!W{^Cz}(tZ7DmNE zwS_C!QGp?Q4}WvJW&S}*PJqehEVqxN^ssU3>f;6KgTO6=W)WzTY=fH^f%xw7Gf-` zGJiF=ng%7PX#-ax)T(ef0U59=Q2|U%FaGlU$LBBJzWj0h;``@s-UKg#7oUP(f^UQG zgYSP2ehPm2J$M~FzuKIfyujLwzpcG|af(H1Fg8&*TN$4P$`u1*1}RKYwwd^DK3)sL zYH(3uI>44E3I_y9SZS07Rd6TSs5cuStoqye>*|lw^Qw{U&;L+F14X4K=&T{0^IBq6 zsL2Gzys!SC2%%F=bzQBA8VFoSb|GPR@2=km0)Zt!Y43Q={AVrj%S7Y0NJ#~NHrVyz zwKRV-;cboLa=fwOG0GkMX)SKZQz~1xA15fF;k& zZ*SYn4<~1Gq}yNRgb&o)6MPIbG+&Tho8Z-z4m;?&M5JN5Y=gI^261BBJXHEanDDsZ zGp*o6s9LDyZ|B!9wSljK?@mtnm~)+($Y^co{whabbd^5SL0hB#zq;~TDxL`}Z^~#O z#uLZ_Of-KW^RoU>UH(R=?SCG#8HUmFFvz@;h6<*)EW0cH^Oddduefq_HNO0(n-SL~ zGaP+Go(13OtFIYQ9gqDlj3$nQ==j(UvtO?nHaVweAOH0ByJ9VSYyHcsZ{Pl<-z`)X zrlY6q6L^H0s?1|>ZZdpV#)%r#Hz%hMBVX~CEevM5NrL|+X~+y2OGTFHpC84)2AYxd z%Oxu%I6o6MPu67{ysjGShYB9cj0C2HafzT1nb%Ao_~-Gl``+=f_o}VJ_l3=sgW*lY z>0^G!nN$Dx*j90T z+?6sLgb;3%W%1a^gA@HSfAB)Y+Xw}2}yi_O0V%eNDfn zW$eB=`&gZxG{JX>qHDe7|8JJ|d$`5m^e?v~p z*E@J%74$$`^+vCa!Q1omzgA~|^qXW-k4(HUz-u6b0srmGd@FQ9Kc2jMfBg+3)CNCS zr#EfzeY>^)e*4Eo8+?O^yh7%`AL0)g#34Iv<|_tp$mV95=h89{&j<<48oec|(ablj z(`{cHItV0n%eg7@8*3{H-oC$Vk+7f6gC7`@zqgm?!3$8n0Rs{GBaueKx5p2egy8XW z`9uFSDHEJvRCaOFLhRyBBRzv2|3m)sYrui_F%)jX6Iq?X-^kGlo?i#A-4Di#!l`n4 z%Ate5Nax1PSn#5iauwQDO~XU^4*PAWsgu#MqDB%K8DA~U6IHC*zxq&;LZ7mwo9Dc zS@c;@UD9qg8*6ZVae4AFSf8KNU|(IfAH-=FaQhA%fSHkl-<@gXihq2ld^Ep53w}Ol z3bPT~K+iS|0Kxa?s5r8~Z5^sp z3Ri>s+3YpBCE60IX1T;Fl#9o+jY155e{yv#dt`7#ZcmQ+KmVaW3Dc*fS^oJ^@@qG& zA_^Hr{=ot!r&K?1rQC>75y|FHitCCvLy#R@p0+~3VmdOhtL zeNdrM#cnc1+v_UQQ_*(BE+SDMZQ0TC@}6`9e?>B&U?|%u1+q3-&VnI zVeoMke2jvRF`G~nu4`_p!I}Q~=Hw!be-zFxv;ypY*XJL;<-%;2r&Pm*=H!9}&==(D z8vKPP-Q97inB5@Wbw%*Q5ui2QaPMrMuPt8M+<$B&Qw-`#6g`?3H0 zNi8Dw9lfIs9*{=ynE#!~Nh^O43KBe)Kelo)lRr8e6~B&yLHJ1=Lpd1=XnR7=B>{Zo zO(tawL^sA|jhT^WUOibdsV7Uu^`to5vlz0wh*YKlw*{RTzt88!E}3mVNClmN`_n){-dtZH;{%+@+uHTQ?$o0E5O^n0@E8_x606f4}r5)S9}6}M6$ zkWMmzR^K);$P{5JyzAXlspN}Ln3h~{L7p`zub3a3D#}Q)2S|=kE{XoIPoJV&X@oSf z{vKtTddd8Ju5mE(#Q8KE?K~4*KWG>c+d083SQfD&XTqlCR+-7DvALyUVpNBaY+wt6 ztUa)7rhf(KnE1yYfq?6QmLGk8@NJ0Y3Gmqhft>Mm@%9Y{Whu+#?YW<4GJt8ZLm*d8 z+aekviIuw}hvmRII+8!9ZbHXJnymgsm$x~m+LCK=w%3$b-d6lJ_ z1ErhS365n+87(9rQSpD}akn%MuU*+n?4l#`j@XMWEEo8g6b?kXC=cf`W@uct z2)2~-S9X|mdb?>J#$WP@h1o|wNtJZGNk9>WWiPLY9A8O<7`8d{v}>NtAro-@$#O>q z932@UKyC>l`G<=u5k0WlD~-L#0p7O@D~ zgc}B^)@PeFHla(26pbR#-%>%%BF4Qe3EvwQ>Au+c_QrBFT#2Yuylgo|5ZIs)#s&O> zP^HBfRr|+ZOq6!%tAN{Va0`MB2HpUKuU2Aoz4}rjv~LjL7~3QvP6&QP!b2wFb2cPI zWxFpv50ahTM>$D3+=wG2-zLG|=Z(T)GIMeAvu@r&`G&NDpaf`2BrQk6)v>&)@-V=A z@m8z!;Lj}Egm?Hyv{>f zm6cVRjXjk9*8q&skdtI?gN^jTSykm z4R9(ez!;1|VCMS}72eJ*5LL};!`>pAcMBV<&TS`v!<7;Bw^76=7Zd4*y53Mqj*i|+ z++N%KND$%qhv!_wuJo2NCFtB%E5MFHoGiJv0SP-I=y3@PXPBY+k7hT2hgWppBb(iWH z?sXZ-0kwS#V={}Alr>PE%7RIgZK^J#ZebKg5Sg_r-6OzV{VT)U#US9@6uV7JV$x(n zlKdl}AtYPhZ^^v&_QWY|pO=JP27r~eg~%%h=s8XzvTG&#&J$n9aU!%)=#&{;9DIH@7x!5qMeK}6}SH)aFq0X#W*%`{oj zB5aazwSt+k*i>9gh?zBcI=nXc4zaP_g9r=+v9s_hIn^yVO5hc<>WB?6%byS9g1;m# z36;$rmxJH551Ef$dmB01w?u?Q7+#o`t@#A)inqjIZ`l)s%Y$l%?(aQc?vv^vkoRRE zBvf$LW)bnkasb&r(Lf^G)GmK~?6f`Gx7lajJn`Hqx8wNnFl|mgN@U9V<^t27CXSX| zpIS69PA9I)0?Ril)Axd!CmNhl-B(bolSaa%LQD#43>Z42JHTR-R`R*%;`|e~BpeA5 zx)CU6LJ*44g>~OQ-q{fHmTcFYdR;;E7-Nm(jL(G!s_$5*VShIDqsO~G^l|pC>|dvbbFQ;6 zD)L;oxP!H12gW)OJDE4L;&UQV#8*ilfq&g_!({IQ4V;Gb(LU=scAz!G>dFO>tB^{E zQ3P8tfa3k-=^#gkL;U8-)@(8P)D3xLiDo`CaGf+CTys9RHPNT7k17&5VU5kmltuqX zbCGm%rLC7U>>#Fk@P~TQwxGBU*}FxEAdE9G#zTQnXPdbX4|(cGHZOOkS}AKZneWff zFEkoK#%Mx%|;U1GyXuudex zb8Un#ZnBK5FfLblydh0l0A%_C{aW0ynD<%{o6R;9pDH&c06oMu<0(1Px9&3wlO*G^ z_bWBoXD~Ew0GVapM#kGO4}jywXm4RZA3O&XHsCYZjM z88mc;7JiXc7Uu8T>vhM$;leRm+Ear~Qpb%9%g7b|F+}MZf&jxz`{q2x?rzt?P<$AZl3YdYlgKd>0 zkmiIVQj#`;Hu%m%mPUA&-LvSsi!eHq(Dze;s#Gi?a^yl{CRSC#%wxJ^b$SK*6*{h{ z?22)6!g0V^5^*yLp~)7|tnTTchKV-s5(_sKHv5K1+)pOvfC-1Iyef(q2p7rr^$QHD z9P}>6Pe*gg2C&ghguNCFT|%qWe>Zq*p&?O(Ia*o~uGVMgYodM`CBoRKb5leG>^Wq+ z^Zx-iQj7LX(EzoQ_^9>O`}0deI7tS(P+*_V|FZCDsA#4yhRLNwFRq2Z`4fT5w1dp4 z5~>HF{J^C^eFi*eP(-@ut z42A(pW`f8TD7%RLFeANe{V_!OlsUyb%mjeUS%U0?wNDsrw)>Qk_kWQzGVx78?GCFv$d&DlzpJtD^|B9s3`#B~?rfR%a!reuvf9z$9; z^6u>TQY*1*PeiCBaKS~G!S#anHNFew4-x1AvyoSzpF}V}inR$wi8#gcp{z1R@VyQCsL~%w^}&T(gQN#@miT@9O5Vwc6Au#l{qQ zWbVGI%RJ~6vAkrhYwnnALYZJNu>i7wAVE=R-BXrce={<&@n(1+b`sb<-K)ogp--?$ z!(jr{IGhm(UH3WNa(+PQ-KTHHPJ!mp_j_+Ms}(YEOYlleOaZ>s;dR3w7m*YHCXEKV zpw1!?5sDP7=F(WTZfW*Tfxu;Iz_sLXCK|w)z0Cq0tYqTC30Zz|e({IekY{y*L`=69 zS{oYpEgpPqE2vx0H%T1w&agcc>OgDT^0lqqp1E7-=40r^5O8i!a>NqOX%g@i` z=-e+Hw?0qsRUz22oFSkV*PE>b`XkW27~LIh5G-4D*N_Bi^F*ip{ne%zqca+f z+~3C&Tl06sA<0>%RE)sZP>71)wmkfQ%)Ms~_+OTwOr3Nm$#aCh`(mF=j_)*rEtt zGVXeps_OLJIjP<6KMXXyap)`fEyg*I|Lv@OM}qxF3G{=cle#k zvyk9N{-2Om!sOvybo+=43r{!~aUrS$NT-v)3;CXmNpvbB5r?GD;DpO1B%2@)QGfdm zaO#cy`f9}`d69Rkyv#Si`+yCaREglSiiMYFT?GfJ&z*O2)d=HGkpW>x$N~M8>yi`1 z-kDaI6JykADctM8hvr93v*P-^C;|Mrod`an;5w2gRG4 zT7+6`9pA-t+HWn%~`^%>JzPWBMq`I8y)}S6C>_mE}A=C#6-B}5L zf_+BB%BSrGNz(6v-+(Uy+wM1WBS_8nBp-azbQYFUa|^tekVR61kVSq{#4SCsgypaW z+D~q!xSz} zc5Pu#A~~eN#plvbZgq`uy^z3q_pl!^UWrC(Yj;x%XVP4fHUmMvl{|8BsCurD-4PmH z3XWN)<%R%3JXuK_7A1*`!wxOCD7mVx0dl(TLp`wYVh_yVjxP~JVi+728FbYjsVLl> ze;_omU4KHGTEDMOx9giziC{!rgz)*c7!L}FQRw4r$=RAyYP@Pe#l=t7WioQN*lx(J zSV^7*DRJb=bdS4Q4pJEk)U{S%AZaFfiBSb0XPBl9schJF+{1zD;OR`Gi5C6*=m@>5 zOA`Sd-j}!r?c0FGw-D=KSIjz8lIBFu zftW4@(Xss}{PUg?BgpDFx2H>W+0~av3!GR5kiBQ==vlr5HE6ScHuk!>IR!x+UqYPV2~U1 zCSuqL!1^!9S7A1X{Nnc_Kdgr}TssDv4oo}4&x!qN$o=T0&#@>CG}dQaus z%Rgihax*oO>_dC~{v6yYciTv0MdbF^Xna%PnXFFXDAog&@1xfM`JcvFL>zZm@O}5N zt5da+5vGO%1{$a}CaebEB9I34HYH>~+6ZrzpS??&gDUQn98+nMHmfAhHpHHBWQtwP zW$)SwQ*$6oyXF;58MZgqmp_7I^!s1hQ?UDFDDWiNd}Z?;)Rbx^yyY!C4sh73GIj5| zxzI7x1Sdr$o?)VB^Mt6pk)k#lVE}x!fiokV!%YSkS4d{Kfa)Ju(Ws}ShoW_ENe*sT zc(gFuh`MgontP67-Za8^O~3#tOBg`z&{H#HXi9Zi#juW%f|v~~yP|C`3|ZGxQ;AGu z%DMqC9(_OO&ht5XYU-wQ(AqSlz?1b0sqr0pYP5K`k?CJ9gz$3SvcTPzp4)zIadbU3 zmBb(pRWS~$77KP>8oTVh=hW7ngN1;3oYXwRLFD||*+6SEomssR1UFd}<@it2P_z3F zsi^Cz*{2X7Z!v?lgrX)SS|gLaIpy2;kpU2fa?oZK3I$AumdMfQ=5vc~uBT>kz$Hz3 zP)kVQHb!MNTWoJdT~AFV5)DjNeM|^G;ndl1pWeBrrfyQNv0oFWjTVKy)EdO(%%5F! zb3HYSgS+&mX~}qoTD;-vc-Z3TdTJ`+0v1&fydyb0gNb98v=ZsgJvDVB>aee2b3uP1 zVS3L#1x$TO_7>b>$jk{7Y#lJzn1#1Er>>%|r*`$m1?PSm=0uCY`C0Fb@CVQjo>gPe*30Z=B7M`o9 z8%0w|-U6_IIj3q?c!aj&N=7&I1yhU}Gy)S@aoDoBjuUb-KCl+6>RM!~LC=kFP?5n5 zNjS06Mk<*r+k(jui2~l)VY&%vF{XU0F`u8(08JVl6}h>ROe z#v>P6t+i6#OBl~5dr@EnwRc#?m$?Ta;PWU`xm%CVF8633a58w zB-H_vGU%@n@9bVi3=A&B{0am2t@~@L*|zu@U~11;%FplU@CNM<5 zez(cBTczTrLk26W855m_(z}1PlL&IK21+)mxVOKUg@XrZPiKhR0VD zVlm5&Wz14d-ALM%Tw+D7@J$dD(GZO>nh#?|?d-TGi}M;oT%XdPvbXGrrJ`x@r6ub7w2s zj(BLfD}m%iPV(+mVe9F-X%=l(5Jt2CKbEvY0z!=bWxL56_gS={r^ZAJkqSi;3UM?3 z2;RABvrx80QE@_MRbA&99P0=5e6UbVJp{{P$^j`LgD;*af`jVmM$ps&G8#mSva2{{ z(9%bBj0D-qj>83vfP}@Ll>)n+2#(5N*)G-8wa3mVBz-wtvmEbaAhxDGR{rbP?=z=> zz!4``R$Qx7JWAsoy41v(p>N0zfeo6((U_37Y^?Y%)zo#?41Ou6I!t9aCGmCI3A}%2 zP36^Qo2*#8#07!}Y}La1S8jwr#-80WkVR3qh}5x2U+Vv0Bu!0u$TALLWsJefjH*2+ zX}18oku3WxC$N#2QTK027grfkwgc8Y93D+Z#jGO90asdo+ma8e%r(rUDoWbXHvK6-tXc;Ro zj^XOSCfdqUHIMqH5bc_31LWgC zerh2ZY@7-3&Uq@izXS*1t;CT(U)EI&bxq$O{*g#|+5>MV)Tm{Ke2##NLS>Z)?k&c^ z0?HdVkq*Vtk>NbEG-6ZPZGvQWM3wDz$Z#T}W`z}whE=Hf-n8UU9}G~E(lcI1<6CVT z9LX>YBIN`EOE2kozk7#^n`bWq>w!UJ229r521p1(s<$yntF;h6%e8C$o~Rvf7HkaL zf{9@^Dk;SO*j`+%>-L(IVev`>4HFZCFJPJN3L6)n@=NpqU$RmLVTHGu_k+Rd_O1e~ zM_CH1{AvYsszUhReicMD_aEY+wgAK8qO{`Qm_LNEak_dJVgphrjxnGT#FulwOReT^ z{1dw>8u3@BKmwxAMr~acpxn!J|8cen2*3OQH*B{S<;TqY$U4@CYhi_D7R7){coe9} zoQvBOdE-6TV3th_o{C}bdBI=xx93{NH^SFC`;k>&Ah90;rxu-~E;A5|Sk2Byk|n;0l>1wE&u%rW<0;GQw*~ z9sz)BRA^9HFYSp!@d{EC%1(lGZb1i*R=BQ)HJJm5nAyudc0|OT@w8eN$xyNZuiCEE z^eoE7Y~0{v#chYCz;KzEysnYM`V5w@bJCLM1wLaP0tJQRLv8_EEQZF1+f^{YJDg4L zP~bfaBdIIf1qgMv(H`*-%qd_Ym2-l~ahl7z$V{z9*o&jt$$HCgIo&OTFG^g5{vflL z64;e*L3=JpYZfFnso&4ynW^&A4HPow(pk8q*BeAT-J2z6sG+V_}r`VX} zFDO&i(&Fhiwe&BdVW_2PW%i*omyeZOLYWiNh+@!Vh`DszR33MWZXs+vKD&NT6$PoG zpzRg73^zFMQNZ}!hOA39$HzujugC>Cb*-C|FfuDf&eWyADk zCT&_W8Qz;R+oH`j)t2m!-J8rOkev?r;!ef@leVD2)iK#XWKivv6pLEnV*PCmhF(tV zN!cbV%GAF&ON;d%vS7$z5qJ_XA#!jHtruuzL14Ee!bH2pW+c}GWY$V%To29w5tnhrh;{?|GYPnJ2{Q-AVxfQ9P% zm8pM#GQAYv3no8702_@xA;Q(1=@v=Fv|H(DkB+{#vwhIyY8qcXzC0)J6~Dm8Gy zi_+QQ@>p0NW&>Xi^b~QCge%5}x$6 zl7xr`s-z87yCGsOM)?(F-j=HaJc#SUmH2?*24sbF59KkIfqd&&1YYV{&nZv{9@O=Fz1)e1mekgW zlbCF4flP1@1$$Cv2fzR!yjLaHL(kM5VvG)p?Jo&e1qb0;L+Kf33=eq&-v;P&8^*eO zdiYT6z5HRCEP;vy^1fj$x4yMW)lY6{O>NP!1y5e!!LYh*-uH^NNny#%ul7HCYmEV^C~#eIr2-n)2Auty z^tb?dm5?cz_J}8dGfEftEsb_WULg5vaAGl!5)Z6(7_qGp?RK2P@Up#-w4fS#WL8H@ zsvUj^vGT}y$G-BOce{Qt;v_kq3p?B0-}^MqH7L!RW!i?$$V8FE^zBhe<=Abdr)j^##AacQ23+NAxkqu&f~fxb%GK zgNZ(LYoXlatltcv5=;r!z45Tq>;`&oSBc4$U|16T36lar_AXnCK=`~&pf44Ez%n;( z(pzp%$>Z0+V*-T@97?BE>Gq69IrpQy`NABiiZ`0p80EKEqqpFuVwQHN?KNz%MaS}{ zcB?-)Btpx?cKs`s7r~~)tONXoLqfbyUvi|`W;NWM2?lc<9a}-b)6Y-O z`h!6Q6~ zpz&Uwg~{7b=f6~cylE@MBhb+a_|4GM!!Uoty-%13@gm~^+7_fOVH6SQr(qG94|5CN zQEzNKQ^d5jC6paF$N)tU7%YC53NmA2S#ZEGUtqO{x`qXJTtlZLb(SSS_TU$2BASj7quId zcq_m5fBfzc0jnCZDV|>Z2q-+PGqU#oaZ~*IME-ad$Q|p7tlrHfH?H=eeG(?am-Zg| zO$l|Yc==Ztv7n87c=4E6{A0qd2!6+8)NmGVgk`2Ph-AsYu&`G;jC(Ds3^V~~$H;i9 z8Zs2nat{$RQFPf7@^jU$hcb!^VJXHl7?ZgMuWBagi1S5*D=P{EjFe6+VuioD`om0U z@YD6S_+J10*#y@#KfF!>^x@V35h!HZrBN}wGk(v7VOn9Dko2&{wvuHfbyMLW;au(x zDt&u_Cg(($-q2fpv+KF`9>q#lDh$34X=^vF`Z4vtoiOLW-(meODOHQ}I8iyXTWtVr( zIsyU)dR@>u>IDAMh)v%;9U*q;@F^CQAPm8DfVrFs$o`eEZ2k`n4={U-?-dieD>DyV zrt>nOh1WrSfv@=L-s4BJXiQAnokSgwiXp^F%;JD)v-{qwvjz;+&+}D+dh#$K8wYkm zSmTD)sg=C$|!7wUx%a26<`?7|>CLp?qj4Q!> zl$a{N04wrDmQ!$D)u-(h;WU@vGC~e=c}{Ns^&j2Gb6YSo1tpkhSTaoi3r4H=?T2># z^7m^4^o+5RymJ7hhzSC75*=<-rmOy-0mO@RwSMQm!uatOrHKG*+5|m@lnuTUINu3VE%HTcL9L8?(0%NWN&310bD_+vhQ`-GwKfG?{Eg=rM_K z5mv*gMq+l_i$l1-@9=#=Xn`wANb0evieF=>G0QP=e5{i4_*m3fxdJ(7OTAw%# zSpK1#;!yFB8AXhB4(0}~LNFpR<$}FIi_N2_U7dZ`N5`;jB$^AKUvqeh7D<&vQsM$7 z+lUZj@V(7Mhbuqil~<3Btj+4^=vlNVI-@}IAb9ZOEe7u`WVh{+kg>Xk=w=UX&CC&>$3g-+l^ei@Jnq# z`29XeX7c9v!o4?*AA)# zcS_`#eb&u!AlWHv+Smq{VQ?7*mb(QYHF!(-^Vi@Fmhw}{4S6f2+_1W9RoPV##)FdC z>G}C@Ho<0CfVW98&cf>j7z(g; zF9YxSt|oF$owRGkbVRMIBvg}HY9JZ7HN(9NR-p>pIAC7B`lV# zCv%iIhA+Y$!3QB`6n-F(2;AqqLT&}!@=%HWRHC8w@Hr2aQ6Igd$(=28y+$P=q*VS7 zh$&JG2M3IyH}ln^yD$ihc*THW216i(Ff=3fLe6a`X4O8Os{xM_$~W_IFhN{fK+H~R z8P{TK=JQKQEr%+-Z^Wd*zHC!7AUzZ zc;jugrv=DpWIL*_+p)WHTEKB6(-M&ZRZ5kM8=u?xz%3^uws00tZ6Rb!CKXu$P{NZ~ zSF`cwu0K0HkN++jB`6n=pRCxcSnr#$C2X(i*udZcx>%SLfQ$hhXGGw?o$?2IKVENE zJ-`j1T#c-dOY=^gGZzL@LoTnqYXg)e03dBd#pCKA)ZEizy;SX=4L0Y}Cs%#>z1m+J zr{XMuK?H2FZG;NK#=XDx2kkvR1cAxHAE4nC3Vx{2Y+yb9b zh&5+is9(=~;{h)8NTE_ps$8Mqgc2NE*MdVjW%en3+Ph_<9Pmx?#--kjI2xtQ(lFSYP`xg-)>{|M$uu#Bl!sr3M@>RBX9}V8yf# zr6xz9b0-2I|1)sa5hb1i%fwMIWv_rk2wVgXRb>jg#7QbQOGXbBnB$RTb5b`lB_1=6 zp3*xt5E*M7OUw~w>!LEO_5|1Al0_k-qOvBEpv=-7)G;vb*jkL;sF+mxWPA4YV^JlK zkEzt-v9(P*KK@qQ);xLiSnT>5i}VPRzCS(sk7tj*R_Emt{r5uifQvxggdeY63rQZ*mMli1pnAP-b(S$Fo~)6X^oPwqIA3p1A+8X)m8uo&#R0{(*w zON!l>RLodz1d~$17Hkr4V3w(({2hZjTw!S>jtZU`)M9hQSVFFBiD!U@EfRA1wbu$3 z215drr3t|{L#gEU(sVz9n2I+A*D{O<7(%g_n|<+=PAv?Z2>H=QleGlKDR8(EAP<;~ z8#$>b#iY^)-;XKZy?TFsiS6~;&MEeWtO(hUP^zOw7+K+$xog7?lo8{7nA&aTn!xZ$ z3L21oY;tnTR+8;JDs$*QBhp+&bl?*{(fN>&nnA7^=eidQdu#eq8g41-L+NbSUK>RnQK}M z2`K4cjkM%d8C=bJu6|coM>rz+cDhC4PlK|JVv)VsXPVr5;hIZxtMXo=^SUU&@?ZZ;grZxwgc1*axCb+cX#FrnfO(^N8+kNES%GX^W#BL)R2SR`6DhX0_OM9+XaOTOUrBBVYIC<-2goCZ)F!t=B;lsO zI70|{RSVHh%scMkz#L~p#Gw1*=22P5ReU1|I4i-YwHdIvFH7y}8+c&W4jyK~1A{xK z$Geklpg-`rEW$p{2Ca#$!x+S9>J#htqp`=w4sqw_&}eD*SslW$36dTM2Fbku_zj1* z$In@5T z#$r0kF(I_%J(KVui2mBDS7&E!4{0(4Kr$1kB?co2h9YSvz?ec|P(e+I_2i6L*`4#D zwWL~ZZ|75z9I>1T%T$!$^%wn1TB!|w)B08dAFs)4ZV%T4=P0H-{sewDDjie6eFhSC zdK9K~11LAhR+4z*OPBFF)P5g2>nwbDnDLs{kk774h&XP2vl6N708(Tx0I~}Q`{Dab5gdzrCJ!)Qd|1{$<_6tO+}B2;9-R2Ek?nV zJdv&now@t01~nguS;i{8D}03_7iwtQ9(9WjU@|S3&h^+it1iI za2t^jUSbu7;Zamdi+Xx5y`aTiDXe=0ifw@+S(5x+Ll2!I^nNfM0kds6zRImv?_rUF zVSA=QRyGqMCV&mj9R%G*LeRLvd(Q`Bn<}#E09>A6wTg&WLOcpUbtPxYK&~Ru{R7nj zA0Hq0+KFcXp>(+F4_%vfo>q{K5&MqJROT$XZhi97;&UHqlqx__ynJ`_0jb#sb?w55 zodWUY5Tydch6#w2ezJqSrF9qrTGpYfwIEjE|A=D}{9)5%C@gkc?yjuEc!K@B2P+&;?O(aM6~ClEO~{5E*vCtg6^;656uw69@L9A1;E@ zvy6EruO`|+XxI&xumyW7-SxfBD>B<+Jj*hX!yw1*cHX0l#w0x<^wT^C929zT@YBHPXPo(cpbGS_6j%&5 z=Qo-pFF=S*o)CeyD&Y7+KDvkU@?Zfy)D{BHP+058a>lCB$Zg1zKsq+#Q+J=CVYIOk z6k!6A-8HFD;;|(Hj}hDEs8Grj1gu_CanuZp_~Loo06q3;ny&&CK<}!tn7Tvap0FH5 z0OfB*pJYYYhx?{v|At~KVR6Y(QleHZOFvwQbA7PXM(w@JqQ<_2^@EhW9CBRl{|k${ z|B^wq=wotUzpqFr{qSvdT|L#M{45aB-Q!N*C1!a#jl_iztV}plR&a66S-_)d>_qWk zG5>3%;f9Q!8mkJV$k<04*4)9;upj7W`%l}uOgJ%`V8K9TNFJjEpYNY=7g#acqqCCh z;Rl~>mzSVh#NDH zxRBu;fwY)Vu`Y4cKa9L?FNh>i`@x>RIK7eVMzNP~n;0+^o$f7;9Q^@Va0!4OGoIu{o17X;F9Mr#L#<(BG< zKAl{@mx>x-+8GT@`)Qk#?1^1u1*tn%Xs^J$J-t7E!*O*GLz3`AE<2fb5V~_(@F~tJ zg0L>Do(*Y8XB0+$p}ofjk$3PZHW?9H3CwPO%sSiGZ``e_1)-Ce=@j}xq6b@ReLQr@ z3Z@?1aT4K2a^8kGA7E!BQLmIct9j-b4?dqNjgkTL8dmZoZsEq`%<$!eq!Ed0+Gcw7 zSJ~Y}Gi8(#SJ5UIH^~l=G~%9U21Rb6&K;Q|&TS04xp47uxxxJ*j3DChHG1;I+xr%5 zTH(`pb}MCefV(8jUBDFsM98+Q#0J)319@k+(}4Vy<8K1yG^_~?V^!qD091M@V`(jH zv6x4D*Dxm8lC6t@0M`@T@hTq+KS7Sr$fF}0Mhd09C0A_Znu&kaC81BQn2V05JSH(` z1I%HOv&0+EUp-)Nx*gM%&!pdPBZ3bq~eNy6|U2tGG|BWU5At?s1E==d5H%^>qU2(__M#}}e zA^Bc4mI$GXlxu)UA`{SdEuc#D`>N~qNEntgW%sV9B;j-Dj_`#Lbu1@~wS>BLv-6u# zI9ocjKP$W-yMROp;8d|_k;KjfbEuow^!cDWy=NtDlpXF`Jd2iUt{_+|T|rDrHVwvG z4Dq8feN_mXg?xO5^P=;iB1A+BtHjlZeNCJUeWM6j7T~Q@JQJ=>Am$;J zQc$E&zlFYLYJk#2c)t-&D#6-BGB29O&}(9zLr!Mh{T zk?LhvP-g~L6=@TY8@@j|hPYI4w7ow% z`u60beyKV6D60q-5<;3*`1Ak|&SVLkd<_1p#hZDu`H`Of-VM97O(aJc`Hypc6;+42 z@|yeu_`7OC>uMa2+G=^`S}vwXm4)9+?#5r*-zPwd_7kbW*BC*P@=$nx%&R(a z2JjusbewYn48rgaifDo>IRq`hotvxRtU5ct3ckI;DvR}@t3Htuh5H$~@V?#rhV(Yh zj~q802F!TNHbo$^*sbxx9CY$7sTH=)Td6P^p`iwU1UZY3k$e%Hf*}Vh+f*OfRW$RB z%vT}gIjh{ZVY=n~z3{wgbT63Bp(=<=t$>1>Bz^%8b^>8(Pz>L6Rlp5`(}N^n;@~Al zk@xQ0rZ+dWw#jl?gJc}xWg=IV#6F)$eW^_ybvnWn6mWrmM4WUJ1scb#=Eb*@B9!q2 zLkk0k1&n?8)H^#V)jpB`S<`T@-t1`R-t!%q%DE0|1?bd(hMPOjV9(uVvOzczJ<}My+cfoCWb~-1=97#( zJA>@22wFxC2W{%1*EO4+U!xepRUbv%o?_^lZdJ$NrXg1vFweWYl3Yb-4uR`!eKtn-gg?q-2)*g zd_ZAYRuQU%bv5^OyT3UwobKO`yT1)AtnOE9W$phdLg=#?%s1foG(eptcy!?Bni|Xp z-yEO-8f)u|L-6B{j->FitB--ho68CYU8+^)X8-O!1d$nF#0@S=BfvB{evXa?*FaH% zI{l!~BUYbtQnn~34aPMNN{PTWVR1I^*VJ^bCi$ZybGqsE)1jYNR+mFXkV-SHbpPGA zLRxHzM&lmcV4P*I_?F{a;w;;pyus-L{w5j0U>KExRE?@E*vez}`TO-vM{GlM1`$;& zAT&t~w)e`$fo2>kf_fuo2z|E%sbON^<{(fJ79CH9;^GpmQ6PCSm7s|VZ=z&0o|_Q9 z%tsYcko+Gm1&{aa-So5{Vdyhq1{fcED5O&iAfTO)lz3^5L3#8K`Olvp#lL#qLGB3xy@W2-Uy>a@mV+G*y+UD8 z+mB0j_*#dHMl>)?H3SuHHrp*XK4xlKtkY|5TmRk@y9x=BSgp1ZM1a|5fFIKF4On3| zQtsV64)l5%COxQmDytAy35=8_asw;7oPO8U)o;NkvgILCg#R^oQJtNgU;o(Zzh0fa zJ_U!Z>+Q(ofSq2hv3g0T@|cTjR&ectlrzc%LdttSsH4A9n}AM@^|g^?RD_2=#I*;a z@RmhxqmRE7_7_pE>r2NwAh6Kf?Y9lVknCNC%RPOH7Buwt+4K{U-N(n@pPyeSQMxfk zK6zx+dlRL9eEg$g%(`d)-!o&Z%zaQqb6^0SB(n3>|6}fbekIAWJTK2$G-AbKgv1IZ zsHUirvR}LXbn`bcp^40l>JD{gRw^U2s(V^3m%06jaPqz9FW--h3`#ArV1dM9HX|V< z#BKx&Hb^iFmct(a5(ptNV#994f(2{f^S$?)*)?->cXNMHJyYHJBI3FEx!3NGbI(2J zd%j0=xVty)GvlX)UsN(85&{cHu@0h?L=P?mdJj`W!S>6K4Dn)6i^_%C*rHE=vmT9^ z?e({;Iq2f9D*Jwpnds}My(krq`QHMVCQGl1(C32}Rofc=AKhJO_~OsocODyoz0=pO z?mZ6jrjP}P7e-?YsyKjbEyL>ZCc*Zt9T(Tb<30YE1JqR3?9ZBagOH3&KV(#7uiRhS z_!8)0cyEZgB_wT-h2+*ze;K*WfA-S1tL*3-5Glc9L-k5*Yv`@HLi*O7 z{{~N5iP~=M(m1qPk9L@3@q7*XdR|fHA&$|he}E46r=r`@QELk#dO$bGO_5!aC%=XSq$DvNZ-OWo z?q?{g?5C(*tezfA%mb-?AhkRjm`&gl>bRz;Hr`eWj<6!7pX@zP8|dQVL%Rul8-qG0 zNx6<-Jtm_EKc08=a-C9nb9+kdF(!E6<6r*D+Cc{6w`X$(p*_*>R$P5mtesM;NetW7 zlH@*)2h4Ty2zNmmv(|#qk~NnOrLm7$p7!wmSL;?$ugSgD z37B&*tmhor17mx*KtAw`{jHc@>~DPN*}Bf*6jT|qUFG*LXZcOF>#2b@2U!nY8iW7=$Me1yILWTx zvmExEIA*IH9c$JMOiGc;62k_zJ}}njceStFkFVneNVgT2Rn!nTout4_1eaFi;A3{p zJ1vBZiw~UNLd!W2PYetoeZUh*HSL21yMP0#G2} z_jq;no7;Oi#NZEvFwn->A(^j1$^evxOBj%bSq9D{e7Z~HC{%QZRX<914P@E`4VCBK{=P-$u7<2#ssLlRJKvQ z=AuFB*}nCt#b~$K=|c`iT4S!)wBtUHGOB6fn_zL(F#G;NU-GD~Dr>SRp=SU^0v}8^ z#V9r-F*VH8#K&S1i`h|-xj@Aqa56UWv4-K3SXq0ud*WCVpr`P`H46&75I1qsp$Z^e zCeEr5uI{k=&im%N#FrOh{-B68OtvZM_SRcrzC0~3H78LCZq5}EZKR=fp?RT{2bGyf z(_(9MA2+eP>B5Z@)-iu7`=u_|klqIs#76W}yF?$3$X!}=+Q7|Yw^c*f5A16D%K3JU zZrS76p#}5tfTwFo#BjTkNX-C8O-NGQTqU2WGig?P>hmb{bd_;PTwGX>#I9azLsM*d zxvpq{6nvu?;dur7BdjY^+$(>0as!^fi*|xQa9N6ruUvzW{bigBgsVxT5Wc=$Q+fc3 zAM-TcGVAoh)kTRgU~BlqsrSM3ys6x!o}OJ^S~Y!nXoQZ)BS2U^vo63IFD9t~}s^Jg}1FF%$ zFjR028@%>7MSK*H*h4hx{(kj9A}A1TR{gEOx2tWvdU&^$7OVh0qG%IxM3T8y$&v50 zqo#v!2VotgvKFT_oMFZQHZLhvm*Q3%SbRHzEp&T|U^e<9Bnx~&N>l;jvYY489z)GljJ4V9*h7L^xU&^f zBB6pd3A)ckV6r9=;=okGk&a)1ehuvU^~0S(&;MC; zju<4(}ZWy7e{lLb1*HrH>=*WhOc zd{bQ;)oyQeB$q+>1iDXzf>8HD&QV?O^mT7yOb*yJoa2Wlv7pR^4&VijB*w6QT7AIN zQd-I2l+X?$TXJt!On=(eG3|o`;cQFEt+&%QZ7>8!*Ewe~=&%%0;AS0=Yq;cg3tD5? z(Y*taf#4&?o3GOf;wf=b>>G&hRQASX2%R<%&G!zh3JTYQ1VH7&!)$IwbibEWU`CYj zzPRW~J2jDqM0IG|!$L7_xLNS?*e(CvL51*L)+hvAZ=my+5WZ5@hE&JhaXx7i+sZ#K zK`NM2U}9ZqGAfcit(c8y7=QJmoq71_Q;LlQ3wi12*g1*Wbg_fd#!-F8~2S(hH!5Gplzx z$Q<&I2mRZf072SrAisfS`*E`%Nc<;Pp8_}}a4d60Q<{!7T0I#QHS#pXh*o#@He-fb zhnX3IOSr00Z~&Q|-^r!S@#K!F<7>;lg2>1V$*DpNTLbf>g2BUn?o|*VAxKB$E<~^{viSi;AKT#45n`xTDyLd>k7KBiLw+Ve+8J z+3<7Dr7IJtolY2woT4SH@S3_Rq#>$IE6t3a8qJ#igwBl|8~ewi`C?yN_QnFMSCIBN zpHr(OR`z2vnf_uO?uMv{qKFE!b5hW_mN1Y0ZZO^Sc7yr1UGCo<-VJ=*>;?$mD@d*$wo;TLFn`sVZNX41tIgi|(!4t+szud+DF8is{K;kPgn387DDS zTXSV@G^08}{^+dr`%l;s+{?Ov&4TN>Z%iJVwM9|m%mjahi!mkPy+3Ok-Nw9GGyir< zDhk^d@Ed4!7};UY%7u(U6y|_p@W)eVZsf&JnKk<0%^EadHSPc^u4nlBT|K`h?RV_D zwqJ*#4OPLG`!waRXEqNdEVL5Urgk$LOhF#q|7C4~A371!t6C}ch z`r9`a&7wYeESfJK7z^c6L*AQFi!omiu;><@zgUMlj511O1H&~`M>x@!Ty%OmY_J>5 z6gnMtcsG34?FQD@lDbW#XoMJgg02ro_M{VCE(zJ`j4>xVxrr>_pnyn#3%y9tcZ8p+ z!+P@Z{cu9VJ`oemT#5_-1o@-0*6%-Heo8cxLW8}dx|A<_%10gmr+m`5ZP}mCM)|M- zEKLPbDyS>wMFQJDe2Ly@`(GO_0}5(Er@{hC;)2qssA_*1Y$Z&Y+ zGC(!B!aGS@oqv+*bIwOQ*$dsrOK9}qh$;z&?@q?vJqlS+2Jtv7g`sft*uj7$}sS`BWpD|`*W;N-hSPk&)17&O|AvrT&kfto6D)b zF;Tql9@RHbQVN8pkW4L-0N;f-tZe|yaea&hBV1JOq9Nt}^S(Gd0Y=opL?A+rLZWX20POTV!hx55VJ=5Ttr@$Aq75 zAokw6EXlv;U<>gH<=pT`grBNhd-8z+tZ}Yk;6jkjdz>VHbk^LebBBXSX6I0(@MpLr z3AU4eXx1n{Q;m^2oKWiI9Tn6zQ$#*?nZGUg)@0IzqIVt*$c~3NxSYjiy z^YB{X%Y{?C>u0Mp_uutL?!0Q&`8=x%+e-NOcvQ9QvxNiR&?>1r-?*7d*x(>~X@YZ2Mj#W&A0~!===;4Ug z-Mg8V8UHsYl!yPluC;{sZKh96W`9FHvG6mH_=+_g^QJk>8uU1#!bl7bxCYGJsg zo6U4oBNPN5ptY)NrT~^$1;+Mhgx?eo`BnQ4)~@utf##lPo;m9kIO-`6pVu|sy1dQ? zyG=8_cOC+n)A&A8llEg+s`k7>GY?}vt-a!@BSOtKATkkA{8FyFBO`Q@bZCAk0<^@T zC0B!Z9`{LaI^T<6^YFp3$uh-9(GRc<@(KsSBW`+6l1>(Il@WWXacglE(f&O$@?%#1 z-jS#8AOS!x<2vH1F9o+pyzBf)(sQaLFMx7p(Yg!)x$l?WjJ%2NYG>IBtOinXf)g8% z9ataA9f58nbcS&)SuS2Cc*c$_UU$zeBB`+zxr>kk7E$8HyLfh)u;WLxfi&&8ML3Lz zy+*(l7_D*N7er;(p+71B=>CTsyM9owRpdq!kXiIh2b~qrub3 z1!v#7XzVH6*ow?gegWuwh&KV~3IZ5qq>c8q&>S*e3)Xrh0CaplRg4)Ig)EyC4Tzq> zy^Vz<>)C!}`s^;6li~!ONb*h>lr9y6-+Im@+6i>BCi&|+S!-hJVGPJxY<-jw>dE4o zG4WLerU&B%u_`(hU`duPRh3V#>Mmg?ZHI-v$jl-XuhbG2Bnph;budJ7?lTSG!pC)v z<@_EiLuodmwf#G9SdbC&O&}4;DKofqi=>4*ok8y~zlH*2W%|b(K?8?rf)0eVeGa-% zQ1j;FC$yrP6ipMDsH}`-UBwjm)E#?T}ezN(o}kIC$&Z{QfPV-p%dh+JfD9jEJtfZuVVNe2>Bb~j$_K0uT=*7$=GWoFmY3mbWS{S_7D#5qT!5mp_ z)|@>p8B(JrbT6Q<*}&ICy2C9wsY(&HbFa1j>i(bDD+G0}9!VYP&Io2Ws?S3UR3|a#3F6QG>5cc5(625MF;?)j3Lh;xZ!JAOZbOYB6y%cA%N;)LPYQ{NiGlE%6j(4A=td z57Jd|b&^kGP5aSmNLC9!ky{(6Ithp*BjX>IZ`iz!!y}2WyU8#5cF*wavUO8=kNY4v zk(wwKem*-u);6*O1or>pg0tc)lJZVHs}kzc5gi0r1j>_opGG>+GOJBF>dW^xrmME8 z{O0||1&Z7JiXUrx3fm8xqw_VCQ-cTi=i=v-)_T|!C)f_bLZn9vpphZBdS%#21zMZh zmPweV3AK;yoT9yE(j`t$7W|}+yEht@eQJ9V-6-o@6H>!$zUhSXjcv%09KsvrQ*j{Nu>c?b#IgASm9OrX-aUo|)q+ zZfy!F*~W_UW<Je2MipDAZ<~?)F#XcRvZkQ1>tfrZiNK*GDbOAvW?mv(X6SjcH}(hE%z{{vGd z4xkJg?9v{fJ=;|a0XAksXp8as8UH-h!i1P73URg)9*6Hxn~Zh!VFz*nnLU(|Yq+8o zd|xpIQ2_tr{4%f58z-aYn?i0A3uv3dj$i@ zNAZ(Kltg8`b_cMw*ySbN>gV`%{66;X# zyN|goew*KHip$I2|6b$qH-B?^N#1*PcVl9i6q>nvEV$2KUVgRxI)Bflv9zXudZc4# zPy1j1)*%r!LBMeaGbkhNyXu27VJ+8uIYO+B zRXy@vc9A>2mx=esX{`eRjmYsOGXURw&VjkVb=~W1+par17rjYM5;THVJq#icL0qQL z&4-)3%^$RSY;C)*@2YYmqV>kD*BF=Q^#!oFLfv!&I4-!illszhVbWX2b(}0g>5>w^ z6f4DOOKllhdlK&73@MICQ}!+@sI#avi^F3$>Pwr{Z!!ug?ox5B4!QaYr9INpdb_nH zo*aLL45Xb)mGKs}b@Ol=Z6U;`3Xc9F9)06Kl1>gXTz=$nt2pD`_3Fp`>QM?PtT}1{ zX=FtP#8(BUb{{h*u+{ridi?Nxpe9#A<)47O4<=N;x>j@YdQH8$3>~Lh0PoZCE`PJV zF;qU}r3V!3c}u1hTqj_KU~dDd!hn)%tE}~4K1mpSEv9tb>i+HaPShC4q^uILZq9OS zt^g1Gv~Gdvvy!Tx@0(A%9 zH4s_ebBeIk?~;>LawP)OjW{YK!mhtZ(w&^(t4C3v1k` zY*#>Vs1q(K7)r8%OvJtj;T|(i+MTER-EcnFWqw7y2`Z)mW$0)RDq)3|a0D>FI47aj zHb7qgfn(Ba+=w;25rqPI&e@#hN>VS}t74=uaU=8bs3Zd*AQQ8BQ;1v;14tTfvk3Up zyo9EX3rO#Yy^>7K(8l>wlite!(@MFF|G zrj`f$*E*ULd+XV+uAIn=3nTO5;+y&dmE(rJA7=Bf zoW{^U6pTC$EB}cD-Jlw+L~)8p49gFSYA$9=$Vy}Yw4X}EF6&pjw7-^=E_AnRG8qTJ z=Q}q`3}>=}@;Qvy(Dvk3pYDv<^0uan3R}@h6@P@rP^3m=5y*gRKOKEf_{I44<^}_B zBXWx>Q6;G&p}1qVgzwRQ-+ewVA%qd=4&!E}LhKSj&Nu3X zqOn}E9M}PfEDRtSB+O*bugLnkxERQpJb{b?e3Zm9bRc8W8u1I?4LD7F>q67p$WcfS z0^`k)EpJMI@-hKlGOCM+9&Q<$LH%%h1ku>;0fvBD|zcNrj{_xshdEW7xjp9<%8La|>WOhe3h*5;3KmT+&!-VPP_W9pbR}-Ra9T0-;~S!kHyC zRj#dF-HTV5B&)mp<_!&fqd!FJx=;SVHHjSsYYIm|qI%?tT1Z>^7>6C{CWv1Cbb|8` z6;V@856+$_f#n<>fljrRsk{Z#A;tG0A<;3I194`qqo4!Ue3cLK({ULSWhH*&03?(ZAK5;S#G~6-uP*k1xRxK@-=fvEa7dhl-CkB^ z$|<7EHShB$`x28}fC~C(3uu=XP(ZU}TwzQx@0r*zSaC>;*^&= zg@uwz$Phnf;1?BobF|4lH88DZYj6xUY7V5@RJV_*Vgv)2nX?{Ss#viuE^KxW=mNuQ zrE0DdH38CLJWMh;6#(72BE~%+QUPZc1gu*SPVY>pXrkl{^bGg#I7v~Hfg_{p<6fpp z-nGIODy9vR7VwdhH0`kXs@L!JmyZ@jHL>GRfk1GQl!V&TuypRAo&j=-@SVPsVMM{v z0Pedv){}DAwGDkp${Dw+Y)vNzE9`+tiF4wgY>k9$O3~k7qAExaex}O)4n@&7E1LU z(HPpBJYWU5Qx#02ex>N?tcD*Mup>aNL+UZQc~E5`2#g|fbk=KpmJ6~NKs(sFav!#} z_zK4c&5?6Jz4{WGL?{#Dz~0n*wuGIZBQLh+Mg)!>miG`=?Rt%e#sLoZO-hH|>E&h} z8nnKiPe>%dAxgF$I@fuk`&z|BxSMxr`0{$K?RgW@$ti__jagL$M{2i@ci-gOtx1Pa zZP(q!b?8kRv>vaGeV0=IT8NAJf&8f)B7eLSID~kI>ri1zQPmO%YTL5U zaZsD?Z!*3DTFw_p)d|ILh4B%TBa_v(kQUpk$7?fw6mc&};v{=g9tKpJ{irp<@!K%L zT%F$7Y0!(*q)~&I1M*cu;^O&Ix`%_zd~apk3-_x6&yjIGhtw;PJ0r}Z*c1-geQcy@ zD|f{jrFjV9D03a*X26S0c{MqY=%PL~N3w5D*j@cZI5AZol>eAT5gttdYW70pg31f9H}dA(2}5{UqH0a8G{?jr+@cS{abfxc4{Ot*&&ZRbH z@GRS_cds0u5p42`rYzz!3U|RQ5y2=|LdZn12_dg|w_fow(*>i!aX1_Jpx2c%6gU;U zIixU$b)e*ted#}Fi{h0r1%9BPf{xlc8qJ9=MHVdY9&haAo8{S9;Hk)Dc29cwKXT8(k!|MrihHm0#!Y(5Iuwu4r2=V z1S0-@?Xs^wbA6lW5jZAfK>AMNg`%v03;|wEl0kuKM38HR08wpIpAH~XL`-C;Pxo|U zX#`wVwYmUYISo}iaS?+hP@T{A(2Wkg$@q%F#sW+d5U!fdrnA94yK6e!(7qr(QTC%ri5dwTGmSX-DRr+mS7=;&`FhK-lYZQvF7X* z4zxqx*h?yPv>{+!6pM*SFQ7y^?yI8>4XIu18$qbMr++=TWsRAcQ~$Dr{m#?_KJukq zs;Lv2gKjdzZwU(piWvHX{jb*aao;e)vfFfYmjJAtGZLu61ymH^uC+r z(wZs+aOZ$u;e?*l;GX$Q5B0SfA9fQg7%_VZ+T1xz?sHw|4h&86#l7=5wOOc|t95`@ zQ|xo00xi>;bu3DmfBP^N{rYip#ZCNP4!QD0ncw>Njzb=~-vJyoG=ocnb9GQu5ITYw z&UKU|SPY&nqq#QeFbItQ`nAdBNa{^>rSk)(M(`Ri4q&{%Rp?`2dtaWLFMs=Zdxe|a zeU~%{ynqBOIjB>v{`(rX-+gs+Q{A;B2SprJb1GLsR>0M7?{_oX=jx&T;u1PqkQAc! zAW-X2hpmol-?sf?M~)EXaB6ZNClwfPxlaD}1o2B!}{M$%zOrOJDJ9NF61sqTdF2O-HM+_aFgz17hk8hR9bY4=<>2# zLt`dU0Wzxwx=$%x`uVUF&ASrrUE7HDYA*^;RF{u;!}E0J4l5iZDsG9S*dA zMY=l}VA6E~6I6=@RPj`$vNy@UwLxR}rO7DKOSGS573Lz-FzcchN43**_lDZQHxIuJ zj+q06sxy);r$3BYZhk>a)VzWlj6`2pyNSQ}_hxlv-lPfsHVEcu%y%ne-Sb5ecjXu@ zT-AwJ7c#%wk9!-ZFT>uBg>FCwo@t03VwFq<>{+8Ax{rG@T1Y;4N^Uw(lVZX^0x;-q zi{ZZmJfD}`o5GoVb;%-|(SBf`=Ul=spHc+Y)bJbG_|QIMn*(s>n!AX~V_7oTd)RkEp;qPv*V47=vS zz-?xe#^FmSA&RJ$)Y(M80*&zfD?JI=GWi=dxlnp!LP8rIUX%{#+v?M$~S{kqH7>|w<%48IfV>#&BDQD1L(ggF|a!b z%iB9Jx%V~(MqI8?>F1IJl6jpC&ati)Ryo~Tk%shW{Dv6H_|Qb%g>PMUTK92pg?18_ zrL6ANeWi^IEFcHW0TDg|;FE9IiTL#J*ROM7fK|2;s5mJy)cswH*})3uQ+?f$_u0ER z)5i@#-mN|Qc^B|YyoMwkQpXuc!W3>$9Djp>eC~L+O)KWml^Su$tvJN83bI{ziA)BR z-31nprc2K>DG@}4aE!7DD1rf(x|QO*-*~zwiV3N{h!YWT2;0QmS9OfLfY$*rJ8o2R zV*s;I$`7va1&$`$9~&}1l(M_a)Pg}le2jWJF(58;&7(`?6*(@IZ+~uQ&_Zv%sp`)F z4@sj>qO)#BZr+FD2mBuh?Zv0JE30roP$}qe% zsaCL|#&zyabRU|1${^DZ_rCPTHDt$IiHGfY@--Q8N)Ky3Hu}qt?;UG@RP(To0HG%gDlun#DQ4{^PZS%_ zl$Xzu1nVVS>TvnPpByO{#rwQnL5oKV$yzFLc7;=`$`t+hmcOJ|+wJ!zi7|{-g)+dY z6hJvB@Vj)AmQ(xn+dHfl<<2Gz9v~v7OQ`~|bs$^e(N*jUq`-l%2H}Rn&y6599`(CZ zQfZ)0PWZXt75oQwB&DVU_d)um;!dU6-c8WOl-V{p(_CK&PD07V!Djr zD@5SCCQuJZxTv5X6^X%D`z4^tHb2S=g1(@-BkyGX;_CJ-DRYoUNvl9akrq^fAP1MU z0@gtH@d-lX&u}EJUcDhfS;MbR5{cLCm2x&LkUYUzK$tWT zu~z%(bcsRu7q32FDfW#OWd@Q$FGOC!HDJ1f)_XbgADAw9sjt0uu5kjv%YxHX6#}YS zfQRF1p&!2vFeqfv|GIC=Y+6#46``9N0T{5sUoOC4X6KhvyBKpy8dhMFmYaT64$#u1OBdA@vJ+-5L9|ceZ3y{g&i_VP~4t-L!0P4(E(EwC_9CC7E3MWz#l}$Mu3lJZhs6EL>XWWiNtcCU6f|M>Q1z z7v|DBz#4N%abpK)>*c=eX+{ZLpBs$))TSV1PVkkip&Ns~Vrj1>J>-4ADF7!OE^H4v zXViv_AwME%2rC)&4;{2s8@@*BH}qPUn`u{Cf&z6Gk&R5zBkI3d_fYSaV?^U6uzb7t zdG1lyC$x}b9hOnZd0hcYEbS;|zP281fvHfoa_crcWxQZ(ObC{d)xXSuxmtI3=3iw- zn>2u+Z>oDSz&63lQ<_cT;Gk@&3RFq4*nQp8nEhr=d%soy=%7<%5F#bi2%8>(t2IG$ z>d%_R;8^Qa>vU({O{3(Pn?JS6e{*Z#ep$`mSKMzowF|OOQ+&!wBcZysU18@7wKq!g zvWhvRh%xDo72Hc__Y_VMb=6!AO?RntV=fB>U!Yu3ku>z!Io)-Vb?LJO?V(wPQX>OR zP~Z~jxo;W2)DC0z>E=xo{zNj&9I6LFwcZ%NADl=~hOk*NB-v8Fqj2QQncfHD3)M}) zdsmR^OC2mu-bz_d&4)b=J#4=b0YvO=md7Y}@^T99v6R1SMI;ABzzx&9dr5qmdImKC zF=z$W7{Tr{3E0&M&5~*cV|V2Z(nmQAY_jMggS`UsE8?$2&Rx8(2hi)S+5HWSYD-Zi z5qYYhBV|Z>fRb(&5|J3)r-;seLO~g?{yq9e4q{Qgkz!xzas?>Gy94W#baT)XV7W6W z{=m1vjbsZr88A(Yf*P-8ZCZEqo^KCU5jYlsPzgA|ThZ*rg932EnyVWKgpkZOm}EnW zp4d%%@QcbDTeYu^`-kK^YWK~Rg5yUD_H?{iephT|*dcHTJ=-2XpO^mJ*>R?f`%Fg1iZCuGNHh_XQZPtc}9EnttlM$JG+1;*ew? zcVHdv3$#OK6SZTx4A6b#7?Wzu;pc#c2W5EsP(XRkkr-E;7|^YiwreRh`_HUoazxEi zp1uijxGmxuqnmU)Mas-N?PZ}e>lYVOTiF-BtHfQvZlKa6M8~QOC1tX67Ef$ubi*$z zZVoBfDkudA_t`h;UD(WvW9PI4bApi;HsRC$f;G(8ns9E8oqj0Fs18{y*qYt+y!AokZzzUxX}`T zRbCG{;lhCzye-N&A}Nhx7(5kdNy&#VhOai5K&l;$Phg2H6H`DKTpR4TexYm~3Bz?@ z#f0g*JDWwgQeM7}dXiVR_3GiB@Zb>R15<|=1~s3M`6$@IzQ+%)4_DxR%0Inr%dJLV*gkv@wr6V*1@5rehjJpUtoBV!*AD_gff$r+!qe-+*7 zn_as{`UX4Y9Kw~FSoe~^f{V||J78vM*f)DO9_ibX-NcN*kVN%vO1mFSv9o~4L4TDQRp!gHME;qWE*2s+ZcG|#F3%}gj1vmBoN!wuKs zr$@#vix(+qQL5W7E8Gmu==WoFMj8M5_A}?PpQwq617nnd*ZNFr&jI8r%e^X{2{dRD$tCk@- zYpRXmQUY2n=?ZSNTJo59dpP*=A>`t?fvOOox=#51N;_4)-FUuyU@&Wlr^uh3CupyM zRykF^-8{a0?$0Xg5t9RpOTr}|b>lNo{zu2hZX~|}9Hjv%UKMVz1w}fCFL2uYT3zpp z2gphg4aLDd1jN9=y?5gHIHl~%hf*6QR~Dk#;i~EbMYIzJ3gF22I0fy?UlUru28L%I z1UBRaPg*~&xVA4JuexMQ+Z0q88=N4?Y4h7CO1}Z{aq|>H)U?3&(;Ry}P8g$tCUTe! z+%F**Y|;Y~%12=_i91jBtX(s9tc`Hv+aZPM6weM28vO6j%uzgwL~*-tdZFT`OwHH2 zt4wuMX58wC$&}QiA~DWs&cw%9HWW-mF>l^X)W=}EQfPOeQh^tr!WU*7dfCf{gy~y& zmtIZn=^VFkjC}=XJx zOLfYa43T-T<8W0bO#>D<} z!0ot9NBa-N944OyU=gl3M6;*K|8BDUHB_#+GpkClL=0FXzvn(49e)nco&N76`f#i9 zl6pX~Eg*-Z&|?B-#ARak3YSf8X>_FU_X^vdLKK6Nbl~8l^1mBk2QEIa#ebWM>vip|E=D1SpTebloUEsfg zg~(3pdJSR$2oDh4h{&ot?0Z-aD|rGp(Qwp-&?hB6CUTu7octBqP zP9_xW>PGj147SfgOnGci6Qy$$1Cb}pw;)lp<#+QJyrHuhV=Ou)qzLsq;p~(sCT9W_ zdhGu77rblc3&&e@R^T$k(qB?Hiy9X&X1nvCm-25(BR+czRmdqT5;7W``UN*?5L>Lt z-4)qX$fO43NtRqfDZw?>s>M!1jUFf2SI~w$$5taeYfy4X3J6*Q)__!DkvMb0*9Yd# z?EwyKiL-=~PwzdIAza=d>>y3!-LYcGV{#8>2 z#O(;smIv8ejE&uJrFhM{bSt*Y;^%9*swQrnl(1Y)Suv_j!6X>jVeKU^4TiO2YWV=I zld(q;uQkEP80t57ckZ3Kds}}+S*eNd7=!GADUVxvq%e~8f%O8Y{Z>qg-LJ3(uBM(P z85C9|3sF-7A97gPQS1e8`Yn9>Zu`6ZeLIcQv_5MS`Cy8nWTOV4-DA58bd-w5o2%(- zgK}Y@u<rg9}EM6$}Viz;+)vh-$)fA6Es|}FE6&xE- zOqD8WVEukQWLr0IT^;PRnu5!jVpo)8f^C4nfWvIke|s7=2DE~VFXzJm8q{Tr2gZ3Bp119pxF z!4%Vg$wPSglQq`HTZoCN6JR521K^^mo_A6U=E8Egg%CghCDOrc;Vuj--xc1ygWYyx z@6hB+_6ErYR9xO8O9wjvmn1hJ6{Ya{@ePb`8p z3^Y+eZmfF;H!Ay_o5l%`|6P`8{2x?zinv4h4ZVcQ&MuTKNmuoOSvDs~Ti6V6QLaS= zshpHari2mKkvSes_t~j36Xi%qBF6~6hdC9rDyp4jiDhQGg22R`qOPX>7|*2HXZ}QVMb)^M<9Fn$2~QtY4IM1w zg!fdTC&hl~7MnjKg`k47Fn}!2;nv*F-|Id0`_(LvqNbcy34)x$B4Q4-YxxvO-r~qZ zVmX*N@|V;t58Eli+Eu~eLvadA5C9aS7H9OUTNZeS;w5BcP!V!BZ!kKibjw>1VhaGj zS%)xIlG%3pcy%j+pbu$XbMinbmjoZ#>9V{fkqh!eI6yqVBz#-9iOaCw>~+YGEeTR# zA%LhU{y$7HWtlO%adVp&i-2d)un-lm`x-KuwEKS@}-BzQY2LW9{~2e{-0LqADW zw?!*R-i zrHp_ObW6@aZkELKewif!^CB)qD(J{j*;*T?^vhck2}qM%syT<0wc&}4T@sW4Sku=; z5aQ`kdN(jZurW@1og~U%6o4ZrhpS9z)>>$<6sL8pT@^UF3bY_~y8x$$^*KH3mIaJM zg472j$*vQsG+0e>(rb3>g6gy6S`@hBphaWw&J|`B23j62`yir``!2#+;S0Q?+Z7u}EnG9qM8#R2lRfGE51KUI`@M-sei(rV$aRmn+ZdrMEB zAj*3~Dvw2EABL0%qRxOAt2>=9%+bVGH2oqImxvRkkGac$>2WtPyD6v1@;V0B7+Jl= zf^`w_!hKvuPfef-L)L@ZpVHI1&I0Ya4%{~;qdu%avV+kdcsq{F=t$Rl!sj@|>u|212=l7a z7(2`5w63!qx~_wkq23CmK43wPh**qBKWWr^!UbANr~#Lw$YAMkCbhp94{W5dmF|Go zZp8=@oKpN7+yOhvRi&CbsUySQmrl_Zs=o&r&Lt?=d&!1wCynEp&1yFetUrVQy0@A7 z4KUg%8N&$#G=OoMt8s61+~Ga4RgG)rNCOE47$^cvJ+&mJl*?(uKjyx2$u5nmfqIy9 zwj!Y{IH~LIg4yf8^BIive@wiNqi$sq4?sMw7E-I>of%vAr-|3yvJ<}!12`~33fU`- zEc^hy?};Zrbxnz0!euHj>yY;SwRvLidpip=3fo0d8W^$HDn7fT6iyTGpumkT4#_wN z<_3TQlyoqr(41L6acVdHrO%*{y$5Yy0>Yb^)=2kHliwhX8_h81EXhj3$)K>YV~zY? zJkjjZ7vc~U1Lhw4U`SM#kUC1Rg4%&$76KKrVr@^oWAqdZ7@RJ6+t%wfrQ&dGxofnY zyF)B-!>&OKryz~$Y7nMfV>0rF&o-{;?>X`aKcKeptgC26Bd?)YK0}}~4T)b8?fBpRI)^l#nXiP}raY{-n zcdbkEil) z_-%ee1=r8>hun>&B4CW@=JxXPbr%6Ud*DKHBGVYGTTxOX&r}v~rwz0D@)8u3VXqO6 z^xP2(*VI_aC>ewIf5DB@e^bG@SQGiJzg7m3_Gg;H=bwD+t)?by%@@ypch#wcc6BK> zHQajW%WeYtOSX?yId>RT!M&tRX`(2kL05I{`O~U^?73~kq9WrIqv#XRQH9CX2It(_ z0`U>xUxC>fo0)2URvc4NTRl0=1b5<+4^rKtPAcvAl%;v=^PdO!3)CX2OO7iJGSs+-Hpj+y1pDG_t_ zD-;XjyTF403X%NT8!yvdlO*(%M!*QL=}XwL7erBnqU~O4xaaM^Z86104V+f~&{qww z?%Vo@J(cm@%{`3j29NaZ_VvTv*?I%&*8s~7KU^J?(bdx%W3Qsq&uFyf-F8aC_4?`c z|J)f)Yw%xy(m|qP#RTqfAF9uDrBlHK=)MYKFY({%646cV$YFbSGgJ-B@hYZNY64&H z&PT3G=L*ENrG*doQ@kYIxi@bX^m}>vn_Ja?efA4GR=n5cWy9uvfA)fb{U*fAvnG;7 zbiP%}u9n3arUTb=>b)YgMk^N?A+2r(Zne5NwZDR&h_a05cN&BmIAC1$V6iC>;kV(> zva70n?xZYr8bI?%grXG9s%_>MFK*tSEs>ZsG@%JTDe&o{1Ly|Fs5i&wc6n)2KNzmh zEy>!sEt1_#qEr@<)$@YuJPwX-tgP}h^%lxTSK4#n z6;`5I%x5=C77#VoxhV!DFf4o5labZ@qzeKOsW5k{s-xi$mgS}Ys4K-moE z_Pqf0O<5a?6mw-F)OYTn7F-Xhkx9a20J&J)yNh^ZUZ(*@p`ADD{<0ebdal<>+GB!#L%2;2z0WI==sliytY~hM`TlXj=i`xAxx?UD9OQ z!tsEs8*0HacId+%e}p4~e)$vWE%y_p65uV9MUpN^XNd9CSVy;?aN?v|mhFjBQEw4N zbZTz*L@wkQC1}wDe+nk57;*>*5rKt+Rv6|!t749=n5n~# zgBoxL6=(=U5saR=Vy3P~O0aRNK^kiS^p0im;J|RHojmLu#Q2-3cZnYr_IR8l+DeC( z3>1}Hxos> zfk$L83NArgJ9>|Ueb;81x@K^DK)08Xj4O2zOc;0A#3pZ55PpE^@O0qcgm7_+bY^wx zR?U`}M1tdzF9D3uZKgxxj{2QE?rhVN(3-$?FdMikhX==9`giKM!vGEmBUcLWUJ2;w z3G4lYaR&)0W^)xsB4eguPB=I+r;K~1dP^x*F8Jld)sH$jGTKd3^-QL+Y)cBXQ^;1S zw#P??3;N_WQ&M>|B+-nTjq)uzYva(!T%WLJG9=6Tf>k02Ax=Er_v;hZOa!ui9bk%u z7{3(vm>~UxaVJL$j0SY*+yN3O0VYU4Vce-RMtuN?R*Bbgu>w+=N69{9FtW6$&UdcKI8*cBM@|aXrv@3s{(l3p;J$xBPT_{A=D0TCs`a* zw-dmdFo8c}K@DH-Ar^suP&!I-^1x%8E~wMM;Y5|3(yljrC15Y@W3ZH;nIJJe+o*?~%flr`6fqsn(SqdSAgH85mNbpr%T)0s5#l>Cz zuD;dvoho48PbPk(%tC@b04+=oKV?HG%XgLEy!rTxFMj*w$G^OLyniS@cCLYsgNrD< zn1B3B(f>nC9Y!B3_u-G{!5;_duYNVVzbpR4eBn=u?e*>E3La5!NuME%*kjQp(Q# zc80j?S@qLxIQ#a~FJ>(H*=qITn{QtH@kd8|;4+q~Oh~)=4c9kX6XXR$2$i523%%JR?J!Z2naJbA~{_vPz&HnVR0?KkX z`;PK}uvS*(%$BlY4DYJh?|-iZ^1t~Twe2vXoN@zHH+>U)Re1{3HBoh8s!&i1kh&l# zkVI;AnIvL;HbqWK3CElK1~Kd<0#T6k<02(<5glwlnh`(kB=L_R;w{S6kK3#KfmOy= zbE2*UP*iRg`@iN;?mh9$L}(Zz)1$-Ft*2nRU+cxVeF{FCKop4{>2Uzljc5Q3{rRU~ zQ&RQj{=r=3OwrqPTi3RNGIj{~*m*@REV+;36tW*ZYl8!tfoPgoSIPq-#J%_?HReneBiT-OPrk!w*@IecHJG*UAdkvlssvwgkJqH9o(#9v| z#h%YVUCEJ-SR zNFLilOG5s)Vm(+Vb(m^{w2Mx%FW|7 zorRcN45$zcD%Pcn5cZ>)qP?>_w7*$8ru(semzdvy1u!IF1Cj|naB-oZ`NNjKy>fpu zyP(Mp(&E0jFg1vctc#0p)Xb}!;))skvC_JG(X6&ul@RD>36KI$Z9JzO9o0eTr#^V* zrd-|dGz_{fF~4%~>On94Dnk(V_Bv-b2g^LXQnTbhh+2W1VsaIz^Z0UhOd5QV#beO0InR3SF979eB#W*Lnf@Ezk23`UPkhi8i&LHfxnm_ku3A zYu{8qYTdsw>waej?KAp0*jFsnW``{BNnwMM2uw{ClecSjh~EG5lHGQBX?EM?Wq-H1 zZatTour+7vL0uvqp6#9e$@@k{3670gC+rbYhK6hUlv9zI4uxbFbMAF1_BnI!PQ@0^ za{8&5P}w6YD4NJb(OhH2Pa#clg$@1J=d&TIIL zAt(q)7ozqQx5%9~4(yWUU}F4DGP272gfaW*j`ki^+RzKEp)#qV1dFKYXLZ$djn`RB zl;R=nr%pw!3^~2Ml1~@pRA*T;C76{cGSXUP8GbmUXjGl8nSRK)=Bkp1>K|2|&0;)Z zF^slVL@>0(Q5nHAkpt=(EC{2fX{%WjOyKNZWv6H6(3n*>rA+MV`u5@d%;FGcqF9|N z8)o);dyN^en$H{n)27J0Du0@dDie*X%c9(~TzZE+a+>3wGSFNXA0Mh!(;1XZx{M)A zf_@Xs5`=H;r{P15Zq4sDT=sM8kd<+p8?v&la z$IS1IKx?q>5oq`M^x5{YvnfqMt^rK5LD*)m46nsdZgl z&$!8(7LB^&AHz!*w^xY|k}Y>})bTrNFu1CmP_z@_2f4R|wJMYAYVgc#b7SlmSCdAf zdWX&6s*WvpL)m0Ui#66Fa0gP9;v}Jd0d(FhJ2b4u?7J6b`Pz=%$bk|eH?>bL+>`Mm z|JD=`vB_cHf^(=YNELlK(+AI#P4|2@RcLA-Z0a0l0qaI#TaYHuG}vRnN@TGd?jJWy z93O@|%8fF$NT|L^RvTC>UYnDu_r#>h3)|XV_N}QZo#smjLBz+h?iKgq0f{_s%68fz z5vx*NU3>)67Dfji9)SK>!kb0(MUIMyfVEh{=-)HtQkvN@>}ZGO#mvnXHmOn+Yrs}X zyMcg%BGcrC*{Rt&dD_Tk7jy=_#e1A!&^KA0;Tvs4vLy+cl6arPriA${Evdmhp~phu z6(Q815v423kdT62#jVc|(c>m>)ZRb{PRpNDaMM&`)b<`Um({6!%wn*t(x0QHe z#)a5yCmT~SBh%AY?M;#gRm=TBnlYkmJ+B>yuquO`BI_}!FdeYPw?^9G_iaWmliG3m zo5Exn;53YUf~N~%IhzlszIuNYW9VzdEJ|pts13cWCd6){*N^Kdn@Eqvd`p{%vU4~` zpoWB7ji3k$Ngs5Z=+sR3mvtg6n}DAMr@UBl=VQ z6O;(fep6;P514p<-zDr>Gn)8J{}k=7%GYo2%&NS9tDJ>2&W2sfI(US2`iqGckXW-o=lfl5h%(RSI3WQd{*w z|9&5Jwu?Q)4%jX)f9Uxlxvpt+YzcJyA|YI(IVFa&IVc$7O+T2$;-ns4$kIW$mo$P% zbYm`cM4}-0G&~4dLann5gQ(jaYX87#`|0N4FSbUtX> zZt~7tGGtsE939p3OJar&EkaR;T5)bg?-e(?9f@5)?}?)ciy*)y^MSUb8&JC)>lnZ(H~}b- zr)@!)Pk|06z-~#1OC0C&p2eSb+h<;_Gk6x35lJrq3A*jmTladyLG-S;9&AQ-JB~_FqKaB%g!Wv9#GaSj+2QaZQkaOS96V^C za8XirhZ{e{IVZ&M?A6P4hcB$vbMPKu8z_(Ninb(f1MLjM#7$mu^+DBQ{lR{mH{NmU zxHJ=T;@L|f*pf<3IwL|#*H}-1vvUu~8{Ou3$2qDn?x1cez;ldl^YeW%W}maUv1#C( zq&z9^zVUs2ej8?^7XnPJ$z*{@W6|feJhTl4I~^lBBb}d4a?OGp>`A-8KTO#LImtFz ztOPHvDh#z9Y4_UumzJBguc|l3n7gUoAS(`_O$79U*R&vio3oeSPda%iae(KMU>Tc2Hu$Tl-3VVXzSgu<9QaTN zn*(Op!2<9HrEinDcz4$ecZG9C-qSkBF+r5QOjCSsY;hY=+jn@ibL>{#p^G;~@Th51 zM9VY>4dgP7n%nlU&#ho?2^SZbE<3kv2zTaC@+MT#jh6-yz(DSsqgLF6evO+=FU=8B`J4$BK52(8B}y`t8;3 zZO`1WImyM2Mw-4TwB3q#x9h_)?c^M~UBjiowQmkeFsGca^2N>W+&*mL{^}nXAB{(F zc-;|4We!OJ)wgkhD|)J_cb(nQj7Mybf!4+0lF(mnWTa$pPk1@|?#tts|HM4h-2R0- z6;m{(0q-pTn=wHKuF{cXrhVbzeurHiS5-uLM~Xe*uz%7U4>ZymHal{PfG5wfV3t;w z>`}m-NeQSBq!AV%Km$lO87Frx*tfjrVmkYr|CpIQvSK|G@l3>@oKXqpNx_*+6$8NJ zbIwwJ-(K+c>hR`D+zlCiX~a>BD&%^DCdV1YGVz?CJYZJLd6(jL_-s2UA(hI-4lvAF zcKG)8*7;e6D;nq*42XFGjcHAEv!`@-oLi?YXbfSMEF*IammmCXX6fvil5ToQ?*%6e z*&VziC~MxTnO;X@vPZ&jQnR%jcNw(GWbgysa+A7q?Qm1k_-S^}JvZ1SOjabpD&q?_ zlqcP+2J>iK5<`8Afqz#c46$O{!C>qdJQH7U%N3ml%u9u3AY|cUfs;*!A|D*rEjzPp zJ68u8xKHelSanU8?f|w+c*hK$I?GnHii(ji21HOr3u1e;O?^$gwA5Jv8xh7OM>dt5l0Gih6zAnfakagFyrabI0{FLnFvwh^$|ZGr zm^rc5bL##6_wG581wJ>89y<nx;^noaH4^vEowA+32ieF+lxYsBU3Gfr_45UCvk1F0Mfr zTZ64V2b_ig6F}w@_3~<587?#S$rh@WO>R>{uz+ZOwWbvD!Gpja$6t1ukYKGTS&g%{ z2q@Uus0e$RU!fN?E97C-53?68$hK#`6Z2H8r($Tww5KRqiYtW*O;n&FbjjhM54xzh z^^5Hs4ejl$x$OPM1dkH_X<|oIsLs|Y^zlICNRs9*Wj;{{_u-P|{O>w=rw%F#MWq_0 zUchoj5w>v6%FzeUFgJ`6aY0a7A3Yb__!9EL1x@UleB2l{r5smUX~MS7X>+>RL2Q+D zYxa17KZcP=`vLbeI_(e&yvjaa`wfffz?y-l^s}=Xb34VY)w=iLxF&* z(7Q2nFP8*ViXNA=ih$~a)LrREe<1hA9nHoEtY zVwaFZCrP!CqNs(Q0KTHYF!5c8S%_&lbW-!gQHk0$?V_yG5Xzo{NF$V~21;TVW%tSi z;fy2e;4t=ksnx!~2!#LuO_A0q)CK)sPS`sB3}en>kU%a3%3)C`dCAVO>!tp2LNBE_ z8B6sNxWJqeK=6FUfCehg2@mNt5djljk=&p_rOL1>DX##6h=(YJWr>u$B|>{oXo8O3 z(ROZ>@YAD7Em$i4HB@@x7&B5*lz39!#g1psKY^>7z$&PADdz%n*2%s znMs0UCCps;1Fo=YT%_1)kPt$fLwaZLk;7uy!-Q14Ad@}l0Z?#tCy~Fx)lfEN8{5Np zaA|C;^_|6_lC$KE%ZZ-DR_lVM$Ha^b9>pLa`Ub%e03D(xh*2H;*O7ax-NCAsl)D1b zOR5&v&ZZ_}+o63%#&AJ~fse;PD0bMkv9xE zU(gY_ynvb!SfAFnfu)DZT!B*sqll?TQTS;>c9v)ofJKD!sDQB*5 zL5D`f*hO8F@JUu9m1N-4DXb)N_G_^XGK2mD{plPYG8QQ3A63>OjH#82u|-Xmh4sC#C>#)g zgn%RW3B$yIRUkqJa}v%w&?NmW;SYi25_bXyHjF}M#hoqOW|ZGmx3az<&;wqreE~TD zcS8r))Tbm<-53Xc(-QjP@U`g3Yd~Ki925=#@><;l0=3tfH1F?*g_T@2g#O z`=XZP*Et6h2Ta*tER>g@!{@ZjDI$tvWujx)JFCt5z`7^ND}nh4KN(d|?7O?ofH8bz zWVz0E*;d0ILQk9&AvA?VtaCUn4=bd0=MK9F;}gJO>Sji{icz~Dlf7k~zJz19z(B~8 zo}bR~+7l7gQDWAXw>wUr`9?Hmak&VJ3U+3$pH0Q<6U-43MTV-Q3JL2E!ijZ*cn?kqbjOYX&n|_e19x?yW0;AYiem` zmXOB0saE-V!x(c|!{dc>AuIxJ$87BOQ|al0@{&gp*l41t9)hZ<7#bR*oz7LbJqc%nEDy|SMk?Uh?R!Wlw|s&W@ByESeIvv_)8nI}wzy9~L- zLya{MRa~z*_!g0`!n!6-#kw{vR6l5%sN8`8T#`bUilV`)pgn%CCtes_% z)EU$tKwcu%YJrB#8SZv<9rq^hMhwC zTncau!!n0SKxX>cYjelMpOYX&&3LShwURij)<|s$=Ogp_`t6m29Fe`^&K+wxbGzyi zd#I5K>0wlmN(sVn$@1?$KJ+3xD(W|P9>OU!@rSOJk|LV8S?jETrhuct1t`3%vi*vs zQwQh(_}zperqg6-*=6apz)>TqZy^q}0F?(=D!8o3{fCq91L@P|1TYEI3vqAa3{MiS z{AAYJ#pw3vu=hK|yR%1e&BN{u2(h99JrpuVTjmR3IIn(L7;;Kb9uOw_3Q2aqvPYRNylRbX$WHvpCsNBQW54< z9LnnE)@dk3&TSyrQ7`Zjz-i6i1ULsA$1cf6y$n0wUy>8m3zd);K=a_ap!fu~^ugij zxA5ua;h;{TXm&*=1NsrAlDn!FZUbmFAHIp3k@q)%+pAhT%?6+zeTBb>6kb58IFMh? zhy%>N=0B!jzry07h=(HnWF~8JjA6RW=Ug50P^LA%AKEZGx5suU93B^lrKeu!z$iN9 z3a)+)3ay0J2!ETPK;6fu^faQl4jicv;9_=XI+{&So6xV-vzP<@kv*lS6B zHOe#v1h}M$=0mfi&ut<|j2Ht2-~v<|dIi#-xzv!kKvXjo+;{NIlUfYzTiF)xNDO~i zy@T6lb^ov_zJIS33EON0+giEi@Bq%&YkuboQ>Q2)BMC&v8p5HvTFB-%Q`D>;H-5v_ zbJ7%nHm(*6Ak7QFxRk23%H&+hV>7cPhKPR%D!mM=uBkMCZVMA;f=X@4IwRW>->68T zO}zAwa^Zo5{}i!%8-jQS#Rk*`4P(+f%qQ)>=zP-yAFVs=`>aGZ5e7px1(FJt985QW zjr%-EE-B`y;LdYqrIL^d7N2|xN{qu!q!mxz>aF6V5^1`9c%gOgJ?9&+@2=SHi~-ka z>OwD;aCoeNC2_!XA5W6V^#;&p0ic@DaYDJvG;z?bG`8%FG`*Kd*txu1?~v8+9YsKM zApHO#NpuIAZdUC1Mw+|a_-9l}1b-R9S_Q}g7mj~@JrG0c#YpTFQK~Ef;RcChJ_ld! z92BjuaJYil$o+t{lR{D=pf*BL_#5F1IHKW4#?8*hnwS;}876tM%9W$o%&MJhAR1;!(a_oUqO7Vno3xnrxwGW)s%~!Cn$Nr#m zp@70TXR&qg(%~-NdCJg0he!LFh%K6;Df&r2V@T79l)>RTCpTO%mSR0+N$9CqKai1T z1sJMgt|$`sLb-gm_lDT!;JV;Ax_@haAOi+h%r{D3fu{h|g6jBw1?%$!vgd_+u=x{V z_#P<~4PZ}p@m%TuZ{OeUrNZjQJ~5BkpNIi_Rl^^^(U;=^7IV?DonpTl-ph52a}qM9 zY)OU_)m4RBzyASFrZ>UuaWUqx#Qao0ph8P11q59O$A)t5SZWi-S5L+IfefCX!IWbiK_9p@g3N}EbB(wv$JT5_hf`A|rhR)yc1lXV=Vnn&>)$Gxiv)&VWvk8N& zr(*q}Z=zQhXBv00jI?C4>5nV;h<%{{5D;)^3VwkT9}X(ryT4!Y$?*ka9%GEG7&w1m z-9k!EIvXXyB!+b`MGTK2hM(#U1wJW>i2oN3au^HDzOIi-(U#`=%nuC-dyujbU`ys4 zc`0wi!733v0Oddb7;?erQjLw`mskM74-ps6XO13jL2guz_arp~QoBFs4QK;u>sFwd zqZs-rc7b`3mae|1dfC6D;3I03yZ7OsNpqKQl($Z1Us%QI!u^GWmgwAcge-|25VSDSNuJTe|<_ zVixYf=1+uyS^)SAS~sP%#ZvXr&}qlds8~;#AIQjAf@m$Qjk4m_#Oczm9!%wlc+|#E z>f=%66Or4<;ZZS*NN?c|#UaL?A@=F2ORK%aI`6;Tb)vY342r?HWWSS8BN%6ufu@Gs z%OE#N7hr)2O9M^i1C!}v3{1W3@zK?35Z3l5qY{QGhz2Svb9E=)iV4N%!TjjvG>6LE z{zMFpMD{p5nF-f2!bVQa@$RIix!V1qX-WthLg|pgT7WTuWy%vry8~4Jjs8PG1_dz? zfB>kz(jicu{Qh`Hv`lLA0~y5Rb!Nj|IR`i@)~UPgvg=Ntn$47;SBK|`FY}&AOar$$m%DIjk0mnO{ zW4|^(kU^M>;*F#R;J<@Wi%~gd$H)ol9HH=)Mj)tgf?_-vm3i#T0iG;5u6&c8UL=_+ znkSjiG87<2W9~jC*X4wl(^Ij2Xn+jeItkmLyl^%mRu`4yLK5?s{fQU?Nx?FYLBN-w zW(8eV8Jr1X%wysYGshiend&8H_X5^g-V^P4Y_v>?CG*3K5y|i{q;fj3!A0VE?CZ9y zlKqJQs2Su|in+@O?8tJdflD8i66-1RLnBJ1vx3}2s_}*3-Z>=o>6D?+V~KefF`|rK zuvxs7v;^dsg6&F`Lgv)!}CmnIl1N~=rDkG<^_(ABC`O&hJMfiQ6F+u zhPi|NOLE5X4#c|HnIC+eT=I%qmXHC>fpgXDjbqCx!V1uTYFn2%&{QSW0}4oNj(=IJ z@S2)!`iTHI!YE1$u#-Os=}!>Qmg{N%f|v?>D5JktkQL~@_OU`jZxAfhjB-|LTSDCG4g3e5bLI%4B3Mx5i0)7?)}BJxeQIX=jdrAQmZ zBNf%TI77s$Zc?duVuHxH_XSxJoUu6TA;iQ=0er4=$(MPE%CqUG6>8Fy=!Jxmv4OSD zr3yUKoY1io+CDO&r;K9Mfx3dP@0a@Iq3sPZ{-HuX*A?r*{O} z)M2@K0AJ6k^iB$sAeo&&o*;cl`IUASm4j&irqsT}{dZ}S-nb)1;|@)S7@x?xRZhAJ zz;zAkkpr(VCiBkhL(FeP;uD2BjFIWfyqhf3F7LNSW(j{EB}AzBo}xwLW*@eXD6y)Y zPNn;qf52X3@~!MJ=>hjQ`+!;b<^eu&Tt_1(s#yS%=@x)#RR5G~j35CS`M4fcLKLTf z8NTL;1EUuY1=LnEMTyyz=)P&!34Nf`^K;V7-Kwhr|x1=qHG62UaSN9jIy_;>|{3v*NqioQQgH>t@*wCt|t2 zlb{O5ABRy+LfQFZy~H0ozH3sp?M)`e`Rx(_&s*tTSQ*_&uenmg;m@os7-jg1pU~@G zMAUY?puRe+*7Ax_70#uxo!N1poQIB+FGC72B`k=&Q4RVDYi<|Rg{e*O6~FN!EHeJ# z4~jre6L3+DW*O$u2oAg;x1C}rb0rh`q9@WTG@^Hv7LXVy0~TCy*0`GO4W&_2Cw050 zrWlH-qTHKM0%-JJmromw-hP1r8AkkaNwkUDA%ksrT5pYR7O+pdJ7t5^)Ptq?DOmKr z(l|}5uQcFGLS>f(NQu%BY(0P8dV>H56(BtL8$npY|IRt%>7tW*>nRPpvr}-DbKIP3 zn7K&pdy43hosAC}mR=xz#DD;}KVg`;moyCT)_|D9;E6I*A$XoJOC+Wm|z;SgJOltRy#o_ z^)|Oa@$kfAtFPB6J&W2tZ$Nqr8*liUOFf;Yyi%#+ms;3o^>@tTpxiTsn6<-+TcS>V z@g|LVx{B_Z97@>^@f2_w!u9Roysq1)%JtR9d;vQIj%T8+Sgn~mtu9B?z9l6ZWj}7+W4# zybvYK(~^h^WPDCrpC^8(o}z#QU`|dxv<~dXr%dIp<*|fIhKn9`6q78Vg z3060Rap^i?IW42C*Th82_*fIz$JLV90i~Wgnh#fqd8)STwPE2A{(>UnUneB9aABp= zV=m)mWm0(VH;Q02e^&^{{=M{mUv9eJKX|`?@P02BL?=oA>b^sGwfC7X@A1Z$sDIh- zZGO71?>Fj={#LesdvJd%+fO;m+ut>x(th`K^N;2k^AGQ_P7a@RqRcorBpsqUWLKa~32Jpd=-GdGlWudXSY z{1e69tLg?4l$(by_3vjw6mU3)QP(aQD1Css^3vNxe={T zX+wW}nZI9G-FMt?Uq6)F$A@q7chAlLX8-)(`Wc9yyd=#1!z!|m-&7Bmmz&$m%U8EQ zs^;t6C&kix|P+K&}u_S>qk-Kp!%<>mIC3=-u1=Kl4=9l-tP&u4%2AI_|2@h*S2;`8e6 zZhJTTXP^Cy($_z&>bt6X_E(SDUq7Gy<^T1ON@PFYYzi_6SMZ{J4}Px5uV(-HKm7=3 z_q%SCx{>|#vHpf}Ib~osH+EcSfA9UwU}IKhV(e7f;rR7c{;)G7uQYv+*>eWM%zA!b zY>fBq2|#qX=t+wJ!I*%#l=v>>lm<=ysnh0FE!3Zj8A37Z=uVD?}A{hz56 zr)CwFhuW;J=d=I(-__Lq1gFp=>q03Tv;5!j#*Ix#SM&Sp%gdU-X|6xt+}UAM7tLy7 z611r7Z~e!bAsm;|jiC3P=d*wG-+n|6>&;f{Q2FT3eql!WHh*|~dHFRzpU?iI7eAX7 zbQoPg%=bN8Ra?bv3-`yLUTxR;)$`eR|F+w@`NQ^FBCp;bUJ}iQoBf}$zIp$6O&ZG$ zRmjWP7ytW5DE&Ww`Ioc*WBHM*2>Ea~`+v5x+5NkA3)}MYY{J`z&Gu$gN7)rTc+hp6 zZ7H4g>Gr2*W~o>W^uOKAX15P_tB1SyY+3>Z;$*y^{qDCvn`sHySMpWn?cKJh?wK>U zHD2EQ_~+I8Pexld1H4ax{AZK2^}}1~N0gxyILq~)d_B5A-8-VB&`w(6MoY~;{ZBrc zRX0Db3ivJWX3r+I=)de)=Y!j2drtt?c5?#E{)a!c}U9lTh*Y~r3@rDJn6$as^;81`|#CCgpnrH7`a7=8j+9PsYC$@Xz|NFbN z_;~+ToAd7Z?0>zQp+;;2ZliL#Z+`lWEQsw5+tliY(T|?b{{7Fr!^o^fPhr@FWlthh zrR)W?RQY`NU;Zy2!OgC105SVN`v*VcEGd`=qZ6u|S>EjXht1X1s@m4JccbscLD0V0 z|2$cAzC^8FRW~}AX8-qp!3lbUX0@BFZ@mIDk|C`=+ z8D-WMGZUvXpD9{oAU zOjU>a)vuqu3mOlc9q5vm{zk-$nmqO>TW2U(b^~9|S;N4@b~aVfBO5&=4+6oNQCucC z!g{ex6Iv_+_)%Tj@PL8OV49M!q~P^EKy7gE_U(M@TT-y;(B>FccbzYP&_N}+`Pc~6 zlJ_wfb;f&R=Rkq|)MMxyylef9{*$ zI*SD5Pg|ns{>5!0yo&<4_Z#q>m`&+_ zQW$?e+%YVVHabiB`6S!zU=hDHRV@1OtGEvCM6LiT_cICuFj7-MEc>uIF~FBSM)h>= zpcb~|)lfeR6F;6&uIZ;TUgUA>1k%buPlpa}<3 zl9`u|Lwh=gN9uC$ke777u#q>N(Z7~$y=}K-Te}#^Uah!iimkxlK&`G+&?5WO7AJhD z5sDl?(!p3n=b^8}+^bWk-?-m9W3C!v+5!G%REx%y^^)9(#`kpeR~UjwR=d&_#D70T zjIjtxF_i5c9F5{)@&7s7%!JJSroJ#?P@k;)Y0e5ek_(TcMAm%cugsKeJj^7IOdKz( zI)>_UA(5)JWGGp%XqH*&`aoZG`b0xe5pm%etf@+fK%YQWVAqd24W%Knec{9U-ovU# z7ge~3r(on)gW|%@P3W{ra_pZ}jVaT9U%Qi^GOPgQ+C#m5ECnK%Z`NZ+W5&|~J0z`b zTL&3mfqkeCPf*yt**5M+wiyK>N>|l6zmfiMCcOeI{q}ATJENhj3iAlu7#C=R>d>kV zi~o~7<}bR{?fl_6nSFL|Mz|4wSdzUiXB(-Y{`TKhKk6fcgPcMiX-AOb41sd(j%*(7 zI2w?Lh)}kQV=S+R3F{gZX#)vY|AK|)1D}}$)E`A@!0~LLV;}#tMkB~IA$Bq&I16E{ z2Pe$cJYnq zK)wZXnmup+jCu1G&JqZ8?C(%jKJyyvlntq>R=TS}B}R|do_|r}yXTCLNO}1qL8O_< zO0By#EWg+UFeKXk6&*uEHI1fcy1%r8j;cx{JOGJg)Teor-@Fr}KiILlUk+Jrf|bki zJBb+R*KE=94)x3>dHrZO6uSh~v$7-)Zx#@%@+XNDjgp&)kP~0=&J5+?6_#%UuQJRK zj~a|4JyhSQBRk9yw@W*xnvj9@m<>#ST9PLN<5MH0rj~k0zQKki42wK64;q%7p65kk zeE3hMV0S#!kQXRjEd@k)GaxU?#cv{t9IEw|O_^l!x7cWSHTiT+{S(Z0H-b>%#3AJq z6RIAJO2)IBeO|18EE({qv?R;&N%mwr*_r|Mn$F*RfE0qpo8=X2hpTlt{S)Jqxs;~~ zCmde!1a9+_W2_27iTRLS8VA)Jan=QH^qJklMYuU%sAI?mHvm3vX--q9Qb-Tr_k((m zDfg2iitld+yN$memRnx#Xp;oz2E>(6KZ{(RWs-x`k%lCnXjfHPR2!_;3pf(54k2MP ztEbjm$uL42cGEP^mOPT(q9iMt>|MMI8AfIDm&ZvT?n_3x)F}-5ER?0Ir(3*tPsou+ ziydW9GnsOWGbT;odk3Yf{=w}d9InPC7T=S|zm?>WEJ{?XmyB%eSv?^NPzqlBCC-X>!8!?jhDwt9vNaSb{$Lv`vF7s5!NpN9!}HD1^|< z%4?i8;5vR2uDFJ6cR6@zd)!J#x-I1{Q?R;ZBZ+`zqLz5D@qL5CKI&O5 zmgMli+7&33VgRZRuzo2C#>_&>p`XTI0bY!F-jNII(R{>wEApLSv&ts#@0BXa3H|o9 z<6(U|SIS{~D%}CR(9Df&neV8YFC1rtP9*I*6hcb#;y(J2PcB#NQtyN$c)lR$l1xG~ z*%CPjhQ&gdma%B+bk_@Qu>oT{Cxs%7=gS*zb(>pqt+ZkS!S>^1 ze%k^W%(rc=)OlmY*0KW`p2U(*pLoE?(UEt4KV>;SRI*?gi0e$FTIQ1UI%O${f!*V; z(|$d(tz)rjgK`{vwbFG|;*8yhg?#8zxM!@9o}^M<=YVAH8SGJAYw@V#!Bv;!jp(=W zR0`08YVVTzM=BP%8}#uSJ`Y+C4D$GMh>xu1QGRhBPo(G)%24jYc_$%QQIxM#wtVR> zHBM)ZR7a|E@P(L5P)@m{ORLX zT9;qGTba?G5pV&)^;I|Ez>sK&JBl0Sod}uL_o=6G;To^`q5}Clj0{g{S*Piw?R}0*ADcu4bqwZE{63@xI)VBdTK=^^@Gb*! zgV6t&SlltVO*daJ@367V7?k{9RY!;AC#Pyrkg^9VS#`Iuc)QW^_fAst($cxmtrTM8 z(Fw76)sC)`T&FBXZqeR9dExf>hc4V|nYb?yT}c8Xy=7}skftLKXLZ?GlBiI3o#LF2 zzDjoorLi)ZV!k7z9>d^k8ze^2Z%1bhRH+(wF}~dvv>BWEpEwgmfqAnK{BzeF!#)wb z+%rt2sKNRDcFyXXDVO6oLiI!Hcs~C+k-7b{CFw?GVV-Y__&sc@6~y@m+tj%Xxs76v z>RF@1Yt_RA6gV}nSb^P~u&y?NeH}VjW0bY!s2D8wD$PP0>VD--3nDHccC#UX4h6R| zWr1@OMFruhb)7lVW!G=6H!lnbgQFvVzhO>7TuDjF_`~C%Y;_IWhI%`%R)i&zZT0y2g#QywaLWn8vlCf_J4#@o2{OuN>MRQ zS*I{pD{>?SysjGx-l#s(4TknbAh|x*W2q(&Gb{#ap>*P~h z6rGrOZE_)y zubgKs3-zjw*zV@#)Zh|ul5=_eGrTqRE3_Wcb<;HUbpGSCTU(NCIJi%tH0r*S^_>h~6-k6fj# zVHZChvVo!1&Q?#e%oJr|=v`A_Nqz5RbNhD*m>ka zD!slmbQin|`TdTy0ft7^jxkgG`YotY)<|DUL_&3%Ei_l6?6BQzqr1JAPj?s%TF-mW zTrS2+;u8_SB&n@6e<5$%&WY@6i=Po7a5FNNv|dJxzZ!3qtr^3^qxKNa_wXc1#1vd7 zMT>g%@U4IgB?Diwx2-V4TYPq}Y&L&yo9RydOeC`)<{e;8ovfazZ z##03bne$UWQ$tig--CVSTSphRRyQp5b z52Wt=5Us24!|E4wV!W3BJ$iO*B;3or=@puEHU@8L|^C-n189afO+#+aoHvno_Hj0J78%CilmhdU0zAj%k^`}w+>LDrpVON`VR$&7S#~NhbnCDfd zx&pyrm#nhp2741nWJJlT?}uefwIqwP<06pgH>qWK!445n&t0iy936OgKnTi8Y$6c% zTJ%<#-j;g1$^E8ugN~B$?9AJUYbeDi>o__c`_n5&0UK>5^T0r#92x;n9if@7>zg-} ztk^&$-*^_PB!}(o$;aBD6U<}Nq_7ik^>}BzV$<8*bueABJ8-Xoqc$yx*vmpz7&mL} z9P*#aCTc&Ej1UNE1pz&Hzo6PQ46BgO5SKDIie~n;@@D>S0caYfuAT=!V`&|Wfa)48 zKL&fQ9x9hI_mFoTn%d>Xv$Z9Z_{y&S;awCMDRhv{8mb=D*hX~^@A(bbWDufMDGH>! zJls=d+={|%*^Xj266F?0Nh!Y$$vx_r;Yvvkq-!*(2#DZ}FISSkz?3RG$@m}XezBv1 zytzqn9mN@;oHUaFF3HQN?n}6qx_nbYAfxGXXSMXE7Sg~8*Z>_E_M7>4TwA}nUC*t6ezXD!fp*+pS>(%uT z*~0cTlT(uWnY}|vkD_^#w$ZgOsQ^(vFc}bJU(Tg_fR;bXUoU?{lf;ImB5ek7Ek$zV zHf~FlQ2*{}#{1dy1Qwa*$Dxr<9f(jl+hswRTV@I9zTn7mwW*OVi@T-nAn_4}kI^$0 zS##rz6cEA_{} zdP#^cgKoK+htSF20(H|ROKhuLNo!m8s>X64yYb`1xCDoT7I$A3tWM6XnoNIgV!mcm zB@i&ai*4l{hwvk<8j`Jn#N@ROaGjN>fv|lx(<+9P;*gVGg~uhB92%~hU1*oN4qc+kVlAERb|=AImfa+sG-!SE*0kF`NsbC#}^tgZ}sqvp+XE$MHB z%~w=AS#F}!1TuH`=rsrFI(_)aXggFMQq;M zl(}J1H`8PoC3Fht+$0!>)f5Odv>Iz=VWNBA-GQ82=b%h3qoO36ja1}><$+b-Zh-=dN)b*NQtFDy$HTKrIb*kr&!BIK^^4kuZ z?gszyZ*_s~=KD&rb=Xz+_zh)pVU#NAqx{dBWLC(Ugs^{r6(OcI#?3tPcG(Bq6du&JN zw!`aKGB9`~B27w=l>@-|cuseuWgOj<;(y*m&2j@|w0h76O~`gG1)s8^b6n-izZAhZ zlugWK^W*Z>KTk|45J~m_1Px$)Q;TdzJDe~5)xobenRH;VAr-1oO_C1%H1r(j4Gwko zK)8o+X?^V1$-ocdN(N0Nfk8p4@w_-^*(f4t$`Jfi;P)re`)_ms2e)g7o83C z_pU9knkrq7+FmfUmcn>HfZ<#KS32?~-nsE4!8=%ZnMj|ip%cWxJYYLfagWyL4^Uw7 z;|7wG@#7`=b{dn-IZJLN|JT*40}%akeh!epsaQkul}4-U!=ouatoO$G*9YK!F~T;? zQ?{ncOq1%G{Z;qFoDxdCyJ|zs{rOjKxqmhvT=y*N4zM>XK%ruUvB$rZ%V|g-4aYp`4VT=x6v5_$H#{3oV zel{E6Lkny6GNy0!iGh;qHG+`c@PWa~r6z<&@FAl6pQ?HD#j zamgjYXt~mBo!0d7 z)4WlUWXMm@K1a#@Iv#ATNM1hiLxN03UF#U%LHRo)K(sW$nnk?ZX~KKie9HOHC=;nb zaX`-fY=HG}VlwU@1aVdjBFh(O(G`2HmhG&Uljd9*;=*FK<^&rxHTvhYRGDJX(Lb0S z*XS~$V+gy}nN*q7YG`71awNL#CN{3acjho2Uf@X=IKlA0JbwX}iIkq6LFV$_s^4n^4$AB_Q}Rf|esjZ%M; zE$=oBwl|7t-l)bqSjvV!OY&pPU(%y1uLF&{jy@M2y`hekQXWZnU_dT|D4-xj%ammi zQ=pUL7+?4iucJMUzTif&mnC^K#TnWqt<@=)FVURopd3kFh2l?Uh;>`-bX{Hq7e0Fb zfBHxpRL8>^2Kjjod-sG$=TL?LGJ*YoG8fHR3Sp6EO%`>m)gb}|l3a*LxutxUWGx|r zIir>_!k7h14t2fiG+;8HttyuQjU6u`$G{J2XP_N_pcN}tJuE+PW4ap25p}<`N>0iQ z`^^Q(wlc95b}j?)Y8+@PH@DE+I8Blih#qsg3nj~a^c2+U^2WA|gl?d^ZY-H8$%m0% zP6Mg;$Y7|yUg`T(>;(;(Z5#q9`Pow#Vb8m zqmCgb{}TfXRwAPcSkif#@+k3-L0n~vHt{UvNt<}m@_)s7u(+${e`9Fs!@%qELT;l! za!rZ*;kxwE2in5o@Wt7{R?F?=3C<}oXd%n!8|dvgdo6~ENjUTJO;K!xm-g2?x~iLq zta%Yo$oD!2F1S?;5LDiOCh!F_W46B7Vt5M^v-rgy2Ad3S=)MfrlEYw1R zUB9tRBOw)!v}|l|FFwV_BNhsHsSzKn4r%3-JVx76+k&|AT~(7W4&rn7&n zvKAfD#BEz5?ajAniW!VA$@d4dP2qWd{JC>_-#fxFd~{>g`r&Mcjg1Kk z=$v<;_`_?K6gwZ}2RwdEa!w@|v^kmB=ExRfx4j~ybXOP^;#m-a&`A^h9**@3QJvPy z=J;Y+yN~y~R);>xtQ4rijqQqmWz8cF$={GKy8fxhpuSfmWedjXI-8M?Pvzyz9oEKK z1!?;x>70^Gr53|glim4NNGHpAAR-K7F9|YJS^z$bPeZ6=V7=s$2U|dFBQg z+Rqx@gEyYxlM8KLaw_+0*^G7Kan~If$<+4Zd&KFOjh#MYJz833yr`8`DhKk~yFFtn zzoc(m?V;w&J|=+*?qCQYVgjcE)fRmwv@$6;e^2_ z9nY_n@5t-fDdyh3fHXGiDQA)HvCL*@_L@j)LRtBS0S#__8a$a9EXUq9Dh@*NEpktW zRDB|IrWSB`2ZYRmO^y<7G&hCMa*P}{F#RVso z=ex5s^QJ9$4AI5t&!Lk=I6w;QF}gD5BfL2GQdWq*P=a>k&DQ8L7;9O>kw z8X|6@R%msV7BYr;p6PCxazM`h}>Aep9QJy#05?V?G-rUw)HO9g3vo&&1jz+VfL+%xx6&j@HPp;Gs1qu`$of z9J?6F3Iv_RiF}4AGItp3SGEbcd&(oDJ;@xT@_xP@O(-j_?@4NVUUxzQ%*?HhZsFzR zgOS^CK#^QS_^ZtyD!tPQ5;P&F6)gF6Mag|nL`iH$yzJ=v)@^{nbw?+Ula1ynE47&v zB{?pSfF##k%t01A@L-9O$IbBd#ov=vKMSg)@9tNwKu_eHdF&}1_%$vr0t@^5k5%U~i~EbQIgBAK|n5N4w45_SMV#FkoE^C}dtu{m;s( zy!UAnZI1kvw`27Hed(~#IGbzZ!%FgNDlly8WGW2AY8``cClar3Yp#I;t&k^qn!2hp zAttD72~MBFn9bKW*4xx}wItiJIE@cX3C_E5<-opqC-~@HN#X;vHzz!B z*(gR<-_H=+syo%?ke9XU!LavGC$^E6+ruHZf{n*0{5J)TW*pK!DRY30EhH4eIJ|>d zvi$508-sV9!*NaRc1CBwZYB9YOrl4!wL6T7asLj6QA6RRz$ZxU$V|nh69WC%qE9Zp z@<7?er#2d;zk_M+MHYZAXt1~MT62N?ndxvzy|WjCtTf2aXc}+HySUd_mjt@ZrYz4)TLw+0GUHVQ(!2I_WT9-eT`ncI}O8 z$&)t4mIl=FbEOaDXLfQOmY1h!854GLn>&$S?of6k_%DZSQJ-%_%kS@nod=&a9}fG! z-(u`Qzx&F#Qw*X(j0RG8GmKYMBB1c0q4UhVDwZuAAe4M{2D1nJK|6FmXmlVq9MuGb z5`R-jFjud`#*E#$ z$Ty%wBTi0UL>$ez2_3!m0+k^@n@J6jy!6#h)a~+d&YwME8vVt9>yU=$Nmd?x*%i+7KBE9_BwLPgZ!rh9}H^om3>m zsLDcSK!r&(mexjj7}Z7Ua*h$@Z3?m#CHVw7N4BY}OauyYg ztPYbN)bd?D+4s0NnqbtckopvX56N%y%T1f)pE{%D9BJ#wEy=De-=q;!<-Op{fi>C; z3Y_=9^?xL2>k`nSwT$LkPkYE+I7vy?pu=!bI~p zNdjpW7JA(o zHdmCkE6a#|JDiFF%^BO_SZ|*5I&8;EJV6F=Q@5aOq@Ye?*hhY>#B5gwOk=r+>3(wG zPL93z(iNddr#~gxdngSif_yhJCVHIi`!j`K@z!i=Htq9Easi%u*n|auIq)H2L;rvC zs|NthF)gHu++i5hUbJGcUo=v-Zqw>bDbrV0uTiGmM{ zw!vbel3a3V2rKL)+@DQ!Tyk_!M`HgrlDNn*i4xkS4ZStT_&;s6_zguOzEm!G(o76j zl8=QUF7^ROUlxqv>BXruXA|>-sXy!xCC(z4>yGXy$-9VzaK}{Zka(3Nf8!z^JL4|3 zr96_F)OP;pw;X{SuxM1NbIb{;DP*rC&zwyuVtTBbT)$aU3Q2FVo*9c{!bGuT&ZL_J z_O-tQko8!kfwgjQLsNxugn-Tg8v@g;2T{K&c7Vce%`FiLl}X%HD16eale{~h7PCDJ zz{-=(N4z-V0Lsy5+y;%b@8*N-(V+2pCxy9u31uVy_N8%@mJijs*2-18H$4Fk$-j9N zff2h7^y;y2Oud?+!vV2|sj~m<=t!ax$78jF2nYcNgJkm6qQ#rZ_DmvNHQceHwU1pd zvm|p|U{p|%mQk)GYAN%b^(aAg9|EhEULu=g)~j$Pdam|3 zx%|ph$SpASF!{|_Gg(F%p1X*n>=7;1o}5}C6X<&&f8RI2tSMEN3lH}x);w{Lvp7K} z*3VrST{UaooEZz2E|M({b)!GDOZUC4{8)ow_VS;N9NF!AvK=YULGt#;Eu;EPVf5&F ze=P8UQ)K$H>isiwzv8;K)fn#nfni*ZH49z{1*!JTHmX^&jTLxD2K}h)q(E*1;x~B= zKobwDv1iDNW`H!u@(5Z1tg+mCKA1CE$Bcv%*I>#+Ah_8(JZ>Uu>}~TygvPE-UCSEZ zf;_q&%8J~SYJdfbe&EbzOItvy1}y28l0ZA0pHVbTpDz48e6G8mHouiAv3N4+&X0dS zRZ4}PtP%dkqaSm?K)F<)5_lr<0r2EsC|K`vg#b~7!G0-x&O zu>6+4f_|t0*H@PvnMO2g#;gnTh!TGuH9eZJisSJtbK(o?=0o1O}B&W2}Sf z#@AkH9%D6=hEZL)cRPYaGLM|@-dUB!kQFq<=v*Yf0~uVof^(0m)22P2OTn+eueem5 zla_$uJRmg4&1~uqW9}`nnLc6- zse!+d)buIeS5gf*DYh-Dp^zy=39yc9~g97CCKyi_G%qNM@%wF5TcV z(s7TN&pjmdD)H|upW+e6IW2;eF&Hg3RWsJZP=%SS7k|-rDtsB%Q!}ngO`V;OLy}81 zEPWsBgt9PoIdvbnfN;2iHL{g^tQ=cS(j(OGacpGIK&38sUhe5-V-BR9E4WN1mnq2~ zE+dp0A)`SwqbIzf%G0P>Zb&pf2hirvQ%_1X#z1hZkY0ALxYs8=F(NmwWRqz+G$CllO(ppV^s^mRAg|upy}fIV zyaT2|i3)_qN5KAt=5?$kKKJ2S=4W$=@cj=m2D=pzFo%#lbSr3T?5Bhhlq|T#&U@aU zF(c0zOe*X0?)ER>9y))*O84r(jzl*{Q}ZO}dhU@CiR#}!B0F6)9k!wQ7YW_^Fv;lu zH?C}GrM5{!;QhaGWzCq%d^<;4YqpvNDtC18UnjDSsY}N=H2#!9zoAHW43oM;JOuT} zOnFP?IXCkOoa}nDGQpv?ve8XyV(xTSek|3(=3pkq$)W7x1YG2dfmP}hKIDXgrb$YJI?3?kD`+O~}GuD~flzDm(Ev-sa zFnX`zE@pGVnCY9eqI^1!W!1>0nzHcD zf~Kth{|QqW`qHwsn<%5q;AwvVw~=>4(0LX#Y5-P*6O3Q^=rNJ&v3F=t`1nk%Oc_k7 z+6%gfd=fKKkP*9*GS@hKYKDvsINLL{%5pigl+nR~T3!1S7TKR5mQWwL-uFNoyVm3o zME-)t5QM20i&*07Fm&h-Xi9)F)ySu}s;8q}tdozl3agd)1-I@$6XqRVyjEkVe$2tJ z?4s$6(FHFh#x|^|TrP&NXyD^n?ojACz~AQduPVvWQ3|~I4PDjhzMNm6M_dod;&r9r zO%NJ_?2?QdR5Fb7r#M6>*ZjL5I`)43{Y2&XNGg4Xt>>R={8}cpVuvM^5sjXVu zr}QKQkllafE6DD(j@Qrtw1H$IXk}R{fA|q2t}@jTozM6JL`)A@^aaI?fk^ z2(SSK?yYi41nvek=;(9V*=@ZoT+`>Ay>9w37?hD9y&Vij$38sYCW3s2oEp_CHdcGg z;+Vv9CvhB7DtxY-&FYHI+buXjqlO_)Q(?OJqp8eH+5R*aD23`=rWx2MhQu%?jcc9Q}ZH@Df4esQVn#v-U@N9uFwvj3+;VGN&< zi!X4ArKX)SlVklF%XW0!kH2IBhKUwRa;ASNlfTHjC-IDS6wRU;p(H2a=M~;rRdWps zn4FqaAiQzls5LYtIUUBTyDD#XEy8I|ImarT2apdAetod~H)c8h*BwL`-@wV!1S?XT zKn3MNk!5O?!g><2v`UvClhQQxELSpo(K@&Gbf-pkQwH8sWh%YZAXl)Z7uop!P*K=h zqy1N_Wo!X22AW5+2nwrXlaT;d`kj^)+4|miTOm7KwUX_Ky>#On`SY_iLctqHhtzxs z;!3B5%EQD|?iJifyHp`ebmr)po0U1#2eAJdWq<(xj%4WcigKm8Vx(Jc@jU|sk8Jv{ zNbmYH!u_*m7{m;xH}g4|z*~~l?A*yq=PaEgGmdpq5^<7|vsXYC6*j$V2d79uSCXo9 zZD6M~jsKS9?K?*wY7)DWJU}|k27dnVFBT?{JsYfc*1BrQ%OM5+GrxDm8AeX6TaF}U zrz|x+VWQ4idLkD&7ihCXK8xcj_B42w6Z27>T`Q8c#WZYkT4-j_p(bM7gLnqPri!;Q zOq)9IqTiI{Gt6!`p>w7$4g}Y$q;_M4O&sy~-Enfl!i6WvpZ=(=Nz``huzAPP$W86J zS$w}^jpGSiEKF9FUY)A*|#VMa@$`{7_ z6}P@Hi}x`Arw*lbOxKYV{;Ycqn_r^QJ4Z_4iLIyLYh(4s;rbyOb|}gnSj5q~&dgUU ztl`y%5~#W3%?023mOBOd_&zAoe_Axg<(r(i+4YI6u^z0aF1pfbU;)-$gN%ecN^9(ca z?X(ptx7U?vX$ZlKnc5)yi39Y~-+TZ9qO;!{0$#P4g~x9gbK}lvk^I9;B5g505t) zqtxX7bKP)BCX)W{qSXXXLiYIuz|fpVXAemmULzY6gW8zC&Wz=b&f4%=W7hwMpduh) zKmI~&jgi-+K;s21t`2fv+}=l-s1^MM>@`{8UruB)55R?{o=!Hf3!3C*pm+(6sF`swNwl28P+ zzFvxnt*1NYE-et>Tw86^g8^ayx?YxQ>`x=VS>YZg3}tqK@dFY(qk4tJaAb6w&Z5T0 zF18`^R$RW;UFOXdi}z~|RhZFn5u-zj=hrmez43{IHJv!I{YR}fc4g9szWEhtotnIV zc4C!H^}MUcO4rtu|SVfnsn*7KQEk24&VrrzqVhe`Zp;ohoi=ZbG9$rd(alnZ4ErFAwvuaS3v`XK;oV zpfFM+En7H_34KfEwU?LAIBCvexiiyfSg<;uyvE6yY;`=yP{;epBGNuO_QcMS3`PCh z{t4ez>t8A7-Gmok+oyl$pvvKnO2=@AuY5}ZCx>+Zn%AgyYm!bUw3i{O<*ii6z!Lg= zy)*U&jhYVt z5{`e_&rKoV@M5{Ur7krxH%g#z-NIV1~;Duq0#yH)yAQWn>zBB_hA-T zdeVVfEy|dT6Uo+DUGNyC#iNWo98+NLr1pf;$tu;#Da#|ehT*(dpOpMezJ%rOjy-76 zy-thr81_M@oyp*i7z8IjB!l!rP`a6cM@dKN^bO=b%^?-vvLLtgvnEC~dKd-YR+ygq zdXBn|j0&V_)~) z@9KN6qxvTu(wbPrJzMzj0%N@AU-fB*JLTe&4AtPly>2MWl&U0!8qAttb{tMeUaO_s z{gvt(H&X1+RQ|^4zUR&9I55F3wGtc5{4jOhdoK`lrmd|g zXZSdO*NUC@A(JH_| z%?i!ot7*(UyXs^%)_msPER>5f(o^KDu5Py0{G3qjWt>Jy zj)$77QZgnpVe!>2%A_+2>qo7wh1qD7;h8YI`TD9jUbg)op%}h4!K+L6(7?!GUG9Ce z@fc9$^; zMb1<>A4=cNziMMUA&TpflON4*rmbYl4kN!P_Y#>AAw6T(8m&4*A52tof0+!l&He4N zsSV?78?Q}o#akskOJ(8GC32Hy%TN!q;12|I+KnLhm(||M6VK>`FB2rWiEp6UgTJUsv>TyZlD(F+%9vU)V0(3V9zj+AY}#8&@;?ZO zmg+oTPgL{%IHyK_AAs+T9@#t0mOUuw1V+16hYml2M)-w}mGh>lICV1fIVoj)gl05l zEQ5>Boa&Hl?8b@?S4*H*l8^4q zGKZ<$Cib858rvtNG1E1W!IM>>l4!Qd!tXD}cq_8MGufa`Km`7_y=fEK5PmjG# zrS0jb^ujimjDuxu;??pY-^nLa9g*F#(hX|mIch!Ljz~tqX2?@}BZniSx+%=Urt_OK zxkf63auPNA7M>bcm>+=$%`C|*+$g*vqw-uR`%O?;eXzHtl-F=iT~?HV8EP3C>Fbi* zL~<#V-^gnnb61((vLt=@ESpld9O$)!xZ%teSQVS8?aTd=7r3zm>m-qt^y`%;6Q3mPH+9S8>>V%|sMcR+d9Eso?phvgz7(1k-4IR&JerrZjo zV9STmu7-4UXdFlPXu0xzC~{5@@H@O@eE~xdqt56` z43RQ63l9iog2WrrA1Wvc)5wj)*l~;8T);$d$&;?u5xJ|2LUD}3vEViZ>@h(Yn1nuX`2U&J*vm#H>4MDlj6*yVrO(0vMxD{1~=2ba_wz5_}MKGtDAbYZf%AWQOYCWcQ81%GQ zfqxO%-4pJ~-0AaakbjEc?%WCJYqbev<+=vs2}mn@Tr<^LA%J$tIGW*f+pI-y3TS+! zAJTlK+zkz6DHa<=p+>hP`;+p5Nw4(6sjuj$bXhv!r_>TUr{@Jk%MVOw7LR&%+($s? zO>>r4E$A~+0gsE04DTrPj^K6iXkdgJE4Q* z-?nuLA+Kh4Ptd|kcZFP*BceyFtr|*p2Gb)KF|4g>8RC*0gey6I>5Rp*sb(qhE zBqr){Jf>C2Po2UkpinSgUfE+Z9v35708k~w!>vM11U@Om-P=2XT4jnalF`$`tPP%AN&bqIlZBT{c}sc4+CxNfB^CApzQ?ZFy4 zB%AllZCCtCn>aO2UI~$ERcjay;sb)axUR9SyJ;8la~CCf1r@_u`|eM?QF|Gc>^;1V zvpF@D^D_E@VUUj>P*O7d+ai9D36uiY;?=g%_W!!DgjJ5l`zU|=uj^Nb9_qv3*k6b**#Wl_>K zI%et!5<#vYQML;4jW1N%moUmgOx|CI6x(xUsmy=`esJ8THccCmgjjG;>StTR;Z0pp z%6YVuHZ`RmHrR}Bw6&7It+l19b_`4XQ4>5pk5dQKboUOd07qQPq+AY->14{RRUUr~ z?T<&AIo%A$IqXVt1IfuD(r4vfo39$sM?`U?kxxPD^WnQGf~EhkMoM_XewKub#<#kX zsxZgTYe2&fO_CdHuS`ERE9Z<{_A6;NF86C37fTT9eXhKiv~f`c>UHZ$2#2PP&+3+O z4xe0zdUkceg0+CrC7E|oTBj%zDbTmW2Q3FKZ&yw%i4O_#AH@FKqzNhi)@wL*kj|X^ z`QuE~^ELW%-9+XmR{J`8hUB7U_Q^&cp37Q!`<2(56PM$ZTl!n#aDeo3aZu-UqQ*7rv>3)Sh#SpV=I4o1r>w%0sWH#Sv| z@TtffNx?+2Ag|m%F{TZa$o!;!C9j4&wj17;H+La>g>Yq9?${}=>V4B=+c_*{i;z{_ zy(repSwQ=wzISSKX0CsCy_`17WR)u2>hy_YfM_N8&l@Pc8lak0j<0D5R9`7y+TOiI zBO<4R0!EDZaJa@X1udpUyRfubzDn|6^!}SmtXI$C5Z5a(j~ey|E0zt{g852V9vcwz zw-8=e*K~m7lLh22x{mGq;m4zWwqekKeKZEEu8-Q53En43wfPV*{2Thn()(7?R9J_l zmD|aDoular>KYjy8LG9Y=GM_qmi8VyOAd_1}jshe7u**4*4NJBbg0VN4|H(l}S5Dd(RcMGm7 z3?hrQuTfRLu*A2;gLR=B^faC~K7n-6iYIUI0J|}={wG9f6FHJNGZNK3L%}A!@<|1Q z=+bH}LuxLkDy&A@iRo^P=H!rzk!sYwH6=aA+f73{rG@p3%~wJ6>YA$KZE50(Q#-Vw z#lL$tR8J`*ei$>NsfH*I_N=XggL=zD0|UcS-L(6?(OwDufd5guD&yrn{p2nA8-zb5 zQTy%OEKQ(G7{Keg4qW9q$*S<eEZn;d`uIJh%KCL9#C3tfrE{|Gs*2@h`Y&Aq z{~SxW>hQpz^z&yACoRt&R1l!E zMmVuk7@ua&75U7{I3DR2cKH?t)N~>$#Yxr^}U9vXX!5V|#(v zmwf|L$s+#-U1}I_w&$WDFuUNBcILHt-`-kxzwE*n8SPy|hlAKp=0_~l+xR1@I=+>s zcIC)t^S72e?X~6# z^t$Gdy`_0e*dnLYlT8VJFOKn~m7s3~X?5eG&*vJQZe!IP2SJxJxQ+Tmxm*{F!8oSU zde=|$11q+d>vrJ_wff)ycFxIA2U4$LAtMYqCiG^m%~w;4`6a%pCS(3fF!6KG+{sf=&mu=7-t-b%Gq}^=J<(;Y6Z87)@4p-BKUBru@kAqPbQ5z~mo;46 z-7ZM4?9AhG*;Vq?UOXwfq9YIJhEJ5sJ}FypcZHeMjt|N+JT>#bYF%_ug&Yk42^0+C=Ot+GHbFa|2xpayrzD)4h#bGS>mA*Q*XeuID0NWG+LR{We5O z&1Gd5E;C*pxMaMnfpdR+I;*J5%Y!2x8f-e2Q-2uF3swD4!gE#3?al&e*U9%>`~ux0 zU`}>?wmto{Y1z0&!GtRn(SRgBA}Yzxj?pU)LMWM9{Ov^zmPjtZHq7lOB$abp-h3T0 zp}#`*O_V)we@jhw#2;}TB6j#!wdvaltqZ{9((x(vBv&W)VEh2DYG z?BR+Pm;|7s?uT1Gzw6Wrr4ia|I`T@9IrA4SIkmia;ld^51q)}-k-J!p4(e}uLHHx+a5X) zx*!W|Z7TBFWbawTqOGrR(FXFb@Y*F_GJSxOtmIx1MdHdF9%FNWmWZJ(!Nc3KRxT^q zywOWRxHh@>%H&bCI@iBaHf}G;l`Xff@zbwIzT$^-cWQ6;zu@PPRBe&1STs| zXTQsnEWOX=>o6E4`3e{IDUo9OW2Cp2(|g%>1s3{*%UEU20$HE9cFru=jQ2ujv`J}u zze)1p7JENG?GV+3nKLaD!eiw;z8^?ilEv(*F9va*0)m1#V>~xwV=vn`UOSn6kUf{Y z;y6=>-htKCA+_+LbEzY{Hzt8R5bqkS+u>8?Rl8;`VepG{r0^N0f|IP=XzT2UbZ=7o zYPP6_h20sU$OI*}_`9o-BQOi%aw0;Bo@3iU9C8Jgq|pQx7^#16FoKP`yA=wiYXsd( z<5bIT=W&OHf=&4#YT-+seZsF ze68)CHyjOiZ|9@E1Twb3a?;4lH}RP+h}sY95Jgw3QQ{#T(AYuCrZDod51*Bs^0f_#D(h!?F8UTuee35|fq^Q2C$wRH3l|1Uc^$4v2=Jc2#9X_s3$ z{p+-8b9+063--c*Le{uAN07KbI^;&TCheJ)x+gG-dQExxJ_aP@dQ{T&*C91-ol{}0 zvPrWCMz8^MVC^bxJhB}&@GL*~*2T-gMtGZGww&~)-65}1^IRuoj7U}BOx@H}xmOj5 zLSFXWDl62!T*&4%ZK=wSHyi$sfWEiFLprq7*kkjSW|v0j4PTko@3=EKbV+oJY1DVl zsrYW&@BwXBDSVu*agL!l6EkzLS2Wh6B$sbYUG@fXHB#xp;zkt7bFzC-{JPtLwPH<+ z49YAdv|f_)k{R3`$Iv3>{S-MA2`J}!&{FDc_dwa4c`7J+&LJ9T+4 z7Ijp<0*UfYg-#A6T_2(@?U;tq@J;fFd?S6VxhWw=Y>bt=yF5poMFMr^+WV!V)1nK0XS>As^gT}Z>&97~w zyoNc#yLbaw80j$u9TXkdfxo)o*+B!fKcC_$ocWUZ?6Xp`c_CY2RVQ*ji*3M5 zW&@Zk zc_7-a5PF}T0W&wQJ-AzWWLh8PC8$|`3ASU>H;u9X;+G$c7p?%YUHz^awxmkM80mEafbyt3e@ZD#0X zeISxgha)K&2VmN^n%~aS@5-$h&f;R|bG9Ab4u)VsEoZPD*r%**Pt9zOSO+cQZ5+e0 z)d9G&v*bL(ubLvQ0%{{q;r7E`Ac-#`Gp5VI*0ci}l9L1v1><>!-qqet!eS~n<0OAM zk6Rz4MU9#ldrl8%KFABT z1&lf_7hbqkETHO71iFm%^t)fMPbP`7^F+SIyb8HZzpm%979zaQ@oK(M_%J@~2}tF| zM>#9*qeyhc(*i{nAgMgMHLG#47zSbcwQ2yF#^1Tzf%KnjW>afa-^(KEDjCp!fPb{Y zXsPT!#TCgn?!gzDgm#^6zE=)7YwVXRvs{9)S1J*a7+foD>c@JjoRC{FXIVAhpy@H= zP+cr%(sUfY5J74_OznN}7J5{cW$y^t)jbaK;rK|l^AWlYkK2N(NBZ*-mTA3IFGRxa zUX#rVzPjDut>F;ajc1PG0(hW<59g$y4p0_$C$)CP%!#2_&JbsP`BVyB9v`D%jP6XX zLwdhLZFafWGr6BRVzW9M6d(s# zAN`en0q*TXRFimvGQIA;4!L>@ivZDSO7fWop1jOnc!s3+V`xpXzj2sAa<`Q`_9xXO_CFi1a zF2vRC-2%CcGQ{8HHO%lkrhe^K8lGCKmZyJ~V>8#KqHgf`Y;-8!K%NvAS!e10@+@Y- zP4%zSYb!JAh%0$YpVS%i5>Xc$dXnaampnLLmR>tf{^Kd$4i;=gJEl%OLf@)$aurbAi9u?Ly;!(mqh6t$%a4u~H4e%gNLzhIy|Y$Z-oy9m zP%za}7>MV8y38h{c-E(=7Yc&u6Si2Gc~|KEgBzVA`6Pw=IP$FL#_krKX`!x$10t zY-OP!sCuQ7l2$L$6WQ(wBS&LnkG&O1(*~)`V=d`eS!FpXZizRj;9;3NqYLZ(H!W&) z9zh+T-11`g1eg+kA(nC4G;r{=Y4bFXbwYK`BootlJVs<`Gq>HKhxx~YD*sBq^wy}P z>UuJkyDUyKe_{beNp}4b+L%q;xRtOM2*>L#JG>k32YrDw zaeUxc6{e4L^xCCn2dU*VC0WG_nd?>Eaz#IvGIb!y1fR!uLpJUj%wtC{_kpPDljDPg z$bLU&Q7B8}I#obRuguy*b$eBL^5DSg!w-{v_+VrL>jABz;Yq+_gYN}C7 z%tY4Plw_B`I>q#L0iEZ0^r0ULoJuprdxpZIIHlWAXAt z7%RGMS+cqF@m4j(O>@plw)TM6sxF<5W-ec49k!t);ZY5yz+9ktq#QnL@=J=1+QQD^ zj$UWcE~S9djUS-7h404Kb>Va)Hb^j8}!eT19sn&6=-1YDAYuSg}>XEj}_we#VBmMI9 z3O-0-2*XrY5uWwQ!1$)yBtp|ZJQRebt#6QGk|TEE!)&eABI+ix0W?Ucksj#l8|W`n znK%Trpf*Pbvu(}tyAnd$iP)8(ktP=C;3?plRSou%o z9d4duQ8)ZC1jii8l7)v)K3c9uBeZeMt&r1*6!o}&&vG1}U&QGBb-xt188BV1?@}3r zW+SokYjQ709T_~|B7>HK^Fr4Utf=wCD)?#0C5g)oH+R z?)~p&(@A5fJqJnLcM^s=shx4V*MRaG-|7v3j}>)8dq6U5xT{6Et&h#4lI#yGI7%Eo1QC|H+)e|jbmA|28J{oZEoP`yO&{5cQoJ+$JYH&O~$2;@m&myUOnkGQbsQUhL zABgA#O2WhvT%GZ>Eh`u^e#njhk)LWhbZl-_EpPs=uCjL z`8a`znQn7;uV5U9P9B#xXB}5?HyM!L+GmXbhRpTZ6fPCpr$>!HIK}K5GbjFjtpusk z0PuY0|8)%xJLFEC*S>Zc?-!gWo`#cph9I3-H7~lEpOxezr=rG8Zj!4fYf#Pp><^y; z2#^`q=|*%_%NRd7|7s7SY<#ZVQw>`ur50#)X04xkW9knlvp6+eJT)twyaw7k$npoc zBZE2WZr|B%5rU;bth%gc`*b*$b{ZmUa`W5#>O0_(%EZOP{6dT9d$k9ORQVfj_Mc2k zG)Jpv*&TPUjBAtUN_}-x2pM9stS$GeUd*RFnw6O`K>#^m42!P%aHwMU;p$+W$$!JE ztL*Al2^<<88PvvO08uAe6pD<>a0Av!)rG^SWcXo5Qqt8Jum*^&cf) zM&dZN2-BFu_@d7{UK>6p+kZiUXQD zMY=D?(4x_G`SAz5_NqO+9>UfIhFDJH?Y_;*gc_Qu`QX@XEm}y0gN_-F&1EL`q0P@L zW~!055IZ~Y%+qj)eYECs3J|7Qs@4N0W`h5c+>)XXv-@Xa6)H6}S_3M%b#ISyr^-9o z7p>Qsfi-toT_ReXWQa|uvS1c17_1^aGqvUd($ys``(SUBFn2yo?)W~AkIwF)>hSPd z`S644nUoeJ?2xKQ!SW?8c1qjqGAtm)KI1qcBJQx*IQ&Zj60(5H`Ns+kF zj@)y56UcPe$u5vXr0i4(*d`xI0|R08P{5o907Dx20#wt%8q~r+nAyHif&kF$sMy3~ zJx31QIAs;i&z|^*}0dq407xX+;duJasqm&1*^8 z1Psh3StHNFUKLXDeh)%!V%juaiJ^X@*7}i?5rsa}rY#s)fVg&*V2Kt#wXt^M2w0GwBVfJp_JpDz=$>S!>za75?5#FPCFOly!}ei*+m3*%>{E;v7~LNi`8+x(-BnG*C*4s3gBhe(V)KF;Ucw**j{^_6Wm5XCidE9(y6;P*eYfG5{b*#fBP zmZL+KVp&;AVWHt9dS_Dd%xy+96oOKlf`?J3p(#gZm;E9D9v6COM+)W{7qKr;$bnt$ zxl~*9;Dg~Ow(R8|YC3Pn<=7KqZDlgSo&7`Ivdh0Id-QRirHdY_t=~a>po)gnkk3*m9ZCZ{9Q?Y{$#9_E*_b$Ccs6oNg%YO zI>guul{1%N%@l^{1gSb_nDIsQ?+PAWFJwabx+F7eiBMhNyNTP7_3w=dJ2eutqamm_ zjtN2W6auZ6TQhhdzliGte{`U3v2rRyvI}a|v7#<}qg~8%f%IW?k+z^wzZ&N787??> z!V#xOM)Q5KUZ|VT`nJ_l9jggHl$#?Ox zYNQNBErXEvxji=#NOr!WAzR>Y(M0qmk9(QNRhiUTEZ2Z^6_2StGXp@l>E{N?(peE+ z4{zTovR*kELr*=c2j2EP5r!C7q?=%`h2wU~#rqN6=7^;sXh@Cn1oeOo(VBWz^gwGR z)H0Xko#4Y!u8D;%$+HiD-Qj)89jo=gVC{HOB3N`}u#q2NWg4JeuH{A^)Dd^tLdJMK z6?b|&;cb9Z?`*k0^`VRqgO)NYr7lK33kb_(f}9Y12uMotaNq&9Lx=1;R+DiuyW7Ad zHZEJHs-)nF+-D{@>r+T3mgE~5**7d1(-MQY}l8sY}?R zH~I9DG7X?iEqFH!^5cLqU)$n&lcoTuf4Y{?uI?I?Pl8LdN<#kYjoe{qsAH`xCm>(C zWbV=BStra`TwdNbd&vp%2S8kAhvhA}Rs7X}R#$5cVlu_T);98}9Y|g(^Y&W<+f5E4 z@*uH)kk`#XsiE8L92R*72aVILb*+_onkT8EGb}kL1?m`!kB_Q5?kTh=j;>N{6AaejU+2lZiFo)S^OR*fg$!UM%t$jtg@M_pcf^)H+c zH_o2Oj9)1z(T!=#gtAdu@dP{c(mR9b=Tveg#T1;Tginn#?zU*}%f;;*w_@ur`=eyU zBxXg+{mffrbs6^5(Jwbp0;dpJi3T%6bkdDt)GV@B+c1iq9jjHlzj2c=3r{2n(=yM7 zFz4Kk3dL>F3h{rAEIH+sGlxj44-E9`G_R_By@f?gDK2%Ei-9$X5!c$91fCR_YwZ^^ z2lA0K8w{F0(fyF8$$*ofXK|`_%QxQ*;tcW^tdAZ(E)!9#DGtQ^CFrYA+%;Jip*Bs$r zHxpH4K7c?{Vx#~;J_CA0v#f{r4XKA!Vxc4t>#GjS7ama4g7GKDU~mlw!PIqI~k&Y6)MyFnVM?r^&lZl+063eiRB`ni?E7=o8iff zluDD!A*hHkr+Uh7jlM@}IFk^zgO^M~AryVYywC=YTcl0!lMw^hEqb>MVfy5 zVz+x?oeX%hvS#aDf5uycgn=_qX|}@sdsboTntrt;U0%~&nbb3^ooy~#s)_pdu+nCD z4Rh|6kP2E@Z>++P5h=YW2_@p1?5n z*Y0+t#}Rqx61()&_JuGvD$P{)aS`yqA{ZNxDbt!oK5duyB{e}vsgEXq8qyJ&>dKIT z`U)I(3OTc&B54ni>E3?kBSJYJ3vOzvs{9gN;8Dtilfd=uphc=&?Q}YhSVc)Kqahyx z9Yl&h7Rivs**g2EzKgOY|{|K8NGu&9n?(JI^{|jMtui)!&A;gxP>%?pH#Ol zSv|14V{IsC;XIAo+-H-DG5dIPACX+yM)nL?-wV@ecni^^nl?=!tsaoQa2TP=2d`!| zQAdCjv72?y52Eu^?V@}+Ls^*zf}(#7@$yo)5EK6zzkq!p$+OH=?mkMQZi^(aBF6o> zZ_mL2LIzshzpJ>r5e;=2&{PV|%;#r7#}OyH8V8NIX3XMn*Yd1+Guqqb+w3up&_zDG ztl=qr%}-zk)hPFT6G5o-OQupsH^X49Lj9I865-#)erh@;H zy#L%B3DOd@Mc6uL-rR~cqg7_q4O7=lvy~R9-KXvl>LK>3$I_d9CMUUf05f37*&DueC`2&%i zlJ63IvD)%>7gmS*DJ?PFh*jg`gQ$7d8Uil7o$IG#zJs+eUOCM6hH^zY{4H8;=Sl*il}XiC;y5+tTJS@h z|FB$zYs!uux`16y3TEW*;7yZqGjp6H3K$7vi~bvd)3dXGJ307;rHd9twQpxL#T!~t zF6ZTJ4y3=v3l+om=$J^i-;Gg@2gp}rj>)3CsbeMSP51(oQ2HubyzD5TDPBKtYR68P zLfY#}9r0nMq#wtTxxs!G!=0NaV(XW1ZAubydT4Nh1!8|$ zLq-q*_ddw{K*U{c30>!6D>VSriL$>`e(A=^gJB2#Vr%YX7H`)Unl6unMChcXx~^R1 z>@4=nYz;=DBv;)NbdiUUPwxa+R=6hpr>~TC+T51&T{Q^rOYoeA;9k300J=NDuGwdh?*zJ56?et?%&gLr(vr1lcB)(T+pyOm-GWxgG3AJOE=so!=p-C8*rRzc0UKf6^T$<`_FSeQ8Xe=qd#75XBMtW32WgEq2`J zZNR+$hTpV!Fksa~u+JJ+XHQ#O_v*X7<|<^fuCIEW42c@p*UzgKl`%aH@6yz}eh-lW zQEF<@4ksdpOp__^vVctP>{dG6hK_gRc-~K{F)o1mi%)yHgGLVd6*64IA#IPXvYH($ z273+Y)bW?z{$`I6MVxR`dSsmZC#W{&tmLSPJT#{(K?{(r8R}C`hGFNMXRvgxv|p-V zH9q0+q45)@`MxDXfV=hRO;@j|RW&`7z(dxJ^Mj-L8GVr=B79=9eB zar@ZM$^&qmdMeNtrfIN1Lzj(>nvr%a(W7(~(e;pUR8S@_}HXFGEtW&{jw*UmwAq`AmsIumf0t)ljeUdH#Z@ z<|wrXw;Poa(T5po;V;t26`^l5Bn9fvzlZ2+|lYk zAg#5FbwC!cMtB*a;R|H`1KgaP3}Wa!L-+E=^3aYtaO=8@H<$J|iQIms+JYWRt#xr9 zr72Q#_0GIsu)2W_G_$2;y*@m-gC*pdrq|45o?Z0ulDy|ME!ky#>9C$6*YXrrYX#$8 zUOhm_e@)|8r;{HGcew?P)Vo;oz%D~;fUD)p|(QXwcWojmBAQx;90yF@-1 zU62JxE_lR|{>}88PxA~zdMKJMh&6C*$xVNOc!te;;kzg#ZTKC)s!x>#iG^<2^4C4;B?^%k6zFAzrx1-d4m44yQ+VGJZxfxr<}H* zJ*6_N^%~#X6}M~>sJ}d+!~bJon1{NG#a_u6gnrrgY?HL0Ohaq~Z>rbeUG*wIXphuO z+s{6N`hz`FWa(hGmt}W1dm8`Z$2QpB-^gCtPC7Y05LH4X-4{Q(B@ZpXL8Q13@?vUn zQ6jYV&)*+m3*o-K7gi#OWktpE$?#n#`@eAStwPLu--x+SH5L0eAT>;hX@vXyxKlEp zP`N&YxAxC(+BJYpaB9I77iI2`0QayvEYCZ3Hf@?LFFe&>P_M7HWOC^B(Wb1La?YivJvjS z!+i5FLMVk*Xzs zQPHQF>Y_Iwku)k&*%r>ze45ABXH8te-)ed%Bt{>t^W<3HdU|CUuV%PamZ7Wtoa1@; zYwYtJq{!#D*ox2VI0wy!B$vFCFDZ_crTZsuQK_Lx$MVPo;8pcZ@-?>^2#8+kwCoG> z;hWPh59?-VA)>bq!+No)W&a@h;M))|C8ooEeg7iAcgioy54!dD{$4l5_p)oh9m$$q zTg58Kukab{6(7~>{sb8*W1o8Lb+2`nx=Su)Llr{GGYGM_M`qYpv^jIYY~P)b7A{zJ z7Jr-FS;!g&dS6>_fB8z{hE(ql*}*>3BVRc&+6G;#iioW%{h*kjWrhT0b>{E!7&%5^o2KgSa`HQB7PF?8o z4ySP{z9@JXgGr|rJm?L_gK#GLfgz^St_i!1mFB2Uz)jd)hWr;fv6~%eQxL9}vvw=c z72ySP`^nGOY#T=(M#t|?M@p>;k0-D&q-pQqk;$6Q0vw|Srz@Gd@DxdAyMz<)Lh7j* zJCO_-LRy0^A0tjbLl^bg+FZ%DAViE7mm@n9UsHxWmo&$}pAAs5FBr+XEJTLr(qZL3 zP99Ri>tH}*Y9GYG#y*<*1C!?Lo=mI1z;Kx3h8l|7VcVlv8 zEs}b;-J>0EqipywT35PRz20GLXOUarRXKZKk|^0;dX(NAN~?$Y;;FFf;yKPWv1qu? z*6kj2?Bx0gVjUO(FDMojhwEUcRHjbQ8<>$^Yr*ZxC;;PD>|->YkUi&ZWHT+On?;!v z1m6!n4`aystnGrInK7EQ(^!D)$-Z3QwqmO>l7)z-A6O~ z8nIQpj-)nQwY8_3egp$?8x@Hl)Q`{Un+O*LDL=f7-{iGz2G-BnCs3Na$GQ%2VU_#& z3g=JXrAflicQ#TRA^p|hJH9-)!79Kv4$PMjOOxxPiCXZyQyDJl`LsQa7?X=t;@;U? zgz5=4>4n7WYXMI2*=~mvc(Sy0D6orr$Bn@kb0zy3X^yg3s zLm#BIv$E>V@U?R0*CK$GYyx+L#XJd*-j4neP4|hyR~X{Fqz_|!k;`*9zHN8}{qwNh zO2hFT%*Xjkk}v=TMFGCr9Z4NDq(1FTspwGX%ko^%L&4mTkd^;K*>0ICe`>=Zti zxQU-Ghkh3Dk7HHFD!p|B7*EkJAnU}O9fT;R^{_5f@d`|=7;QsvWFvt}qV}Juv_g39 zpo`S9)`mI12WJXLAnBv=vI@1k8m_JO#}RHMlJ2+lPHTTXDiEcnBbQKFn11{fT&Cs_ z?Ys-247Il>SW`Cs`#OH_8`sXkG@9ePKZ-y(%fnX(WryXUBg)c8b0=*uiD%b--}XB3 zME!pI5}&D=tM~gnWZ2xb;&p=TADvN{BL#%GQFWmD`ye~;7x%u5$k;|1&k|`cmd6XZ zyH_O#HsZB5EFU*mc_<=Dr6V%n%Q#V*XXwoaua07U$$m_^9EpPeaKUI7G2Tcee ArT_o{ literal 0 HcmV?d00001 diff --git a/lib/runtime-c-api/wasmer.h b/lib/runtime-c-api/wasmer.h index d2c9e2f15..f0cee98fd 100644 --- a/lib/runtime-c-api/wasmer.h +++ b/lib/runtime-c-api/wasmer.h @@ -23,6 +23,8 @@ typedef uint32_t wasmer_value_tag; typedef struct wasmer_import_object_t wasmer_import_object_t; +typedef struct wasmer_instance_context_t wasmer_instance_context_t; + typedef struct wasmer_instance_t wasmer_instance_t; typedef union { @@ -41,6 +43,11 @@ void wasmer_import_object_destroy(wasmer_import_object_t *import_object); wasmer_import_object_t *wasmer_import_object_new(void); +void wasmer_imports_set_import_func(wasmer_import_object_t *import_object, + const char *namespace_, + const char *name, + void (*func)(void *data)); + wasmer_call_result_t wasmer_instance_call(wasmer_instance_t *instance, const char *name, const wasmer_value_t *params, @@ -48,6 +55,8 @@ wasmer_call_result_t wasmer_instance_call(wasmer_instance_t *instance, wasmer_value_t *results, int results_len); +void wasmer_instance_context_memory(wasmer_instance_context_t *instance); + void wasmer_instance_destroy(wasmer_instance_t *instance); wasmer_compile_result_t wasmer_instantiate(wasmer_instance_t **instance, From d31c1c60685f6467283ddabd7d2baf92bee354cc Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Sat, 2 Feb 2019 18:07:37 -0600 Subject: [PATCH 009/262] Fix lints --- lib/runtime-c-api/src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index db01f7fe6..74b039132 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -176,8 +176,9 @@ pub unsafe extern "C" fn wasmer_instance_call( } } +#[allow(clippy::cast_ptr_alignment)] #[no_mangle] -pub extern "C" fn wasmer_imports_set_import_func( +pub unsafe extern "C" fn wasmer_imports_set_import_func( import_object: *mut wasmer_import_object_t, namespace: *const c_char, name: *const c_char, From 5d9e05c2f699fea75523ad487839800f99ce8e4b Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Sat, 2 Feb 2019 19:10:08 -0600 Subject: [PATCH 010/262] Add function signature parameters to set import func --- lib/runtime-c-api/src/lib.rs | 25 ++++++++++++++++++- .../tests/test-import-function.c | 4 ++- lib/runtime-c-api/wasmer.h | 6 ++++- 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index 74b039132..445aa8262 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -183,6 +183,10 @@ pub unsafe extern "C" fn wasmer_imports_set_import_func( namespace: *const c_char, name: *const c_char, func: extern "C" fn(data: *mut c_void), + params: *const wasmer_value_tag, + params_len: c_int, + returns: *const wasmer_value_tag, + returns_len: c_int, ) { let mut import_object = unsafe { Box::from_raw(import_object as *mut ImportObject) }; let namespace_c = unsafe { CStr::from_ptr(namespace) }; @@ -190,10 +194,15 @@ pub unsafe extern "C" fn wasmer_imports_set_import_func( let name_c = unsafe { CStr::from_ptr(name) }; let name_r = name_c.to_str().unwrap(); + let params: &[wasmer_value_tag] = slice::from_raw_parts(params, params_len as usize); + let params: Vec = params.iter().cloned().map(|x| x.into()).collect(); + let returns: &[wasmer_value_tag] = slice::from_raw_parts(returns, returns_len as usize); + let returns: Vec = returns.iter().cloned().map(|x| x.into()).collect(); + let export = Export::Function { func: unsafe { FuncPointer::new(func as _) }, ctx: Context::Internal, - signature: Arc::new(FuncSig::new(vec![Type::I32, Type::I32], vec![])), + signature: Arc::new(FuncSig::new(params, returns)), }; // TODO handle existing namespace @@ -257,3 +266,17 @@ impl From for Value { } } } + +impl From for Type { + fn from(v: wasmer_value_tag) -> Self { + unsafe { + match v { + wasmer_value_tag::WASM_I32 => Type::I32, + wasmer_value_tag::WASM_I64 => Type::I64, + wasmer_value_tag::WASM_F32 => Type::F32, + wasmer_value_tag::WASM_F64 => Type::F64, + _ => panic!("not implemented"), + } + } + } +} diff --git a/lib/runtime-c-api/tests/test-import-function.c b/lib/runtime-c-api/tests/test-import-function.c index eecacc347..c96ae38f9 100644 --- a/lib/runtime-c-api/tests/test-import-function.c +++ b/lib/runtime-c-api/tests/test-import-function.c @@ -13,7 +13,9 @@ void print_str(int32_t ptr, int32_t len, wasmer_instance_context_t *ctx) { int main() { wasmer_import_object_t *import_object = wasmer_import_object_new(); - wasmer_imports_set_import_func(import_object, "env", "print_str", print_str); + wasmer_value_tag params_sig[] = {WASM_I32, WASM_I32}; + wasmer_value_tag returns_sig[] = {}; + wasmer_imports_set_import_func(import_object, "env", "print_str", print_str, params_sig, 2, returns_sig, 0); // Read the wasm file bytes FILE *file = fopen("wasm_sample_app.wasm", "r"); diff --git a/lib/runtime-c-api/wasmer.h b/lib/runtime-c-api/wasmer.h index f0cee98fd..c10859f2f 100644 --- a/lib/runtime-c-api/wasmer.h +++ b/lib/runtime-c-api/wasmer.h @@ -46,7 +46,11 @@ wasmer_import_object_t *wasmer_import_object_new(void); void wasmer_imports_set_import_func(wasmer_import_object_t *import_object, const char *namespace_, const char *name, - void (*func)(void *data)); + void (*func)(void *data), + const wasmer_value_tag *params, + int params_len, + const wasmer_value_tag *returns, + int returns_len); wasmer_call_result_t wasmer_instance_call(wasmer_instance_t *instance, const char *name, From 6f7db9062d32581285ba828cffc31f51c6f7a3fb Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Sat, 2 Feb 2019 20:16:53 -0600 Subject: [PATCH 011/262] Run cmake tests as part of a rust test --- Makefile | 1 + lib/runtime-c-api/README.md | 6 ++- .../tests/runtime_c_api_tests.rs | 37 ++++++++++++++++++- 3 files changed, 41 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 4a700f222..62bf5d05b 100644 --- a/Makefile +++ b/Makefile @@ -40,6 +40,7 @@ test: # cargo test --all -- --test-threads=1 $(runargs) # cargo test --all --exclude wasmer-emscripten -- --test-threads=1 $(runargs) cargo test -p wasmer-spectests -- --test-threads=1 $(runargs) + cargo test -p wasmer-runtime-c-api -- --nocapture release: # If you are in OS-X, you will need mingw-w64 for cross compiling to windows diff --git a/lib/runtime-c-api/README.md b/lib/runtime-c-api/README.md index 7792a8c17..02ba9a705 100644 --- a/lib/runtime-c-api/README.md +++ b/lib/runtime-c-api/README.md @@ -4,5 +4,7 @@ Run `make capi` from wasmer project root directory ## Running tests -`cmake . && make && make test` from runtime-c-api/tests directory -(TODO run this within a rust test) \ No newline at end of file +The tests can be run via `cargo test`, E.g. `cargo test -p wasmer-runtime-c-api -- --nocapture` + +*Running manually* +`cmake . && make && make test` from the `lib/runtime-c-api/tests` directory diff --git a/lib/runtime-c-api/tests/runtime_c_api_tests.rs b/lib/runtime-c-api/tests/runtime_c_api_tests.rs index f9112c83c..b605da49e 100644 --- a/lib/runtime-c-api/tests/runtime_c_api_tests.rs +++ b/lib/runtime-c-api/tests/runtime_c_api_tests.rs @@ -1,4 +1,39 @@ +use std::process::Command; + #[test] fn test_c_api() { - // TODO run `cmake . && make && make test` + let project_tests_dir = concat!(env!("CARGO_MANIFEST_DIR"), "/tests"); + run_command("cmake", project_tests_dir, Some(".")); + run_command("make", project_tests_dir, None); + run_command("make", project_tests_dir, Some("test")); +} + +fn run_command(command_str: &str, dir: &str, arg: Option<&str>) { + println!("Running command: `{}` arg: {:?}", command_str, arg); + let mut command = Command::new(command_str); + if let Some(a) = arg { + command.arg(a); + } + command.current_dir(dir); + let result = command.output(); + match result { + Ok(r) => { + println!("output:"); + if let Some(code) = r.status.code() { + println!("status: {}", code); + } else { + println!("status: None"); + } + println!("stdout:"); + println!("{}", String::from_utf8_lossy(&r.stdout[..])); + println!("stderr:"); + println!("{}", String::from_utf8_lossy(&r.stderr[..])); + if r.status.success() { + assert!(true) + } else { + panic!("Command failed with exit status: {:?}", r.status); + } + } + Err(e) => panic!("Command failed: {}", e), + } } From 6185eb73a8821896ded619245eafaab464b1cd97 Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Sun, 3 Feb 2019 12:14:14 -0600 Subject: [PATCH 012/262] Configure cmake to find dylib/so/dll wasmer library --- lib/runtime-c-api/tests/CMakeLists.txt | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/lib/runtime-c-api/tests/CMakeLists.txt b/lib/runtime-c-api/tests/CMakeLists.txt index 7d47da19c..b8ad14445 100644 --- a/lib/runtime-c-api/tests/CMakeLists.txt +++ b/lib/runtime-c-api/tests/CMakeLists.txt @@ -4,11 +4,19 @@ project (WasmerCApiTests) add_executable(test-instantiate test-instantiate.c) add_executable(test-import-function test-import-function.c) -target_link_libraries(test-instantiate - general "${CMAKE_SOURCE_DIR}/../../../target/debug/libwasmer_runtime_c_api.dylib") +find_library( + WASMER_LIB NAMES libwasmer_runtime_c_api.dylib libwasmer_runtime_c_api.so libwasmer_runtime_c_api.dll + PATHS ${CMAKE_SOURCE_DIR}/../../../target/debug/ +) +if(NOT WASMER_LIB) + message(FATAL_ERROR "wasmer library not found") +endif() + +target_link_libraries(test-instantiate + general ${WASMER_LIB}) target_link_libraries(test-import-function - general "${CMAKE_SOURCE_DIR}/../../../target/debug/libwasmer_runtime_c_api.dylib") + general ${WASMER_LIB}) enable_testing() add_test(test-instantiate test-instantiate) From 358c306ceaa07bb3d57d188003561b086e350bda Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Sun, 3 Feb 2019 12:33:42 -0600 Subject: [PATCH 013/262] Add runtime-c-api as external project to build dependency --- lib/runtime-c-api/tests/.gitignore | 3 ++- lib/runtime-c-api/tests/CMakeLists.txt | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/lib/runtime-c-api/tests/.gitignore b/lib/runtime-c-api/tests/.gitignore index 30324d55c..2e8c46610 100644 --- a/lib/runtime-c-api/tests/.gitignore +++ b/lib/runtime-c-api/tests/.gitignore @@ -10,4 +10,5 @@ compile_commands.json CTestTestfile.cmake _deps test-instantiate -test-import-function \ No newline at end of file +test-import-function +rust-build \ No newline at end of file diff --git a/lib/runtime-c-api/tests/CMakeLists.txt b/lib/runtime-c-api/tests/CMakeLists.txt index b8ad14445..ea9cfd84e 100644 --- a/lib/runtime-c-api/tests/CMakeLists.txt +++ b/lib/runtime-c-api/tests/CMakeLists.txt @@ -4,6 +4,21 @@ project (WasmerCApiTests) add_executable(test-instantiate test-instantiate.c) add_executable(test-import-function test-import-function.c) +include(ExternalProject) +set_directory_properties(PROPERTIES EP_PREFIX ${CMAKE_BINARY_DIR}/rust-build) +ExternalProject_Add( + wasmer-runtime-c-api + DOWNLOAD_COMMAND "" + CONFIGURE_COMMAND "" + BUILD_COMMAND cargo build + COMMAND cargo build + BINARY_DIR "${CMAKE_SOURCE_DIR}/../" + INSTALL_COMMAND "" + LOG_BUILD ON) +add_dependencies(test-instantiate wasmer-runtime-c-api) +add_dependencies(test-import-function wasmer-runtime-c-api) + + find_library( WASMER_LIB NAMES libwasmer_runtime_c_api.dylib libwasmer_runtime_c_api.so libwasmer_runtime_c_api.dll PATHS ${CMAKE_SOURCE_DIR}/../../../target/debug/ From fa959fa6ee78b5f1a0f972653bbe85eb4b9e7d08 Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Sun, 3 Feb 2019 13:21:59 -0600 Subject: [PATCH 014/262] Call cargo build during make test to build C API lib --- Makefile | 1 + lib/runtime-c-api/tests/CMakeLists.txt | 15 --------------- 2 files changed, 1 insertion(+), 15 deletions(-) diff --git a/Makefile b/Makefile index 62bf5d05b..4c3618e80 100644 --- a/Makefile +++ b/Makefile @@ -40,6 +40,7 @@ test: # cargo test --all -- --test-threads=1 $(runargs) # cargo test --all --exclude wasmer-emscripten -- --test-threads=1 $(runargs) cargo test -p wasmer-spectests -- --test-threads=1 $(runargs) + cargo build -p wasmer-runtime-c-api cargo test -p wasmer-runtime-c-api -- --nocapture release: diff --git a/lib/runtime-c-api/tests/CMakeLists.txt b/lib/runtime-c-api/tests/CMakeLists.txt index ea9cfd84e..b8ad14445 100644 --- a/lib/runtime-c-api/tests/CMakeLists.txt +++ b/lib/runtime-c-api/tests/CMakeLists.txt @@ -4,21 +4,6 @@ project (WasmerCApiTests) add_executable(test-instantiate test-instantiate.c) add_executable(test-import-function test-import-function.c) -include(ExternalProject) -set_directory_properties(PROPERTIES EP_PREFIX ${CMAKE_BINARY_DIR}/rust-build) -ExternalProject_Add( - wasmer-runtime-c-api - DOWNLOAD_COMMAND "" - CONFIGURE_COMMAND "" - BUILD_COMMAND cargo build - COMMAND cargo build - BINARY_DIR "${CMAKE_SOURCE_DIR}/../" - INSTALL_COMMAND "" - LOG_BUILD ON) -add_dependencies(test-instantiate wasmer-runtime-c-api) -add_dependencies(test-import-function wasmer-runtime-c-api) - - find_library( WASMER_LIB NAMES libwasmer_runtime_c_api.dylib libwasmer_runtime_c_api.so libwasmer_runtime_c_api.dll PATHS ${CMAKE_SOURCE_DIR}/../../../target/debug/ From 6ed72a50ce9e38caff10050276774aa46b60b25e Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Mon, 4 Feb 2019 19:49:28 -0600 Subject: [PATCH 015/262] Add instance_destroy back to test --- lib/runtime-c-api/tests/test-import-function.c | 6 +++--- lib/runtime-c-api/tests/test-instantiate.c | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/runtime-c-api/tests/test-import-function.c b/lib/runtime-c-api/tests/test-import-function.c index c96ae38f9..c6d723664 100644 --- a/lib/runtime-c-api/tests/test-import-function.c +++ b/lib/runtime-c-api/tests/test-import-function.c @@ -39,10 +39,10 @@ int main() assert(print_str_called); - // TODO review import object ownership, instantiate moves it + printf("Destroy instance\n"); - //wasmer_instance_destroy(instance); // TODO error here + wasmer_instance_destroy(instance); printf("Destroy import object\n"); - //wasmer_import_object_destroy(import_object); // TODO error here + //wasmer_import_object_destroy(import_object); // TODO update instantiate and try this again return 0; } \ No newline at end of file diff --git a/lib/runtime-c-api/tests/test-instantiate.c b/lib/runtime-c-api/tests/test-instantiate.c index 4ad4c1ec7..bd6a35004 100644 --- a/lib/runtime-c-api/tests/test-instantiate.c +++ b/lib/runtime-c-api/tests/test-instantiate.c @@ -39,8 +39,8 @@ int main() assert(call_result == WASMER_CALL_OK); printf("Destroy instance\n"); - //wasmer_instance_destroy(instance); // error here + wasmer_instance_destroy(instance); printf("Destroy import object\n"); - //wasmer_import_object_destroy(import_object); // error here + //wasmer_import_object_destroy(import_object); // TODO update instantiate and try this again return 0; } \ No newline at end of file From 2defd27fac4a68af44ab1d39a56b9971216bfa11 Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Mon, 4 Feb 2019 19:54:12 -0600 Subject: [PATCH 016/262] Also generate C++ bindings --- lib/runtime-c-api/build.rs | 11 ++++-- lib/runtime-c-api/wasmer.hh | 71 +++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 lib/runtime-c-api/wasmer.hh diff --git a/lib/runtime-c-api/build.rs b/lib/runtime-c-api/build.rs index 40398c2f9..bc8ad1af6 100644 --- a/lib/runtime-c-api/build.rs +++ b/lib/runtime-c-api/build.rs @@ -17,11 +17,18 @@ fn build() { use cbindgen::Language; cbindgen::Builder::new() - .with_crate(crate_dir) + .with_crate(crate_dir.clone()) .with_language(Language::C) .generate() - .expect("Unable to generate bindings") + .expect("Unable to generate C bindings") .write_to_file("wasmer.h"); + + cbindgen::Builder::new() + .with_crate(crate_dir) + .with_language(Language::Cxx) + .generate() + .expect("Unable to generate C++ bindings") + .write_to_file("wasmer.hh"); } #[cfg(not(feature = "generate-c-api-headers"))] diff --git a/lib/runtime-c-api/wasmer.hh b/lib/runtime-c-api/wasmer.hh new file mode 100644 index 000000000..161a9f90e --- /dev/null +++ b/lib/runtime-c-api/wasmer.hh @@ -0,0 +1,71 @@ +#include +#include +#include + +enum class wasmer_call_result_t { + WASMER_CALL_OK = 1, + WASMER_CALL_ERROR = 2, +}; + +enum class wasmer_compile_result_t { + WASMER_COMPILE_OK = 1, + WASMER_COMPILE_ERROR = 2, +}; + +enum class wasmer_value_tag : uint32_t { + WASM_I32, + WASM_I64, + WASM_F32, + WASM_F64, +}; + +struct wasmer_import_object_t; + +struct wasmer_instance_context_t; + +struct wasmer_instance_t; + +union wasmer_value { + int32_t I32; + int64_t I64; + float F32; + double F64; +}; + +struct wasmer_value_t { + wasmer_value_tag tag; + wasmer_value value; +}; + +extern "C" { + +void wasmer_import_object_destroy(wasmer_import_object_t *import_object); + +wasmer_import_object_t *wasmer_import_object_new(); + +void wasmer_imports_set_import_func(wasmer_import_object_t *import_object, + const char *namespace_, + const char *name, + void (*func)(void *data), + const wasmer_value_tag *params, + int params_len, + const wasmer_value_tag *returns, + int returns_len); + +wasmer_call_result_t wasmer_instance_call(wasmer_instance_t *instance, + const char *name, + const wasmer_value_t *params, + int params_len, + wasmer_value_t *results, + int results_len); + +void wasmer_instance_context_memory(wasmer_instance_context_t *instance); + +void wasmer_instance_destroy(wasmer_instance_t *instance); + +wasmer_compile_result_t wasmer_instantiate(wasmer_instance_t **instance, + uint8_t *wasm_bytes, + uint32_t wasm_bytes_len, + wasmer_import_object_t *import_object); + +} // extern "C" From 8d8dea7ec8babfe728888d4ce1e6d68bf6672b8a Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Mon, 4 Feb 2019 21:46:47 -0600 Subject: [PATCH 017/262] Implement basic C API memory functions --- lib/runtime-c-api/src/lib.rs | 65 ++++++++++++++++++++++++-- lib/runtime-c-api/tests/.gitignore | 1 + lib/runtime-c-api/tests/CMakeLists.txt | 4 ++ lib/runtime-c-api/tests/test-memory.c | 23 +++++++++ lib/runtime-c-api/wasmer.h | 20 ++++++++ lib/runtime-c-api/wasmer.hh | 20 ++++++++ 6 files changed, 128 insertions(+), 5 deletions(-) create mode 100644 lib/runtime-c-api/tests/test-memory.c diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index 445aa8262..a8f4d1278 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -7,10 +7,11 @@ use std::slice; use std::str; use std::sync::Arc; use std::{ffi::c_void, mem, ptr}; -use wasmer_runtime::{ImportObject, Instance, Value}; +use wasmer_runtime::{ImportObject, Instance, Memory, Value}; use wasmer_runtime_core::export::{Context, Export, FuncPointer}; use wasmer_runtime_core::import::{LikeNamespace, Namespace}; -use wasmer_runtime_core::types::{FuncSig, Type}; +use wasmer_runtime_core::types::{FuncSig, MemoryDescriptor, Type}; +use wasmer_runtime_core::units::Pages; #[allow(non_camel_case_types)] pub struct wasmer_import_object_t(); @@ -37,6 +38,14 @@ pub enum wasmer_call_result_t { WASMER_CALL_ERROR = 2, } +#[allow(non_camel_case_types)] +#[no_mangle] +#[repr(C)] +pub enum wasmer_memory_result_t { + WASMER_MEMORY_OK = 1, + WASMER_MEMORY_ERROR = 2, +} + #[repr(u32)] #[derive(Clone)] pub enum wasmer_value_tag { @@ -64,9 +73,16 @@ pub struct wasmer_value_t { #[repr(C)] #[derive(Clone)] -pub struct wasmer_memory_t { - pub ptr: *mut uint8_t, - pub len: uint32_t, +pub struct wasmer_memory_t(); +//{ +// pub ptr: *mut uint8_t, +// pub len: uint32_t, +//} + +#[repr(C)] +pub struct wasmer_limits_t { + pub min: uint32_t, + pub max: uint32_t, } #[no_mangle] @@ -74,6 +90,37 @@ pub extern "C" fn wasmer_import_object_new() -> *mut wasmer_import_object_t { Box::into_raw(Box::new(ImportObject::new())) as *mut wasmer_import_object_t } +#[no_mangle] +pub unsafe extern "C" fn wasmer_memory_new( + mut memory: *mut *mut wasmer_memory_t, + limits: wasmer_limits_t, +) -> wasmer_memory_result_t { + let desc = MemoryDescriptor { + minimum: Pages(limits.min), + maximum: Some(Pages(limits.max)), + shared: false, + }; + let result = Memory::new(desc); + let new_memory = match result { + Ok(memory) => memory, + Err(error) => { + println!("Err: {:?}", error); + return wasmer_memory_result_t::WASMER_MEMORY_ERROR; + } + }; + unsafe { *memory = Box::into_raw(Box::new(new_memory)) as *mut wasmer_memory_t }; + wasmer_memory_result_t::WASMER_MEMORY_OK +} + +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub extern "C" fn wasmer_memory_length(memory: *mut wasmer_memory_t) -> uint32_t { + let memory = unsafe { Box::from_raw(memory as *mut Memory) }; + let Pages(len) = memory.size(); + Box::into_raw(memory); + len +} + #[allow(clippy::cast_ptr_alignment)] #[no_mangle] pub extern "C" fn wasmer_import_object_destroy(import_object: *mut wasmer_import_object_t) { @@ -82,6 +129,14 @@ pub extern "C" fn wasmer_import_object_destroy(import_object: *mut wasmer_import } } +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub extern "C" fn wasmer_memory_destroy(memory: *mut wasmer_memory_t) { + if !memory.is_null() { + drop(unsafe { Box::from_raw(memory as *mut Memory) }); + } +} + #[allow(clippy::cast_ptr_alignment)] #[no_mangle] pub unsafe extern "C" fn wasmer_instantiate( diff --git a/lib/runtime-c-api/tests/.gitignore b/lib/runtime-c-api/tests/.gitignore index 2e8c46610..789a20e67 100644 --- a/lib/runtime-c-api/tests/.gitignore +++ b/lib/runtime-c-api/tests/.gitignore @@ -11,4 +11,5 @@ CTestTestfile.cmake _deps test-instantiate test-import-function +test-memory rust-build \ No newline at end of file diff --git a/lib/runtime-c-api/tests/CMakeLists.txt b/lib/runtime-c-api/tests/CMakeLists.txt index b8ad14445..ee7b10970 100644 --- a/lib/runtime-c-api/tests/CMakeLists.txt +++ b/lib/runtime-c-api/tests/CMakeLists.txt @@ -3,6 +3,7 @@ project (WasmerCApiTests) add_executable(test-instantiate test-instantiate.c) add_executable(test-import-function test-import-function.c) +add_executable(test-memory test-memory.c) find_library( WASMER_LIB NAMES libwasmer_runtime_c_api.dylib libwasmer_runtime_c_api.so libwasmer_runtime_c_api.dll @@ -17,8 +18,11 @@ target_link_libraries(test-instantiate general ${WASMER_LIB}) target_link_libraries(test-import-function general ${WASMER_LIB}) +target_link_libraries(test-memory + general ${WASMER_LIB}) enable_testing() add_test(test-instantiate test-instantiate) add_test(test-import-function test-import-function) +add_test(test-memory test-memory) diff --git a/lib/runtime-c-api/tests/test-memory.c b/lib/runtime-c-api/tests/test-memory.c new file mode 100644 index 000000000..0201a36c1 --- /dev/null +++ b/lib/runtime-c-api/tests/test-memory.c @@ -0,0 +1,23 @@ +#include +#include "../wasmer.h" +#include +#include + +int main() +{ + wasmer_memory_t *memory = NULL; + wasmer_limits_t descriptor; + descriptor.min = 10; + descriptor.max = 10; + wasmer_memory_result_t memory_result = wasmer_memory_new(&memory, descriptor); + printf("Memory result: %d\n", memory_result); + assert(memory_result == WASMER_MEMORY_OK); + + uint32_t len = wasmer_memory_length(memory); + printf("Memory pages length: %d\n", len); + assert(len == 10); + + printf("Destroy memory\n"); + wasmer_memory_destroy(memory); + return 0; +} diff --git a/lib/runtime-c-api/wasmer.h b/lib/runtime-c-api/wasmer.h index c10859f2f..168918638 100644 --- a/lib/runtime-c-api/wasmer.h +++ b/lib/runtime-c-api/wasmer.h @@ -13,6 +13,11 @@ typedef enum { WASMER_COMPILE_ERROR = 2, } wasmer_compile_result_t; +typedef enum { + WASMER_MEMORY_OK = 1, + WASMER_MEMORY_ERROR = 2, +} wasmer_memory_result_t; + enum wasmer_value_tag { WASM_I32, WASM_I64, @@ -39,6 +44,15 @@ typedef struct { wasmer_value value; } wasmer_value_t; +typedef struct { + +} wasmer_memory_t; + +typedef struct { + uint32_t min; + uint32_t max; +} wasmer_limits_t; + void wasmer_import_object_destroy(wasmer_import_object_t *import_object); wasmer_import_object_t *wasmer_import_object_new(void); @@ -67,3 +81,9 @@ wasmer_compile_result_t wasmer_instantiate(wasmer_instance_t **instance, uint8_t *wasm_bytes, uint32_t wasm_bytes_len, wasmer_import_object_t *import_object); + +void wasmer_memory_destroy(wasmer_memory_t *memory); + +uint32_t wasmer_memory_length(wasmer_memory_t *memory); + +wasmer_memory_result_t wasmer_memory_new(wasmer_memory_t **memory, wasmer_limits_t limits); diff --git a/lib/runtime-c-api/wasmer.hh b/lib/runtime-c-api/wasmer.hh index 161a9f90e..7e1d72b67 100644 --- a/lib/runtime-c-api/wasmer.hh +++ b/lib/runtime-c-api/wasmer.hh @@ -12,6 +12,11 @@ enum class wasmer_compile_result_t { WASMER_COMPILE_ERROR = 2, }; +enum class wasmer_memory_result_t { + WASMER_MEMORY_OK = 1, + WASMER_MEMORY_ERROR = 2, +}; + enum class wasmer_value_tag : uint32_t { WASM_I32, WASM_I64, @@ -37,6 +42,15 @@ struct wasmer_value_t { wasmer_value value; }; +struct wasmer_memory_t { + +}; + +struct wasmer_limits_t { + uint32_t min; + uint32_t max; +}; + extern "C" { void wasmer_import_object_destroy(wasmer_import_object_t *import_object); @@ -68,4 +82,10 @@ wasmer_compile_result_t wasmer_instantiate(wasmer_instance_t **instance, uint32_t wasm_bytes_len, wasmer_import_object_t *import_object); +void wasmer_memory_destroy(wasmer_memory_t *memory); + +uint32_t wasmer_memory_length(wasmer_memory_t *memory); + +wasmer_memory_result_t wasmer_memory_new(wasmer_memory_t **memory, wasmer_limits_t limits); + } // extern "C" From 309246e0d6c7ffc68643de682a316e095429ecf1 Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Tue, 5 Feb 2019 00:01:01 -0600 Subject: [PATCH 018/262] Add validate function and test --- lib/runtime-c-api/src/lib.rs | 11 +++++++++++ lib/runtime-c-api/tests/.gitignore | 1 + lib/runtime-c-api/tests/CMakeLists.txt | 4 ++++ lib/runtime-c-api/tests/test-validate.c | 22 ++++++++++++++++++++++ lib/runtime-c-api/wasmer.h | 2 ++ lib/runtime-c-api/wasmer.hh | 2 ++ 6 files changed, 42 insertions(+) create mode 100644 lib/runtime-c-api/tests/test-validate.c diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index a8f4d1278..98c00e196 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -85,6 +85,17 @@ pub struct wasmer_limits_t { pub max: uint32_t, } +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub unsafe extern "C" fn wasmer_validate(wasm_bytes: *mut uint8_t, wasm_bytes_len: uint32_t) -> bool { + if wasm_bytes.is_null() { + return false; + } + let bytes: &[u8] = + unsafe { ::std::slice::from_raw_parts_mut(wasm_bytes, wasm_bytes_len as usize) }; + wasmer_runtime_core::validate(bytes) +} + #[no_mangle] pub extern "C" fn wasmer_import_object_new() -> *mut wasmer_import_object_t { Box::into_raw(Box::new(ImportObject::new())) as *mut wasmer_import_object_t diff --git a/lib/runtime-c-api/tests/.gitignore b/lib/runtime-c-api/tests/.gitignore index 789a20e67..76d5a7d2e 100644 --- a/lib/runtime-c-api/tests/.gitignore +++ b/lib/runtime-c-api/tests/.gitignore @@ -12,4 +12,5 @@ _deps test-instantiate test-import-function test-memory +test-validate rust-build \ No newline at end of file diff --git a/lib/runtime-c-api/tests/CMakeLists.txt b/lib/runtime-c-api/tests/CMakeLists.txt index ee7b10970..d682bfe3b 100644 --- a/lib/runtime-c-api/tests/CMakeLists.txt +++ b/lib/runtime-c-api/tests/CMakeLists.txt @@ -4,6 +4,7 @@ project (WasmerCApiTests) add_executable(test-instantiate test-instantiate.c) add_executable(test-import-function test-import-function.c) add_executable(test-memory test-memory.c) +add_executable(test-validate test-validate.c) find_library( WASMER_LIB NAMES libwasmer_runtime_c_api.dylib libwasmer_runtime_c_api.so libwasmer_runtime_c_api.dll @@ -20,9 +21,12 @@ target_link_libraries(test-import-function general ${WASMER_LIB}) target_link_libraries(test-memory general ${WASMER_LIB}) +target_link_libraries(test-validate + general ${WASMER_LIB}) enable_testing() add_test(test-instantiate test-instantiate) add_test(test-import-function test-import-function) add_test(test-memory test-memory) +add_test(test-validate test-validate) diff --git a/lib/runtime-c-api/tests/test-validate.c b/lib/runtime-c-api/tests/test-validate.c new file mode 100644 index 000000000..689cf50f2 --- /dev/null +++ b/lib/runtime-c-api/tests/test-validate.c @@ -0,0 +1,22 @@ +#include +#include "../wasmer.h" +#include +#include + +int main() +{ + // Read the wasm file bytes + FILE *file = fopen("sum.wasm", "r"); + fseek(file, 0, SEEK_END); + long len = ftell(file); + uint8_t *bytes = malloc(len); + fseek(file, 0, SEEK_SET); + fread(bytes, 1, len, file); + fclose(file); + + bool result = wasmer_validate(bytes, len); + printf("Result: %d", result); + assert(result); + + return 0; +} diff --git a/lib/runtime-c-api/wasmer.h b/lib/runtime-c-api/wasmer.h index 168918638..26b343e29 100644 --- a/lib/runtime-c-api/wasmer.h +++ b/lib/runtime-c-api/wasmer.h @@ -87,3 +87,5 @@ void wasmer_memory_destroy(wasmer_memory_t *memory); uint32_t wasmer_memory_length(wasmer_memory_t *memory); wasmer_memory_result_t wasmer_memory_new(wasmer_memory_t **memory, wasmer_limits_t limits); + +bool wasmer_validate(uint8_t *wasm_bytes, uint32_t wasm_bytes_len); diff --git a/lib/runtime-c-api/wasmer.hh b/lib/runtime-c-api/wasmer.hh index 7e1d72b67..37400cea9 100644 --- a/lib/runtime-c-api/wasmer.hh +++ b/lib/runtime-c-api/wasmer.hh @@ -88,4 +88,6 @@ uint32_t wasmer_memory_length(wasmer_memory_t *memory); wasmer_memory_result_t wasmer_memory_new(wasmer_memory_t **memory, wasmer_limits_t limits); +bool wasmer_validate(uint8_t *wasm_bytes, uint32_t wasm_bytes_len); + } // extern "C" From aa90a33501a57850a8728672a8c92624f2798284 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Fri, 8 Feb 2019 14:19:58 -0800 Subject: [PATCH 019/262] Make module info store FuncSig, not Arc --- lib/clif-backend/src/module_env.rs | 5 +---- lib/clif-backend/src/resolver.rs | 6 +++--- lib/clif-backend/src/signal/mod.rs | 8 ++++---- lib/runtime-core/src/backend.rs | 1 + lib/runtime-core/src/backing.rs | 26 ++++++++++++++------------ lib/runtime-core/src/error.rs | 18 +++++------------- lib/runtime-core/src/instance.rs | 20 ++++++++++---------- lib/runtime-core/src/module.rs | 2 +- lib/runtime-core/src/sig_registry.rs | 16 ++++++++++++++++ 9 files changed, 55 insertions(+), 47 deletions(-) diff --git a/lib/clif-backend/src/module_env.rs b/lib/clif-backend/src/module_env.rs index 8a26b2731..de625cc23 100644 --- a/lib/clif-backend/src/module_env.rs +++ b/lib/clif-backend/src/module_env.rs @@ -62,10 +62,7 @@ impl<'module, 'isa, 'data> ModuleEnvironment<'data> for ModuleEnv<'module, 'isa> /// Declares a function signature to the environment. fn declare_signature(&mut self, sig: &ir::Signature) { self.signatures.push(sig.clone()); - self.module - .info - .signatures - .push(Arc::new(Converter(sig).into())); + self.module.info.signatures.push(Converter(sig).into()); } /// Return the signature with the given index. diff --git a/lib/clif-backend/src/resolver.rs b/lib/clif-backend/src/resolver.rs index 315bd154a..034f0f540 100644 --- a/lib/clif-backend/src/resolver.rs +++ b/lib/clif-backend/src/resolver.rs @@ -201,7 +201,7 @@ impl FuncResolverBuilder { pub fn finalize( mut self, - signatures: &SliceMap>, + signatures: &SliceMap, ) -> CompileResult { for (index, relocs) in self.external_relocs.iter() { for ref reloc in relocs.iter() { @@ -263,8 +263,8 @@ impl FuncResolverBuilder { }, }, RelocationType::Signature(sig_index) => { - let sig_index = - SigRegistry.lookup_sig_index(Arc::clone(&signatures[sig_index])); + let signature = SigRegistry.lookup_signature_ref(&signatures[sig_index]); + let sig_index = SigRegistry.lookup_sig_index(signature); sig_index.index() as _ } }; diff --git a/lib/clif-backend/src/signal/mod.rs b/lib/clif-backend/src/signal/mod.rs index eab9e62e7..0767f9527 100644 --- a/lib/clif-backend/src/signal/mod.rs +++ b/lib/clif-backend/src/signal/mod.rs @@ -137,11 +137,11 @@ impl ProtectedCaller for Caller { } } -fn get_func_from_index( - module: &ModuleInner, +fn get_func_from_index<'a>( + module: &'a ModuleInner, import_backing: &ImportBacking, func_index: FuncIndex, -) -> (*const vm::Func, Context, Arc, SigIndex) { +) -> (*const vm::Func, Context, &'a FuncSig, SigIndex) { let sig_index = *module .info .func_assoc @@ -167,7 +167,7 @@ fn get_func_from_index( } }; - let signature = Arc::clone(&module.info.signatures[sig_index]); + let signature = &module.info.signatures[sig_index]; (func_ptr, ctx, signature, sig_index) } diff --git a/lib/runtime-core/src/backend.rs b/lib/runtime-core/src/backend.rs index 9b5ec049e..f69ef2361 100644 --- a/lib/runtime-core/src/backend.rs +++ b/lib/runtime-core/src/backend.rs @@ -23,6 +23,7 @@ pub use crate::sig_registry::SigRegistry; #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum Backend { Cranelift, + LLVM, } /// This type cannot be constructed from diff --git a/lib/runtime-core/src/backing.rs b/lib/runtime-core/src/backing.rs index d81e33065..46f1fe982 100644 --- a/lib/runtime-core/src/backing.rs +++ b/lib/runtime-core/src/backing.rs @@ -14,7 +14,7 @@ use crate::{ }, vm, }; -use std::{slice, sync::Arc}; +use std::slice; #[derive(Debug)] pub struct LocalBacking { @@ -172,10 +172,11 @@ impl LocalBacking { table.anyfunc_direct_access_mut(|elements| { for (i, &func_index) in init.elements.iter().enumerate() { let sig_index = module.info.func_assoc[func_index]; - let signature = &module.info.signatures[sig_index]; - let sig_id = vm::SigId( - SigRegistry.lookup_sig_index(Arc::clone(&signature)).index() as u32, - ); + // let signature = &module.info.signatures[sig_index]; + let signature = SigRegistry + .lookup_signature_ref(&module.info.signatures[sig_index]); + let sig_id = + vm::SigId(SigRegistry.lookup_sig_index(signature).index() as u32); let (func, ctx) = match func_index.local_or_import(module) { LocalOrImport::Local(local_func_index) => ( @@ -210,10 +211,11 @@ impl LocalBacking { table.anyfunc_direct_access_mut(|elements| { for (i, &func_index) in init.elements.iter().enumerate() { let sig_index = module.info.func_assoc[func_index]; - let signature = &module.info.signatures[sig_index]; - let sig_id = vm::SigId( - SigRegistry.lookup_sig_index(Arc::clone(&signature)).index() as u32, - ); + let signature = SigRegistry + .lookup_signature_ref(&module.info.signatures[sig_index]); + // let signature = &module.info.signatures[sig_index]; + let sig_id = + vm::SigId(SigRegistry.lookup_sig_index(signature).index() as u32); let (func, ctx) = match func_index.local_or_import(module) { LocalOrImport::Local(local_func_index) => ( @@ -379,7 +381,7 @@ fn import_functions( ctx, signature, }) => { - if *expected_sig == signature { + if *expected_sig == *signature { functions.push(vm::ImportedFunc { func: func.inner(), vmctx: match ctx { @@ -391,8 +393,8 @@ fn import_functions( link_errors.push(LinkError::IncorrectImportSignature { namespace: namespace.to_string(), name: name.to_string(), - expected: expected_sig.clone(), - found: signature.clone(), + expected: (*expected_sig).clone(), + found: (*signature).clone(), }); } } diff --git a/lib/runtime-core/src/error.rs b/lib/runtime-core/src/error.rs index b72c74242..ec9c5e772 100644 --- a/lib/runtime-core/src/error.rs +++ b/lib/runtime-core/src/error.rs @@ -1,7 +1,6 @@ use crate::types::{ FuncSig, GlobalDescriptor, MemoryDescriptor, MemoryIndex, TableDescriptor, TableIndex, Type, }; -use std::sync::Arc; pub type Result = std::result::Result; pub type CompileResult = std::result::Result; @@ -42,8 +41,8 @@ pub enum LinkError { IncorrectImportSignature { namespace: String, name: String, - expected: Arc, - found: Arc, + expected: FuncSig, + found: FuncSig, }, ImportNotFound { namespace: String, @@ -117,16 +116,9 @@ impl PartialEq for RuntimeError { /// Comparing two `ResolveError`s always evaluates to false. #[derive(Debug, Clone)] pub enum ResolveError { - Signature { - expected: Arc, - found: Vec, - }, - ExportNotFound { - name: String, - }, - ExportWrongType { - name: String, - }, + Signature { expected: FuncSig, found: Vec }, + ExportNotFound { name: String }, + ExportWrongType { name: String }, } impl PartialEq for ResolveError { diff --git a/lib/runtime-core/src/instance.rs b/lib/runtime-core/src/instance.rs index a8f36325a..8255c125d 100644 --- a/lib/runtime-core/src/instance.rs +++ b/lib/runtime-core/src/instance.rs @@ -7,6 +7,7 @@ use crate::{ import::{ImportObject, LikeNamespace}, memory::Memory, module::{ExportIndex, Module, ModuleInner}, + sig_registry::SigRegistry, table::Table, typed_func::{Func, Safe, WasmTypeList}, types::{FuncIndex, FuncSig, GlobalIndex, LocalOrImport, MemoryIndex, TableIndex, Value}, @@ -112,11 +113,12 @@ impl Instance { .func_assoc .get(*func_index) .expect("broken invariant, incorrect func index"); - let signature = &self.module.info.signatures[sig_index]; + let signature = + SigRegistry.lookup_signature_ref(&self.module.info.signatures[sig_index]); if signature.params() != Args::types() || signature.returns() != Rets::types() { Err(ResolveError::Signature { - expected: Arc::clone(&signature), + expected: (*signature).clone(), found: Args::types().to_vec(), })?; } @@ -183,7 +185,8 @@ impl Instance { .func_assoc .get(*func_index) .expect("broken invariant, incorrect func index"); - let signature = Arc::clone(&self.module.info.signatures[sig_index]); + let signature = + SigRegistry.lookup_signature_ref(&self.module.info.signatures[sig_index]); Ok(DynFunc { signature, @@ -374,13 +377,10 @@ impl InstanceInner { } }; - let signature = &module.info.signatures[sig_index]; + let signature = SigRegistry.lookup_signature_ref(&module.info.signatures[sig_index]); + // let signature = &module.info.signatures[sig_index]; - ( - unsafe { FuncPointer::new(func_ptr) }, - ctx, - Arc::clone(signature), - ) + (unsafe { FuncPointer::new(func_ptr) }, ctx, signature) } fn get_memory_from_index(&self, module: &ModuleInner, mem_index: MemoryIndex) -> Memory { @@ -457,7 +457,7 @@ impl<'a> DynFunc<'a> { pub fn call(&mut self, params: &[Value]) -> CallResult> { if !self.signature.check_param_value_types(params) { Err(ResolveError::Signature { - expected: self.signature.clone(), + expected: (*self.signature).clone(), found: params.iter().map(|val| val.ty()).collect(), })? } diff --git a/lib/runtime-core/src/module.rs b/lib/runtime-core/src/module.rs index 0fdb24018..54306153b 100644 --- a/lib/runtime-core/src/module.rs +++ b/lib/runtime-core/src/module.rs @@ -46,7 +46,7 @@ pub struct ModuleInfo { pub start_func: Option, pub func_assoc: Map, - pub signatures: Map>, + pub signatures: Map, pub backend: Backend, pub namespace_table: StringTable, diff --git a/lib/runtime-core/src/sig_registry.rs b/lib/runtime-core/src/sig_registry.rs index 77c9a0d3c..1f6d87b4f 100644 --- a/lib/runtime-core/src/sig_registry.rs +++ b/lib/runtime-core/src/sig_registry.rs @@ -49,4 +49,20 @@ impl SigRegistry { let global = (*GLOBAL_SIG_REGISTRY).read(); Arc::clone(&global.sig_assoc[sig_index]) } + + pub fn lookup_signature_ref(&self, func_sig: &FuncSig) -> Arc { + let mut global = (*GLOBAL_SIG_REGISTRY).write(); + let global = &mut *global; + + let func_table = &mut global.func_table; + let sig_assoc = &mut global.sig_assoc; + + if func_table.contains_key(func_sig) { + Arc::clone(&sig_assoc[func_table[func_sig]]) + } else { + let arc = Arc::new(func_sig.clone()); + func_table.insert(Arc::clone(&arc), sig_assoc.push(Arc::clone(&arc))); + arc + } + } } From c3707efa084b848b8691e86957a9117d2173fed0 Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Sat, 9 Feb 2019 13:09:54 -0600 Subject: [PATCH 020/262] Update for merge from master --- Cargo.lock | 112 +++++++++++++++++++++++++++++++---- lib/runtime-c-api/src/lib.rs | 7 ++- 2 files changed, 106 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d061df27b..82e1fb81c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -28,7 +28,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "block-buffer" -version = "0.7.2" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "block-padding 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -60,6 +60,21 @@ name = "cast" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "cbindgen" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "cc" version = "1.0.28" @@ -404,6 +419,14 @@ dependencies = [ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "proc-macro2" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "proc-macro2" version = "0.4.26" @@ -412,6 +435,14 @@ dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "quote" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "quote" version = "0.6.11" @@ -547,6 +578,14 @@ dependencies = [ "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "remove_dir_all" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rustc_version" version = "0.2.3" @@ -582,6 +621,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "serde" version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "serde-bench" @@ -602,12 +644,12 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.85" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.13.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -625,7 +667,7 @@ name = "sha2" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "block-buffer 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "block-buffer 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -669,6 +711,16 @@ dependencies = [ "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "syn" +version = "0.13.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "syn" version = "0.15.26" @@ -700,6 +752,19 @@ dependencies = [ "serde_json 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "tempfile" +version = "3.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", + "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "termion" version = "1.5.1" @@ -728,6 +793,14 @@ dependencies = [ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "toml" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "typenum" version = "1.10.0" @@ -772,7 +845,7 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", "wabt-sys 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -815,7 +888,7 @@ dependencies = [ "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", "serde-bench 0.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", "target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-runtime-core 0.1.2", "wasmparser 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -843,6 +916,16 @@ dependencies = [ "wasmer-runtime-core 0.1.2", ] +[[package]] +name = "wasmer-runtime-c-api" +version = "0.1.4" +dependencies = [ + "cbindgen 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmer-runtime 0.1.4", + "wasmer-runtime-core 0.1.2", +] + [[package]] name = "wasmer-runtime-core" version = "0.1.2" @@ -860,7 +943,7 @@ dependencies = [ "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", "serde-bench 0.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-clif-backend 0.1.2", "wasmparser 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -920,11 +1003,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" "checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" -"checksum block-buffer 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "509de513cca6d92b6aacf9c61acfe7eaa160837323a81068d690cc1f8e5740da" +"checksum block-buffer 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49665c62e0e700857531fa5d3763e91b539ff1abeebd56808d378b495870d60d" "checksum block-padding 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d75255892aeb580d3c566f213a2b6fdc1c66667839f45719ee1d30ebf2aea591" "checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" "checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" "checksum cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "926013f2860c46252efceabb19f4a6b308197505082c609025aa6706c011d427" +"checksum cbindgen 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "32e01024aaf5390d6a8145047371a4f5b0063a14c1e411bc731353bd2278ca44" "checksum cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4a8b715cb4597106ea87c7c84b2f1d452c7492033765df7f32651e66fcf749" "checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" "checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e" @@ -967,7 +1051,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum page_size 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f89ef58b3d32420dbd1a43d2f38ae92f6239ef12bb556ab09ca55445f5a67242" "checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" "checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" +"checksum proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1b06e2f335f48d24442b35a19df506a835fb3547bc3c06ef27340da9acf5cae7" "checksum proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)" = "38fddd23d98b2144d197c0eca5705632d4fe2667d14a6be5df8934f8d74f1978" +"checksum quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9949cfe66888ffe1d53e6ec9d9f3b70714083854be20fd5e271b232a017401e8" "checksum quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cdd8e04bd9c52e0342b406469d494fcb033be4bdbe5c606016defbb1681411e1" "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" "checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" @@ -983,6 +1069,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" "checksum redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)" = "423e376fffca3dfa06c9e9790a9ccd282fafb3cc6e6397d01dbf64f9bacc6b85" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" +"checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" @@ -991,7 +1078,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)" = "534b8b91a95e0f71bca3ed5824752d558da048d4248c91af873b63bd60519752" "checksum serde-bench 0.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "d733da87e79faaac25616e33d26299a41143fd4cd42746cbb0e91d8feea243fd" "checksum serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)" = "adb6e51a6b3696b301bc221d785f898b4457c619b51d7ce195a6d20baecb37b3" -"checksum serde_derive 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)" = "a915306b0f1ac5607797697148c223bedeaa36bcc2e28a01441cd638cc6567b4" +"checksum serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)" = "ac38f51a52a556cd17545798e29536885fb1a3fa63d6399f5ef650f4a7d35901" "checksum serde_json 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)" = "4b90a9fbe1211e57d3e1c15670f1cb00802988fb23a1a4aad7a2b63544f1920e" "checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d" "checksum smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "88aea073965ab29f6edb5493faf96ad662fb18aa9eeb186a3b7057951605ed15" @@ -999,12 +1086,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" "checksum structopt 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "670ad348dc73012fcf78c71f06f9d942232cdd4c859d4b6975e27836c3efc0c3" "checksum structopt-derive 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "ef98172b1a00b0bec738508d3726540edcbd186d50dfd326f2b1febbb3559f04" +"checksum syn 0.13.11 (registry+https://github.com/rust-lang/crates.io-index)" = "14f9bf6292f3a61d2c716723fdb789a41bbe104168e6f496dc6497e531ea1b9b" "checksum syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)" = "f92e629aa1d9c827b2bb8297046c1ccffc57c99b947a680d3ccff1f136a3bee9" "checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" "checksum target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4af5e2227f0b887d591d3724b796a96eff04226104d872f5b3883fcd427d64b9" +"checksum tempfile 3.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "37daa55a7240c4931c84559f03b3cad7d19535840d1c4a0cc4e9b2fb0dcf70ff" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" "checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6" "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" +"checksum toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "758664fc71a3a69038656bee8b6be6477d2a6c315a6b81f7081f591bffa4111f" "checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" "checksum unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa6024fc12ddfd1c6dbc14a80fa2324d4568849869b779f6bd37e5e4c03344d1" "checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index 98c00e196..252322e2b 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -87,7 +87,10 @@ pub struct wasmer_limits_t { #[allow(clippy::cast_ptr_alignment)] #[no_mangle] -pub unsafe extern "C" fn wasmer_validate(wasm_bytes: *mut uint8_t, wasm_bytes_len: uint32_t) -> bool { +pub unsafe extern "C" fn wasmer_validate( + wasm_bytes: *mut uint8_t, + wasm_bytes_len: uint32_t, +) -> bool { if wasm_bytes.is_null() { return false; } @@ -162,7 +165,7 @@ pub unsafe extern "C" fn wasmer_instantiate( } let bytes: &[u8] = unsafe { ::std::slice::from_raw_parts_mut(wasm_bytes, wasm_bytes_len as usize) }; - let result = wasmer_runtime::instantiate(bytes, *import_object); + let result = wasmer_runtime::instantiate(bytes, &*import_object); let new_instance = match result { Ok(instance) => instance, Err(error) => { From 4e5e525626883c8c71c183508692bb132966dfc0 Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Sat, 9 Feb 2019 13:37:07 -0600 Subject: [PATCH 021/262] Add basic Table functions --- lib/runtime-c-api/src/lib.rs | 60 ++++++++++++++++++++++---- lib/runtime-c-api/tests/.gitignore | 1 + lib/runtime-c-api/tests/CMakeLists.txt | 4 ++ lib/runtime-c-api/tests/test-tables.c | 23 ++++++++++ lib/runtime-c-api/wasmer.h | 15 +++++++ lib/runtime-c-api/wasmer.hh | 15 +++++++ 6 files changed, 110 insertions(+), 8 deletions(-) create mode 100644 lib/runtime-c-api/tests/test-tables.c diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index 252322e2b..84ee8cf38 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -7,10 +7,10 @@ use std::slice; use std::str; use std::sync::Arc; use std::{ffi::c_void, mem, ptr}; -use wasmer_runtime::{ImportObject, Instance, Memory, Value}; +use wasmer_runtime::{ImportObject, Instance, Memory, Table, Value}; use wasmer_runtime_core::export::{Context, Export, FuncPointer}; use wasmer_runtime_core::import::{LikeNamespace, Namespace}; -use wasmer_runtime_core::types::{FuncSig, MemoryDescriptor, Type}; +use wasmer_runtime_core::types::{ElementType, FuncSig, MemoryDescriptor, TableDescriptor, Type}; use wasmer_runtime_core::units::Pages; #[allow(non_camel_case_types)] @@ -46,6 +46,14 @@ pub enum wasmer_memory_result_t { WASMER_MEMORY_ERROR = 2, } +#[allow(non_camel_case_types)] +#[no_mangle] +#[repr(C)] +pub enum wasmer_table_result_t { + WASMER_TABLE_OK = 1, + WASMER_TABLE_ERROR = 2, +} + #[repr(u32)] #[derive(Clone)] pub enum wasmer_value_tag { @@ -74,10 +82,10 @@ pub struct wasmer_value_t { #[repr(C)] #[derive(Clone)] pub struct wasmer_memory_t(); -//{ -// pub ptr: *mut uint8_t, -// pub len: uint32_t, -//} + +#[repr(C)] +#[derive(Clone)] +pub struct wasmer_table_t(); #[repr(C)] pub struct wasmer_limits_t { @@ -118,7 +126,6 @@ pub unsafe extern "C" fn wasmer_memory_new( let new_memory = match result { Ok(memory) => memory, Err(error) => { - println!("Err: {:?}", error); return wasmer_memory_result_t::WASMER_MEMORY_ERROR; } }; @@ -135,6 +142,44 @@ pub extern "C" fn wasmer_memory_length(memory: *mut wasmer_memory_t) -> uint32_t len } +#[no_mangle] +pub unsafe extern "C" fn wasmer_table_new( + mut table: *mut *mut wasmer_table_t, + limits: wasmer_limits_t, +) -> wasmer_table_result_t { + let desc = TableDescriptor { + element: ElementType::Anyfunc, + minimum: limits.min, + maximum: Some(limits.max), + }; + let result = Table::new(desc); + let new_table = match result { + Ok(table) => table, + Err(error) => { + return wasmer_table_result_t::WASMER_TABLE_ERROR; + } + }; + unsafe { *table = Box::into_raw(Box::new(new_table)) as *mut wasmer_table_t }; + wasmer_table_result_t::WASMER_TABLE_OK +} + +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub extern "C" fn wasmer_table_length(table: *mut wasmer_table_t) -> uint32_t { + let table = unsafe { Box::from_raw(table as *mut Table) }; + let len = table.size(); + Box::into_raw(table); + len +} + +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub extern "C" fn wasmer_table_destroy(table: *mut wasmer_table_t) { + if !table.is_null() { + drop(unsafe { Box::from_raw(table as *mut Table) }); + } +} + #[allow(clippy::cast_ptr_alignment)] #[no_mangle] pub extern "C" fn wasmer_import_object_destroy(import_object: *mut wasmer_import_object_t) { @@ -169,7 +214,6 @@ pub unsafe extern "C" fn wasmer_instantiate( let new_instance = match result { Ok(instance) => instance, Err(error) => { - println!("Err: {:?}", error); return wasmer_compile_result_t::WASMER_COMPILE_ERROR; } }; diff --git a/lib/runtime-c-api/tests/.gitignore b/lib/runtime-c-api/tests/.gitignore index 76d5a7d2e..8ac4f1ab0 100644 --- a/lib/runtime-c-api/tests/.gitignore +++ b/lib/runtime-c-api/tests/.gitignore @@ -12,5 +12,6 @@ _deps test-instantiate test-import-function test-memory +test-tables test-validate rust-build \ No newline at end of file diff --git a/lib/runtime-c-api/tests/CMakeLists.txt b/lib/runtime-c-api/tests/CMakeLists.txt index d682bfe3b..58b1ac3cd 100644 --- a/lib/runtime-c-api/tests/CMakeLists.txt +++ b/lib/runtime-c-api/tests/CMakeLists.txt @@ -5,6 +5,7 @@ add_executable(test-instantiate test-instantiate.c) add_executable(test-import-function test-import-function.c) add_executable(test-memory test-memory.c) add_executable(test-validate test-validate.c) +add_executable(test-tables test-tables.c) find_library( WASMER_LIB NAMES libwasmer_runtime_c_api.dylib libwasmer_runtime_c_api.so libwasmer_runtime_c_api.dll @@ -23,10 +24,13 @@ target_link_libraries(test-memory general ${WASMER_LIB}) target_link_libraries(test-validate general ${WASMER_LIB}) +target_link_libraries(test-tables + general ${WASMER_LIB}) enable_testing() add_test(test-instantiate test-instantiate) add_test(test-import-function test-import-function) add_test(test-memory test-memory) add_test(test-validate test-validate) +add_test(test-tables test-tables) diff --git a/lib/runtime-c-api/tests/test-tables.c b/lib/runtime-c-api/tests/test-tables.c new file mode 100644 index 000000000..88d86d842 --- /dev/null +++ b/lib/runtime-c-api/tests/test-tables.c @@ -0,0 +1,23 @@ +#include +#include "../wasmer.h" +#include +#include + +int main() +{ + wasmer_table_t *table = NULL; + wasmer_limits_t descriptor; + descriptor.min = 10; + descriptor.max = 10; + wasmer_table_result_t table_result = wasmer_table_new(&table, descriptor); + printf("Table result: %d\n", table_result); + assert(table_result == WASMER_TABLE_OK); + + uint32_t len = wasmer_table_length(table); + printf("Table length: %d\n", len); + assert(len == 10); + + printf("Destroy table\n"); + wasmer_table_destroy(table); + return 0; +} diff --git a/lib/runtime-c-api/wasmer.h b/lib/runtime-c-api/wasmer.h index 26b343e29..0d72375c9 100644 --- a/lib/runtime-c-api/wasmer.h +++ b/lib/runtime-c-api/wasmer.h @@ -18,6 +18,11 @@ typedef enum { WASMER_MEMORY_ERROR = 2, } wasmer_memory_result_t; +typedef enum { + WASMER_TABLE_OK = 1, + WASMER_TABLE_ERROR = 2, +} wasmer_table_result_t; + enum wasmer_value_tag { WASM_I32, WASM_I64, @@ -53,6 +58,10 @@ typedef struct { uint32_t max; } wasmer_limits_t; +typedef struct { + +} wasmer_table_t; + void wasmer_import_object_destroy(wasmer_import_object_t *import_object); wasmer_import_object_t *wasmer_import_object_new(void); @@ -88,4 +97,10 @@ uint32_t wasmer_memory_length(wasmer_memory_t *memory); wasmer_memory_result_t wasmer_memory_new(wasmer_memory_t **memory, wasmer_limits_t limits); +void wasmer_table_destroy(wasmer_table_t *table); + +uint32_t wasmer_table_length(wasmer_table_t *table); + +wasmer_table_result_t wasmer_table_new(wasmer_table_t **table, wasmer_limits_t limits); + bool wasmer_validate(uint8_t *wasm_bytes, uint32_t wasm_bytes_len); diff --git a/lib/runtime-c-api/wasmer.hh b/lib/runtime-c-api/wasmer.hh index 37400cea9..cb271c9d5 100644 --- a/lib/runtime-c-api/wasmer.hh +++ b/lib/runtime-c-api/wasmer.hh @@ -17,6 +17,11 @@ enum class wasmer_memory_result_t { WASMER_MEMORY_ERROR = 2, }; +enum class wasmer_table_result_t { + WASMER_TABLE_OK = 1, + WASMER_TABLE_ERROR = 2, +}; + enum class wasmer_value_tag : uint32_t { WASM_I32, WASM_I64, @@ -51,6 +56,10 @@ struct wasmer_limits_t { uint32_t max; }; +struct wasmer_table_t { + +}; + extern "C" { void wasmer_import_object_destroy(wasmer_import_object_t *import_object); @@ -88,6 +97,12 @@ uint32_t wasmer_memory_length(wasmer_memory_t *memory); wasmer_memory_result_t wasmer_memory_new(wasmer_memory_t **memory, wasmer_limits_t limits); +void wasmer_table_destroy(wasmer_table_t *table); + +uint32_t wasmer_table_length(wasmer_table_t *table); + +wasmer_table_result_t wasmer_table_new(wasmer_table_t **table, wasmer_limits_t limits); + bool wasmer_validate(uint8_t *wasm_bytes, uint32_t wasm_bytes_len); } // extern "C" From 8364c39b4c983bc75b45e427da939870c49d82cb Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Sat, 9 Feb 2019 13:58:50 -0600 Subject: [PATCH 022/262] Add Table grow function --- lib/runtime-c-api/src/lib.rs | 16 ++++++++++++++++ lib/runtime-c-api/tests/test-tables.c | 17 +++++++++++++++-- lib/runtime-c-api/wasmer.h | 2 ++ lib/runtime-c-api/wasmer.hh | 2 ++ 4 files changed, 35 insertions(+), 2 deletions(-) diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index 84ee8cf38..9f2ffb12c 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -163,6 +163,22 @@ pub unsafe extern "C" fn wasmer_table_new( wasmer_table_result_t::WASMER_TABLE_OK } +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub extern "C" fn wasmer_table_grow( + table: *mut wasmer_table_t, + delta: uint32_t, +) -> wasmer_table_result_t { + let table = unsafe { Box::from_raw(table as *mut Table) }; + let maybe_delta = table.grow(delta); + Box::into_raw(table); + if let Some(_delta) = maybe_delta { + wasmer_table_result_t::WASMER_TABLE_OK + } else { + wasmer_table_result_t::WASMER_TABLE_ERROR + } +} + #[allow(clippy::cast_ptr_alignment)] #[no_mangle] pub extern "C" fn wasmer_table_length(table: *mut wasmer_table_t) -> uint32_t { diff --git a/lib/runtime-c-api/tests/test-tables.c b/lib/runtime-c-api/tests/test-tables.c index 88d86d842..7e3f51a2f 100644 --- a/lib/runtime-c-api/tests/test-tables.c +++ b/lib/runtime-c-api/tests/test-tables.c @@ -8,14 +8,27 @@ int main() wasmer_table_t *table = NULL; wasmer_limits_t descriptor; descriptor.min = 10; - descriptor.max = 10; + descriptor.max = 15; wasmer_table_result_t table_result = wasmer_table_new(&table, descriptor); printf("Table result: %d\n", table_result); assert(table_result == WASMER_TABLE_OK); uint32_t len = wasmer_table_length(table); printf("Table length: %d\n", len); - assert(len == 10); + assert(len == 15); + + // wasmer_table_result_t grow_result1 = wasmer_table_grow(&table, 5); + // assert(grow_result1 == WASMER_TABLE_OK); + // uint32_t len_grow1 = wasmer_table_length(table); + // printf("Table length: %d\n", len_grow1); + // assert(len_grow1 == 15); + + // // Try to grow beyond max + // wasmer_table_result_t grow_result2 = wasmer_table_grow(&table, 1); + // assert(grow_result2 == WASMER_TABLE_ERROR); + // uint32_t len_grow2 = wasmer_table_length(table); + // printf("Table length: %d\n", len_grow2); + // assert(len_grow2 == 15); printf("Destroy table\n"); wasmer_table_destroy(table); diff --git a/lib/runtime-c-api/wasmer.h b/lib/runtime-c-api/wasmer.h index 0d72375c9..08f891fa8 100644 --- a/lib/runtime-c-api/wasmer.h +++ b/lib/runtime-c-api/wasmer.h @@ -99,6 +99,8 @@ wasmer_memory_result_t wasmer_memory_new(wasmer_memory_t **memory, wasmer_limits void wasmer_table_destroy(wasmer_table_t *table); +wasmer_table_result_t wasmer_table_grow(wasmer_table_t *table, uint32_t delta); + uint32_t wasmer_table_length(wasmer_table_t *table); wasmer_table_result_t wasmer_table_new(wasmer_table_t **table, wasmer_limits_t limits); diff --git a/lib/runtime-c-api/wasmer.hh b/lib/runtime-c-api/wasmer.hh index cb271c9d5..c0d266489 100644 --- a/lib/runtime-c-api/wasmer.hh +++ b/lib/runtime-c-api/wasmer.hh @@ -99,6 +99,8 @@ wasmer_memory_result_t wasmer_memory_new(wasmer_memory_t **memory, wasmer_limits void wasmer_table_destroy(wasmer_table_t *table); +wasmer_table_result_t wasmer_table_grow(wasmer_table_t *table, uint32_t delta); + uint32_t wasmer_table_length(wasmer_table_t *table); wasmer_table_result_t wasmer_table_new(wasmer_table_t **table, wasmer_limits_t limits); From 393b7dbdf3936ec9efceb844c5e45cf08a9e78be Mon Sep 17 00:00:00 2001 From: Syrus Date: Sat, 9 Feb 2019 13:33:22 -0800 Subject: [PATCH 023/262] Moved ctx in func macro to be first arg --- lib/runtime-core/src/import.rs | 2 +- lib/runtime-core/src/macros.rs | 2 +- lib/runtime-core/src/typed_func.rs | 10 +++++----- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/runtime-core/src/import.rs b/lib/runtime-core/src/import.rs index cf833ec6e..7073a5ac1 100644 --- a/lib/runtime-core/src/import.rs +++ b/lib/runtime-core/src/import.rs @@ -32,7 +32,7 @@ impl IsExport for Export { /// }, /// }; /// -/// fn foo(n: i32, _: &mut Ctx) -> i32 { +/// fn foo(_: &mut Ctx, n: i32) -> i32 { /// n /// } /// ``` diff --git a/lib/runtime-core/src/macros.rs b/lib/runtime-core/src/macros.rs index 620f65046..a7bdff1b0 100644 --- a/lib/runtime-core/src/macros.rs +++ b/lib/runtime-core/src/macros.rs @@ -38,7 +38,7 @@ macro_rules! func { /// }, /// }; /// -/// fn foo(n: i32, _: &mut Ctx) -> i32 { +/// fn foo(_: &mut Ctx, n: i32) -> i32 { /// n /// } /// ``` diff --git a/lib/runtime-core/src/typed_func.rs b/lib/runtime-core/src/typed_func.rs index 9cbcdc911..9989764c6 100644 --- a/lib/runtime-core/src/typed_func.rs +++ b/lib/runtime-core/src/typed_func.rs @@ -183,16 +183,16 @@ macro_rules! impl_traits { } } - impl< $( $x: WasmExternType, )* Rets: WasmTypeList, Trap: TrapEarly, FN: Fn( $( $x, )* &mut Ctx) -> Trap> ExternalFunction<($( $x ),*), Rets> for FN { + impl< $( $x: WasmExternType, )* Rets: WasmTypeList, Trap: TrapEarly, FN: Fn( &mut Ctx $( ,$x )* ) -> Trap> ExternalFunction<($( $x ),*), Rets> for FN { #[allow(non_snake_case)] fn to_raw(&self) -> *const () { assert_eq!(mem::size_of::(), 0, "you cannot use a closure that captures state for `Func`."); - extern fn wrap<$( $x: WasmExternType, )* Rets: WasmTypeList, Trap: TrapEarly, FN: Fn( $( $x, )* &mut Ctx) -> Trap>( $( $x: $x, )* ctx: &mut Ctx) -> Rets::CStruct { + extern fn wrap<$( $x: WasmExternType, )* Rets: WasmTypeList, Trap: TrapEarly, FN: Fn( &mut Ctx $( ,$x )* ) -> Trap>( ctx: &mut Ctx $( ,$x: $x )* ) -> Rets::CStruct { let f: FN = unsafe { mem::transmute_copy(&()) }; let msg = match panic::catch_unwind(panic::AssertUnwindSafe(|| { - f( $( $x, )* ctx).report() + f( ctx $( ,$x )* ).report() })) { Ok(Ok(returns)) => return returns.into_c_struct(), Ok(Err(err)) => err, @@ -271,7 +271,7 @@ mod tests { use super::*; #[test] fn test_call() { - fn foo(a: i32, b: i32, _ctx: &mut Ctx) -> (i32, i32) { + fn foo(_ctx: &mut Ctx, a: i32, b: i32) -> (i32, i32) { (a, b) } @@ -282,7 +282,7 @@ mod tests { fn test_imports() { use crate::{func, imports}; - fn foo(a: i32, _ctx: &mut Ctx) -> i32 { + fn foo(_ctx: &mut Ctx, a: i32) -> i32 { a } From 6c7fd55b875363182045c13d429887d9a55ab1e7 Mon Sep 17 00:00:00 2001 From: Syrus Date: Sat, 9 Feb 2019 13:58:05 -0800 Subject: [PATCH 024/262] Moved ctx to be the first argument in emscripten --- lib/emscripten/src/README.md | 16 ++--- lib/emscripten/src/env/mod.rs | 16 ++--- lib/emscripten/src/env/unix/mod.rs | 18 +++--- lib/emscripten/src/env/windows/mod.rs | 18 +++--- lib/emscripten/src/errno.rs | 2 +- lib/emscripten/src/exception.rs | 6 +- lib/emscripten/src/io/unix.rs | 4 +- lib/emscripten/src/io/windows.rs | 4 +- lib/emscripten/src/jmp.rs | 6 +- lib/emscripten/src/lib.rs | 10 ++-- lib/emscripten/src/linking.rs | 6 +- lib/emscripten/src/lock.rs | 6 +- lib/emscripten/src/math.rs | 12 ++-- lib/emscripten/src/memory.rs | 6 +- lib/emscripten/src/nullfunc.rs | 52 ++++++++-------- lib/emscripten/src/process.rs | 42 ++++++------- lib/emscripten/src/signal.rs | 12 ++-- lib/emscripten/src/syscalls/mod.rs | 82 +++++++++++++------------- lib/emscripten/src/syscalls/unix.rs | 26 ++++---- lib/emscripten/src/syscalls/windows.rs | 26 ++++---- lib/emscripten/src/time.rs | 38 ++++++------ lib/emscripten/src/utils.rs | 10 ++-- 22 files changed, 209 insertions(+), 209 deletions(-) diff --git a/lib/emscripten/src/README.md b/lib/emscripten/src/README.md index 128ef1783..54b9f9dc1 100644 --- a/lib/emscripten/src/README.md +++ b/lib/emscripten/src/README.md @@ -10,7 +10,7 @@ ``` - **abort** ✅ 🔥     [:top:](#host-apis) ```rust - fn abort(message: u32, ctx: &mut Ctx) + fn abort(ctx: &mut Ctx, message: u32, ) ``` - **abort_on_cannot_grow_memory** ✅     [:top:](#host-apis) ```rust @@ -28,11 +28,11 @@ - **\_getenv** ✅     [:top:](#host-apis) ```rust - fn _getenv(name: c_int, ctx: &mut Ctx) + fn _getenv(ctx: &mut Ctx, name: c_int, ) ``` - **\_putenv** ✅     [:top:](#host-apis) ```rust - fn _putenv(name: c_int, ctx: &mut Ctx) + fn _putenv(ctx: &mut Ctx, name: c_int, ) ``` - **\_setenv** ✅     [:top:](#host-apis) ```rust @@ -40,7 +40,7 @@ ``` - **\_unsetenv** ✅     [:top:](#host-apis) ```rust - fn _unsetenv(name: c_int, ctx: &mut Ctx) + fn _unsetenv(ctx: &mut Ctx, name: c_int, ) ``` ###### THREAD @@ -70,7 +70,7 @@ - **\_emscripten_memcpy_big** ✅ 🔥     [:top:](#host-apis) ```rust - fn _emscripten_memcpy_big(dest: u32, src: u32, len: u32, ctx: &mut Ctx) -> u32 + fn _emscripten_memcpy_big(ctx: &mut Ctx, dest: u32, src: u32, len: u32, ) -> u32 ``` - **enlarge_memory** ✅     [:top:](#host-apis) ```rust @@ -78,7 +78,7 @@ ``` - **get_total_memory** ✅     [:top:](#host-apis) ```rust - fn get_total_memory(ctx: &mut Ctx) -> u32 + fn get_total_memory(ctx: &mut Ctx, ) -> u32 ``` ###### TIMING @@ -337,7 +337,7 @@ ``` - **open** (\_\_\_syscall5) ✅ ❗️ 🔥     [:top:](#host-apis) ```rust - fn open(path: u32, flags: c_int, mode: c_int, ctx: &mut Ctx) -> c_int + fn open(ctx: &mut Ctx, path: u32, flags: c_int, mode: c_int, ) -> c_int ``` - **openat** (\_\_\_syscall295)     [:top:](#host-apis) ```rust @@ -385,7 +385,7 @@ ``` - **read** (\_\_\_syscall3) ✅ ❗️     [:top:](#host-apis) ```rust - fn read(fd: c_int, buf: u32, count: size_t, ctx: &mut Ctx) -> ssize_t + fn read(ctx: &mut Ctx, fd: c_int, buf: u32, count: size_t, ) -> ssize_t ``` - **readlink** (\_\_\_syscall85)     [:top:](#host-apis) ```rust diff --git a/lib/emscripten/src/env/mod.rs b/lib/emscripten/src/env/mod.rs index 50b7a48f9..89f55fd09 100644 --- a/lib/emscripten/src/env/mod.rs +++ b/lib/emscripten/src/env/mod.rs @@ -14,16 +14,16 @@ use crate::{allocate_on_stack, EmscriptenData}; use std::os::raw::c_int; use wasmer_runtime_core::vm::Ctx; -pub fn _getaddrinfo(_one: i32, _two: i32, _three: i32, _four: i32, _ctx: &mut Ctx) -> i32 { +pub fn _getaddrinfo(_ctx: &mut Ctx, _one: i32, _two: i32, _three: i32, _four: i32) -> i32 { debug!("emscripten::_getaddrinfo"); -1 } -pub fn call_malloc(size: u32, ctx: &mut Ctx) -> u32 { +pub fn call_malloc(ctx: &mut Ctx, size: u32) -> u32 { get_emscripten_data(ctx).malloc.call(size).unwrap() } -pub fn call_memalign(alignment: u32, size: u32, ctx: &mut Ctx) -> u32 { +pub fn call_memalign(ctx: &mut Ctx, alignment: u32, size: u32) -> u32 { if let Some(memalign) = &get_emscripten_data(ctx).memalign { memalign.call(alignment, size).unwrap() } else { @@ -31,7 +31,7 @@ pub fn call_memalign(alignment: u32, size: u32, ctx: &mut Ctx) -> u32 { } } -pub fn call_memset(pointer: u32, value: u32, size: u32, ctx: &mut Ctx) -> u32 { +pub fn call_memset(ctx: &mut Ctx, pointer: u32, value: u32, size: u32) -> u32 { get_emscripten_data(ctx) .memset .call(pointer, value, size) @@ -48,16 +48,16 @@ pub fn _getpagesize(_ctx: &mut Ctx) -> u32 { } #[allow(clippy::cast_ptr_alignment)] -pub fn ___build_environment(environ: c_int, ctx: &mut Ctx) { +pub fn ___build_environment(ctx: &mut Ctx, environ: c_int) { debug!("emscripten::___build_environment {}", environ); const MAX_ENV_VALUES: u32 = 64; const TOTAL_ENV_SIZE: u32 = 1024; let environment = emscripten_memory_pointer!(ctx.memory(0), environ) as *mut c_int; unsafe { let (pool_offset, _pool_slice): (u32, &mut [u8]) = - allocate_on_stack(TOTAL_ENV_SIZE as u32, ctx); + allocate_on_stack(ctx, TOTAL_ENV_SIZE as u32); let (env_offset, _env_slice): (u32, &mut [u8]) = - allocate_on_stack((MAX_ENV_VALUES * 4) as u32, ctx); + allocate_on_stack(ctx, (MAX_ENV_VALUES * 4) as u32); let env_ptr = emscripten_memory_pointer!(ctx.memory(0), env_offset) as *mut c_int; let mut _pool_ptr = emscripten_memory_pointer!(ctx.memory(0), pool_offset) as *mut c_int; *env_ptr = pool_offset as i32; @@ -70,7 +70,7 @@ pub fn ___build_environment(environ: c_int, ctx: &mut Ctx) { // }; } -pub fn ___assert_fail(a: c_int, b: c_int, c: c_int, d: c_int, _ctx: &mut Ctx) { +pub fn ___assert_fail(_ctx: &mut Ctx, a: c_int, b: c_int, c: c_int, d: c_int) { debug!("emscripten::___assert_fail {} {} {} {}", a, b, c, d); // TODO: Implement like emscripten expects regarding memory/page size // TODO raise an error diff --git a/lib/emscripten/src/env/unix/mod.rs b/lib/emscripten/src/env/unix/mod.rs index 55fe0c000..5c4ef3d3a 100644 --- a/lib/emscripten/src/env/unix/mod.rs +++ b/lib/emscripten/src/env/unix/mod.rs @@ -14,7 +14,7 @@ use wasmer_runtime_core::vm::Ctx; // #[no_mangle] /// emscripten: _getenv // (name: *const char) -> *const c_char; -pub fn _getenv(name: i32, ctx: &mut Ctx) -> u32 { +pub fn _getenv(ctx: &mut Ctx, name: i32) -> u32 { debug!("emscripten::_getenv"); let name_addr = emscripten_memory_pointer!(ctx.memory(0), name) as *const c_char; @@ -30,7 +30,7 @@ pub fn _getenv(name: i32, ctx: &mut Ctx) -> u32 { } /// emscripten: _setenv // (name: *const char, name: *const value, overwrite: int); -pub fn _setenv(name: c_int, value: c_int, overwrite: c_int, ctx: &mut Ctx) -> c_int { +pub fn _setenv(ctx: &mut Ctx, name: c_int, value: c_int, overwrite: c_int) -> c_int { debug!("emscripten::_setenv"); let name_addr = emscripten_memory_pointer!(ctx.memory(0), name) as *const c_char; @@ -43,7 +43,7 @@ pub fn _setenv(name: c_int, value: c_int, overwrite: c_int, ctx: &mut Ctx) -> c_ } /// emscripten: _putenv // (name: *const char); -pub fn _putenv(name: c_int, ctx: &mut Ctx) -> c_int { +pub fn _putenv(ctx: &mut Ctx, name: c_int) -> c_int { debug!("emscripten::_putenv"); let name_addr = emscripten_memory_pointer!(ctx.memory(0), name) as *const c_char; @@ -54,7 +54,7 @@ pub fn _putenv(name: c_int, ctx: &mut Ctx) -> c_int { } /// emscripten: _unsetenv // (name: *const char); -pub fn _unsetenv(name: c_int, ctx: &mut Ctx) -> c_int { +pub fn _unsetenv(ctx: &mut Ctx, name: c_int) -> c_int { debug!("emscripten::_unsetenv"); let name_addr = emscripten_memory_pointer!(ctx.memory(0), name) as *const c_char; @@ -65,7 +65,7 @@ pub fn _unsetenv(name: c_int, ctx: &mut Ctx) -> c_int { } #[allow(clippy::cast_ptr_alignment)] -pub fn _getpwnam(name_ptr: c_int, ctx: &mut Ctx) -> c_int { +pub fn _getpwnam(ctx: &mut Ctx, name_ptr: c_int) -> c_int { debug!("emscripten::_getpwnam {}", name_ptr); #[repr(C)] @@ -86,7 +86,7 @@ pub fn _getpwnam(name_ptr: c_int, ctx: &mut Ctx) -> c_int { unsafe { let passwd = &*libc_getpwnam(name.as_ptr()); - let passwd_struct_offset = call_malloc(mem::size_of::() as _, ctx); + let passwd_struct_offset = call_malloc(ctx, mem::size_of::() as _); let passwd_struct_ptr = emscripten_memory_pointer!(ctx.memory(0), passwd_struct_offset) as *mut GuestPasswd; @@ -103,7 +103,7 @@ pub fn _getpwnam(name_ptr: c_int, ctx: &mut Ctx) -> c_int { } #[allow(clippy::cast_ptr_alignment)] -pub fn _getgrnam(name_ptr: c_int, ctx: &mut Ctx) -> c_int { +pub fn _getgrnam(ctx: &mut Ctx, name_ptr: c_int) -> c_int { debug!("emscripten::_getgrnam {}", name_ptr); #[repr(C)] @@ -121,7 +121,7 @@ pub fn _getgrnam(name_ptr: c_int, ctx: &mut Ctx) -> c_int { unsafe { let group = &*libc_getgrnam(name.as_ptr()); - let group_struct_offset = call_malloc(mem::size_of::() as _, ctx); + let group_struct_offset = call_malloc(ctx, mem::size_of::() as _); let group_struct_ptr = emscripten_memory_pointer!(ctx.memory(0), group_struct_offset) as *mut GuestGroup; @@ -134,7 +134,7 @@ pub fn _getgrnam(name_ptr: c_int, ctx: &mut Ctx) -> c_int { } } -pub fn _sysconf(name: c_int, _ctx: &mut Ctx) -> i32 { +pub fn _sysconf(_ctx: &mut Ctx, name: c_int) -> i32 { debug!("emscripten::_sysconf {}", name); // TODO: Implement like emscripten expects regarding memory/page size unsafe { sysconf(name) as i32 } // TODO review i64 diff --git a/lib/emscripten/src/env/windows/mod.rs b/lib/emscripten/src/env/windows/mod.rs index b4171e13c..b4ee6ecff 100644 --- a/lib/emscripten/src/env/windows/mod.rs +++ b/lib/emscripten/src/env/windows/mod.rs @@ -16,7 +16,7 @@ extern "C" { // #[no_mangle] /// emscripten: _getenv // (name: *const char) -> *const c_char; -pub fn _getenv(name: u32, ctx: &mut Ctx) -> u32 { +pub fn _getenv(ctx: &mut Ctx, name: u32) -> u32 { debug!("emscripten::_getenv"); let name_string = read_string_from_wasm(ctx.memory(0), name); debug!("=> name({:?})", name_string); @@ -28,7 +28,7 @@ pub fn _getenv(name: u32, ctx: &mut Ctx) -> u32 { } /// emscripten: _setenv // (name: *const char, name: *const value, overwrite: int); -pub fn _setenv(name: u32, value: u32, overwrite: u32, ctx: &mut Ctx) -> c_int { +pub fn _setenv(ctx: &mut Ctx, name: u32, value: u32, overwrite: u32) -> c_int { debug!("emscripten::_setenv"); let name_addr = emscripten_memory_pointer!(ctx.memory(0), name); let value_addr = emscripten_memory_pointer!(ctx.memory(0), value); @@ -44,7 +44,7 @@ pub fn _setenv(name: u32, value: u32, overwrite: u32, ctx: &mut Ctx) -> c_int { } /// emscripten: _putenv // (name: *const char); -pub fn _putenv(name: c_int, ctx: &mut Ctx) -> c_int { +pub fn _putenv(ctx: &mut Ctx, name: c_int) -> c_int { debug!("emscripten::_putenv"); let name_addr = emscripten_memory_pointer!(ctx.memory(0), name) as *const c_char; @@ -54,7 +54,7 @@ pub fn _putenv(name: c_int, ctx: &mut Ctx) -> c_int { } /// emscripten: _unsetenv // (name: *const char); -pub fn _unsetenv(name: u32, ctx: &mut Ctx) -> c_int { +pub fn _unsetenv(ctx: &mut Ctx, name: u32) -> c_int { debug!("emscripten::_unsetenv"); let name_addr = emscripten_memory_pointer!(ctx.memory(0), name); let name = read_string_from_wasm(ctx.memory(0), name); @@ -67,7 +67,7 @@ pub fn _unsetenv(name: u32, ctx: &mut Ctx) -> c_int { } #[allow(clippy::cast_ptr_alignment)] -pub fn _getpwnam(name_ptr: c_int, ctx: &mut Ctx) -> c_int { +pub fn _getpwnam(ctx: &mut Ctx, name_ptr: c_int) -> c_int { debug!("emscripten::_getpwnam {}", name_ptr); #[repr(C)] @@ -83,7 +83,7 @@ pub fn _getpwnam(name_ptr: c_int, ctx: &mut Ctx) -> c_int { // stub this in windows as it is not valid unsafe { - let passwd_struct_offset = call_malloc(mem::size_of::() as _, ctx); + let passwd_struct_offset = call_malloc(ctx, mem::size_of::() as _); let passwd_struct_ptr = emscripten_memory_pointer!(ctx.memory(0), passwd_struct_offset) as *mut GuestPasswd; (*passwd_struct_ptr).pw_name = 0; @@ -99,7 +99,7 @@ pub fn _getpwnam(name_ptr: c_int, ctx: &mut Ctx) -> c_int { } #[allow(clippy::cast_ptr_alignment)] -pub fn _getgrnam(name_ptr: c_int, ctx: &mut Ctx) -> c_int { +pub fn _getgrnam(ctx: &mut Ctx, name_ptr: c_int) -> c_int { debug!("emscripten::_getgrnam {}", name_ptr); #[repr(C)] @@ -112,7 +112,7 @@ pub fn _getgrnam(name_ptr: c_int, ctx: &mut Ctx) -> c_int { // stub the group struct as it is not supported on windows unsafe { - let group_struct_offset = call_malloc(mem::size_of::() as _, ctx); + let group_struct_offset = call_malloc(ctx, mem::size_of::() as _); let group_struct_ptr = emscripten_memory_pointer!(ctx.memory(0), group_struct_offset) as *mut GuestGroup; (*group_struct_ptr).gr_name = 0; @@ -123,7 +123,7 @@ pub fn _getgrnam(name_ptr: c_int, ctx: &mut Ctx) -> c_int { } } -pub fn _sysconf(name: c_int, _ctx: &mut Ctx) -> c_long { +pub fn _sysconf(_ctx: &mut Ctx, name: c_int) -> c_long { debug!("emscripten::_sysconf {}", name); // stub because sysconf is not valid on windows 0 diff --git a/lib/emscripten/src/errno.rs b/lib/emscripten/src/errno.rs index 647932810..06267e210 100644 --- a/lib/emscripten/src/errno.rs +++ b/lib/emscripten/src/errno.rs @@ -1,7 +1,7 @@ // use std::collections::HashMap; use wasmer_runtime_core::vm::Ctx; -pub fn ___seterrno(value: i32, _ctx: &mut Ctx) { +pub fn ___seterrno(_ctx: &mut Ctx, value: i32) { debug!("emscripten::___seterrno {}", value); // TODO: Incomplete impl eprintln!("failed to set errno!"); diff --git a/lib/emscripten/src/exception.rs b/lib/emscripten/src/exception.rs index b1814e107..b0aab78dd 100644 --- a/lib/emscripten/src/exception.rs +++ b/lib/emscripten/src/exception.rs @@ -3,14 +3,14 @@ use super::process::_abort; use wasmer_runtime_core::vm::Ctx; /// emscripten: ___cxa_allocate_exception -pub fn ___cxa_allocate_exception(size: u32, ctx: &mut Ctx) -> u32 { +pub fn ___cxa_allocate_exception(ctx: &mut Ctx, size: u32) -> u32 { debug!("emscripten::___cxa_allocate_exception"); - env::call_malloc(size as _, ctx) + env::call_malloc(ctx, size as _) } /// emscripten: ___cxa_throw /// TODO: We don't have support for exceptions yet -pub fn ___cxa_throw(_ptr: u32, _ty: u32, _destructor: u32, ctx: &mut Ctx) { +pub fn ___cxa_throw(ctx: &mut Ctx, _ptr: u32, _ty: u32, _destructor: u32) { debug!("emscripten::___cxa_throw"); _abort(ctx); } diff --git a/lib/emscripten/src/io/unix.rs b/lib/emscripten/src/io/unix.rs index a7c26a196..38324ac1e 100644 --- a/lib/emscripten/src/io/unix.rs +++ b/lib/emscripten/src/io/unix.rs @@ -3,12 +3,12 @@ use libc::printf as _printf; use wasmer_runtime_core::vm::Ctx; /// putchar -pub fn putchar(chr: i32, ctx: &mut Ctx) { +pub fn putchar(ctx: &mut Ctx, chr: i32) { unsafe { libc::putchar(chr) }; } /// printf -pub fn printf(memory_offset: i32, extra: i32, ctx: &mut Ctx) -> i32 { +pub fn printf(ctx: &mut Ctx, memory_offset: i32, extra: i32) -> i32 { debug!("emscripten::printf {}, {}", memory_offset, extra); unsafe { let addr = emscripten_memory_pointer!(ctx.memory(0), memory_offset) as _; diff --git a/lib/emscripten/src/io/windows.rs b/lib/emscripten/src/io/windows.rs index b85d9c54a..903d05900 100644 --- a/lib/emscripten/src/io/windows.rs +++ b/lib/emscripten/src/io/windows.rs @@ -15,12 +15,12 @@ use wasmer_runtime_core::vm::Ctx; //} /// putchar -pub fn putchar(chr: i32, ctx: &mut Ctx) { +pub fn putchar(ctx: &mut Ctx, chr: i32) { unsafe { libc::putchar(chr) }; } /// printf -pub fn printf(memory_offset: i32, extra: i32, ctx: &mut Ctx) -> i32 { +pub fn printf(ctx: &mut Ctx, memory_offset: i32, extra: i32) -> i32 { debug!("emscripten::printf {}, {}", memory_offset, extra); // unsafe { // let addr = emscripten_memory_pointer!(ctx.memory(0), memory_offset) as _; diff --git a/lib/emscripten/src/jmp.rs b/lib/emscripten/src/jmp.rs index 0c63593aa..c5b54f02b 100644 --- a/lib/emscripten/src/jmp.rs +++ b/lib/emscripten/src/jmp.rs @@ -4,7 +4,7 @@ use std::cell::UnsafeCell; use wasmer_runtime_core::vm::Ctx; /// setjmp -pub fn __setjmp(env_addr: u32, ctx: &mut Ctx) -> c_int { +pub fn __setjmp(ctx: &mut Ctx, env_addr: u32) -> c_int { debug!("emscripten::__setjmp (setjmp)"); unsafe { // Rather than using the env as the holder of the jump buffer pointer, @@ -15,7 +15,7 @@ pub fn __setjmp(env_addr: u32, ctx: &mut Ctx) -> c_int { let jump_buf: UnsafeCell<[u32; 27]> = UnsafeCell::new([0; 27]); let jumps = &mut get_emscripten_data(ctx).jumps; let result = setjmp(jump_buf.get() as _); - // We set the jump index to be the last value of jumps + // We set the jump index to be the last 3value of jumps *jump_index = jumps.len() as _; // We hold the reference of the jump buffer jumps.push(jump_buf); @@ -25,7 +25,7 @@ pub fn __setjmp(env_addr: u32, ctx: &mut Ctx) -> c_int { /// longjmp #[allow(unreachable_code)] -pub fn __longjmp(env_addr: u32, val: c_int, ctx: &mut Ctx) { +pub fn __longjmp(ctx: &mut Ctx, env_addr: u32, val: c_int) { debug!("emscripten::__longjmp (longmp)"); unsafe { // We retrieve the jump index from the env address diff --git a/lib/emscripten/src/lib.rs b/lib/emscripten/src/lib.rs index 0fb07d72c..999addb2e 100644 --- a/lib/emscripten/src/lib.rs +++ b/lib/emscripten/src/lib.rs @@ -141,7 +141,7 @@ pub fn run_emscripten_instance( let num_params = main_func.signature().params().len(); let _result = match num_params { 2 => { - let (argc, argv) = store_module_arguments(path, args, instance.context_mut()); + let (argc, argv) = store_module_arguments(instance.context_mut(), path, args); instance.call("_main", &[Value::I32(argc as i32), Value::I32(argv as i32)])?; } 0 => { @@ -158,17 +158,17 @@ pub fn run_emscripten_instance( Ok(()) } -fn store_module_arguments(path: &str, args: Vec<&str>, ctx: &mut Ctx) -> (u32, u32) { +fn store_module_arguments(ctx: &mut Ctx, path: &str, args: Vec<&str>) -> (u32, u32) { let argc = args.len() + 1; let mut args_slice = vec![0; argc]; - args_slice[0] = unsafe { allocate_cstr_on_stack(path, ctx).0 }; + args_slice[0] = unsafe { allocate_cstr_on_stack(ctx, path).0 }; for (slot, arg) in args_slice[1..argc].iter_mut().zip(args.iter()) { - *slot = unsafe { allocate_cstr_on_stack(&arg, ctx).0 }; + *slot = unsafe { allocate_cstr_on_stack(ctx, &arg).0 }; } let (argv_offset, argv_slice): (_, &mut [u32]) = - unsafe { allocate_on_stack(((argc + 1) * 4) as u32, ctx) }; + unsafe { allocate_on_stack(ctx, ((argc + 1) * 4) as u32) }; assert!(!argv_slice.is_empty()); for (slot, arg) in argv_slice[0..argc].iter_mut().zip(args_slice.iter()) { *slot = *arg diff --git a/lib/emscripten/src/linking.rs b/lib/emscripten/src/linking.rs index e61b9d1b1..831712e91 100644 --- a/lib/emscripten/src/linking.rs +++ b/lib/emscripten/src/linking.rs @@ -3,19 +3,19 @@ use wasmer_runtime_core::vm::Ctx; // TODO: Need to implement. /// emscripten: dlopen(filename: *const c_char, flag: c_int) -> *mut c_void -pub fn _dlopen(_filename: u32, _flag: u32, _ctx: &mut Ctx) -> i32 { +pub fn _dlopen(_ctx: &mut Ctx, _filename: u32, _flag: u32) -> i32 { debug!("emscripten::_dlopen"); -1 } /// emscripten: dlclose(handle: *mut c_void) -> c_int -pub fn _dlclose(_filename: u32, _ctx: &mut Ctx) -> i32 { +pub fn _dlclose(_ctx: &mut Ctx, _filename: u32) -> i32 { debug!("emscripten::_dlclose"); -1 } /// emscripten: dlsym(handle: *mut c_void, symbol: *const c_char) -> *mut c_void -pub fn _dlsym(_filepath: u32, _symbol: u32, _ctx: &mut Ctx) -> i32 { +pub fn _dlsym(_ctx: &mut Ctx, _filepath: u32, _symbol: u32) -> i32 { debug!("emscripten::_dlsym"); -1 } diff --git a/lib/emscripten/src/lock.rs b/lib/emscripten/src/lock.rs index 005a1baed..45f09581f 100644 --- a/lib/emscripten/src/lock.rs +++ b/lib/emscripten/src/lock.rs @@ -2,16 +2,16 @@ use libc::c_int; use wasmer_runtime_core::vm::Ctx; // NOTE: Not implemented by Emscripten -pub fn ___lock(what: c_int, _ctx: &mut Ctx) { +pub fn ___lock(_ctx: &mut Ctx, what: c_int) { debug!("emscripten::___lock {}", what); } // NOTE: Not implemented by Emscripten -pub fn ___unlock(what: c_int, _ctx: &mut Ctx) { +pub fn ___unlock(_ctx: &mut Ctx, what: c_int) { debug!("emscripten::___unlock {}", what); } // NOTE: Not implemented by Emscripten -pub fn ___wait(_which: u32, _varargs: u32, _three: u32, _four: u32, _ctx: &mut Ctx) { +pub fn ___wait(_ctx: &mut Ctx, _which: u32, _varargs: u32, _three: u32, _four: u32) { debug!("emscripten::___wait"); } diff --git a/lib/emscripten/src/math.rs b/lib/emscripten/src/math.rs index 16f3ed419..a60966a1c 100644 --- a/lib/emscripten/src/math.rs +++ b/lib/emscripten/src/math.rs @@ -1,23 +1,23 @@ use wasmer_runtime_core::vm::Ctx; /// emscripten: _llvm_log10_f64 -pub fn _llvm_log10_f64(value: f64, _ctx: &mut Ctx) -> f64 { +pub fn _llvm_log10_f64(_ctx: &mut Ctx, value: f64) -> f64 { debug!("emscripten::_llvm_log10_f64"); value.log10() } /// emscripten: _llvm_log2_f64 -pub fn _llvm_log2_f64(value: f64, _ctx: &mut Ctx) -> f64 { +pub fn _llvm_log2_f64(_ctx: &mut Ctx, value: f64) -> f64 { debug!("emscripten::_llvm_log2_f64"); value.log2() } -pub fn _llvm_log10_f32(_value: f64, _ctx: &mut Ctx) -> f64 { +pub fn _llvm_log10_f32(_ctx: &mut Ctx, _value: f64) -> f64 { debug!("emscripten::_llvm_log10_f32"); -1.0 } -pub fn _llvm_log2_f32(_value: f64, _ctx: &mut Ctx) -> f64 { +pub fn _llvm_log2_f32(_ctx: &mut Ctx, _value: f64) -> f64 { debug!("emscripten::_llvm_log10_f32"); -1.0 } @@ -28,12 +28,12 @@ pub fn _emscripten_random(_ctx: &mut Ctx) -> f64 { } // emscripten: f64-rem -pub fn f64_rem(x: f64, y: f64, _ctx: &mut Ctx) -> f64 { +pub fn f64_rem(_ctx: &mut Ctx, x: f64, y: f64) -> f64 { debug!("emscripten::f64-rem"); x % y } // emscripten: global.Math pow -pub fn pow(x: f64, y: f64, _ctx: &mut Ctx) -> f64 { +pub fn pow(_ctx: &mut Ctx, x: f64, y: f64) -> f64 { x.powf(y) } diff --git a/lib/emscripten/src/memory.rs b/lib/emscripten/src/memory.rs index e174e023d..c4540dff0 100644 --- a/lib/emscripten/src/memory.rs +++ b/lib/emscripten/src/memory.rs @@ -3,7 +3,7 @@ use libc::{c_int, c_void, memcpy, size_t}; use wasmer_runtime_core::vm::Ctx; /// emscripten: _emscripten_memcpy_big -pub fn _emscripten_memcpy_big(dest: u32, src: u32, len: u32, ctx: &mut Ctx) -> u32 { +pub fn _emscripten_memcpy_big(ctx: &mut Ctx, dest: u32, src: u32, len: u32) -> u32 { debug!( "emscripten::_emscripten_memcpy_big {}, {}, {}", dest, src, len @@ -35,12 +35,12 @@ pub fn enlarge_memory(_ctx: &mut Ctx) -> u32 { /// emscripten: abortOnCannotGrowMemory pub fn abort_on_cannot_grow_memory(ctx: &mut Ctx) -> u32 { debug!("emscripten::abort_on_cannot_grow_memory"); - abort_with_message("Cannot enlarge memory arrays!", ctx); + abort_with_message(ctx, "Cannot enlarge memory arrays!"); 0 } /// emscripten: ___map_file -pub fn ___map_file(_one: u32, _two: u32, _ctx: &mut Ctx) -> c_int { +pub fn ___map_file(_ctx: &mut Ctx, _one: u32, _two: u32) -> c_int { debug!("emscripten::___map_file"); // NOTE: TODO: Em returns -1 here as well. May need to implement properly -1 diff --git a/lib/emscripten/src/nullfunc.rs b/lib/emscripten/src/nullfunc.rs index 253edf8f6..7fb44ab11 100644 --- a/lib/emscripten/src/nullfunc.rs +++ b/lib/emscripten/src/nullfunc.rs @@ -1,67 +1,67 @@ use super::process::abort_with_message; use wasmer_runtime_core::vm::Ctx; -pub fn nullfunc_i(x: u32, ctx: &mut Ctx) { +pub fn nullfunc_i(ctx: &mut Ctx, x: u32) { debug!("emscripten::nullfunc_i {}", x); - abort_with_message("Invalid function pointer called with signature 'i'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)", ctx); + abort_with_message(ctx, "Invalid function pointer called with signature 'i'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)"); } -pub fn nullfunc_ii(x: u32, ctx: &mut Ctx) { +pub fn nullfunc_ii(ctx: &mut Ctx, x: u32) { debug!("emscripten::nullfunc_ii {}", x); - abort_with_message("Invalid function pointer called with signature 'ii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)", ctx); + abort_with_message(ctx, "Invalid function pointer called with signature 'ii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)"); } -pub fn nullfunc_iii(x: u32, ctx: &mut Ctx) { +pub fn nullfunc_iii(ctx: &mut Ctx, x: u32) { debug!("emscripten::nullfunc_iii {}", x); - abort_with_message("Invalid function pointer called with signature 'iii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)", ctx); + abort_with_message(ctx, "Invalid function pointer called with signature 'iii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)"); } -pub fn nullfunc_iiii(x: u32, ctx: &mut Ctx) { +pub fn nullfunc_iiii(ctx: &mut Ctx, x: u32) { debug!("emscripten::nullfunc_iiii {}", x); - abort_with_message("Invalid function pointer called with signature 'iiii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)", ctx); + abort_with_message(ctx, "Invalid function pointer called with signature 'iiii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)"); } -pub fn nullfunc_iiiii(x: u32, ctx: &mut Ctx) { +pub fn nullfunc_iiiii(ctx: &mut Ctx, x: u32) { debug!("emscripten::nullfunc_iiiii {}", x); - abort_with_message("Invalid function pointer called with signature 'iiiii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)", ctx); + abort_with_message(ctx, "Invalid function pointer called with signature 'iiiii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)"); } -pub fn nullfunc_iiiiii(x: u32, ctx: &mut Ctx) { +pub fn nullfunc_iiiiii(ctx: &mut Ctx, x: u32) { debug!("emscripten::nullfunc_iiiiii {}", x); - abort_with_message("Invalid function pointer called with signature 'iiiiii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)", ctx); + abort_with_message(ctx, "Invalid function pointer called with signature 'iiiiii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)"); } -pub fn nullfunc_v(x: u32, ctx: &mut Ctx) { +pub fn nullfunc_v(ctx: &mut Ctx, x: u32) { debug!("emscripten::nullfunc_v {}", x); - abort_with_message("Invalid function pointer called with signature 'v'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)", ctx); + abort_with_message(ctx, "Invalid function pointer called with signature 'v'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)"); } -pub fn nullfunc_vi(x: u32, ctx: &mut Ctx) { +pub fn nullfunc_vi(ctx: &mut Ctx, x: u32) { debug!("emscripten::nullfunc_vi {}", x); - abort_with_message("Invalid function pointer called with signature 'vi'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)", ctx); + abort_with_message(ctx, "Invalid function pointer called with signature 'vi'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)"); } -pub fn nullfunc_vii(x: u32, ctx: &mut Ctx) { +pub fn nullfunc_vii(ctx: &mut Ctx, x: u32) { debug!("emscripten::nullfunc_vii {}", x); - abort_with_message("Invalid function pointer called with signature 'vii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)", ctx); + abort_with_message(ctx, "Invalid function pointer called with signature 'vii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)"); } -pub fn nullfunc_viii(x: u32, ctx: &mut Ctx) { +pub fn nullfunc_viii(ctx: &mut Ctx, x: u32) { debug!("emscripten::nullfunc_viii {}", x); - abort_with_message("Invalid function pointer called with signature 'viii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)", ctx); + abort_with_message(ctx, "Invalid function pointer called with signature 'viii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)"); } -pub fn nullfunc_viiii(x: u32, ctx: &mut Ctx) { +pub fn nullfunc_viiii(ctx: &mut Ctx, x: u32) { debug!("emscripten::nullfunc_viiii {}", x); - abort_with_message("Invalid function pointer called with signature 'viiii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)", ctx); + abort_with_message(ctx, "Invalid function pointer called with signature 'viiii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)"); } -pub fn nullfunc_viiiii(_x: u32, ctx: &mut Ctx) { +pub fn nullfunc_viiiii(ctx: &mut Ctx, _x: u32) { debug!("emscripten::nullfunc_viiiii"); - abort_with_message("Invalid function pointer called with signature 'viiiii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)", ctx); + abort_with_message(ctx, "Invalid function pointer called with signature 'viiiii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)"); } -pub fn nullfunc_viiiiii(_x: u32, ctx: &mut Ctx) { +pub fn nullfunc_viiiiii(ctx: &mut Ctx, _x: u32) { debug!("emscripten::nullfunc_viiiiii"); - abort_with_message("Invalid function pointer called with signature 'viiiiii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)", ctx); + abort_with_message(ctx, "Invalid function pointer called with signature 'viiiiii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)"); } diff --git a/lib/emscripten/src/process.rs b/lib/emscripten/src/process.rs index d6be7a78b..8d1dddb48 100644 --- a/lib/emscripten/src/process.rs +++ b/lib/emscripten/src/process.rs @@ -9,7 +9,7 @@ type pid_t = c_int; use std::ffi::CStr; use wasmer_runtime_core::vm::Ctx; -pub fn abort_with_message(message: &str, ctx: &mut Ctx) { +pub fn abort_with_message(ctx: &mut Ctx, message: &str) { debug!("emscripten::abort_with_message"); println!("{}", message); _abort(ctx); @@ -34,19 +34,19 @@ pub fn _endgrent(_ctx: &mut Ctx) { debug!("emscripten::_endgrent"); } -pub fn _execve(_one: i32, _two: i32, _three: i32, _ctx: &mut Ctx) -> i32 { +pub fn _execve(_ctx: &mut Ctx, _one: i32, _two: i32, _three: i32) -> i32 { debug!("emscripten::_execve"); -1 } #[allow(unreachable_code)] -pub fn _exit(status: c_int, _ctx: &mut Ctx) { +pub fn _exit(_ctx: &mut Ctx, status: c_int) { // -> ! debug!("emscripten::_exit {}", status); unsafe { exit(status) } } -pub fn em_abort(message: u32, ctx: &mut Ctx) { +pub fn em_abort(ctx: &mut Ctx, message: u32) { debug!("emscripten::em_abort {}", message); let message_addr = emscripten_memory_pointer!(ctx.memory(0), message) as *mut c_char; unsafe { @@ -54,11 +54,11 @@ pub fn em_abort(message: u32, ctx: &mut Ctx) { .to_str() .unwrap_or("Unexpected abort"); - abort_with_message(message, ctx); + abort_with_message(ctx, message); } } -pub fn _kill(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 { +pub fn _kill(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { debug!("emscripten::_kill"); -1 } @@ -73,26 +73,26 @@ pub fn _llvm_stacksave(_ctx: &mut Ctx) -> i32 { -1 } -pub fn _llvm_stackrestore(_one: i32, _ctx: &mut Ctx) { +pub fn _llvm_stackrestore(_ctx: &mut Ctx, _one: i32) { debug!("emscripten::_llvm_stackrestore"); } -pub fn _raise(_one: i32, _ctx: &mut Ctx) -> i32 { +pub fn _raise(_ctx: &mut Ctx, _one: i32) -> i32 { debug!("emscripten::_raise"); -1 } -pub fn _sem_init(_one: i32, _two: i32, _three: i32, _ctx: &mut Ctx) -> i32 { +pub fn _sem_init(_ctx: &mut Ctx, _one: i32, _two: i32, _three: i32) -> i32 { debug!("emscripten::_sem_init"); -1 } -pub fn _sem_post(_one: i32, _ctx: &mut Ctx) -> i32 { +pub fn _sem_post(_ctx: &mut Ctx, _one: i32) -> i32 { debug!("emscripten::_sem_post"); -1 } -pub fn _sem_wait(_one: i32, _ctx: &mut Ctx) -> i32 { +pub fn _sem_wait(_ctx: &mut Ctx, _one: i32) -> i32 { debug!("emscripten::_sem_post"); -1 } @@ -107,53 +107,53 @@ pub fn _setgrent(_ctx: &mut Ctx) { debug!("emscripten::_setgrent"); } -pub fn _setgroups(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 { +pub fn _setgroups(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { debug!("emscripten::_setgroups"); -1 } -pub fn _setitimer(_one: i32, _two: i32, _three: i32, _ctx: &mut Ctx) -> i32 { +pub fn _setitimer(_ctx: &mut Ctx, _one: i32, _two: i32, _three: i32) -> i32 { debug!("emscripten::_setitimer"); -1 } -pub fn _usleep(_one: i32, _ctx: &mut Ctx) -> i32 { +pub fn _usleep(_ctx: &mut Ctx, _one: i32) -> i32 { debug!("emscripten::_usleep"); -1 } -pub fn _utimes(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 { +pub fn _utimes(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { debug!("emscripten::_utimes"); -1 } -pub fn _waitpid(_one: i32, _two: i32, _three: i32, _ctx: &mut Ctx) -> i32 { +pub fn _waitpid(_ctx: &mut Ctx, _one: i32, _two: i32, _three: i32) -> i32 { debug!("emscripten::_waitpid"); -1 } -pub fn abort_stack_overflow(_what: c_int, ctx: &mut Ctx) { +pub fn abort_stack_overflow(ctx: &mut Ctx, _what: c_int) { debug!("emscripten::abort_stack_overflow"); // TODO: Message incomplete. Need to finish em runtime data first abort_with_message( - "Stack overflow! Attempted to allocate some bytes on the stack", ctx, + "Stack overflow! Attempted to allocate some bytes on the stack", ); } pub fn _llvm_trap(ctx: &mut Ctx) { debug!("emscripten::_llvm_trap"); - abort_with_message("abort!", ctx); + abort_with_message(ctx, "abort!"); } -pub fn _system(_one: i32, _ctx: &mut Ctx) -> c_int { +pub fn _system(_ctx: &mut Ctx, _one: i32) -> c_int { debug!("emscripten::_system"); // TODO: May need to change this Em impl to a working version eprintln!("Can't call external programs"); return EAGAIN; } -pub fn _popen(_one: i32, _two: i32, _ctx: &mut Ctx) -> c_int { +pub fn _popen(_ctx: &mut Ctx, _one: i32, _two: i32) -> c_int { debug!("emscripten::_popen"); // TODO: May need to change this Em impl to a working version eprintln!("Missing function: popen"); diff --git a/lib/emscripten/src/signal.rs b/lib/emscripten/src/signal.rs index 1a6d43078..f7657630b 100644 --- a/lib/emscripten/src/signal.rs +++ b/lib/emscripten/src/signal.rs @@ -2,7 +2,7 @@ use wasmer_runtime_core::vm::Ctx; #[allow(clippy::cast_ptr_alignment)] -pub fn _sigemptyset(set: u32, ctx: &mut Ctx) -> i32 { +pub fn _sigemptyset(ctx: &mut Ctx, set: u32) -> i32 { debug!("emscripten::_sigemptyset"); let set_addr = emscripten_memory_pointer!(ctx.memory(0), set) as *mut u32; unsafe { @@ -11,13 +11,13 @@ pub fn _sigemptyset(set: u32, ctx: &mut Ctx) -> i32 { 0 } -pub fn _sigaction(signum: u32, act: u32, oldact: u32, _ctx: &mut Ctx) -> i32 { +pub fn _sigaction(_ctx: &mut Ctx, signum: u32, act: u32, oldact: u32) -> i32 { debug!("emscripten::_sigaction {}, {}, {}", signum, act, oldact); 0 } #[allow(clippy::cast_ptr_alignment)] -pub fn _sigaddset(set: u32, signum: u32, ctx: &mut Ctx) -> i32 { +pub fn _sigaddset(ctx: &mut Ctx, set: u32, signum: u32) -> i32 { debug!("emscripten::_sigaddset {}, {}", set, signum); let set_addr = emscripten_memory_pointer!(ctx.memory(0), set) as *mut u32; unsafe { @@ -26,17 +26,17 @@ pub fn _sigaddset(set: u32, signum: u32, ctx: &mut Ctx) -> i32 { 0 } -pub fn _sigsuspend(_one: i32, _ctx: &mut Ctx) -> i32 { +pub fn _sigsuspend(_ctx: &mut Ctx, _one: i32) -> i32 { debug!("emscripten::_sigsuspend"); -1 } -pub fn _sigprocmask(_one: i32, _two: i32, _three: i32, _ctx: &mut Ctx) -> i32 { +pub fn _sigprocmask(_ctx: &mut Ctx, _one: i32, _two: i32, _three: i32) -> i32 { debug!("emscripten::_sigprocmask"); 0 } -pub fn _signal(sig: u32, _two: i32, _ctx: &mut Ctx) -> i32 { +pub fn _signal(_ctx: &mut Ctx, sig: u32, _two: i32) -> i32 { debug!("emscripten::_signal ({})", sig); 0 } diff --git a/lib/emscripten/src/syscalls/mod.rs b/lib/emscripten/src/syscalls/mod.rs index edae4860c..38c4157d1 100644 --- a/lib/emscripten/src/syscalls/mod.rs +++ b/lib/emscripten/src/syscalls/mod.rs @@ -70,7 +70,7 @@ use libc::SO_NOSIGPIPE; const SO_NOSIGPIPE: c_int = 0; /// exit -pub fn ___syscall1(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) { +pub fn ___syscall1(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) { debug!("emscripten::___syscall1 (exit) {}", which); let status: i32 = varargs.get(ctx); unsafe { @@ -79,7 +79,7 @@ pub fn ___syscall1(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) { } /// read -pub fn ___syscall3(which: i32, mut varargs: VarArgs, ctx: &mut Ctx) -> i32 { +pub fn ___syscall3(ctx: &mut Ctx, which: i32, mut varargs: VarArgs) -> i32 { // -> ssize_t debug!("emscripten::___syscall3 (read) {}", which); let fd: i32 = varargs.get(ctx); @@ -93,7 +93,7 @@ pub fn ___syscall3(which: i32, mut varargs: VarArgs, ctx: &mut Ctx) -> i32 { } /// write -pub fn ___syscall4(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int { +pub fn ___syscall4(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall4 (write) {}", which); let fd: i32 = varargs.get(ctx); let buf: u32 = varargs.get(ctx); @@ -104,7 +104,7 @@ pub fn ___syscall4(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int { } /// open -pub fn ___syscall5(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int { +pub fn ___syscall5(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall5 (open) {}", which); let pathname: u32 = varargs.get(ctx); let flags: i32 = varargs.get(ctx); @@ -120,7 +120,7 @@ pub fn ___syscall5(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int { } /// close -pub fn ___syscall6(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int { +pub fn ___syscall6(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall6 (close) {}", which); let fd: i32 = varargs.get(ctx); debug!("fd: {}", fd); @@ -128,7 +128,7 @@ pub fn ___syscall6(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int { } // chdir -pub fn ___syscall12(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int { +pub fn ___syscall12(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall12 (chdir) {}", which); let path_addr: i32 = varargs.get(ctx); unsafe { @@ -140,42 +140,42 @@ pub fn ___syscall12(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int } } -pub fn ___syscall10(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 { +pub fn ___syscall10(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall10"); -1 } -pub fn ___syscall15(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 { +pub fn ___syscall15(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall15"); -1 } // getpid -pub fn ___syscall20(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 { +pub fn ___syscall20(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall20 (getpid)"); unsafe { getpid() } } -pub fn ___syscall38(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 { +pub fn ___syscall38(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall38"); -1 } // rmdir -pub fn ___syscall40(_which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int { +pub fn ___syscall40(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall40 (rmdir)"); let pathname: u32 = varargs.get(ctx); let pathname_addr = emscripten_memory_pointer!(ctx.memory(0), pathname) as *const i8; unsafe { rmdir(pathname_addr) } } -pub fn ___syscall60(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 { +pub fn ___syscall60(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall60"); -1 } // dup2 -pub fn ___syscall63(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int { +pub fn ___syscall63(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall63 (dup2) {}", which); let src: i32 = varargs.get(ctx); @@ -185,43 +185,43 @@ pub fn ___syscall63(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int } // getppid -pub fn ___syscall64(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 { +pub fn ___syscall64(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall64 (getppid)"); unsafe { getpid() } } -pub fn ___syscall66(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 { +pub fn ___syscall66(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall66"); -1 } -pub fn ___syscall75(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 { +pub fn ___syscall75(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall75"); -1 } -pub fn ___syscall85(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 { +pub fn ___syscall85(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall85"); -1 } -pub fn ___syscall91(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 { +pub fn ___syscall91(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall91"); -1 } -pub fn ___syscall97(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 { +pub fn ___syscall97(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall97"); -1 } -pub fn ___syscall110(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 { +pub fn ___syscall110(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall110"); -1 } // mmap2 -pub fn ___syscall192(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int { +pub fn ___syscall192(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall192 (mmap2) {}", which); let addr: i32 = varargs.get(ctx); let len: u32 = varargs.get(ctx); @@ -235,11 +235,11 @@ pub fn ___syscall192(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int ); if fd == -1 { - let ptr = env::call_memalign(16384, len, ctx); + let ptr = env::call_memalign(ctx, 16384, len); if ptr == 0 { return -1; } - env::call_memset(ptr, 0, len, ctx); + env::call_memset(ctx, ptr, 0, len); ptr as _ } else { -1 @@ -247,7 +247,7 @@ pub fn ___syscall192(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int } /// lseek -pub fn ___syscall140(which: i32, mut varargs: VarArgs, ctx: &mut Ctx) -> i32 { +pub fn ___syscall140(ctx: &mut Ctx, which: i32, mut varargs: VarArgs) -> i32 { // -> c_int debug!("emscripten::___syscall140 (lseek) {}", which); let fd: i32 = varargs.get(ctx); @@ -259,7 +259,7 @@ pub fn ___syscall140(which: i32, mut varargs: VarArgs, ctx: &mut Ctx) -> i32 { /// readv #[allow(clippy::cast_ptr_alignment)] -pub fn ___syscall145(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> i32 { +pub fn ___syscall145(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> i32 { // -> ssize_t debug!("emscripten::___syscall145 (readv) {}", which); // let fd: i32 = varargs.get(ctx); @@ -302,7 +302,7 @@ pub fn ___syscall145(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> i32 { // writev #[allow(clippy::cast_ptr_alignment)] -pub fn ___syscall146(which: i32, mut varargs: VarArgs, ctx: &mut Ctx) -> i32 { +pub fn ___syscall146(ctx: &mut Ctx, which: i32, mut varargs: VarArgs) -> i32 { // -> ssize_t debug!("emscripten::___syscall146 (writev) {}", which); let fd: i32 = varargs.get(ctx); @@ -336,33 +336,33 @@ pub fn ___syscall146(which: i32, mut varargs: VarArgs, ctx: &mut Ctx) -> i32 { } } -pub fn ___syscall168(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 { +pub fn ___syscall168(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall168"); -1 } -pub fn ___syscall191(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 { +pub fn ___syscall191(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall191 - stub"); -1 } -pub fn ___syscall194(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 { +pub fn ___syscall194(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall194 - stub"); -1 } -pub fn ___syscall196(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 { +pub fn ___syscall196(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall194 - stub"); -1 } -pub fn ___syscall199(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 { +pub fn ___syscall199(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall199 - stub"); -1 } // stat64 -pub fn ___syscall195(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int { +pub fn ___syscall195(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall195 (stat64) {}", which); let pathname: u32 = varargs.get(ctx); let buf: u32 = varargs.get(ctx); @@ -382,7 +382,7 @@ pub fn ___syscall195(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int } // fstat64 -pub fn ___syscall197(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int { +pub fn ___syscall197(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall197 (fstat64) {}", which); let fd: c_int = varargs.get(ctx); let buf: u32 = varargs.get(ctx); @@ -400,13 +400,13 @@ pub fn ___syscall197(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int 0 } -pub fn ___syscall220(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 { +pub fn ___syscall220(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall220"); -1 } // fcntl64 -pub fn ___syscall221(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int { +pub fn ___syscall221(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall221 (fcntl64) {}", which); // fcntl64 let _fd: i32 = varargs.get(ctx); @@ -417,33 +417,33 @@ pub fn ___syscall221(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int } } -pub fn ___syscall268(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 { +pub fn ___syscall268(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall268"); -1 } -pub fn ___syscall272(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 { +pub fn ___syscall272(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall272"); -1 } -pub fn ___syscall295(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 { +pub fn ___syscall295(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall295"); -1 } -pub fn ___syscall300(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 { +pub fn ___syscall300(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall300"); -1 } -pub fn ___syscall334(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 { +pub fn ___syscall334(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall334"); -1 } // prlimit64 -pub fn ___syscall340(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int { +pub fn ___syscall340(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall340 (prlimit64), {}", which); // NOTE: Doesn't really matter. Wasm modules cannot exceed WASM_PAGE_SIZE anyway. let _pid: i32 = varargs.get(ctx); diff --git a/lib/emscripten/src/syscalls/unix.rs b/lib/emscripten/src/syscalls/unix.rs index 00b3b47e8..766f78b92 100644 --- a/lib/emscripten/src/syscalls/unix.rs +++ b/lib/emscripten/src/syscalls/unix.rs @@ -94,7 +94,7 @@ use libc::SO_NOSIGPIPE; const SO_NOSIGPIPE: c_int = 0; // chown -pub fn ___syscall212(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int { +pub fn ___syscall212(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall212 (chown) {}", which); let pathname: u32 = varargs.get(ctx); @@ -107,7 +107,7 @@ pub fn ___syscall212(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int } // mkdir -pub fn ___syscall39(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int { +pub fn ___syscall39(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall39 (mkdir) {}", which); let pathname: u32 = varargs.get(ctx); let mode: u32 = varargs.get(ctx); @@ -116,7 +116,7 @@ pub fn ___syscall39(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int } // getgid -pub fn ___syscall201(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 { +pub fn ___syscall201(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall201 (getgid)"); unsafe { // Maybe fix: Emscripten returns 0 always @@ -125,7 +125,7 @@ pub fn ___syscall201(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 { } // getgid32 -pub fn ___syscall202(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 { +pub fn ___syscall202(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { // gid_t debug!("emscripten::___syscall202 (getgid32)"); unsafe { @@ -135,7 +135,7 @@ pub fn ___syscall202(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 { } /// dup3 -pub fn ___syscall330(_which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> pid_t { +pub fn ___syscall330(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> pid_t { // Implementation based on description at https://linux.die.net/man/2/dup3 debug!("emscripten::___syscall330 (dup3)"); let oldfd: c_int = varargs.get(ctx); @@ -169,7 +169,7 @@ pub fn ___syscall330(_which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> pid_ } /// ioctl -pub fn ___syscall54(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int { +pub fn ___syscall54(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall54 (ioctl) {}", which); let fd: i32 = varargs.get(ctx); let request: u32 = varargs.get(ctx); @@ -212,7 +212,7 @@ pub fn ___syscall54(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int // socketcall #[allow(clippy::cast_ptr_alignment)] -pub fn ___syscall102(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int { +pub fn ___syscall102(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall102 (socketcall) {}", which); let call: u32 = varargs.get(ctx); let mut socket_varargs: VarArgs = varargs.get(ctx); @@ -464,7 +464,7 @@ pub fn ___syscall102(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int } // pread -pub fn ___syscall180(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int { +pub fn ___syscall180(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall180 (pread) {}", which); let fd: i32 = varargs.get(ctx); let buf: u32 = varargs.get(ctx); @@ -481,7 +481,7 @@ pub fn ___syscall180(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int } // pwrite -pub fn ___syscall181(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int { +pub fn ___syscall181(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall181 (pwrite) {}", which); let fd: i32 = varargs.get(ctx); let buf: u32 = varargs.get(ctx); @@ -503,7 +503,7 @@ pub fn ___syscall181(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int /// wait4 #[allow(clippy::cast_ptr_alignment)] -pub fn ___syscall114(_which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> pid_t { +pub fn ___syscall114(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> pid_t { debug!("emscripten::___syscall114 (wait4)"); let pid: pid_t = varargs.get(ctx); let status: u32 = varargs.get(ctx); @@ -521,7 +521,7 @@ pub fn ___syscall114(_which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> pid_ // select #[allow(clippy::cast_ptr_alignment)] -pub fn ___syscall142(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int { +pub fn ___syscall142(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall142 (newselect) {}", which); let nfds: i32 = varargs.get(ctx); @@ -540,7 +540,7 @@ pub fn ___syscall142(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int } // setpgid -pub fn ___syscall57(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int { +pub fn ___syscall57(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall57 (setpgid) {}", which); let pid: i32 = varargs.get(ctx); let pgid: i32 = varargs.get(ctx); @@ -549,7 +549,7 @@ pub fn ___syscall57(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int /// uname // NOTE: Wondering if we should return custom utsname, like Emscripten. -pub fn ___syscall122(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int { +pub fn ___syscall122(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall122 (uname) {}", which); let buf: u32 = varargs.get(ctx); debug!("=> buf: {}", buf); diff --git a/lib/emscripten/src/syscalls/windows.rs b/lib/emscripten/src/syscalls/windows.rs index 2b577fcac..41c4cf7eb 100644 --- a/lib/emscripten/src/syscalls/windows.rs +++ b/lib/emscripten/src/syscalls/windows.rs @@ -6,13 +6,13 @@ use wasmer_runtime_core::vm::Ctx; type pid_t = c_int; // chown -pub fn ___syscall212(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int { +pub fn ___syscall212(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall212 (chown) {}", which); -1 } // mkdir -pub fn ___syscall39(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int { +pub fn ___syscall39(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall39 (mkdir) {}", which); let pathname: u32 = varargs.get(ctx); let mode: u32 = varargs.get(ctx); @@ -21,72 +21,72 @@ pub fn ___syscall39(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int } // getgid -pub fn ___syscall201(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 { +pub fn ___syscall201(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall201 (getgid)"); -1 } // getgid32 -pub fn ___syscall202(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 { +pub fn ___syscall202(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { // gid_t debug!("emscripten::___syscall202 (getgid32)"); -1 } /// dup3 -pub fn ___syscall330(_which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> pid_t { +pub fn ___syscall330(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> pid_t { debug!("emscripten::___syscall330 (dup3)"); -1 } /// ioctl -pub fn ___syscall54(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int { +pub fn ___syscall54(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall54 (ioctl) {}", which); -1 } // socketcall #[allow(clippy::cast_ptr_alignment)] -pub fn ___syscall102(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int { +pub fn ___syscall102(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall102 (socketcall) {}", which); -1 } // pread -pub fn ___syscall180(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int { +pub fn ___syscall180(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall180 (pread) {}", which); -1 } // pwrite -pub fn ___syscall181(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int { +pub fn ___syscall181(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall181 (pwrite) {}", which); -1 } /// wait4 #[allow(clippy::cast_ptr_alignment)] -pub fn ___syscall114(_which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> pid_t { +pub fn ___syscall114(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> pid_t { debug!("emscripten::___syscall114 (wait4)"); -1 } // select #[allow(clippy::cast_ptr_alignment)] -pub fn ___syscall142(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int { +pub fn ___syscall142(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall142 (newselect) {}", which); -1 } // setpgid -pub fn ___syscall57(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int { +pub fn ___syscall57(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall57 (setpgid) {}", which); -1 } /// uname // NOTE: Wondering if we should return custom utsname, like Emscripten. -pub fn ___syscall122(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int { +pub fn ___syscall122(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall122 (uname) {}", which); -1 } diff --git a/lib/emscripten/src/time.rs b/lib/emscripten/src/time.rs index 2ecdfe6a8..8386a36ae 100644 --- a/lib/emscripten/src/time.rs +++ b/lib/emscripten/src/time.rs @@ -38,7 +38,7 @@ const CLOCK_MONOTONIC_COARSE: clockid_t = 6; /// emscripten: _gettimeofday #[allow(clippy::cast_ptr_alignment)] -pub fn _gettimeofday(tp: c_int, tz: c_int, ctx: &mut Ctx) -> c_int { +pub fn _gettimeofday(ctx: &mut Ctx, tp: c_int, tz: c_int) -> c_int { debug!("emscripten::_gettimeofday {} {}", tp, tz); #[repr(C)] struct GuestTimeVal { @@ -63,7 +63,7 @@ pub fn _gettimeofday(tp: c_int, tz: c_int, ctx: &mut Ctx) -> c_int { /// emscripten: _clock_gettime #[allow(clippy::cast_ptr_alignment)] -pub fn _clock_gettime(clk_id: clockid_t, tp: c_int, ctx: &mut Ctx) -> c_int { +pub fn _clock_gettime(ctx: &mut Ctx, clk_id: clockid_t, tp: c_int) -> c_int { debug!("emscripten::_clock_gettime {} {}", clk_id, tp); // debug!("Memory {:?}", ctx.memory(0)[..]); #[repr(C)] @@ -94,9 +94,9 @@ pub fn _clock_gettime(clk_id: clockid_t, tp: c_int, ctx: &mut Ctx) -> c_int { } /// emscripten: ___clock_gettime -pub fn ___clock_gettime(clk_id: clockid_t, tp: c_int, ctx: &mut Ctx) -> c_int { +pub fn ___clock_gettime(ctx: &mut Ctx, clk_id: clockid_t, tp: c_int) -> c_int { debug!("emscripten::___clock_gettime {} {}", clk_id, tp); - _clock_gettime(clk_id, tp, ctx) + _clock_gettime(ctx, clk_id, tp) } /// emscripten: _clock @@ -106,22 +106,22 @@ pub fn _clock(_ctx: &mut Ctx) -> c_int { } /// emscripten: _difftime -pub fn _difftime(t0: u32, t1: u32, _ctx: &mut Ctx) -> f64 { +pub fn _difftime(_ctx: &mut Ctx, t0: u32, t1: u32) -> f64 { debug!("emscripten::_difftime"); (t0 - t1) as _ } -pub fn _gmtime_r(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 { +pub fn _gmtime_r(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { debug!("emscripten::_gmtime_r"); -1 } -pub fn _mktime(_one: i32, _ctx: &mut Ctx) -> i32 { +pub fn _mktime(_ctx: &mut Ctx, _one: i32) -> i32 { debug!("emscripten::_mktime"); -1 } -pub fn _gmtime(_one: i32, _ctx: &mut Ctx) -> i32 { +pub fn _gmtime(_ctx: &mut Ctx, _one: i32) -> i32 { debug!("emscripten::_gmtime"); -1 } @@ -148,7 +148,7 @@ pub fn _tvset(_ctx: &mut Ctx) { /// formats time as a C string #[allow(clippy::cast_ptr_alignment)] -unsafe fn fmt_time(time: u32, ctx: &mut Ctx) -> *const c_char { +unsafe fn fmt_time(ctx: &mut Ctx, time: u32) -> *const c_char { let date = &*(emscripten_memory_pointer!(ctx.memory(0), time) as *mut guest_tm); let days = vec!["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; @@ -173,11 +173,11 @@ unsafe fn fmt_time(time: u32, ctx: &mut Ctx) -> *const c_char { } /// emscripten: _asctime -pub fn _asctime(time: u32, ctx: &mut Ctx) -> u32 { +pub fn _asctime(ctx: &mut Ctx, time: u32) -> u32 { debug!("emscripten::_asctime {}", time); unsafe { - let time_str_ptr = fmt_time(time, ctx); + let time_str_ptr = fmt_time(ctx, time); copy_cstr_into_wasm(ctx, time_str_ptr) // let c_str = emscripten_memory_pointer!(ctx.memory(0), res) as *mut i8; @@ -187,7 +187,7 @@ pub fn _asctime(time: u32, ctx: &mut Ctx) -> u32 { } /// emscripten: _asctime_r -pub fn _asctime_r(time: u32, buf: u32, ctx: &mut Ctx) -> u32 { +pub fn _asctime_r(ctx: &mut Ctx, time: u32, buf: u32) -> u32 { debug!("emscripten::_asctime_r {}, {}", time, buf); unsafe { @@ -195,8 +195,8 @@ pub fn _asctime_r(time: u32, buf: u32, ctx: &mut Ctx) -> u32 { // to write out more than 26 bytes (including the null terminator). // See http://pubs.opengroup.org/onlinepubs/9699919799/functions/asctime.html // Our undefined behavior is to truncate the write to at most 26 bytes, including null terminator. - let time_str_ptr = fmt_time(time, ctx); - write_to_buf(time_str_ptr, buf, 26, ctx) + let time_str_ptr = fmt_time(ctx, time); + write_to_buf(ctx, time_str_ptr, buf, 26) // let c_str = emscripten_memory_pointer!(ctx.memory(0), res) as *mut i8; // use std::ffi::CStr; @@ -206,7 +206,7 @@ pub fn _asctime_r(time: u32, buf: u32, ctx: &mut Ctx) -> u32 { /// emscripten: _localtime #[allow(clippy::cast_ptr_alignment)] -pub fn _localtime(time_p: u32, ctx: &mut Ctx) -> c_int { +pub fn _localtime(ctx: &mut Ctx, time_p: u32) -> c_int { debug!("emscripten::_localtime {}", time_p); // NOTE: emscripten seems to want tzset() called in this function // https://stackoverflow.com/questions/19170721/real-time-awareness-of-timezone-change-in-localtime-vs-localtime-r @@ -219,7 +219,7 @@ pub fn _localtime(time_p: u32, ctx: &mut Ctx) -> c_int { let result_tm = time::at(timespec); unsafe { - let tm_struct_offset = env::call_malloc(mem::size_of::() as _, ctx); + let tm_struct_offset = env::call_malloc(ctx, mem::size_of::() as _); let tm_struct_ptr = emscripten_memory_pointer!(ctx.memory(0), tm_struct_offset) as *mut guest_tm; // debug!( @@ -244,7 +244,7 @@ pub fn _localtime(time_p: u32, ctx: &mut Ctx) -> c_int { } /// emscripten: _localtime_r #[allow(clippy::cast_ptr_alignment)] -pub fn _localtime_r(time_p: u32, result: u32, ctx: &mut Ctx) -> c_int { +pub fn _localtime_r(ctx: &mut Ctx, time_p: u32, result: u32) -> c_int { debug!("emscripten::_localtime_r {}", time_p); // NOTE: emscripten seems to want tzset() called in this function @@ -281,7 +281,7 @@ pub fn _localtime_r(time_p: u32, result: u32, ctx: &mut Ctx) -> c_int { /// emscripten: _time #[allow(clippy::cast_ptr_alignment)] -pub fn _time(time_p: u32, ctx: &mut Ctx) -> i32 { +pub fn _time(ctx: &mut Ctx, time_p: u32) -> i32 { debug!("emscripten::_time {}", time_p); unsafe { @@ -292,11 +292,11 @@ pub fn _time(time_p: u32, ctx: &mut Ctx) -> i32 { /// emscripten: _strftime pub fn _strftime( + _ctx: &mut Ctx, s_ptr: c_int, maxsize: u32, format_ptr: c_int, tm_ptr: c_int, - _ctx: &mut Ctx, ) -> i32 { debug!( "emscripten::_strftime {} {} {} {}", diff --git a/lib/emscripten/src/utils.rs b/lib/emscripten/src/utils.rs index fe3381d76..92d51cf25 100644 --- a/lib/emscripten/src/utils.rs +++ b/lib/emscripten/src/utils.rs @@ -42,7 +42,7 @@ pub fn get_emscripten_memory_size(module: &Module) -> (Pages, Option) { (memory.minimum, memory.maximum) } -pub unsafe fn write_to_buf(string: *const c_char, buf: u32, max: u32, ctx: &mut Ctx) -> u32 { +pub unsafe fn write_to_buf(ctx: &mut Ctx, string: *const c_char, buf: u32, max: u32) -> u32 { let buf_addr = emscripten_memory_pointer!(ctx.memory(0), buf) as *mut c_char; for i in 0..max { @@ -56,7 +56,7 @@ pub unsafe fn write_to_buf(string: *const c_char, buf: u32, max: u32, ctx: &mut pub unsafe fn copy_cstr_into_wasm(ctx: &mut Ctx, cstr: *const c_char) -> u32 { let s = CStr::from_ptr(cstr).to_str().unwrap(); let cstr_len = s.len(); - let space_offset = env::call_malloc((cstr_len as u32) + 1, ctx); + let space_offset = env::call_malloc(ctx, (cstr_len as u32) + 1); let raw_memory = emscripten_memory_pointer!(ctx.memory(0), space_offset) as *mut c_char; let slice = slice::from_raw_parts_mut(raw_memory, cstr_len); @@ -71,7 +71,7 @@ pub unsafe fn copy_cstr_into_wasm(ctx: &mut Ctx, cstr: *const c_char) -> u32 { space_offset } -pub unsafe fn allocate_on_stack<'a, T: Copy>(count: u32, ctx: &'a mut Ctx) -> (u32, &'a mut [T]) { +pub unsafe fn allocate_on_stack<'a, T: Copy>(ctx: &'a mut Ctx, count: u32) -> (u32, &'a mut [T]) { let offset = get_emscripten_data(ctx) .stack_alloc .call(count * (size_of::() as u32)) @@ -82,8 +82,8 @@ pub unsafe fn allocate_on_stack<'a, T: Copy>(count: u32, ctx: &'a mut Ctx) -> (u (offset, slice) } -pub unsafe fn allocate_cstr_on_stack<'a>(s: &str, ctx: &'a mut Ctx) -> (u32, &'a [u8]) { - let (offset, slice) = allocate_on_stack((s.len() + 1) as u32, ctx); +pub unsafe fn allocate_cstr_on_stack<'a>(ctx: &'a mut Ctx, s: &str) -> (u32, &'a [u8]) { + let (offset, slice) = allocate_on_stack(ctx, (s.len() + 1) as u32); use std::iter; for (byte, loc) in s.bytes().chain(iter::once(0)).zip(slice.iter_mut()) { From 227d5e24cfe2a8da63e456fc72bcfbd93eab24ed Mon Sep 17 00:00:00 2001 From: Syrus Date: Sat, 9 Feb 2019 14:18:53 -0800 Subject: [PATCH 025/262] Moved ctx to first argument in Cranelift backend --- lib/clif-backend/src/func_env.rs | 10 +++++----- lib/clif-backend/src/module_env.rs | 10 +++++----- lib/clif-backend/src/resolver.rs | 13 +++++++------ lib/clif-backend/src/trampoline.rs | 2 +- 4 files changed, 18 insertions(+), 17 deletions(-) diff --git a/lib/clif-backend/src/func_env.rs b/lib/clif-backend/src/func_env.rs index 789195264..cada963d1 100644 --- a/lib/clif-backend/src/func_env.rs +++ b/lib/clif-backend/src/func_env.rs @@ -460,7 +460,7 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> { // and the vmctx parameter. let mut args = Vec::with_capacity(call_args.len() + 1); args.extend(call_args.iter().cloned()); - args.push(vmctx_ptr); + args.insert(0, vmctx_ptr); Ok(pos.ins().call_indirect(sig_ref, func_ptr, &args)) } @@ -486,7 +486,7 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> { let mut args = Vec::with_capacity(call_args.len() + 1); args.extend(call_args.iter().cloned()); - args.push(vmctx); + args.insert(0, vmctx); Ok(pos.ins().call(callee, &args)) } @@ -533,7 +533,7 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> { let mut args = Vec::with_capacity(call_args.len() + 1); args.extend(call_args.iter().cloned()); - args.push(imported_vmctx_addr); + args.insert(0, imported_vmctx_addr); Ok(pos .ins() @@ -604,7 +604,7 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> { let call_inst = pos .ins() - .call(mem_grow_func, &[const_mem_index, by_value, vmctx]); + .call(mem_grow_func, &[vmctx, const_mem_index, by_value]); Ok(*pos.func.dfg.inst_results(call_inst).first().unwrap()) } @@ -664,7 +664,7 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> { .special_param(ir::ArgumentPurpose::VMContext) .expect("missing vmctx parameter"); - let call_inst = pos.ins().call(mem_grow_func, &[const_mem_index, vmctx]); + let call_inst = pos.ins().call(mem_grow_func, &[vmctx, const_mem_index]); Ok(*pos.func.dfg.inst_results(call_inst).first().unwrap()) } diff --git a/lib/clif-backend/src/module_env.rs b/lib/clif-backend/src/module_env.rs index 8a26b2731..6b22b4ce6 100644 --- a/lib/clif-backend/src/module_env.rs +++ b/lib/clif-backend/src/module_env.rs @@ -536,14 +536,14 @@ impl<'module, 'isa, 'data> ModuleEnvironment<'data> for ModuleEnv<'module, 'isa> let func_index = pos.ins().iconst(ir::types::I32, func_index.index() as i64); - pos.ins().call(start_debug, &[func_index, vmctx]); + pos.ins().call(start_debug, &[vmctx, func_index]); for param in new_ebb_params.iter().cloned() { match pos.func.dfg.value_type(param) { - ir::types::I32 => pos.ins().call(i32_print, &[param, vmctx]), - ir::types::I64 => pos.ins().call(i64_print, &[param, vmctx]), - ir::types::F32 => pos.ins().call(f32_print, &[param, vmctx]), - ir::types::F64 => pos.ins().call(f64_print, &[param, vmctx]), + ir::types::I32 => pos.ins().call(i32_print, &[vmctx, param]), + ir::types::I64 => pos.ins().call(i64_print, &[vmctx, param]), + ir::types::F32 => pos.ins().call(f32_print, &[vmctx, param]), + ir::types::F64 => pos.ins().call(f64_print, &[vmctx, param]), _ => unimplemented!(), }; } diff --git a/lib/clif-backend/src/resolver.rs b/lib/clif-backend/src/resolver.rs index 1e62c0c20..ddc7cd3b9 100644 --- a/lib/clif-backend/src/resolver.rs +++ b/lib/clif-backend/src/resolver.rs @@ -34,6 +34,7 @@ use wasmer_runtime_core::{ types::{FuncSig, LocalFuncIndex, SigIndex}, vm, vmcalls, }; +use wasmer_runtime_core::vm::Ctx; extern "C" { #[cfg(not(target_os = "windows"))] @@ -350,21 +351,21 @@ fn round_up(n: usize, multiple: usize) -> usize { (n + multiple - 1) & !(multiple - 1) } -extern "C" fn i32_print(n: i32) { +extern "C" fn i32_print(_ctx: &mut Ctx, n: i32) { print!(" i32: {},", n); } -extern "C" fn i64_print(n: i64) { +extern "C" fn i64_print(_ctx: &mut Ctx, n: i64) { print!(" i64: {},", n); } -extern "C" fn f32_print(n: f32) { +extern "C" fn f32_print(_ctx: &mut Ctx, n: f32) { print!(" f32: {},", n); } -extern "C" fn f64_print(n: f64) { +extern "C" fn f64_print(_ctx: &mut Ctx, n: f64) { print!(" f64: {},", n); } -extern "C" fn start_debug(func_index: u32) { +extern "C" fn start_debug(_ctx: &mut Ctx, func_index: u32) { print!("func ({}), args: [", func_index); } -extern "C" fn end_debug() { +extern "C" fn end_debug(_ctx: &mut Ctx) { println!(" ]"); } diff --git a/lib/clif-backend/src/trampoline.rs b/lib/clif-backend/src/trampoline.rs index 0751cea14..a30dfd114 100644 --- a/lib/clif-backend/src/trampoline.rs +++ b/lib/clif-backend/src/trampoline.rs @@ -169,6 +169,7 @@ fn generate_func(func_sig: &FuncSig) -> ir::Function { let mut pos = FuncCursor::new(&mut func).at_first_insertion_point(entry_ebb); let mut args_vec = Vec::with_capacity(func_sig.params().len() + 1); + args_vec.push(vmctx_ptr); for (index, wasm_ty) in func_sig.params().iter().enumerate() { let mem_flags = ir::MemFlags::trusted(); @@ -180,7 +181,6 @@ fn generate_func(func_sig: &FuncSig) -> ir::Function { ); args_vec.push(val); } - args_vec.push(vmctx_ptr); let call_inst = pos.ins().call_indirect(export_sig_ref, func_ptr, &args_vec); From 94c5acedbfb89b3cc6048fba6e2bc19d415cc7f6 Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Sat, 9 Feb 2019 17:39:15 -0600 Subject: [PATCH 026/262] Add basic Global API --- lib/runtime-c-api/src/lib.rs | 105 ++++++++++++++++++++++++- lib/runtime-c-api/tests/.gitignore | 1 + lib/runtime-c-api/tests/CMakeLists.txt | 4 + lib/runtime-c-api/tests/test-globals.c | 30 +++++++ lib/runtime-c-api/wasmer.h | 19 +++++ lib/runtime-c-api/wasmer.hh | 19 +++++ 6 files changed, 176 insertions(+), 2 deletions(-) create mode 100644 lib/runtime-c-api/tests/test-globals.c diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index 9f2ffb12c..1bebd8336 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -7,10 +7,12 @@ use std::slice; use std::str; use std::sync::Arc; use std::{ffi::c_void, mem, ptr}; -use wasmer_runtime::{ImportObject, Instance, Memory, Table, Value}; +use wasmer_runtime::{Global, ImportObject, Instance, Memory, Table, Value}; use wasmer_runtime_core::export::{Context, Export, FuncPointer}; use wasmer_runtime_core::import::{LikeNamespace, Namespace}; -use wasmer_runtime_core::types::{ElementType, FuncSig, MemoryDescriptor, TableDescriptor, Type}; +use wasmer_runtime_core::types::{ + ElementType, FuncSig, GlobalDescriptor, MemoryDescriptor, TableDescriptor, Type, +}; use wasmer_runtime_core::units::Pages; #[allow(non_camel_case_types)] @@ -79,6 +81,13 @@ pub struct wasmer_value_t { value: wasmer_value, } +#[repr(C)] +#[derive(Clone)] +pub struct wasmer_global_descriptor_t { + mutable: bool, + kind: wasmer_value_tag, +} + #[repr(C)] #[derive(Clone)] pub struct wasmer_memory_t(); @@ -87,6 +96,10 @@ pub struct wasmer_memory_t(); #[derive(Clone)] pub struct wasmer_table_t(); +#[repr(C)] +#[derive(Clone)] +pub struct wasmer_global_t(); + #[repr(C)] pub struct wasmer_limits_t { pub min: uint32_t, @@ -196,6 +209,59 @@ pub extern "C" fn wasmer_table_destroy(table: *mut wasmer_table_t) { } } +#[no_mangle] +pub unsafe extern "C" fn wasmer_global_new( + value: wasmer_value_t, + mutable: bool, +) -> *mut wasmer_global_t { + let global = if mutable { + Global::new_mutable(value.into()) + } else { + Global::new(value.into()) + }; + unsafe { Box::into_raw(Box::new(global)) as *mut wasmer_global_t } +} + +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub extern "C" fn wasmer_global_get(global: *mut wasmer_global_t) -> wasmer_value_t { + let global = unsafe { Box::from_raw(global as *mut Global) }; + let value: wasmer_value_t = global.get().into(); + Box::into_raw(global); + value +} + +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub extern "C" fn wasmer_global_set(global: *mut wasmer_global_t, value: wasmer_value_t) { + let global = unsafe { Box::from_raw(global as *mut Global) }; + global.set(value.into()); + Box::into_raw(global); +} + +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub extern "C" fn wasmer_global_get_descriptor( + global: *mut wasmer_global_t, +) -> wasmer_global_descriptor_t { + let global = unsafe { Box::from_raw(global as *mut Global) }; + let descriptor = global.descriptor(); + let desc = wasmer_global_descriptor_t { + mutable: descriptor.mutable, + kind: descriptor.ty.into(), + }; + Box::into_raw(global); + desc +} + +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub extern "C" fn wasmer_global_destroy(global: *mut wasmer_global_t) { + if !global.is_null() { + drop(unsafe { Box::from_raw(global as *mut Global) }); + } +} + #[allow(clippy::cast_ptr_alignment)] #[no_mangle] pub extern "C" fn wasmer_import_object_destroy(import_object: *mut wasmer_import_object_t) { @@ -396,6 +462,41 @@ impl From for Value { } } +impl From for wasmer_value_t { + fn from(val: Value) -> Self { + match val { + Value::I32(x) => wasmer_value_t { + tag: wasmer_value_tag::WASM_I32, + value: wasmer_value { I32: x }, + }, + Value::I64(x) => wasmer_value_t { + tag: wasmer_value_tag::WASM_I64, + value: wasmer_value { I64: x }, + }, + Value::F32(x) => wasmer_value_t { + tag: wasmer_value_tag::WASM_F32, + value: wasmer_value { F32: x }, + }, + Value::F64(x) => wasmer_value_t { + tag: wasmer_value_tag::WASM_F64, + value: wasmer_value { F64: x }, + }, + } + } +} + +impl From for wasmer_value_tag { + fn from(ty: Type) -> Self { + match ty { + Type::I32 => wasmer_value_tag::WASM_I32, + Type::I64 => wasmer_value_tag::WASM_I64, + Type::F32 => wasmer_value_tag::WASM_F32, + Type::F64 => wasmer_value_tag::WASM_F64, + _ => panic!("not implemented"), + } + } +} + impl From for Type { fn from(v: wasmer_value_tag) -> Self { unsafe { diff --git a/lib/runtime-c-api/tests/.gitignore b/lib/runtime-c-api/tests/.gitignore index 8ac4f1ab0..6a96cd53f 100644 --- a/lib/runtime-c-api/tests/.gitignore +++ b/lib/runtime-c-api/tests/.gitignore @@ -9,6 +9,7 @@ install_manifest.txt compile_commands.json CTestTestfile.cmake _deps +test-globals test-instantiate test-import-function test-memory diff --git a/lib/runtime-c-api/tests/CMakeLists.txt b/lib/runtime-c-api/tests/CMakeLists.txt index 58b1ac3cd..d15934df5 100644 --- a/lib/runtime-c-api/tests/CMakeLists.txt +++ b/lib/runtime-c-api/tests/CMakeLists.txt @@ -1,6 +1,7 @@ cmake_minimum_required (VERSION 2.6) project (WasmerCApiTests) +add_executable(test-globals test-globals.c) add_executable(test-instantiate test-instantiate.c) add_executable(test-import-function test-import-function.c) add_executable(test-memory test-memory.c) @@ -16,6 +17,8 @@ if(NOT WASMER_LIB) message(FATAL_ERROR "wasmer library not found") endif() +target_link_libraries(test-globals + general ${WASMER_LIB}) target_link_libraries(test-instantiate general ${WASMER_LIB}) target_link_libraries(test-import-function @@ -28,6 +31,7 @@ target_link_libraries(test-tables general ${WASMER_LIB}) enable_testing() +add_test(test-globals test-globals) add_test(test-instantiate test-instantiate) add_test(test-import-function test-import-function) add_test(test-memory test-memory) diff --git a/lib/runtime-c-api/tests/test-globals.c b/lib/runtime-c-api/tests/test-globals.c new file mode 100644 index 000000000..a694d2e75 --- /dev/null +++ b/lib/runtime-c-api/tests/test-globals.c @@ -0,0 +1,30 @@ +#include +#include "../wasmer.h" +#include +#include + +int main() +{ + wasmer_value_t val; + val.tag = WASM_I32; + val.value.I32 = 7; + wasmer_global_t *global = wasmer_global_new(val, true); + + wasmer_value_t get_val = wasmer_global_get(global); + assert( get_val.value.I32 == 7); + + wasmer_value_t val2; + val2.tag = WASM_I32; + val2.value.I32 = 14; + wasmer_global_set(global, val2); + + wasmer_value_t new_get_val = wasmer_global_get(global); + assert( new_get_val.value.I32 == 14); + + wasmer_global_descriptor_t desc = wasmer_global_get_descriptor(global); + assert(desc.mutable_); + assert(desc.kind == WASM_I32); + + wasmer_global_destroy(global); + return 0; +} diff --git a/lib/runtime-c-api/wasmer.h b/lib/runtime-c-api/wasmer.h index 08f891fa8..c6e649bd4 100644 --- a/lib/runtime-c-api/wasmer.h +++ b/lib/runtime-c-api/wasmer.h @@ -37,6 +37,10 @@ typedef struct wasmer_instance_context_t wasmer_instance_context_t; typedef struct wasmer_instance_t wasmer_instance_t; +typedef struct { + +} wasmer_global_t; + typedef union { int32_t I32; int64_t I64; @@ -49,6 +53,11 @@ typedef struct { wasmer_value value; } wasmer_value_t; +typedef struct { + bool mutable_; + wasmer_value_tag kind; +} wasmer_global_descriptor_t; + typedef struct { } wasmer_memory_t; @@ -62,6 +71,16 @@ typedef struct { } wasmer_table_t; +void wasmer_global_destroy(wasmer_global_t *global); + +wasmer_value_t wasmer_global_get(wasmer_global_t *global); + +wasmer_global_descriptor_t wasmer_global_get_descriptor(wasmer_global_t *global); + +wasmer_global_t *wasmer_global_new(wasmer_value_t value, bool mutable_); + +void wasmer_global_set(wasmer_global_t *global, wasmer_value_t value); + void wasmer_import_object_destroy(wasmer_import_object_t *import_object); wasmer_import_object_t *wasmer_import_object_new(void); diff --git a/lib/runtime-c-api/wasmer.hh b/lib/runtime-c-api/wasmer.hh index c0d266489..7ac6b1e19 100644 --- a/lib/runtime-c-api/wasmer.hh +++ b/lib/runtime-c-api/wasmer.hh @@ -35,6 +35,10 @@ struct wasmer_instance_context_t; struct wasmer_instance_t; +struct wasmer_global_t { + +}; + union wasmer_value { int32_t I32; int64_t I64; @@ -47,6 +51,11 @@ struct wasmer_value_t { wasmer_value value; }; +struct wasmer_global_descriptor_t { + bool mutable_; + wasmer_value_tag kind; +}; + struct wasmer_memory_t { }; @@ -62,6 +71,16 @@ struct wasmer_table_t { extern "C" { +void wasmer_global_destroy(wasmer_global_t *global); + +wasmer_value_t wasmer_global_get(wasmer_global_t *global); + +wasmer_global_descriptor_t wasmer_global_get_descriptor(wasmer_global_t *global); + +wasmer_global_t *wasmer_global_new(wasmer_value_t value, bool mutable_); + +void wasmer_global_set(wasmer_global_t *global, wasmer_value_t value); + void wasmer_import_object_destroy(wasmer_import_object_t *import_object); wasmer_import_object_t *wasmer_import_object_new(); From a8dcc0ee872ec3502c77dc8e23c8e50a1296c4bf Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Sat, 9 Feb 2019 17:42:58 -0600 Subject: [PATCH 027/262] Fix make test exclude --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index e91aff4bf..2506f196c 100644 --- a/Makefile +++ b/Makefile @@ -37,7 +37,7 @@ precommit: lint test test: # We use one thread so the emscripten stdouts doesn't collide - cargo test --all --exclude wasmer-emscripten -- --test-threads=1 $(runargs) + cargo test --all --exclude wasmer-runtime-c-api -- --test-threads=1 $(runargs) # cargo test --all --exclude wasmer-emscripten -- --test-threads=1 $(runargs) cargo build -p wasmer-runtime-c-api cargo test -p wasmer-runtime-c-api -- --nocapture From a0288c87acb27288ee5165a3bc0573a36631bd32 Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Sat, 9 Feb 2019 17:53:03 -0600 Subject: [PATCH 028/262] Add Memory Grow C API --- lib/runtime-c-api/src/lib.rs | 16 ++++++++++++++++ lib/runtime-c-api/tests/test-memory.c | 13 ++++++++++++- lib/runtime-c-api/wasmer.h | 2 ++ lib/runtime-c-api/wasmer.hh | 2 ++ 4 files changed, 32 insertions(+), 1 deletion(-) diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index 1bebd8336..d7d513604 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -146,6 +146,22 @@ pub unsafe extern "C" fn wasmer_memory_new( wasmer_memory_result_t::WASMER_MEMORY_OK } +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub extern "C" fn wasmer_memory_grow( + memory: *mut wasmer_memory_t, + delta: uint32_t, +) -> wasmer_memory_result_t { + let memory = unsafe { Box::from_raw(memory as *mut Memory) }; + let maybe_delta = memory.grow(Pages(delta)); + Box::into_raw(memory); + if let Some(_delta) = maybe_delta { + wasmer_memory_result_t::WASMER_MEMORY_OK + } else { + wasmer_memory_result_t::WASMER_MEMORY_ERROR + } +} + #[allow(clippy::cast_ptr_alignment)] #[no_mangle] pub extern "C" fn wasmer_memory_length(memory: *mut wasmer_memory_t) -> uint32_t { diff --git a/lib/runtime-c-api/tests/test-memory.c b/lib/runtime-c-api/tests/test-memory.c index 0201a36c1..631a6a983 100644 --- a/lib/runtime-c-api/tests/test-memory.c +++ b/lib/runtime-c-api/tests/test-memory.c @@ -8,7 +8,7 @@ int main() wasmer_memory_t *memory = NULL; wasmer_limits_t descriptor; descriptor.min = 10; - descriptor.max = 10; + descriptor.max = 15; wasmer_memory_result_t memory_result = wasmer_memory_new(&memory, descriptor); printf("Memory result: %d\n", memory_result); assert(memory_result == WASMER_MEMORY_OK); @@ -17,6 +17,17 @@ int main() printf("Memory pages length: %d\n", len); assert(len == 10); + wasmer_memory_result_t grow_result = wasmer_memory_grow(memory, 2); + assert(grow_result == WASMER_MEMORY_OK); + + uint32_t new_len = wasmer_memory_length(memory); + printf("Memory pages length: %d\n", new_len); + assert(new_len == 12); + + // Err, grow beyond max + wasmer_memory_result_t grow_result2 = wasmer_memory_grow(memory, 10); + assert(grow_result2 == WASMER_MEMORY_ERROR); + printf("Destroy memory\n"); wasmer_memory_destroy(memory); return 0; diff --git a/lib/runtime-c-api/wasmer.h b/lib/runtime-c-api/wasmer.h index c6e649bd4..4df5001ef 100644 --- a/lib/runtime-c-api/wasmer.h +++ b/lib/runtime-c-api/wasmer.h @@ -112,6 +112,8 @@ wasmer_compile_result_t wasmer_instantiate(wasmer_instance_t **instance, void wasmer_memory_destroy(wasmer_memory_t *memory); +wasmer_memory_result_t wasmer_memory_grow(wasmer_memory_t *memory, uint32_t delta); + uint32_t wasmer_memory_length(wasmer_memory_t *memory); wasmer_memory_result_t wasmer_memory_new(wasmer_memory_t **memory, wasmer_limits_t limits); diff --git a/lib/runtime-c-api/wasmer.hh b/lib/runtime-c-api/wasmer.hh index 7ac6b1e19..5fb292cb1 100644 --- a/lib/runtime-c-api/wasmer.hh +++ b/lib/runtime-c-api/wasmer.hh @@ -112,6 +112,8 @@ wasmer_compile_result_t wasmer_instantiate(wasmer_instance_t **instance, void wasmer_memory_destroy(wasmer_memory_t *memory); +wasmer_memory_result_t wasmer_memory_grow(wasmer_memory_t *memory, uint32_t delta); + uint32_t wasmer_memory_length(wasmer_memory_t *memory); wasmer_memory_result_t wasmer_memory_new(wasmer_memory_t **memory, wasmer_limits_t limits); From 327e3a4a1aeddb6ea07a753eed8046d7daed3673 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Sat, 9 Feb 2019 15:53:40 -0800 Subject: [PATCH 029/262] Implement many wasm instructions --- Cargo.lock | 169 ++++++- Cargo.toml | 2 +- lib/clif-backend/src/func_env.rs | 134 ++--- lib/clif-backend/src/module_env.rs | 6 +- lib/clif-backend/src/signal/mod.rs | 2 +- lib/llvm-backend/.llvmenv | 1 + lib/llvm-backend/Cargo.toml | 17 + lib/llvm-backend/src/code.rs | 765 +++++++++++++++++++++++++++++ lib/llvm-backend/src/example.rs | 61 +++ lib/llvm-backend/src/intrinsics.rs | 99 ++++ lib/llvm-backend/src/lib.rs | 52 ++ lib/llvm-backend/src/read_info.rs | 333 +++++++++++++ lib/llvm-backend/src/state.rs | 105 ++++ lib/runtime-core/src/backing.rs | 10 +- lib/runtime-core/src/instance.rs | 18 +- lib/runtime-core/src/types.rs | 19 +- lib/runtime-core/src/vm.rs | 2 +- 17 files changed, 1700 insertions(+), 95 deletions(-) create mode 100644 lib/llvm-backend/.llvmenv create mode 100644 lib/llvm-backend/Cargo.toml create mode 100644 lib/llvm-backend/src/code.rs create mode 100644 lib/llvm-backend/src/example.rs create mode 100644 lib/llvm-backend/src/intrinsics.rs create mode 100644 lib/llvm-backend/src/lib.rs create mode 100644 lib/llvm-backend/src/read_info.rs create mode 100644 lib/llvm-backend/src/state.rs diff --git a/Cargo.lock b/Cargo.lock index d061df27b..209d06782 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,3 +1,11 @@ +[[package]] +name = "aho-corasick" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ansi_term" version = "0.11.0" @@ -28,7 +36,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "block-buffer" -version = "0.7.2" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "block-padding 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -178,6 +186,20 @@ dependencies = [ "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "either" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "enum-methods" +version = "0.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "errno" version = "0.2.4" @@ -281,6 +303,27 @@ name = "indexmap" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "inkwell" +version = "0.1.0" +source = "git+https://github.com/TheDan64/inkwell?branch=llvm7-0#83b9188bad1e098f97e6aad8f6d45becb6d1ccdd" +dependencies = [ + "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "enum-methods 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "inkwell_internal_macros 0.1.0 (git+https://github.com/TheDan64/inkwell?branch=llvm7-0)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "llvm-sys 70.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "inkwell_internal_macros" +version = "0.1.0" +source = "git+https://github.com/TheDan64/inkwell?branch=llvm7-0#83b9188bad1e098f97e6aad8f6d45becb6d1ccdd" +dependencies = [ + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "itoa" version = "0.4.3" @@ -310,6 +353,29 @@ name = "libc" version = "0.2.48" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "llvm-backend" +version = "0.1.0" +dependencies = [ + "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "inkwell 0.1.0 (git+https://github.com/TheDan64/inkwell?branch=llvm7-0)", + "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmer-runtime-core 0.1.2", + "wasmparser 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "llvm-sys" +version = "70.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "lock_api" version = "0.1.5" @@ -327,6 +393,15 @@ dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "memchr" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "memmap" version = "0.7.0" @@ -412,6 +487,11 @@ dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "quote" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "quote" version = "0.6.11" @@ -547,6 +627,26 @@ dependencies = [ "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "regex" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "regex-syntax" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rustc_version" version = "0.2.3" @@ -625,7 +725,7 @@ name = "sha2" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "block-buffer 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "block-buffer 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -669,6 +769,16 @@ dependencies = [ "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "syn" +version = "0.11.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "syn" version = "0.15.26" @@ -679,6 +789,14 @@ dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "synom" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "synstructure" version = "0.10.1" @@ -718,6 +836,14 @@ dependencies = [ "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "thread_local" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "time" version = "0.1.42" @@ -733,6 +859,11 @@ name = "typenum" version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "ucd-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "unicode-segmentation" version = "1.2.1" @@ -743,6 +874,11 @@ name = "unicode-width" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "unicode-xid" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "unicode-xid" version = "0.1.0" @@ -756,6 +892,11 @@ dependencies = [ "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "utf8-ranges" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "vec_map" version = "0.8.1" @@ -886,6 +1027,11 @@ name = "wasmparser" version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "wasmparser" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "winapi" version = "0.2.8" @@ -916,11 +1062,12 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] +"checksum aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1e9a933f4e58658d7b12defcf96dc5c720f20832deebe3e0a19efd3b6aaeeb9e" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" "checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" -"checksum block-buffer 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "509de513cca6d92b6aacf9c61acfe7eaa160837323a81068d690cc1f8e5740da" +"checksum block-buffer 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49665c62e0e700857531fa5d3763e91b539ff1abeebd56808d378b495870d60d" "checksum block-padding 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d75255892aeb580d3c566f213a2b6fdc1c66667839f45719ee1d30ebf2aea591" "checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" "checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" @@ -938,6 +1085,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum cranelift-native 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "474bee81d620a473bf43411a3d6f10ffbf7965141dc5e5b76d8d2151dde3285d" "checksum cranelift-wasm 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49723365dab9a48b354bdc24cb6d9d5719bc1d3b858ffd2ea179d0d7d885804a" "checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c" +"checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0" +"checksum enum-methods 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7798e7da2d4cb0d6d6fc467e8d6b5bf247e9e989f786dde1732d79899c32bb10" "checksum errno 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c2a071601ed01b988f896ab14b95e67335d1eeb50190932a1320f7fe3cadc84e" "checksum errno-dragonfly 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "14ca354e36190500e1e1fb267c647932382b54053c50b14970856c0b00a35067" "checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" @@ -952,13 +1101,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3bae29b6653b3412c2e71e9d486db9f9df5d701941d86683005efb9f2d28e3da" "checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" "checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d" +"checksum inkwell 0.1.0 (git+https://github.com/TheDan64/inkwell?branch=llvm7-0)" = "" +"checksum inkwell_internal_macros 0.1.0 (git+https://github.com/TheDan64/inkwell?branch=llvm7-0)" = "" "checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1" "checksum libc 0.2.48 (git+https://github.com/rust-lang/libc)" = "" "checksum libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)" = "e962c7641008ac010fa60a7dfdc1712449f29c44ef2d4702394aea943ee75047" +"checksum llvm-sys 70.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60a9ee82fe0fa72ae6ef6d018b407296085863836451c7a97384f84ed7e26b9f" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" +"checksum memchr 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e1dd4eaac298c32ce07eb6ed9242eda7d82955b9170b7d6db59b2e02cc63fcb8" "checksum memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" "checksum nix 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "921f61dc817b379d0834e45d5ec45beaacfae97082090a49c2cf30dcbc30206f" "checksum nix 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46f0f3210768d796e8fa79ec70ee6af172dacbe7147f5e69be5240a47778302b" @@ -968,6 +1121,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" "checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" "checksum proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)" = "38fddd23d98b2144d197c0eca5705632d4fe2667d14a6be5df8934f8d74f1978" +"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" "checksum quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cdd8e04bd9c52e0342b406469d494fcb033be4bdbe5c606016defbb1681411e1" "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" "checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" @@ -983,6 +1137,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" "checksum redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)" = "423e376fffca3dfa06c9e9790a9ccd282fafb3cc6e6397d01dbf64f9bacc6b85" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" +"checksum regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "37e7cbbd370869ce2e8dff25c7018702d10b21a20ef7135316f8daecd6c25b7f" +"checksum regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8c2f35eedad5295fdf00a63d7d4b238135723f92b434ec06774dad15c7ab0861" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" @@ -999,23 +1155,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" "checksum structopt 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "670ad348dc73012fcf78c71f06f9d942232cdd4c859d4b6975e27836c3efc0c3" "checksum structopt-derive 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "ef98172b1a00b0bec738508d3726540edcbd186d50dfd326f2b1febbb3559f04" +"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" "checksum syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)" = "f92e629aa1d9c827b2bb8297046c1ccffc57c99b947a680d3ccff1f136a3bee9" +"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" "checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" "checksum target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4af5e2227f0b887d591d3724b796a96eff04226104d872f5b3883fcd427d64b9" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" "checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6" +"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" "checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" +"checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" "checksum unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa6024fc12ddfd1c6dbc14a80fa2324d4568849869b779f6bd37e5e4c03344d1" "checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" +"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" +"checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" "checksum wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "74e463a508e390cc7447e70f640fbf44ad52e1bd095314ace1fdf99516d32add" "checksum wabt-sys 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a6265b25719e82598d104b3717375e37661d41753e2c84cde3f51050c7ed7e3c" "checksum wasmparser 0.22.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f46e666ecb4a406483a59a49f9d0c17f327e70da53a128eccddae2eadb95865c" "checksum wasmparser 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b5e01c420bc7d36e778bd242e1167b079562ba8b34087122cc9057187026d060" +"checksum wasmparser 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)" = "40f426b1929bd26517fb10702e2a8e520d1845c49567aa4d244f426f10b206c1" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" diff --git a/Cargo.toml b/Cargo.toml index b570c9b09..77bf8a4b8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,7 +27,7 @@ wasmer-runtime-core = { path = "lib/runtime-core" } wasmer-emscripten = { path = "lib/emscripten" } [workspace] -members = ["lib/clif-backend", "lib/runtime", "lib/runtime-core", "lib/emscripten", "lib/spectests"] +members = ["lib/clif-backend", "lib/runtime", "lib/runtime-core", "lib/emscripten", "lib/spectests", "lib/llvm-backend"] [build-dependencies] wabt = "0.7.2" diff --git a/lib/clif-backend/src/func_env.rs b/lib/clif-backend/src/func_env.rs index 789195264..f24cfc433 100644 --- a/lib/clif-backend/src/func_env.rs +++ b/lib/clif-backend/src/func_env.rs @@ -75,7 +75,7 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> { let vmctx = func.create_global_value(ir::GlobalValueData::VMContext); let ptr_type = self.pointer_type(); - let local_global_addr = match global_index.local_or_import(self.env.module) { + let local_global_addr = match global_index.local_or_import(&self.env.module.info) { LocalOrImport::Local(local_global_index) => { let globals_base_addr = func.create_global_value(ir::GlobalValueData::Load { base: vmctx, @@ -145,48 +145,49 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> { let vmctx = func.create_global_value(ir::GlobalValueData::VMContext); let ptr_type = self.pointer_type(); - let (local_memory_ptr_ptr, description) = match mem_index.local_or_import(self.env.module) { - LocalOrImport::Local(local_mem_index) => { - let memories_base_addr = func.create_global_value(ir::GlobalValueData::Load { - base: vmctx, - offset: (vm::Ctx::offset_memories() as i32).into(), - global_type: ptr_type, - readonly: true, - }); - - let local_memory_ptr_offset = - local_mem_index.index() * mem::size_of::<*mut vm::LocalMemory>(); - - ( - func.create_global_value(ir::GlobalValueData::IAddImm { - base: memories_base_addr, - offset: (local_memory_ptr_offset as i64).into(), + let (local_memory_ptr_ptr, description) = + match mem_index.local_or_import(&self.env.module.info) { + LocalOrImport::Local(local_mem_index) => { + let memories_base_addr = func.create_global_value(ir::GlobalValueData::Load { + base: vmctx, + offset: (vm::Ctx::offset_memories() as i32).into(), global_type: ptr_type, - }), - self.env.module.info.memories[local_mem_index], - ) - } - LocalOrImport::Import(import_mem_index) => { - let memories_base_addr = func.create_global_value(ir::GlobalValueData::Load { - base: vmctx, - offset: (vm::Ctx::offset_imported_memories() as i32).into(), - global_type: ptr_type, - readonly: true, - }); + readonly: true, + }); - let local_memory_ptr_offset = - import_mem_index.index() * mem::size_of::<*mut vm::LocalMemory>(); + let local_memory_ptr_offset = + local_mem_index.index() * mem::size_of::<*mut vm::LocalMemory>(); - ( - func.create_global_value(ir::GlobalValueData::IAddImm { - base: memories_base_addr, - offset: (local_memory_ptr_offset as i64).into(), + ( + func.create_global_value(ir::GlobalValueData::IAddImm { + base: memories_base_addr, + offset: (local_memory_ptr_offset as i64).into(), + global_type: ptr_type, + }), + self.env.module.info.memories[local_mem_index], + ) + } + LocalOrImport::Import(import_mem_index) => { + let memories_base_addr = func.create_global_value(ir::GlobalValueData::Load { + base: vmctx, + offset: (vm::Ctx::offset_imported_memories() as i32).into(), global_type: ptr_type, - }), - self.env.module.info.imported_memories[import_mem_index].1, - ) - } - }; + readonly: true, + }); + + let local_memory_ptr_offset = + import_mem_index.index() * mem::size_of::<*mut vm::LocalMemory>(); + + ( + func.create_global_value(ir::GlobalValueData::IAddImm { + base: memories_base_addr, + offset: (local_memory_ptr_offset as i64).into(), + global_type: ptr_type, + }), + self.env.module.info.imported_memories[import_mem_index].1, + ) + } + }; let (local_memory_ptr, local_memory_base) = { let local_memory_ptr = func.create_global_value(ir::GlobalValueData::Load { @@ -253,7 +254,8 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> { let vmctx = func.create_global_value(ir::GlobalValueData::VMContext); let ptr_type = self.pointer_type(); - let (table_struct_ptr_ptr, description) = match table_index.local_or_import(self.env.module) + let (table_struct_ptr_ptr, description) = match table_index + .local_or_import(&self.env.module.info) { LocalOrImport::Local(local_table_index) => { let tables_base = func.create_global_value(ir::GlobalValueData::Load { @@ -476,7 +478,7 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> { ) -> cranelift_wasm::WasmResult { let callee_index: FuncIndex = Converter(clif_callee_index).into(); - match callee_index.local_or_import(self.env.module) { + match callee_index.local_or_import(&self.env.module.info) { LocalOrImport::Local(_) => { // this is an internal function let vmctx = pos @@ -568,18 +570,19 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> { let mem_index: MemoryIndex = Converter(clif_mem_index).into(); - let (namespace, mem_index, description) = match mem_index.local_or_import(self.env.module) { - LocalOrImport::Local(local_mem_index) => ( - call_names::LOCAL_NAMESPACE, - local_mem_index.index(), - self.env.module.info.memories[local_mem_index], - ), - LocalOrImport::Import(import_mem_index) => ( - call_names::IMPORT_NAMESPACE, - import_mem_index.index(), - self.env.module.info.imported_memories[import_mem_index].1, - ), - }; + let (namespace, mem_index, description) = + match mem_index.local_or_import(&self.env.module.info) { + LocalOrImport::Local(local_mem_index) => ( + call_names::LOCAL_NAMESPACE, + local_mem_index.index(), + self.env.module.info.memories[local_mem_index], + ), + LocalOrImport::Import(import_mem_index) => ( + call_names::IMPORT_NAMESPACE, + import_mem_index.index(), + self.env.module.info.imported_memories[import_mem_index].1, + ), + }; let name_index = match description.memory_type() { MemoryType::Dynamic => call_names::DYNAMIC_MEM_GROW, @@ -631,18 +634,19 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> { let mem_index: MemoryIndex = Converter(clif_mem_index).into(); - let (namespace, mem_index, description) = match mem_index.local_or_import(self.env.module) { - LocalOrImport::Local(local_mem_index) => ( - call_names::LOCAL_NAMESPACE, - local_mem_index.index(), - self.env.module.info.memories[local_mem_index], - ), - LocalOrImport::Import(import_mem_index) => ( - call_names::IMPORT_NAMESPACE, - import_mem_index.index(), - self.env.module.info.imported_memories[import_mem_index].1, - ), - }; + let (namespace, mem_index, description) = + match mem_index.local_or_import(&self.env.module.info) { + LocalOrImport::Local(local_mem_index) => ( + call_names::LOCAL_NAMESPACE, + local_mem_index.index(), + self.env.module.info.memories[local_mem_index], + ), + LocalOrImport::Import(import_mem_index) => ( + call_names::IMPORT_NAMESPACE, + import_mem_index.index(), + self.env.module.info.imported_memories[import_mem_index].1, + ), + }; let name_index = match description.memory_type() { MemoryType::Dynamic => call_names::DYNAMIC_MEM_SIZE, diff --git a/lib/clif-backend/src/module_env.rs b/lib/clif-backend/src/module_env.rs index de625cc23..9ff85dcf3 100644 --- a/lib/clif-backend/src/module_env.rs +++ b/lib/clif-backend/src/module_env.rs @@ -136,7 +136,7 @@ impl<'module, 'isa, 'data> ModuleEnvironment<'data> for ModuleEnv<'module, 'isa> // assert!(!desc.mutable); let global_index: GlobalIndex = Converter(global_index).into(); let imported_global_index = global_index - .local_or_import(self.module) + .local_or_import(&self.module.info) .import() .expect("invalid global initializer when declaring an imported global"); Initializer::GetGlobal(imported_global_index) @@ -246,7 +246,7 @@ impl<'module, 'isa, 'data> ModuleEnvironment<'data> for ModuleEnv<'module, 'isa> let base = match base { Some(global_index) => { let global_index: GlobalIndex = Converter(global_index).into(); - Initializer::GetGlobal(match global_index.local_or_import(self.module) { + Initializer::GetGlobal(match global_index.local_or_import(&self.module.info) { LocalOrImport::Import(imported_global_index) => imported_global_index, LocalOrImport::Local(_) => { panic!("invalid global initializer when declaring an imported global") @@ -316,7 +316,7 @@ impl<'module, 'isa, 'data> ModuleEnvironment<'data> for ModuleEnv<'module, 'isa> let base = match base { Some(global_index) => { let global_index: GlobalIndex = Converter(global_index).into(); - Initializer::GetGlobal(match global_index.local_or_import(self.module) { + Initializer::GetGlobal(match global_index.local_or_import(&self.module.info) { LocalOrImport::Import(imported_global_index) => imported_global_index, LocalOrImport::Local(_) => { panic!("invalid global initializer when declaring an imported global") diff --git a/lib/clif-backend/src/signal/mod.rs b/lib/clif-backend/src/signal/mod.rs index 0767f9527..1ff73e055 100644 --- a/lib/clif-backend/src/signal/mod.rs +++ b/lib/clif-backend/src/signal/mod.rs @@ -148,7 +148,7 @@ fn get_func_from_index<'a>( .get(func_index) .expect("broken invariant, incorrect func index"); - let (func_ptr, ctx) = match func_index.local_or_import(module) { + let (func_ptr, ctx) = match func_index.local_or_import(&module.info) { LocalOrImport::Local(local_func_index) => ( module .func_resolver diff --git a/lib/llvm-backend/.llvmenv b/lib/llvm-backend/.llvmenv new file mode 100644 index 000000000..6d1e3080f --- /dev/null +++ b/lib/llvm-backend/.llvmenv @@ -0,0 +1 @@ +/usr/local/opt/llvm/bin \ No newline at end of file diff --git a/lib/llvm-backend/Cargo.toml b/lib/llvm-backend/Cargo.toml new file mode 100644 index 000000000..000265b7d --- /dev/null +++ b/lib/llvm-backend/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "llvm-backend" +version = "0.1.0" +authors = ["Lachlan Sneff "] +edition = "2018" + +[dependencies] +wasmer-runtime-core = { path = "../runtime-core", version = "0.1.2" } +wasmparser = "0.28.0" +inkwell = { git = "https://github.com/TheDan64/inkwell", branch = "llvm7-0" } +hashbrown = "0.1.8" + +[dev-dependencies] +wabt = "0.7.4" + +[features] +debug = ["wasmer-runtime-core/debug"] \ No newline at end of file diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs new file mode 100644 index 000000000..50a31065a --- /dev/null +++ b/lib/llvm-backend/src/code.rs @@ -0,0 +1,765 @@ +use hashbrown::HashMap; +use inkwell::{ + basic_block::BasicBlock, + builder::Builder, + context::Context, + module::Module, + types::{BasicType, BasicTypeEnum, FunctionType}, + values::{AggregateValue, BasicValue, BasicValueEnum, FunctionValue}, + IntPredicate, +}; +use wasmer_runtime_core::{ + module::ModuleInfo, + structures::{Map, SliceMap, TypedIndex}, + types::{FuncIndex, FuncSig, LocalFuncIndex, LocalOrImport, SigIndex, Type}, +}; +use wasmparser::{BinaryReaderError, CodeSectionReader, LocalsReader, Operator, OperatorsReader}; + +use crate::intrinsics::Intrinsics; +use crate::read_info::type_to_type; +use crate::state::State; + +fn func_sig_to_llvm(context: &Context, sig: &FuncSig) -> FunctionType { + let param_types: Vec<_> = sig + .params() + .iter() + .map(|&ty| type_to_llvm(context, ty)) + .collect(); + + match sig.returns() { + [] => context.void_type().fn_type(¶m_types, false), + [single_value] => type_to_llvm(context, *single_value).fn_type(¶m_types, false), + returns @ _ => { + let basic_types: Vec<_> = returns + .iter() + .map(|&ty| type_to_llvm(context, ty)) + .collect(); + + context + .struct_type(&basic_types, false) + .fn_type(¶m_types, false) + } + } +} + +fn type_to_llvm(context: &Context, ty: Type) -> BasicTypeEnum { + match ty { + Type::I32 => context.i32_type().as_basic_type_enum(), + Type::I64 => context.i64_type().as_basic_type_enum(), + Type::F32 => context.f32_type().as_basic_type_enum(), + Type::F64 => context.f64_type().as_basic_type_enum(), + } +} + +pub fn parse_function_bodies( + info: &ModuleInfo, + code_reader: CodeSectionReader, +) -> Result<(), BinaryReaderError> { + let context = Context::create(); + let module = context.create_module("module"); + let builder = context.create_builder(); + + let intrinsics = Intrinsics::declare(&module, &context); + + let signatures: Map = info + .signatures + .iter() + .map(|(_, sig)| func_sig_to_llvm(&context, sig)) + .collect(); + let functions: Map = info + .func_assoc + .iter() + .skip(info.imported_functions.len()) + .map(|(func_index, &sig_index)| { + module.add_function( + &format!("fn:{}", func_index.index()), + signatures[sig_index], + None, + ) + }) + .collect(); + + for (local_func_index, body) in code_reader.into_iter().enumerate() { + let body = body?; + + let locals_reader = body.get_locals_reader()?; + let op_reader = body.get_operators_reader()?; + + parse_function( + &context, + &module, + &builder, + &intrinsics, + info, + &signatures, + &functions, + LocalFuncIndex::new(local_func_index), + locals_reader, + op_reader, + )?; + } + + Ok(()) +} + +fn parse_function( + context: &Context, + module: &Module, + builder: &Builder, + intrinsics: &Intrinsics, + info: &ModuleInfo, + signatures: &SliceMap, + functions: &SliceMap, + func_index: LocalFuncIndex, + locals_reader: LocalsReader, + op_reader: OperatorsReader, +) -> Result<(), BinaryReaderError> { + let llvm_sig = &signatures[info.func_assoc[func_index.convert_up(info)]]; + + let function = functions[func_index]; + let entry_block = context.append_basic_block(&function, "entry"); + builder.position_at_end(&entry_block); + + let mut state = State::new(); + + let mut locals = Vec::with_capacity(locals_reader.get_count() as usize); + locals.extend(function.get_param_iter().enumerate().map(|(index, param)| { + let ty = param.get_type(); + + let alloca = builder.build_alloca(ty, &state.var_name()); + builder.build_store(alloca, param); + alloca + })); + + for (index, local) in locals_reader.into_iter().enumerate().skip(locals.len()) { + let (_, ty) = local?; + + let wasmer_ty = type_to_type(ty)?; + + let ty = type_to_llvm(context, wasmer_ty); + + let alloca = builder.build_alloca(ty, &state.var_name()); + + let default_value = match wasmer_ty { + Type::I32 => context.i32_type().const_int(0, false).as_basic_value_enum(), + Type::I64 => context.i64_type().const_int(0, false).as_basic_value_enum(), + Type::F32 => context.f32_type().const_float(0.0).as_basic_value_enum(), + Type::F64 => context.f64_type().const_float(0.0).as_basic_value_enum(), + }; + + builder.build_store(alloca, default_value); + + locals.push(alloca); + } + + for op in op_reader { + match op? { + /*************************** + * Basic instructions. + * https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#basic-instructions + ***************************/ + Operator::Nop => { + // Do nothing. + } + Operator::Drop => { + state.pop1()?; + } + + // Generate const values. + Operator::I32Const { value } => { + let i = context.i32_type().const_int(value as u64, false); + state.push1(i); + } + Operator::I64Const { value } => { + let i = context.i64_type().const_int(value as u64, false); + state.push1(i); + } + Operator::F32Const { value } => { + let f = context + .f32_type() + .const_float(f64::from_bits(value.bits() as u64)); + state.push1(f); + } + Operator::F64Const { value } => { + let f = context.f64_type().const_float(f64::from_bits(value.bits())); + state.push1(f); + } + + // Operate on locals. + Operator::GetLocal { local_index } => { + let pointer_value = locals[local_index as usize]; + let v = builder.build_load(pointer_value, &state.var_name()); + state.push1(v); + } + Operator::SetLocal { local_index } => { + let pointer_value = locals[local_index as usize]; + let v = state.pop1()?; + builder.build_store(pointer_value, v); + } + Operator::TeeLocal { local_index } => { + let pointer_value = locals[local_index as usize]; + let v = state.peek1()?; + builder.build_store(pointer_value, v); + } + + Operator::GetGlobal { global_index } => unimplemented!(), + Operator::SetGlobal { global_index } => unimplemented!(), + + Operator::Select => { + let (v1, v2, cond) = state.pop3()?; + let cond = cond.into_int_value(); + let res = builder.build_select(cond, v1, v2, &state.var_name()); + state.push1(res); + } + Operator::Call { function_index } => { + let func_index = FuncIndex::new(function_index as usize); + let sigindex = info.func_assoc[func_index]; + let llvm_sig = signatures[sigindex]; + + match func_index.local_or_import(info) { + LocalOrImport::Local(local_func_index) => { + let func_sig = &info.signatures[sigindex]; + let func_value = functions[local_func_index]; + let call_site = builder.build_call( + func_value, + &state.peekn(func_sig.params().len())?.to_vec(), + &state.var_name(), + ); + if let Some(basic_value) = call_site.try_as_basic_value().left() { + match func_sig.returns().len() { + 1 => state.push1(basic_value), + count @ _ => { + // This is a multi-value return. + let struct_value = basic_value.into_struct_value(); + for i in 0..(count as u32) { + let value = builder.build_extract_value( + struct_value, + i, + &state.var_name(), + ); + state.push1(value); + } + } + } + } + } + LocalOrImport::Import(import_func_index) => { + // unimplemented!() + } + } + } + Operator::CallIndirect { index, table_index } => { + unimplemented!("{}, {}", index, table_index); + } + + /*************************** + * Integer Arithmetic instructions. + * https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#integer-arithmetic-instructions + ***************************/ + Operator::I32Add | Operator::I64Add => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); + let res = builder.build_int_add(v1, v2, &state.var_name()); + state.push1(res); + } + Operator::I32Sub | Operator::I64Sub => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); + let res = builder.build_int_sub(v1, v2, &state.var_name()); + state.push1(res); + } + Operator::I32Mul | Operator::I64Mul => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); + let res = builder.build_int_mul(v1, v2, &state.var_name()); + state.push1(res); + } + Operator::I32DivS | Operator::I64DivS => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); + let res = builder.build_int_signed_div(v1, v2, &state.var_name()); + state.push1(res); + } + Operator::I32DivU | Operator::I64DivU => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); + let res = builder.build_int_unsigned_div(v1, v2, &state.var_name()); + state.push1(res); + } + Operator::I32RemS | Operator::I64RemS => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); + let res = builder.build_int_signed_rem(v1, v2, &state.var_name()); + state.push1(res); + } + Operator::I32RemU | Operator::I64RemU => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); + let res = builder.build_int_unsigned_rem(v1, v2, &state.var_name()); + state.push1(res); + } + Operator::I32And | Operator::I64And => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); + let res = builder.build_and(v1, v2, &state.var_name()); + state.push1(res); + } + Operator::I32Or | Operator::I64Or => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); + let res = builder.build_or(v1, v2, &state.var_name()); + state.push1(res); + } + Operator::I32Xor | Operator::I64Xor => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); + let res = builder.build_xor(v1, v2, &state.var_name()); + state.push1(res); + } + Operator::I32Shl | Operator::I64Shl => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); + let res = builder.build_left_shift(v1, v2, &state.var_name()); + state.push1(res); + } + Operator::I32ShrS | Operator::I64ShrS => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); + let res = builder.build_right_shift(v1, v2, true, &state.var_name()); + state.push1(res); + } + Operator::I32ShrU | Operator::I64ShrU => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); + let res = builder.build_right_shift(v1, v2, false, &state.var_name()); + state.push1(res); + } + Operator::I32Rotl => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); + let lhs = builder.build_left_shift(v1, v2, &state.var_name()); + let rhs = { + let int_width = context.i32_type().const_int(32 as u64, false); + let rhs = builder.build_int_sub(int_width, v2, &state.var_name()); + builder.build_right_shift(v1, rhs, false, &state.var_name()) + }; + let res = builder.build_or(lhs, rhs, &state.var_name()); + state.push1(res); + } + Operator::I64Rotl => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); + let lhs = builder.build_left_shift(v1, v2, &state.var_name()); + let rhs = { + let int_width = context.i64_type().const_int(64 as u64, false); + let rhs = builder.build_int_sub(int_width, v2, &state.var_name()); + builder.build_right_shift(v1, rhs, false, &state.var_name()) + }; + let res = builder.build_or(lhs, rhs, &state.var_name()); + state.push1(res); + } + Operator::I32Rotr => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); + let lhs = builder.build_right_shift(v1, v2, false, &state.var_name()); + let rhs = { + let int_width = context.i32_type().const_int(32 as u64, false); + let rhs = builder.build_int_sub(int_width, v2, &state.var_name()); + builder.build_left_shift(v1, rhs, &state.var_name()) + }; + let res = builder.build_or(lhs, rhs, &state.var_name()); + state.push1(res); + } + Operator::I64Rotr => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); + let lhs = builder.build_right_shift(v1, v2, false, &state.var_name()); + let rhs = { + let int_width = context.i64_type().const_int(64 as u64, false); + let rhs = builder.build_int_sub(int_width, v2, &state.var_name()); + builder.build_left_shift(v1, rhs, &state.var_name()) + }; + let res = builder.build_or(lhs, rhs, &state.var_name()); + state.push1(res); + } + Operator::I32Clz => { + let input = state.pop1()?; + let ensure_defined_zero = context + .bool_type() + .const_int(1 as u64, false) + .as_basic_value_enum(); + let res = builder + .build_call( + intrinsics.ctlz_i32, + &[input, ensure_defined_zero], + &state.var_name(), + ) + .try_as_basic_value() + .left() + .unwrap(); + state.push1(res); + } + Operator::I64Clz => { + let input = state.pop1()?; + let ensure_defined_zero = context + .bool_type() + .const_int(1 as u64, false) + .as_basic_value_enum(); + let res = builder + .build_call( + intrinsics.ctlz_i64, + &[input, ensure_defined_zero], + &state.var_name(), + ) + .try_as_basic_value() + .left() + .unwrap(); + state.push1(res); + } + Operator::I32Ctz => { + let input = state.pop1()?; + let ensure_defined_zero = context + .bool_type() + .const_int(1 as u64, false) + .as_basic_value_enum(); + let res = builder + .build_call( + intrinsics.cttz_i32, + &[input, ensure_defined_zero], + &state.var_name(), + ) + .try_as_basic_value() + .left() + .unwrap(); + state.push1(res); + } + Operator::I64Ctz => { + let input = state.pop1()?; + let ensure_defined_zero = context + .bool_type() + .const_int(1 as u64, false) + .as_basic_value_enum(); + let res = builder + .build_call( + intrinsics.cttz_i64, + &[input, ensure_defined_zero], + &state.var_name(), + ) + .try_as_basic_value() + .left() + .unwrap(); + state.push1(res); + } + Operator::I32Popcnt => { + let input = state.pop1()?; + let res = builder + .build_call(intrinsics.ctpop_i32, &[input], &state.var_name()) + .try_as_basic_value() + .left() + .unwrap(); + state.push1(res); + } + Operator::I64Popcnt => { + let input = state.pop1()?; + let res = builder + .build_call(intrinsics.ctpop_i64, &[input], &state.var_name()) + .try_as_basic_value() + .left() + .unwrap(); + state.push1(res); + } + Operator::I32Eqz => { + let input = state.pop1()?.into_int_value(); + let zero = context.i32_type().const_int(0, false); + let res = + builder.build_int_compare(IntPredicate::EQ, input, zero, &state.var_name()); + state.push1(res); + } + Operator::I64Eqz => { + let input = state.pop1()?.into_int_value(); + let zero = context.i64_type().const_int(0, false); + let res = + builder.build_int_compare(IntPredicate::EQ, input, zero, &state.var_name()); + state.push1(res); + } + + /*************************** + * Floating-Point Arithmetic instructions. + * https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#floating-point-arithmetic-instructions + ***************************/ + Operator::F32Add | Operator::F64Add => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_float_value(), v2.into_float_value()); + let res = builder.build_float_add(v1, v2, &state.var_name()); + state.push1(res); + } + Operator::F32Sub | Operator::F32Sub => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_float_value(), v2.into_float_value()); + let res = builder.build_float_sub(v1, v2, &state.var_name()); + state.push1(res); + } + Operator::F32Mul | Operator::F64Mul => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_float_value(), v2.into_float_value()); + let res = builder.build_float_mul(v1, v2, &state.var_name()); + state.push1(res); + } + Operator::F32Div | Operator::F64Div => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_float_value(), v2.into_float_value()); + let res = builder.build_float_div(v1, v2, &state.var_name()); + state.push1(res); + } + Operator::F32Sqrt => { + let input = state.pop1()?; + let res = builder + .build_call(intrinsics.sqrt_f32, &[input], &state.var_name()) + .try_as_basic_value() + .left() + .unwrap(); + state.push1(res); + } + Operator::F64Sqrt => { + let input = state.pop1()?; + let res = builder + .build_call(intrinsics.sqrt_f64, &[input], &state.var_name()) + .try_as_basic_value() + .left() + .unwrap(); + state.push1(res); + } + Operator::F32Min => { + let (v1, v2) = state.pop2()?; + let res = builder + .build_call(intrinsics.minimum_f32, &[v1, v2], &state.var_name()) + .try_as_basic_value() + .left() + .unwrap(); + state.push1(res); + } + Operator::F64Min => { + let (v1, v2) = state.pop2()?; + let res = builder + .build_call(intrinsics.minimum_f64, &[v1, v2], &state.var_name()) + .try_as_basic_value() + .left() + .unwrap(); + state.push1(res); + } + Operator::F32Max => { + let (v1, v2) = state.pop2()?; + let res = builder + .build_call(intrinsics.maximum_f32, &[v1, v2], &state.var_name()) + .try_as_basic_value() + .left() + .unwrap(); + state.push1(res); + } + Operator::F64Max => { + let (v1, v2) = state.pop2()?; + let res = builder + .build_call(intrinsics.maximum_f64, &[v1, v2], &state.var_name()) + .try_as_basic_value() + .left() + .unwrap(); + state.push1(res); + } + Operator::F32Ceil => { + let input = state.pop1()?; + let res = builder + .build_call(intrinsics.ceil_f32, &[input], &state.var_name()) + .try_as_basic_value() + .left() + .unwrap(); + state.push1(res); + } + Operator::F64Ceil => { + let input = state.pop1()?; + let res = builder + .build_call(intrinsics.ceil_f64, &[input], &state.var_name()) + .try_as_basic_value() + .left() + .unwrap(); + state.push1(res); + } + Operator::F32Floor => { + let input = state.pop1()?; + let res = builder + .build_call(intrinsics.floor_f32, &[input], &state.var_name()) + .try_as_basic_value() + .left() + .unwrap(); + state.push1(res); + } + Operator::F64Floor => { + let input = state.pop1()?; + let res = builder + .build_call(intrinsics.floor_f64, &[input], &state.var_name()) + .try_as_basic_value() + .left() + .unwrap(); + state.push1(res); + } + Operator::F32Trunc => { + let input = state.pop1()?; + let res = builder + .build_call(intrinsics.trunc_f32, &[input], &state.var_name()) + .try_as_basic_value() + .left() + .unwrap(); + state.push1(res); + } + Operator::F64Trunc => { + let input = state.pop1()?; + let res = builder + .build_call(intrinsics.trunc_f64, &[input], &state.var_name()) + .try_as_basic_value() + .left() + .unwrap(); + state.push1(res); + } + Operator::F32Nearest => { + let input = state.pop1()?; + let res = builder + .build_call(intrinsics.nearbyint_f32, &[input], &state.var_name()) + .try_as_basic_value() + .left() + .unwrap(); + state.push1(res); + } + Operator::F64Nearest => { + let input = state.pop1()?; + let res = builder + .build_call(intrinsics.nearbyint_f64, &[input], &state.var_name()) + .try_as_basic_value() + .left() + .unwrap(); + state.push1(res); + } + Operator::F32Abs => { + let input = state.pop1()?; + let res = builder + .build_call(intrinsics.fabs_f32, &[input], &state.var_name()) + .try_as_basic_value() + .left() + .unwrap(); + state.push1(res); + } + Operator::F64Abs => { + let input = state.pop1()?; + let res = builder + .build_call(intrinsics.fabs_f64, &[input], &state.var_name()) + .try_as_basic_value() + .left() + .unwrap(); + state.push1(res); + } + Operator::F32Neg | Operator::F64Neg => { + let input = state.pop1()?.into_float_value(); + let res = builder.build_float_neg(input, &state.var_name()); + state.push1(res); + } + Operator::F32Copysign => { + let input = state.pop1()?; + let res = builder + .build_call(intrinsics.copysign_f32, &[input], &state.var_name()) + .try_as_basic_value() + .left() + .unwrap(); + state.push1(res); + } + Operator::F64Copysign => { + let input = state.pop1()?; + let res = builder + .build_call(intrinsics.copysign_f64, &[input], &state.var_name()) + .try_as_basic_value() + .left() + .unwrap(); + state.push1(res); + } + + /*************************** + * Integer Comparison instructions. + * https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#integer-comparison-instructions + ***************************/ + Operator::I32Eq | Operator::I64Eq => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); + let res = builder.build_int_compare(IntPredicate::EQ, v1, v2, &state.var_name()); + state.push1(res); + } + Operator::I32Ne | Operator::I64Ne => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); + let res = builder.build_int_compare(IntPredicate::NE, v1, v2, &state.var_name()); + state.push1(res); + } + Operator::I32LtS | Operator::I64LtS => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); + let res = builder.build_int_compare(IntPredicate::SLT, v1, v2, &state.var_name()); + state.push1(res); + } + Operator::I32LtU | Operator::I64LtU => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); + let res = builder.build_int_compare(IntPredicate::ULT, v1, v2, &state.var_name()); + state.push1(res); + } + Operator::I32LeS | Operator::I64LeS => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); + let res = builder.build_int_compare(IntPredicate::SLE, v1, v2, &state.var_name()); + state.push1(res); + } + Operator::I32LeU | Operator::I64LeU => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); + let res = builder.build_int_compare(IntPredicate::ULE, v1, v2, &state.var_name()); + state.push1(res); + } + Operator::I32GtS | Operator::I64GtS => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); + let res = builder.build_int_compare(IntPredicate::SGT, v1, v2, &state.var_name()); + state.push1(res); + } + Operator::I32GtU | Operator::I64GtU => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); + let res = builder.build_int_compare(IntPredicate::UGT, v1, v2, &state.var_name()); + state.push1(res); + } + Operator::I32GeS | Operator::I64GeS => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); + let res = builder.build_int_compare(IntPredicate::SGE, v1, v2, &state.var_name()); + state.push1(res); + } + Operator::I32GeU | Operator::I64GeU => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); + let res = builder.build_int_compare(IntPredicate::UGE, v1, v2, &state.var_name()); + state.push1(res); + } + + /*************************** + * Floating-Point Comparison instructions. + * https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#floating-point-comparison-instructions + ***************************/ + Operator::Unreachable => { + // Emit an unreachable instruction. + // If llvm cannot prove that this is never touched, + // it will emit a `ud2` instruction on x86_64 arches. + builder.build_unreachable(); + } + op @ _ => { + println!("{}", module.print_to_string().to_string()); + unimplemented!("{:?}", op); + } + } + } + + Ok(()) +} diff --git a/lib/llvm-backend/src/example.rs b/lib/llvm-backend/src/example.rs new file mode 100644 index 000000000..5ce3c9a5f --- /dev/null +++ b/lib/llvm-backend/src/example.rs @@ -0,0 +1,61 @@ +use inkwell::OptimizationLevel; +use inkwell::builder::Builder; +use inkwell::context::Context; +use inkwell::execution_engine::{ExecutionEngine, JitFunction}; +use inkwell::module::Module; +use inkwell::targets::{InitializationConfig, Target}; +use std::error::Error; + +/// Convenience type alias for the `sum` function. +/// +/// Calling this is innately `unsafe` because there's no guarantee it doesn't +/// do `unsafe` operations internally. +type SumFunc = unsafe extern "C" fn(u64, u64, u64) -> u64; + +#[test] +fn test_sum() -> Result<(), Box> { + let context = Context::create(); + let module = context.create_module("sum"); + let builder = context.create_builder(); + let execution_engine = module.create_jit_execution_engine(OptimizationLevel::Aggressive)?; + + let sum = jit_compile_sum(&context, &module, &builder, &execution_engine) + .ok_or("Unable to JIT compile `sum`")?; + + let x = 1u64; + let y = 2u64; + let z = 3u64; + + unsafe { + println!("{} + {} + {} = {}", x, y, z, sum.call(x, y, z)); + assert_eq!(sum.call(x, y, z), x + y + z); + } + + Ok(()) +} + +fn jit_compile_sum( + context: &Context, + module: &Module, + builder: &Builder, + execution_engine: &ExecutionEngine, +) -> Option> { + let i64_type = context.i64_type(); + let fn_type = i64_type.fn_type(&[i64_type.into(), i64_type.into(), i64_type.into()], false); + + let function = module.add_function("sum", fn_type, None); + let basic_block = context.append_basic_block(&function, "entry"); + + builder.position_at_end(&basic_block); + + let x = function.get_nth_param(0)?.into_int_value(); + let y = function.get_nth_param(1)?.into_int_value(); + let z = function.get_nth_param(2)?.into_int_value(); + + let sum = builder.build_int_add(x, y, "sum"); + let sum = builder.build_int_add(sum, z, "sum"); + + builder.build_return(Some(&sum)); + + unsafe { execution_engine.get_function("sum").ok() } +} diff --git a/lib/llvm-backend/src/intrinsics.rs b/lib/llvm-backend/src/intrinsics.rs new file mode 100644 index 000000000..824317e8e --- /dev/null +++ b/lib/llvm-backend/src/intrinsics.rs @@ -0,0 +1,99 @@ +use inkwell::{context::Context, module::Module, types::BasicType, values::FunctionValue}; + +pub struct Intrinsics { + pub ctlz_i32: FunctionValue, + pub ctlz_i64: FunctionValue, + + pub cttz_i32: FunctionValue, + pub cttz_i64: FunctionValue, + + pub ctpop_i32: FunctionValue, + pub ctpop_i64: FunctionValue, + + pub sqrt_f32: FunctionValue, + pub sqrt_f64: FunctionValue, + + pub minimum_f32: FunctionValue, + pub minimum_f64: FunctionValue, + + pub maximum_f32: FunctionValue, + pub maximum_f64: FunctionValue, + + pub ceil_f32: FunctionValue, + pub ceil_f64: FunctionValue, + + pub floor_f32: FunctionValue, + pub floor_f64: FunctionValue, + + pub trunc_f32: FunctionValue, + pub trunc_f64: FunctionValue, + + pub nearbyint_f32: FunctionValue, + pub nearbyint_f64: FunctionValue, + + pub fabs_f32: FunctionValue, + pub fabs_f64: FunctionValue, + + pub copysign_f32: FunctionValue, + pub copysign_f64: FunctionValue, +} + +impl Intrinsics { + pub fn declare(module: &Module, context: &Context) -> Self { + let i1_ty = context.bool_type().as_basic_type_enum(); + let i32_ty = context.i32_type().as_basic_type_enum(); + let i64_ty = context.i64_type().as_basic_type_enum(); + let f32_ty = context.f32_type().as_basic_type_enum(); + let f64_ty = context.f64_type().as_basic_type_enum(); + + let ret_i32_take_i32_i1 = i32_ty.fn_type(&[i32_ty, i1_ty], false); + let ret_i64_take_i64_i1 = i64_ty.fn_type(&[i64_ty, i1_ty], false); + + let ret_i32_take_i32 = i32_ty.fn_type(&[i32_ty], false); + let ret_i64_take_i64 = i64_ty.fn_type(&[i64_ty], false); + + let ret_f32_take_f32 = f32_ty.fn_type(&[f32_ty], false); + let ret_f64_take_f64 = f64_ty.fn_type(&[f64_ty], false); + + let ret_f32_take_f32_f32 = f32_ty.fn_type(&[f32_ty, f32_ty], false); + let ret_f64_take_f64_f64 = f64_ty.fn_type(&[f64_ty, f64_ty], false); + + Self { + ctlz_i32: module.add_function("llvm.ctlz.i32", ret_i32_take_i32_i1, None), + ctlz_i64: module.add_function("llvm.ctlz.i64", ret_i64_take_i64_i1, None), + + cttz_i32: module.add_function("llvm.cttz.i32", ret_i32_take_i32_i1, None), + cttz_i64: module.add_function("llvm.cttz.i64", ret_i64_take_i64_i1, None), + + ctpop_i32: module.add_function("llvm.ctpop.i32", ret_i32_take_i32, None), + ctpop_i64: module.add_function("llvm.ctpop.i64", ret_i64_take_i64, None), + + sqrt_f32: module.add_function("llvm.sqrt.f32", ret_f32_take_f32, None), + sqrt_f64: module.add_function("llvm.sqrt.f64", ret_f64_take_f64, None), + + minimum_f32: module.add_function("llvm.minimum.f32", ret_f32_take_f32_f32, None), + minimum_f64: module.add_function("llvm.minimum.f64", ret_f64_take_f64_f64, None), + + maximum_f32: module.add_function("llvm.maximum.f32", ret_f32_take_f32_f32, None), + maximum_f64: module.add_function("llvm.maximum.f64", ret_f64_take_f64_f64, None), + + ceil_f32: module.add_function("llvm.ceil.f32", ret_f32_take_f32, None), + ceil_f64: module.add_function("llvm.ceil.f64", ret_f64_take_f64, None), + + floor_f32: module.add_function("llvm.floor.f32", ret_f32_take_f32, None), + floor_f64: module.add_function("llvm.floor.f64", ret_f64_take_f64, None), + + trunc_f32: module.add_function("llvm.trunc.f32", ret_f32_take_f32, None), + trunc_f64: module.add_function("llvm.trunc.f64", ret_f64_take_f64, None), + + nearbyint_f32: module.add_function("llvm.nearbyint.f32", ret_f32_take_f32, None), + nearbyint_f64: module.add_function("llvm.nearbyint.f64", ret_f64_take_f64, None), + + fabs_f32: module.add_function("llvm.fabs.f32", ret_f32_take_f32, None), + fabs_f64: module.add_function("llvm.fabs.f64", ret_f64_take_f64, None), + + copysign_f32: module.add_function("llvm.copysign.f32", ret_f32_take_f32_f32, None), + copysign_f64: module.add_function("llvm.copysign.f64", ret_f64_take_f64_f64, None), + } + } +} diff --git a/lib/llvm-backend/src/lib.rs b/lib/llvm-backend/src/lib.rs new file mode 100644 index 000000000..9b1b3eab6 --- /dev/null +++ b/lib/llvm-backend/src/lib.rs @@ -0,0 +1,52 @@ +use wasmer_runtime_core::{ + backend::{Compiler, Token}, + error::CompileError, + module::{ModuleInfo, ModuleInner}, +}; + +mod code; +mod intrinsics; +mod read_info; +mod state; + +pub struct LLVMCompiler { + _private: (), +} + +impl LLVMCompiler { + pub fn new() -> Self { + Self { _private: () } + } +} + +impl Compiler for LLVMCompiler { + fn compile(&self, wasm: &[u8], _: Token) -> Result { + let (_info, _code_reader) = read_info::read_module(wasm).unwrap(); + + unimplemented!() + } +} + +#[test] +fn test_read_module() { + use wabt::wat2wasm; + let WAT: &'static str = r#" + (module + (type $t0 (func (param i32) (result i32))) + (import "env" "memory" (memory 1 1)) + (import "env" "table" (table 10 anyfunc)) + (import "env" "global" (global i32)) + (import "env" "print_i32" (func $print_i32 (type $t0))) + (func $identity (type $t0) (param $p0 i32) (result i32) + get_local $p0) + (func $print_num (export "print_num") (type $t0) (param $p0 i32) (result i32) + get_global 0 + call $identity + call $print_i32)) + "#; + let wasm = wat2wasm(WAT).unwrap(); + + let (info, code_reader) = read_info::read_module(&wasm).unwrap(); + + code::parse_function_bodies(&info, code_reader).unwrap(); +} diff --git a/lib/llvm-backend/src/read_info.rs b/lib/llvm-backend/src/read_info.rs new file mode 100644 index 000000000..c1ac2cf6b --- /dev/null +++ b/lib/llvm-backend/src/read_info.rs @@ -0,0 +1,333 @@ +use wasmer_runtime_core::{ + backend::Backend, + module::{ + DataInitializer, ExportIndex, ImportName, ModuleInfo, StringTable, StringTableBuilder, + TableInitializer, + }, + structures::{Map, TypedIndex}, + types::{ + ElementType, FuncIndex, FuncSig, GlobalDescriptor, GlobalIndex, GlobalInit, + ImportedGlobalIndex, Initializer, MemoryDescriptor, MemoryIndex, SigIndex, TableDescriptor, + TableIndex, Type, Value, + }, + units::Pages, +}; +use wasmparser::{ + BinaryReaderError, CodeSectionReader, Data, DataKind, Element, ElementKind, Export, + ExternalKind, FuncType, Import, ImportSectionEntryType, InitExpr, ModuleReader, Operator, + SectionCode, Type as WpType, +}; + +pub fn read_module(wasm: &[u8]) -> Result<(ModuleInfo, CodeSectionReader), BinaryReaderError> { + let mut info = ModuleInfo { + memories: Map::new(), + globals: Map::new(), + tables: Map::new(), + + imported_functions: Map::new(), + imported_memories: Map::new(), + imported_tables: Map::new(), + imported_globals: Map::new(), + + exports: Default::default(), + + data_initializers: Vec::new(), + elem_initializers: Vec::new(), + + start_func: None, + + func_assoc: Map::new(), + signatures: Map::new(), + backend: Backend::LLVM, + + namespace_table: StringTable::new(), + name_table: StringTable::new(), + }; + + let mut reader = ModuleReader::new(wasm)?; + let mut code_reader = None; + + loop { + if reader.eof() { + return Ok((info, code_reader.unwrap())); + } + + let section = reader.read()?; + + match section.code { + SectionCode::Type => { + let type_reader = section.get_type_section_reader()?; + + for ty in type_reader { + let ty = ty?; + info.signatures.push(func_type_to_func_sig(ty)?); + } + } + SectionCode::Import => { + let import_reader = section.get_import_section_reader()?; + let mut namespace_builder = StringTableBuilder::new(); + let mut name_builder = StringTableBuilder::new(); + + for import in import_reader { + let Import { module, field, ty } = import?; + + let namespace_index = namespace_builder.register(module); + let name_index = name_builder.register(field); + let import_name = ImportName { + namespace_index, + name_index, + }; + + match ty { + ImportSectionEntryType::Function(sigindex) => { + let sigindex = SigIndex::new(sigindex as usize); + info.imported_functions.push(import_name); + info.func_assoc.push(sigindex); + } + ImportSectionEntryType::Table(table_ty) => { + assert_eq!(table_ty.element_type, WpType::AnyFunc); + let table_desc = TableDescriptor { + element: ElementType::Anyfunc, + minimum: table_ty.limits.initial, + maximum: table_ty.limits.maximum, + }; + + info.imported_tables.push((import_name, table_desc)); + } + ImportSectionEntryType::Memory(memory_ty) => { + let mem_desc = MemoryDescriptor { + minimum: Pages(memory_ty.limits.initial), + maximum: memory_ty.limits.maximum.map(|max| Pages(max)), + shared: memory_ty.shared, + }; + info.imported_memories.push((import_name, mem_desc)); + } + ImportSectionEntryType::Global(global_ty) => { + let global_desc = GlobalDescriptor { + mutable: global_ty.mutable, + ty: type_to_type(global_ty.content_type)?, + }; + info.imported_globals.push((import_name, global_desc)); + } + } + } + } + SectionCode::Function => { + let func_decl_reader = section.get_function_section_reader()?; + + for sigindex in func_decl_reader { + let sigindex = sigindex?; + + let sigindex = SigIndex::new(sigindex as usize); + info.func_assoc.push(sigindex); + } + } + SectionCode::Table => { + let table_decl_reader = section.get_table_section_reader()?; + + for table_ty in table_decl_reader { + let table_ty = table_ty?; + + let table_desc = TableDescriptor { + element: ElementType::Anyfunc, + minimum: table_ty.limits.initial, + maximum: table_ty.limits.maximum, + }; + + info.tables.push(table_desc); + } + } + SectionCode::Memory => { + let mem_decl_reader = section.get_memory_section_reader()?; + + for memory_ty in mem_decl_reader { + let memory_ty = memory_ty?; + + let mem_desc = MemoryDescriptor { + minimum: Pages(memory_ty.limits.initial), + maximum: memory_ty.limits.maximum.map(|max| Pages(max)), + shared: memory_ty.shared, + }; + + info.memories.push(mem_desc); + } + } + SectionCode::Global => { + let global_decl_reader = section.get_global_section_reader()?; + + for global in global_decl_reader { + let global = global?; + + let desc = GlobalDescriptor { + mutable: global.ty.mutable, + ty: type_to_type(global.ty.content_type)?, + }; + + let global_init = GlobalInit { + desc, + init: eval_init_expr(&global.init_expr)?, + }; + + info.globals.push(global_init); + } + } + SectionCode::Export => { + let export_reader = section.get_export_section_reader()?; + + for export in export_reader { + let Export { field, kind, index } = export?; + + let export_index = match kind { + ExternalKind::Function => ExportIndex::Func(FuncIndex::new(index as usize)), + ExternalKind::Table => ExportIndex::Table(TableIndex::new(index as usize)), + ExternalKind::Memory => { + ExportIndex::Memory(MemoryIndex::new(index as usize)) + } + ExternalKind::Global => { + ExportIndex::Global(GlobalIndex::new(index as usize)) + } + }; + + info.exports.insert(field.to_string(), export_index); + } + } + SectionCode::Start => { + let start_index = section.get_start_section_content()?; + + info.start_func = Some(FuncIndex::new(start_index as usize)); + } + SectionCode::Element => { + let element_reader = section.get_element_section_reader()?; + + for element in element_reader { + let Element { kind, items } = element?; + + match kind { + ElementKind::Active { + table_index, + init_expr, + } => { + let table_index = TableIndex::new(table_index as usize); + let base = eval_init_expr(&init_expr)?; + let items_reader = items.get_items_reader()?; + + let elements: Vec<_> = items_reader + .into_iter() + .map(|res| res.map(|index| FuncIndex::new(index as usize))) + .collect::>()?; + + let table_init = TableInitializer { + table_index, + base, + elements, + }; + + info.elem_initializers.push(table_init); + } + ElementKind::Passive(_ty) => { + return Err(BinaryReaderError { + message: "passive tables are not yet supported", + offset: -1isize as usize, + }); + } + } + } + } + SectionCode::Code => { + code_reader = Some(section.get_code_section_reader()?); + } + SectionCode::Data => { + let data_reader = section.get_data_section_reader()?; + + for data in data_reader { + let Data { kind, data } = data?; + + match kind { + DataKind::Active { + memory_index, + init_expr, + } => { + let memory_index = MemoryIndex::new(memory_index as usize); + let base = eval_init_expr(&init_expr)?; + + let data_init = DataInitializer { + memory_index, + base, + data: data.to_vec(), + }; + + info.data_initializers.push(data_init); + } + DataKind::Passive => { + return Err(BinaryReaderError { + message: "passive memories are not yet supported", + offset: -1isize as usize, + }); + } + } + } + } + SectionCode::DataCount => {} + SectionCode::Custom { .. } => {} + } + } +} + +pub fn 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 => { + return Err(BinaryReaderError { + message: "the wasmer llvm backend does not yet support the simd extension", + offset: -1isize as usize, + }); + } + _ => panic!("broken invariant, invalid type"), + }) +} + +fn func_type_to_func_sig(func_ty: FuncType) -> Result { + assert_eq!(func_ty.form, WpType::Func); + + Ok(FuncSig::new( + func_ty + .params + .iter() + .cloned() + .map(type_to_type) + .collect::, _>>()?, + func_ty + .returns + .iter() + .cloned() + .map(type_to_type) + .collect::, _>>()?, + )) +} + +fn eval_init_expr(expr: &InitExpr) -> Result { + let mut reader = expr.get_operators_reader(); + let (op, offset) = reader.read_with_offset()?; + Ok(match op { + Operator::GetGlobal { global_index } => { + Initializer::GetGlobal(ImportedGlobalIndex::new(global_index as usize)) + } + Operator::I32Const { value } => Initializer::Const(Value::I32(value)), + Operator::I64Const { value } => Initializer::Const(Value::I64(value)), + Operator::F32Const { value } => { + Initializer::Const(Value::F32(f32::from_bits(value.bits()))) + } + Operator::F64Const { value } => { + Initializer::Const(Value::F64(f64::from_bits(value.bits()))) + } + _ => { + return Err(BinaryReaderError { + message: "init expr evaluation failed: unsupported opcode", + offset, + }); + } + }) +} diff --git a/lib/llvm-backend/src/state.rs b/lib/llvm-backend/src/state.rs new file mode 100644 index 000000000..38b1178ce --- /dev/null +++ b/lib/llvm-backend/src/state.rs @@ -0,0 +1,105 @@ +use inkwell::{ + basic_block::BasicBlock, + values::{BasicValue, BasicValueEnum}, +}; +use wasmparser::BinaryReaderError; + +enum ControlFrame { + If { + dest: BasicBlock, + stack_size_snapshot: usize, + }, + Block { + dest: BasicBlock, + stack_size_snapshot: usize, + num_ret_values: usize, + }, +} + +pub struct State { + stack: Vec, + control_stack: Vec, + value_counter: usize, +} + +impl State { + pub fn new() -> Self { + Self { + stack: vec![], + control_stack: vec![], + value_counter: 0, + } + } + + pub fn var_name(&mut self) -> String { + let s = self.value_counter.to_string(); + self.value_counter += 1; + s + } + + pub fn push1(&mut self, value: T) { + self.stack.push(value.as_basic_value_enum()) + } + + pub fn pop1(&mut self) -> Result { + self.stack.pop().ok_or_else(|| BinaryReaderError { + message: "invalid value stack", + offset: -1isize as usize, + }) + } + + pub fn pop2(&mut self) -> Result<(BasicValueEnum, BasicValueEnum), BinaryReaderError> { + let v2 = self.pop1()?; + let v1 = self.pop1()?; + Ok((v1, v2)) + } + + pub fn pop3( + &mut self, + ) -> Result<(BasicValueEnum, BasicValueEnum, BasicValueEnum), BinaryReaderError> { + let v3 = self.pop1()?; + let v2 = self.pop1()?; + let v1 = self.pop1()?; + Ok((v1, v2, v3)) + } + + pub fn peek1(&self) -> Result { + self.stack + .get(self.stack.len() - 1) + .ok_or_else(|| BinaryReaderError { + message: "invalid value stack", + offset: -1isize as usize, + }) + .map(|v| *v) + } + + pub fn peekn(&self, n: usize) -> Result<&[BasicValueEnum], BinaryReaderError> { + self.stack + .get(self.stack.len() - n..) + .ok_or_else(|| BinaryReaderError { + message: "invalid value stack", + offset: -1isize as usize, + }) + } + + pub fn popn(&mut self, n: usize) -> Result<(), BinaryReaderError> { + if self.stack.len() < n { + return Err(BinaryReaderError { + message: "invalid value stack", + offset: -1isize as usize, + }); + } + + let new_len = self.stack.len() - n; + self.stack.truncate(new_len); + Ok(()) + } + + pub fn push_block(&mut self, dest: BasicBlock, num_ret_values: usize) { + self.control_stack.push(ControlFrame::Block { + dest, + stack_size_snapshot: self.stack.len(), + num_ret_values, + }); + } +} diff --git a/lib/runtime-core/src/backing.rs b/lib/runtime-core/src/backing.rs index 46f1fe982..9734f0c02 100644 --- a/lib/runtime-core/src/backing.rs +++ b/lib/runtime-core/src/backing.rs @@ -91,7 +91,7 @@ impl LocalBacking { } } as usize; - match init.memory_index.local_or_import(module) { + match init.memory_index.local_or_import(&module.info) { LocalOrImport::Local(local_memory_index) => { let memory_desc = module.info.memories[local_memory_index]; let data_top = init_base + init.data.len(); @@ -159,7 +159,7 @@ impl LocalBacking { } } as usize; - match init.table_index.local_or_import(module) { + match init.table_index.local_or_import(&module.info) { LocalOrImport::Local(local_table_index) => { let table = &tables[local_table_index]; @@ -178,7 +178,7 @@ impl LocalBacking { let sig_id = vm::SigId(SigRegistry.lookup_sig_index(signature).index() as u32); - let (func, ctx) = match func_index.local_or_import(module) { + let (func, ctx) = match func_index.local_or_import(&module.info) { LocalOrImport::Local(local_func_index) => ( module .func_resolver @@ -217,7 +217,7 @@ impl LocalBacking { let sig_id = vm::SigId(SigRegistry.lookup_sig_index(signature).index() as u32); - let (func, ctx) = match func_index.local_or_import(module) { + let (func, ctx) = match func_index.local_or_import(&module.info) { LocalOrImport::Local(local_func_index) => ( module .func_resolver @@ -366,7 +366,7 @@ fn import_functions( }, ) in &module.info.imported_functions { - let sig_index = module.info.func_assoc[index.convert_up(module)]; + let sig_index = module.info.func_assoc[index.convert_up(&module.info)]; let expected_sig = &module.info.signatures[sig_index]; let namespace = module.info.namespace_table.get(*namespace_index); diff --git a/lib/runtime-core/src/instance.rs b/lib/runtime-core/src/instance.rs index 8255c125d..6a4d5d438 100644 --- a/lib/runtime-core/src/instance.rs +++ b/lib/runtime-core/src/instance.rs @@ -123,14 +123,14 @@ impl Instance { })?; } - let ctx = match func_index.local_or_import(&*self.module) { + let ctx = match func_index.local_or_import(&self.module.info) { LocalOrImport::Local(_) => self.inner.vmctx, LocalOrImport::Import(imported_func_index) => { self.inner.import_backing.vm_functions[imported_func_index].vmctx } }; - let func_ptr = match func_index.local_or_import(&self.module) { + let func_ptr = match func_index.local_or_import(&self.module.info) { LocalOrImport::Local(local_func_index) => self .module .func_resolver @@ -291,7 +291,7 @@ impl Instance { })? } - let vmctx = match func_index.local_or_import(&self.module) { + let vmctx = match func_index.local_or_import(&self.module.info) { LocalOrImport::Local(_) => self.inner.vmctx, LocalOrImport::Import(imported_func_index) => { self.inner.import_backing.vm_functions[imported_func_index].vmctx @@ -358,7 +358,7 @@ impl InstanceInner { .get(func_index) .expect("broken invariant, incorrect func index"); - let (func_ptr, ctx) = match func_index.local_or_import(module) { + let (func_ptr, ctx) = match func_index.local_or_import(&module.info) { LocalOrImport::Local(local_func_index) => ( module .func_resolver @@ -384,7 +384,7 @@ impl InstanceInner { } fn get_memory_from_index(&self, module: &ModuleInner, mem_index: MemoryIndex) -> Memory { - match mem_index.local_or_import(module) { + match mem_index.local_or_import(&module.info) { LocalOrImport::Local(local_mem_index) => self.backing.memories[local_mem_index].clone(), LocalOrImport::Import(imported_mem_index) => { self.import_backing.memories[imported_mem_index].clone() @@ -393,7 +393,7 @@ impl InstanceInner { } fn get_global_from_index(&self, module: &ModuleInner, global_index: GlobalIndex) -> Global { - match global_index.local_or_import(module) { + match global_index.local_or_import(&module.info) { LocalOrImport::Local(local_global_index) => { self.backing.globals[local_global_index].clone() } @@ -404,7 +404,7 @@ impl InstanceInner { } fn get_table_from_index(&self, module: &ModuleInner, table_index: TableIndex) -> Table { - match table_index.local_or_import(module) { + match table_index.local_or_import(&module.info) { LocalOrImport::Local(local_table_index) => { self.backing.tables[local_table_index].clone() } @@ -462,7 +462,7 @@ impl<'a> DynFunc<'a> { })? } - let vmctx = match self.func_index.local_or_import(self.module) { + let vmctx = match self.func_index.local_or_import(&self.module.info) { LocalOrImport::Local(_) => self.instance_inner.vmctx, LocalOrImport::Import(imported_func_index) => { self.instance_inner.import_backing.vm_functions[imported_func_index].vmctx @@ -488,7 +488,7 @@ impl<'a> DynFunc<'a> { } pub fn raw(&self) -> *const vm::Func { - match self.func_index.local_or_import(self.module) { + match self.func_index.local_or_import(&self.module.info) { LocalOrImport::Local(local_func_index) => self .module .func_resolver diff --git a/lib/runtime-core/src/types.rs b/lib/runtime-core/src/types.rs index c6b3f0a2b..bec1500b6 100644 --- a/lib/runtime-core/src/types.rs +++ b/lib/runtime-core/src/types.rs @@ -1,4 +1,9 @@ -use crate::{memory::MemoryType, module::ModuleInner, structures::TypedIndex, units::Pages}; +use crate::{ + memory::MemoryType, + module::{ModuleInfo, ModuleInner}, + structures::TypedIndex, + units::Pages, +}; use std::{borrow::Cow, mem}; /// Represents a WebAssembly type. @@ -340,23 +345,23 @@ define_map_index![ macro_rules! define_local_or_import { ($ty:ident, $local_ty:ident, $imported_ty:ident, $imports:ident) => { impl $ty { - pub fn local_or_import(self, module: &ModuleInner) -> LocalOrImport<$ty> { - if self.index() < module.info.$imports.len() { + pub fn local_or_import(self, info: &ModuleInfo) -> LocalOrImport<$ty> { + if self.index() < info.$imports.len() { LocalOrImport::Import(::Import::new(self.index())) } else { - LocalOrImport::Local(::Local::new(self.index() - module.info.$imports.len())) + LocalOrImport::Local(::Local::new(self.index() - info.$imports.len())) } } } impl $local_ty { - pub fn convert_up(self, module: &ModuleInner) -> $ty { - $ty ((self.index() + module.info.$imports.len()) as u32) + pub fn convert_up(self, info: &ModuleInfo) -> $ty { + $ty ((self.index() + info.$imports.len()) as u32) } } impl $imported_ty { - pub fn convert_up(self, _module: &ModuleInner) -> $ty { + pub fn convert_up(self, _module: &ModuleInfo) -> $ty { $ty (self.index() as u32) } } diff --git a/lib/runtime-core/src/vm.rs b/lib/runtime-core/src/vm.rs index 8cb9f0986..eaa76fd22 100644 --- a/lib/runtime-core/src/vm.rs +++ b/lib/runtime-core/src/vm.rs @@ -116,7 +116,7 @@ impl Ctx { pub fn memory(&self, mem_index: u32) -> &Memory { let module = unsafe { &*self.module }; let mem_index = MemoryIndex::new(mem_index as usize); - match mem_index.local_or_import(module) { + match mem_index.local_or_import(&module.info) { LocalOrImport::Local(local_mem_index) => unsafe { let local_backing = &*self.local_backing; &local_backing.memories[local_mem_index] From 2fa9cec0ed200de804464fbb2ed6f6ecd0967118 Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Sat, 9 Feb 2019 18:07:05 -0600 Subject: [PATCH 030/262] Add include guard --- lib/runtime-c-api/build.rs | 2 ++ lib/runtime-c-api/wasmer.h | 5 +++++ lib/runtime-c-api/wasmer.hh | 5 +++++ 3 files changed, 12 insertions(+) diff --git a/lib/runtime-c-api/build.rs b/lib/runtime-c-api/build.rs index bc8ad1af6..f78c5cf69 100644 --- a/lib/runtime-c-api/build.rs +++ b/lib/runtime-c-api/build.rs @@ -19,6 +19,7 @@ fn build() { cbindgen::Builder::new() .with_crate(crate_dir.clone()) .with_language(Language::C) + .with_include_guard("WASMER_H") .generate() .expect("Unable to generate C bindings") .write_to_file("wasmer.h"); @@ -26,6 +27,7 @@ fn build() { cbindgen::Builder::new() .with_crate(crate_dir) .with_language(Language::Cxx) + .with_include_guard("WASMER_H") .generate() .expect("Unable to generate C++ bindings") .write_to_file("wasmer.hh"); diff --git a/lib/runtime-c-api/wasmer.h b/lib/runtime-c-api/wasmer.h index 4df5001ef..0cfd919c9 100644 --- a/lib/runtime-c-api/wasmer.h +++ b/lib/runtime-c-api/wasmer.h @@ -1,3 +1,6 @@ +#ifndef WASMER_H +#define WASMER_H + #include #include #include @@ -127,3 +130,5 @@ uint32_t wasmer_table_length(wasmer_table_t *table); wasmer_table_result_t wasmer_table_new(wasmer_table_t **table, wasmer_limits_t limits); bool wasmer_validate(uint8_t *wasm_bytes, uint32_t wasm_bytes_len); + +#endif /* WASMER_H */ diff --git a/lib/runtime-c-api/wasmer.hh b/lib/runtime-c-api/wasmer.hh index 5fb292cb1..1d2c7d0af 100644 --- a/lib/runtime-c-api/wasmer.hh +++ b/lib/runtime-c-api/wasmer.hh @@ -1,3 +1,6 @@ +#ifndef WASMER_H +#define WASMER_H + #include #include #include @@ -129,3 +132,5 @@ wasmer_table_result_t wasmer_table_new(wasmer_table_t **table, wasmer_limits_t l bool wasmer_validate(uint8_t *wasm_bytes, uint32_t wasm_bytes_len); } // extern "C" + +#endif // WASMER_H From 4311a37defbdd65d2357e1afe2528b33d6ae2548 Mon Sep 17 00:00:00 2001 From: Syrus Date: Sat, 9 Feb 2019 14:19:04 -0800 Subject: [PATCH 031/262] Fixed simple spectests example compilation --- lib/clif-backend/src/func_env.rs | 8 ++++---- lib/clif-backend/src/resolver.rs | 13 ++++++------- lib/runtime-core/src/vmcalls.rs | 20 ++++++++++---------- lib/spectests/examples/simple/main.rs | 2 +- 4 files changed, 21 insertions(+), 22 deletions(-) diff --git a/lib/clif-backend/src/func_env.rs b/lib/clif-backend/src/func_env.rs index cada963d1..723ab71d9 100644 --- a/lib/clif-backend/src/func_env.rs +++ b/lib/clif-backend/src/func_env.rs @@ -32,7 +32,7 @@ impl<'env, 'module, 'isa> FuncEnv<'env, 'module, 'isa> { let mut signature = self.env.signatures[Converter(clif_sig_index).into()].clone(); // Add the vmctx parameter type to it - signature.params.push(ir::AbiParam::special( + signature.params.insert(0, ir::AbiParam::special( self.pointer_type(), ir::ArgumentPurpose::VMContext, )); @@ -559,9 +559,9 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> { let signature = pos.func.import_signature(ir::Signature { call_conv: self.target_config().default_call_conv, params: vec![ - ir::AbiParam::new(ir::types::I32), - ir::AbiParam::new(ir::types::I32), ir::AbiParam::special(self.pointer_type(), ir::ArgumentPurpose::VMContext), + ir::AbiParam::new(ir::types::I32), + ir::AbiParam::new(ir::types::I32), ], returns: vec![ir::AbiParam::new(ir::types::I32)], }); @@ -623,8 +623,8 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> { let signature = pos.func.import_signature(ir::Signature { call_conv: self.target_config().default_call_conv, params: vec![ - ir::AbiParam::new(ir::types::I32), ir::AbiParam::special(self.pointer_type(), ir::ArgumentPurpose::VMContext), + ir::AbiParam::new(ir::types::I32), ], returns: vec![ir::AbiParam::new(ir::types::I32)], }); diff --git a/lib/clif-backend/src/resolver.rs b/lib/clif-backend/src/resolver.rs index ddc7cd3b9..91e6102ef 100644 --- a/lib/clif-backend/src/resolver.rs +++ b/lib/clif-backend/src/resolver.rs @@ -34,7 +34,6 @@ use wasmer_runtime_core::{ types::{FuncSig, LocalFuncIndex, SigIndex}, vm, vmcalls, }; -use wasmer_runtime_core::vm::Ctx; extern "C" { #[cfg(not(target_os = "windows"))] @@ -351,21 +350,21 @@ fn round_up(n: usize, multiple: usize) -> usize { (n + multiple - 1) & !(multiple - 1) } -extern "C" fn i32_print(_ctx: &mut Ctx, n: i32) { +extern "C" fn i32_print(_ctx: &mut vm::Ctx, n: i32) { print!(" i32: {},", n); } -extern "C" fn i64_print(_ctx: &mut Ctx, n: i64) { +extern "C" fn i64_print(_ctx: &mut vm::Ctx, n: i64) { print!(" i64: {},", n); } -extern "C" fn f32_print(_ctx: &mut Ctx, n: f32) { +extern "C" fn f32_print(_ctx: &mut vm::Ctx, n: f32) { print!(" f32: {},", n); } -extern "C" fn f64_print(_ctx: &mut Ctx, n: f64) { +extern "C" fn f64_print(_ctx: &mut vm::Ctx, n: f64) { print!(" f64: {},", n); } -extern "C" fn start_debug(_ctx: &mut Ctx, func_index: u32) { +extern "C" fn start_debug(_ctx: &mut vm::Ctx, func_index: u32) { print!("func ({}), args: [", func_index); } -extern "C" fn end_debug(_ctx: &mut Ctx) { +extern "C" fn end_debug(_ctx: &mut vm::Ctx) { println!(" ]"); } diff --git a/lib/runtime-core/src/vmcalls.rs b/lib/runtime-core/src/vmcalls.rs index 8a6e683b5..576ca34ce 100644 --- a/lib/runtime-core/src/vmcalls.rs +++ b/lib/runtime-core/src/vmcalls.rs @@ -13,9 +13,9 @@ use crate::{ // +****************************+ pub unsafe extern "C" fn local_static_memory_grow( + ctx: &mut vm::Ctx, memory_index: LocalMemoryIndex, delta: Pages, - ctx: &mut vm::Ctx, ) -> i32 { let local_memory = *ctx.memories.add(memory_index.index()); let memory = (*local_memory).memory as *mut StaticMemory; @@ -28,8 +28,8 @@ pub unsafe extern "C" fn local_static_memory_grow( } pub unsafe extern "C" fn local_static_memory_size( - memory_index: LocalMemoryIndex, ctx: &vm::Ctx, + memory_index: LocalMemoryIndex, ) -> Pages { let local_memory = *ctx.memories.add(memory_index.index()); let memory = (*local_memory).memory as *mut StaticMemory; @@ -38,9 +38,9 @@ pub unsafe extern "C" fn local_static_memory_size( } pub unsafe extern "C" fn local_dynamic_memory_grow( + ctx: &mut vm::Ctx, memory_index: LocalMemoryIndex, delta: Pages, - ctx: &mut vm::Ctx, ) -> i32 { let local_memory = *ctx.memories.add(memory_index.index()); let memory = (*local_memory).memory as *mut DynamicMemory; @@ -53,8 +53,8 @@ pub unsafe extern "C" fn local_dynamic_memory_grow( } pub unsafe extern "C" fn local_dynamic_memory_size( - memory_index: LocalMemoryIndex, ctx: &vm::Ctx, + memory_index: LocalMemoryIndex, ) -> Pages { let local_memory = *ctx.memories.add(memory_index.index()); let memory = (*local_memory).memory as *mut DynamicMemory; @@ -67,9 +67,9 @@ pub unsafe extern "C" fn local_dynamic_memory_size( // +****************************+ pub unsafe extern "C" fn imported_static_memory_grow( + ctx: &mut vm::Ctx, import_memory_index: ImportedMemoryIndex, delta: Pages, - ctx: &mut vm::Ctx, ) -> i32 { let local_memory = *ctx.imported_memories.add(import_memory_index.index()); let memory = (*local_memory).memory as *mut StaticMemory; @@ -82,8 +82,8 @@ pub unsafe extern "C" fn imported_static_memory_grow( } pub unsafe extern "C" fn imported_static_memory_size( - import_memory_index: ImportedMemoryIndex, ctx: &vm::Ctx, + import_memory_index: ImportedMemoryIndex, ) -> Pages { let local_memory = *ctx.imported_memories.add(import_memory_index.index()); let memory = (*local_memory).memory as *mut StaticMemory; @@ -92,9 +92,9 @@ pub unsafe extern "C" fn imported_static_memory_size( } pub unsafe extern "C" fn imported_dynamic_memory_grow( + ctx: &mut vm::Ctx, memory_index: ImportedMemoryIndex, delta: Pages, - ctx: &mut vm::Ctx, ) -> i32 { let local_memory = *ctx.imported_memories.add(memory_index.index()); let memory = (*local_memory).memory as *mut DynamicMemory; @@ -107,8 +107,8 @@ pub unsafe extern "C" fn imported_dynamic_memory_grow( } pub unsafe extern "C" fn imported_dynamic_memory_size( - memory_index: ImportedMemoryIndex, ctx: &vm::Ctx, + memory_index: ImportedMemoryIndex, ) -> Pages { let local_memory = *ctx.imported_memories.add(memory_index.index()); let memory = (*local_memory).memory as *mut DynamicMemory; @@ -121,9 +121,9 @@ pub unsafe extern "C" fn imported_dynamic_memory_size( // +****************************+ pub unsafe extern "C" fn local_table_grow( + ctx: &mut vm::Ctx, table_index: LocalTableIndex, delta: u32, - ctx: &mut vm::Ctx, ) -> i32 { let _ = table_index; let _ = delta; @@ -131,7 +131,7 @@ pub unsafe extern "C" fn local_table_grow( unimplemented!() } -pub unsafe extern "C" fn local_table_size(table_index: LocalTableIndex, ctx: &vm::Ctx) -> u32 { +pub unsafe extern "C" fn local_table_size(ctx: &vm::Ctx, table_index: LocalTableIndex) -> u32 { let _ = table_index; let _ = ctx; unimplemented!() diff --git a/lib/spectests/examples/simple/main.rs b/lib/spectests/examples/simple/main.rs index fb215ee21..e418c9abe 100644 --- a/lib/spectests/examples/simple/main.rs +++ b/lib/spectests/examples/simple/main.rs @@ -61,7 +61,7 @@ fn main() -> error::Result<()> { Ok(()) } -fn print_num(n: i32, ctx: &mut vm::Ctx) -> Result { +fn print_num(ctx: &mut vm::Ctx, n: i32) -> Result { println!("print_num({})", n); let memory: &Memory = ctx.memory(0); From 0cfe864fe63e5e25a6ad2c04ec8138c0d535705d Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Sun, 10 Feb 2019 14:14:42 -0600 Subject: [PATCH 032/262] Add Memory data length --- lib/runtime-c-api/src/lib.rs | 25 ++++++++++--------------- lib/runtime-c-api/tests/test-memory.c | 4 ++++ lib/runtime-c-api/wasmer.h | 2 ++ lib/runtime-c-api/wasmer.hh | 2 ++ 4 files changed, 18 insertions(+), 15 deletions(-) diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index d7d513604..7dddd7ef7 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -7,13 +7,13 @@ use std::slice; use std::str; use std::sync::Arc; use std::{ffi::c_void, mem, ptr}; -use wasmer_runtime::{Global, ImportObject, Instance, Memory, Table, Value}; +use wasmer_runtime::{Ctx, Global, ImportObject, Instance, Memory, Table, Value}; use wasmer_runtime_core::export::{Context, Export, FuncPointer}; use wasmer_runtime_core::import::{LikeNamespace, Namespace}; use wasmer_runtime_core::types::{ ElementType, FuncSig, GlobalDescriptor, MemoryDescriptor, TableDescriptor, Type, }; -use wasmer_runtime_core::units::Pages; +use wasmer_runtime_core::units::{Bytes, Pages}; #[allow(non_camel_case_types)] pub struct wasmer_import_object_t(); @@ -428,22 +428,17 @@ pub unsafe extern "C" fn wasmer_imports_set_import_func( // }; } -//#[no_mangle] -//pub extern "C" fn wasmer_debug_print(kind: uint8_t, thing: *mut c_void) { -// match kind { -// 1 => { -// println!("wasmer import object:"); -// let import_object = unsafe { Box::from_raw(thing as *mut ImportObject) }; -// println!("after import object"); -// Box::into_raw(import_object); -// }, -// _ => panic!("unknown kind {:?}", kind) -// } -//} - #[no_mangle] pub extern "C" fn wasmer_instance_context_memory(instance: *mut wasmer_instance_context_t) {} +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub extern "C" fn wasmer_memory_data_length(mem: *mut wasmer_memory_t) -> uint32_t { + let memory = mem as *mut Memory; + let Bytes(len) = unsafe { (*memory).size().bytes() }; + len as uint32_t +} + #[allow(clippy::cast_ptr_alignment)] #[no_mangle] pub extern "C" fn wasmer_instance_destroy(instance: *mut wasmer_instance_t) { diff --git a/lib/runtime-c-api/tests/test-memory.c b/lib/runtime-c-api/tests/test-memory.c index 631a6a983..42a957e23 100644 --- a/lib/runtime-c-api/tests/test-memory.c +++ b/lib/runtime-c-api/tests/test-memory.c @@ -24,6 +24,10 @@ int main() printf("Memory pages length: %d\n", new_len); assert(new_len == 12); + uint32_t bytes_len = wasmer_memory_data_length(memory); + printf("Memory bytes length: %d\n", bytes_len); + assert(bytes_len == 12 * 65536); + // Err, grow beyond max wasmer_memory_result_t grow_result2 = wasmer_memory_grow(memory, 10); assert(grow_result2 == WASMER_MEMORY_ERROR); diff --git a/lib/runtime-c-api/wasmer.h b/lib/runtime-c-api/wasmer.h index 0cfd919c9..99fd96def 100644 --- a/lib/runtime-c-api/wasmer.h +++ b/lib/runtime-c-api/wasmer.h @@ -113,6 +113,8 @@ wasmer_compile_result_t wasmer_instantiate(wasmer_instance_t **instance, uint32_t wasm_bytes_len, wasmer_import_object_t *import_object); +uint32_t wasmer_memory_data_length(wasmer_memory_t *mem); + void wasmer_memory_destroy(wasmer_memory_t *memory); wasmer_memory_result_t wasmer_memory_grow(wasmer_memory_t *memory, uint32_t delta); diff --git a/lib/runtime-c-api/wasmer.hh b/lib/runtime-c-api/wasmer.hh index 1d2c7d0af..4c1134a5c 100644 --- a/lib/runtime-c-api/wasmer.hh +++ b/lib/runtime-c-api/wasmer.hh @@ -113,6 +113,8 @@ wasmer_compile_result_t wasmer_instantiate(wasmer_instance_t **instance, uint32_t wasm_bytes_len, wasmer_import_object_t *import_object); +uint32_t wasmer_memory_data_length(wasmer_memory_t *mem); + void wasmer_memory_destroy(wasmer_memory_t *memory); wasmer_memory_result_t wasmer_memory_grow(wasmer_memory_t *memory, uint32_t delta); From 7ef472dae230c886175f2ccf763b5542870ee6fa Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Sun, 10 Feb 2019 14:24:36 -0600 Subject: [PATCH 033/262] Add instance context memory --- lib/runtime-c-api/src/lib.rs | 10 +++++++++- lib/runtime-c-api/tests/test-import-function.c | 8 ++++++-- lib/runtime-c-api/wasmer.h | 3 ++- lib/runtime-c-api/wasmer.hh | 3 ++- 4 files changed, 19 insertions(+), 5 deletions(-) diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index 7dddd7ef7..74b6fa6c7 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -428,8 +428,16 @@ pub unsafe extern "C" fn wasmer_imports_set_import_func( // }; } +#[allow(clippy::cast_ptr_alignment)] #[no_mangle] -pub extern "C" fn wasmer_instance_context_memory(instance: *mut wasmer_instance_context_t) {} +pub extern "C" fn wasmer_instance_context_memory( + ctx: *mut wasmer_instance_context_t, + memory_idx: uint32_t, +) -> *const wasmer_memory_t { + let mut ctx = unsafe { Box::from_raw(ctx as *mut Ctx) }; + let memory = ctx.memory(0); + memory as *const Memory as *const wasmer_memory_t +} #[allow(clippy::cast_ptr_alignment)] #[no_mangle] diff --git a/lib/runtime-c-api/tests/test-import-function.c b/lib/runtime-c-api/tests/test-import-function.c index c6d723664..8f4deeb13 100644 --- a/lib/runtime-c-api/tests/test-import-function.c +++ b/lib/runtime-c-api/tests/test-import-function.c @@ -4,10 +4,14 @@ #include static print_str_called = false; +static memory_len = 0; void print_str(int32_t ptr, int32_t len, wasmer_instance_context_t *ctx) { - printf("In print_str\n"); + wasmer_memory_t *memory = wasmer_instance_context_memory(ctx, 0); + uint32_t mem_len = wasmer_memory_length(memory); + printf("In print_str, memory len: %d\n", mem_len); print_str_called = true; + memory_len = mem_len; } int main() @@ -38,7 +42,7 @@ int main() assert(call_result == WASMER_CALL_OK); assert(print_str_called); - + assert(memory_len == 17); printf("Destroy instance\n"); wasmer_instance_destroy(instance); diff --git a/lib/runtime-c-api/wasmer.h b/lib/runtime-c-api/wasmer.h index 99fd96def..39ff3f0c6 100644 --- a/lib/runtime-c-api/wasmer.h +++ b/lib/runtime-c-api/wasmer.h @@ -104,7 +104,8 @@ wasmer_call_result_t wasmer_instance_call(wasmer_instance_t *instance, wasmer_value_t *results, int results_len); -void wasmer_instance_context_memory(wasmer_instance_context_t *instance); +const wasmer_memory_t *wasmer_instance_context_memory(wasmer_instance_context_t *ctx, + uint32_t memory_idx); void wasmer_instance_destroy(wasmer_instance_t *instance); diff --git a/lib/runtime-c-api/wasmer.hh b/lib/runtime-c-api/wasmer.hh index 4c1134a5c..12b0ecebb 100644 --- a/lib/runtime-c-api/wasmer.hh +++ b/lib/runtime-c-api/wasmer.hh @@ -104,7 +104,8 @@ wasmer_call_result_t wasmer_instance_call(wasmer_instance_t *instance, wasmer_value_t *results, int results_len); -void wasmer_instance_context_memory(wasmer_instance_context_t *instance); +const wasmer_memory_t *wasmer_instance_context_memory(wasmer_instance_context_t *ctx, + uint32_t memory_idx); void wasmer_instance_destroy(wasmer_instance_t *instance); From a502da58e3398de39bb456f2782510e50dcacd90 Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Sun, 10 Feb 2019 14:27:08 -0600 Subject: [PATCH 034/262] Fix import object destroy --- lib/runtime-c-api/src/lib.rs | 2 +- lib/runtime-c-api/tests/test-import-function.c | 2 +- lib/runtime-c-api/tests/test-instantiate.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index 74b6fa6c7..adb520071 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -316,7 +316,7 @@ pub unsafe extern "C" fn wasmer_instantiate( } }; unsafe { *instance = Box::into_raw(Box::new(new_instance)) as *mut wasmer_instance_t }; - // Box::into_raw(import_object); // TODO Review is this the correct way not to drop + Box::into_raw(import_object); wasmer_compile_result_t::WASMER_COMPILE_OK } diff --git a/lib/runtime-c-api/tests/test-import-function.c b/lib/runtime-c-api/tests/test-import-function.c index 8f4deeb13..83c5b7535 100644 --- a/lib/runtime-c-api/tests/test-import-function.c +++ b/lib/runtime-c-api/tests/test-import-function.c @@ -47,6 +47,6 @@ int main() printf("Destroy instance\n"); wasmer_instance_destroy(instance); printf("Destroy import object\n"); - //wasmer_import_object_destroy(import_object); // TODO update instantiate and try this again + wasmer_import_object_destroy(import_object); return 0; } \ No newline at end of file diff --git a/lib/runtime-c-api/tests/test-instantiate.c b/lib/runtime-c-api/tests/test-instantiate.c index bd6a35004..e3ef602eb 100644 --- a/lib/runtime-c-api/tests/test-instantiate.c +++ b/lib/runtime-c-api/tests/test-instantiate.c @@ -41,6 +41,6 @@ int main() printf("Destroy instance\n"); wasmer_instance_destroy(instance); printf("Destroy import object\n"); - //wasmer_import_object_destroy(import_object); // TODO update instantiate and try this again + wasmer_import_object_destroy(import_object); return 0; } \ No newline at end of file From 66bf13c9dd92c0b3c08f9b1cca5a2695265f3d84 Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Sun, 10 Feb 2019 15:20:35 -0600 Subject: [PATCH 035/262] Add memory data function --- lib/runtime-c-api/src/lib.rs | 8 ++++++++ lib/runtime-c-api/tests/test-import-function.c | 12 +++++++++++- lib/runtime-c-api/wasmer.h | 2 ++ lib/runtime-c-api/wasmer.hh | 2 ++ 4 files changed, 23 insertions(+), 1 deletion(-) diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index adb520071..1072f5cd3 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -439,6 +439,14 @@ pub extern "C" fn wasmer_instance_context_memory( memory as *const Memory as *const wasmer_memory_t } +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub extern "C" fn wasmer_memory_data(mem: *mut wasmer_memory_t) -> *mut uint8_t { + let memory = mem as *mut Memory; + use std::cell::Cell; + unsafe { ((*memory).view::()[..]).as_ptr() as *mut Cell as *mut u8 } +} + #[allow(clippy::cast_ptr_alignment)] #[no_mangle] pub extern "C" fn wasmer_memory_data_length(mem: *mut wasmer_memory_t) -> uint32_t { diff --git a/lib/runtime-c-api/tests/test-import-function.c b/lib/runtime-c-api/tests/test-import-function.c index 83c5b7535..13ce81cab 100644 --- a/lib/runtime-c-api/tests/test-import-function.c +++ b/lib/runtime-c-api/tests/test-import-function.c @@ -5,13 +5,21 @@ static print_str_called = false; static memory_len = 0; +static ptr_len = 0; +static char actual_str[14] = {}; void print_str(int32_t ptr, int32_t len, wasmer_instance_context_t *ctx) { wasmer_memory_t *memory = wasmer_instance_context_memory(ctx, 0); uint32_t mem_len = wasmer_memory_length(memory); - printf("In print_str, memory len: %d\n", mem_len); + uint8_t *mem_bytes = wasmer_memory_data(memory); + for(int32_t idx = 0; idx < len; idx++){ + actual_str[idx] = mem_bytes[ptr + idx]; + } + actual_str[13] = '\0'; + printf("In print_str, memory len: %d, ptr_len: %d\n, str %s", mem_len, len, actual_str); print_str_called = true; memory_len = mem_len; + ptr_len = len; } int main() @@ -43,6 +51,8 @@ int main() assert(print_str_called); assert(memory_len == 17); + assert(ptr_len == 13); + assert(0 == strcmp(actual_str, "Hello, World!")); printf("Destroy instance\n"); wasmer_instance_destroy(instance); diff --git a/lib/runtime-c-api/wasmer.h b/lib/runtime-c-api/wasmer.h index 39ff3f0c6..0bffb7859 100644 --- a/lib/runtime-c-api/wasmer.h +++ b/lib/runtime-c-api/wasmer.h @@ -114,6 +114,8 @@ wasmer_compile_result_t wasmer_instantiate(wasmer_instance_t **instance, uint32_t wasm_bytes_len, wasmer_import_object_t *import_object); +uint8_t *wasmer_memory_data(wasmer_memory_t *mem); + uint32_t wasmer_memory_data_length(wasmer_memory_t *mem); void wasmer_memory_destroy(wasmer_memory_t *memory); diff --git a/lib/runtime-c-api/wasmer.hh b/lib/runtime-c-api/wasmer.hh index 12b0ecebb..6d2a9d878 100644 --- a/lib/runtime-c-api/wasmer.hh +++ b/lib/runtime-c-api/wasmer.hh @@ -114,6 +114,8 @@ wasmer_compile_result_t wasmer_instantiate(wasmer_instance_t **instance, uint32_t wasm_bytes_len, wasmer_import_object_t *import_object); +uint8_t *wasmer_memory_data(wasmer_memory_t *mem); + uint32_t wasmer_memory_data_length(wasmer_memory_t *mem); void wasmer_memory_destroy(wasmer_memory_t *memory); From b70e319f5c17250286fb7f40579fc701f38cb359 Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Sun, 10 Feb 2019 17:57:23 -0600 Subject: [PATCH 036/262] Add initial error messaging --- lib/runtime-c-api/src/lib.rs | 65 +++++++++++++++++++++- lib/runtime-c-api/tests/test-instantiate.c | 13 +++++ lib/runtime-c-api/tests/test-memory.c | 20 +++++++ lib/runtime-c-api/tests/test-tables.c | 8 +++ lib/runtime-c-api/wasmer.h | 4 ++ lib/runtime-c-api/wasmer.hh | 4 ++ lib/runtime-core/src/error.rs | 18 ++++++ 7 files changed, 131 insertions(+), 1 deletion(-) diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index 1072f5cd3..d1ccf69e4 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -2,6 +2,8 @@ extern crate wasmer_runtime; extern crate wasmer_runtime_core; use libc::{c_char, c_int, int32_t, int64_t, uint32_t, uint8_t}; +use std::cell::RefCell; +use std::error::Error; use std::ffi::CStr; use std::slice; use std::str; @@ -139,6 +141,7 @@ pub unsafe extern "C" fn wasmer_memory_new( let new_memory = match result { Ok(memory) => memory, Err(error) => { + update_last_error(error); return wasmer_memory_result_t::WASMER_MEMORY_ERROR; } }; @@ -185,6 +188,7 @@ pub unsafe extern "C" fn wasmer_table_new( let new_table = match result { Ok(table) => table, Err(error) => { + update_last_error(error); return wasmer_table_result_t::WASMER_TABLE_ERROR; } }; @@ -381,7 +385,7 @@ pub unsafe extern "C" fn wasmer_instance_call( wasmer_call_result_t::WASMER_CALL_OK } Err(err) => { - println!("Call Err: {:?}", err); + update_last_error(err); wasmer_call_result_t::WASMER_CALL_ERROR } } @@ -537,3 +541,62 @@ impl From for Type { } } } + +// Error reporting + +thread_local! { + static LAST_ERROR: RefCell>> = RefCell::new(None); +} + +fn update_last_error(err: E) { + LAST_ERROR.with(|prev| { + *prev.borrow_mut() = Some(Box::new(err)); + }); +} + +/// Retrieve the most recent error, clearing it in the process. +fn take_last_error() -> Option> { + LAST_ERROR.with(|prev| prev.borrow_mut().take()) +} + +#[no_mangle] +pub extern "C" fn wasmer_last_error_length() -> c_int { + LAST_ERROR.with(|prev| match *prev.borrow() { + Some(ref err) => err.to_string().len() as c_int + 1, + None => 0, + }) +} + +#[no_mangle] +pub unsafe extern "C" fn wasmer_last_error_message(buffer: *mut c_char, length: c_int) -> c_int { + if buffer.is_null() { + // buffer pointer is null + return -1; + } + + let last_error = match take_last_error() { + Some(err) => err, + None => return 0, + }; + + let error_message = last_error.to_string(); + + let buffer = slice::from_raw_parts_mut(buffer as *mut u8, length as usize); + + if error_message.len() >= buffer.len() { + // buffer to small for err message + return -1; + } + + ptr::copy_nonoverlapping( + error_message.as_ptr(), + buffer.as_mut_ptr(), + error_message.len(), + ); + + // Add a trailing null so people using the string as a `char *` don't + // accidentally read into garbage. + buffer[error_message.len()] = 0; + + error_message.len() as c_int +} diff --git a/lib/runtime-c-api/tests/test-instantiate.c b/lib/runtime-c-api/tests/test-instantiate.c index e3ef602eb..604f9544d 100644 --- a/lib/runtime-c-api/tests/test-instantiate.c +++ b/lib/runtime-c-api/tests/test-instantiate.c @@ -38,6 +38,19 @@ int main() assert(results[0].value.I32 == 15); assert(call_result == WASMER_CALL_OK); + + wasmer_call_result_t call_result2 = wasmer_instance_call(instance, "sum", params, 1, results, 1); + printf("Call result bad: %d\n", call_result2); + assert(call_result2 == WASMER_CALL_ERROR); + + int error_len = wasmer_last_error_length(); + printf("Error len: `%d`\n", error_len); + char *error_str = malloc(error_len); + wasmer_last_error_message(error_str, error_len); + printf("Error str: `%s`\n", error_str); + assert(0 == strcmp(error_str, "Call error")); + free(error_str); + printf("Destroy instance\n"); wasmer_instance_destroy(instance); printf("Destroy import object\n"); diff --git a/lib/runtime-c-api/tests/test-memory.c b/lib/runtime-c-api/tests/test-memory.c index 42a957e23..d9379c78a 100644 --- a/lib/runtime-c-api/tests/test-memory.c +++ b/lib/runtime-c-api/tests/test-memory.c @@ -31,6 +31,26 @@ int main() // Err, grow beyond max wasmer_memory_result_t grow_result2 = wasmer_memory_grow(memory, 10); assert(grow_result2 == WASMER_MEMORY_ERROR); +// int error_len = wasmer_last_error_length(); +// char *error_str = malloc(error_len); +// wasmer_last_error_message(error_str, error_len); +// assert(0 == strcmp(error_str, "Creation error")); +// free(error_str); + + +// wasmer_memory_t *bad_memory = NULL; +// wasmer_limits_t bad_descriptor; +// bad_descriptor.min = 15; +// bad_descriptor.max = 10; +// wasmer_memory_result_t bad_memory_result = wasmer_memory_new(&bad_memory, bad_descriptor); +// printf("Bad memory result: %d\n", bad_memory_result); +// assert(memory_result == WASMER_MEMORY_ERROR); +// +// int error_len = wasmer_last_error_length(); +// char *error_str = malloc(error_len); +// wasmer_last_error_message(error_str, error_len); +// assert(0 == strcmp(error_str, "Creation error")); +// free(error_str); printf("Destroy memory\n"); wasmer_memory_destroy(memory); diff --git a/lib/runtime-c-api/tests/test-tables.c b/lib/runtime-c-api/tests/test-tables.c index 7e3f51a2f..f50a5af5f 100644 --- a/lib/runtime-c-api/tests/test-tables.c +++ b/lib/runtime-c-api/tests/test-tables.c @@ -30,6 +30,14 @@ int main() // printf("Table length: %d\n", len_grow2); // assert(len_grow2 == 15); +// wasmer_table_t *table_bad = NULL; +// wasmer_limits_t bad_descriptor; +// bad_descriptor.min = 15; +// bad_descriptor.max = 10; +// wasmer_table_result_t table_bad_result = wasmer_table_new(&table_bad, bad_descriptor); +// printf("Table result: %d\n", table_bad_result); +// assert(table_result == WASMER_TABLE_ERROR); + printf("Destroy table\n"); wasmer_table_destroy(table); return 0; diff --git a/lib/runtime-c-api/wasmer.h b/lib/runtime-c-api/wasmer.h index 0bffb7859..3f4a34a94 100644 --- a/lib/runtime-c-api/wasmer.h +++ b/lib/runtime-c-api/wasmer.h @@ -114,6 +114,10 @@ wasmer_compile_result_t wasmer_instantiate(wasmer_instance_t **instance, uint32_t wasm_bytes_len, wasmer_import_object_t *import_object); +int wasmer_last_error_length(void); + +int wasmer_last_error_message(char *buffer, int length); + uint8_t *wasmer_memory_data(wasmer_memory_t *mem); uint32_t wasmer_memory_data_length(wasmer_memory_t *mem); diff --git a/lib/runtime-c-api/wasmer.hh b/lib/runtime-c-api/wasmer.hh index 6d2a9d878..c7ddb5bdd 100644 --- a/lib/runtime-c-api/wasmer.hh +++ b/lib/runtime-c-api/wasmer.hh @@ -114,6 +114,10 @@ wasmer_compile_result_t wasmer_instantiate(wasmer_instance_t **instance, uint32_t wasm_bytes_len, wasmer_import_object_t *import_object); +int wasmer_last_error_length(); + +int wasmer_last_error_message(char *buffer, int length); + uint8_t *wasmer_memory_data(wasmer_memory_t *mem); uint32_t wasmer_memory_data_length(wasmer_memory_t *mem); diff --git a/lib/runtime-core/src/error.rs b/lib/runtime-core/src/error.rs index b72c74242..d75a2ca90 100644 --- a/lib/runtime-core/src/error.rs +++ b/lib/runtime-core/src/error.rs @@ -1,6 +1,8 @@ use crate::types::{ FuncSig, GlobalDescriptor, MemoryDescriptor, MemoryIndex, TableDescriptor, TableIndex, Type, }; +use std::error::Error as StdError; +use std::fmt; use std::sync::Arc; pub type Result = std::result::Result; @@ -154,6 +156,14 @@ impl PartialEq for CallError { } } +impl fmt::Display for CallError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "Call error") + } +} + +impl StdError for CallError {} + /// This error type is produced when creating something, /// like a `Memory` or a `Table`. #[derive(Debug, Clone)] @@ -168,6 +178,14 @@ impl PartialEq for CreationError { } } +impl fmt::Display for CreationError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "Creation error") + } +} + +impl StdError for CreationError {} + /// The amalgamation of all errors that can occur /// during the compilation, instantiation, or execution /// of a webassembly module. From 019ef9ea01d3aac1f09a5db0387e25cbb5a0e261 Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Mon, 11 Feb 2019 19:07:28 -0600 Subject: [PATCH 037/262] Consolidate result type to one enum --- lib/runtime-c-api/src/lib.rs | 74 +++++++------------ .../tests/test-import-function.c | 8 +- lib/runtime-c-api/tests/test-instantiate.c | 12 +-- lib/runtime-c-api/tests/test-memory.c | 14 ++-- lib/runtime-c-api/tests/test-tables.c | 16 ++-- lib/runtime-c-api/wasmer.h | 49 +++++------- lib/runtime-c-api/wasmer.hh | 49 +++++------- 7 files changed, 84 insertions(+), 138 deletions(-) diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index d1ccf69e4..97267866d 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -29,33 +29,9 @@ pub struct wasmer_instance_context_t(); #[allow(non_camel_case_types)] #[no_mangle] #[repr(C)] -pub enum wasmer_compile_result_t { - WASMER_COMPILE_OK = 1, - WASMER_COMPILE_ERROR = 2, -} - -#[allow(non_camel_case_types)] -#[no_mangle] -#[repr(C)] -pub enum wasmer_call_result_t { - WASMER_CALL_OK = 1, - WASMER_CALL_ERROR = 2, -} - -#[allow(non_camel_case_types)] -#[no_mangle] -#[repr(C)] -pub enum wasmer_memory_result_t { - WASMER_MEMORY_OK = 1, - WASMER_MEMORY_ERROR = 2, -} - -#[allow(non_camel_case_types)] -#[no_mangle] -#[repr(C)] -pub enum wasmer_table_result_t { - WASMER_TABLE_OK = 1, - WASMER_TABLE_ERROR = 2, +pub enum wasmer_result_t { + WASMER_OK = 1, + WASMER_ERROR = 2, } #[repr(u32)] @@ -131,7 +107,7 @@ pub extern "C" fn wasmer_import_object_new() -> *mut wasmer_import_object_t { pub unsafe extern "C" fn wasmer_memory_new( mut memory: *mut *mut wasmer_memory_t, limits: wasmer_limits_t, -) -> wasmer_memory_result_t { +) -> wasmer_result_t { let desc = MemoryDescriptor { minimum: Pages(limits.min), maximum: Some(Pages(limits.max)), @@ -142,11 +118,11 @@ pub unsafe extern "C" fn wasmer_memory_new( Ok(memory) => memory, Err(error) => { update_last_error(error); - return wasmer_memory_result_t::WASMER_MEMORY_ERROR; + return wasmer_result_t::WASMER_ERROR; } }; unsafe { *memory = Box::into_raw(Box::new(new_memory)) as *mut wasmer_memory_t }; - wasmer_memory_result_t::WASMER_MEMORY_OK + wasmer_result_t::WASMER_OK } #[allow(clippy::cast_ptr_alignment)] @@ -154,14 +130,14 @@ pub unsafe extern "C" fn wasmer_memory_new( pub extern "C" fn wasmer_memory_grow( memory: *mut wasmer_memory_t, delta: uint32_t, -) -> wasmer_memory_result_t { +) -> wasmer_result_t { let memory = unsafe { Box::from_raw(memory as *mut Memory) }; let maybe_delta = memory.grow(Pages(delta)); Box::into_raw(memory); if let Some(_delta) = maybe_delta { - wasmer_memory_result_t::WASMER_MEMORY_OK + wasmer_result_t::WASMER_OK } else { - wasmer_memory_result_t::WASMER_MEMORY_ERROR + wasmer_result_t::WASMER_ERROR } } @@ -178,7 +154,7 @@ pub extern "C" fn wasmer_memory_length(memory: *mut wasmer_memory_t) -> uint32_t pub unsafe extern "C" fn wasmer_table_new( mut table: *mut *mut wasmer_table_t, limits: wasmer_limits_t, -) -> wasmer_table_result_t { +) -> wasmer_result_t { let desc = TableDescriptor { element: ElementType::Anyfunc, minimum: limits.min, @@ -189,11 +165,11 @@ pub unsafe extern "C" fn wasmer_table_new( Ok(table) => table, Err(error) => { update_last_error(error); - return wasmer_table_result_t::WASMER_TABLE_ERROR; + return wasmer_result_t::WASMER_ERROR; } }; unsafe { *table = Box::into_raw(Box::new(new_table)) as *mut wasmer_table_t }; - wasmer_table_result_t::WASMER_TABLE_OK + wasmer_result_t::WASMER_OK } #[allow(clippy::cast_ptr_alignment)] @@ -201,14 +177,14 @@ pub unsafe extern "C" fn wasmer_table_new( pub extern "C" fn wasmer_table_grow( table: *mut wasmer_table_t, delta: uint32_t, -) -> wasmer_table_result_t { +) -> wasmer_result_t { let table = unsafe { Box::from_raw(table as *mut Table) }; let maybe_delta = table.grow(delta); Box::into_raw(table); if let Some(_delta) = maybe_delta { - wasmer_table_result_t::WASMER_TABLE_OK + wasmer_result_t::WASMER_OK } else { - wasmer_table_result_t::WASMER_TABLE_ERROR + wasmer_result_t::WASMER_ERROR } } @@ -305,10 +281,10 @@ pub unsafe extern "C" fn wasmer_instantiate( wasm_bytes: *mut uint8_t, wasm_bytes_len: uint32_t, import_object: *mut wasmer_import_object_t, -) -> wasmer_compile_result_t { +) -> wasmer_result_t { let import_object = unsafe { Box::from_raw(import_object as *mut ImportObject) }; if wasm_bytes.is_null() { - return wasmer_compile_result_t::WASMER_COMPILE_ERROR; + return wasmer_result_t::WASMER_ERROR; } let bytes: &[u8] = unsafe { ::std::slice::from_raw_parts_mut(wasm_bytes, wasm_bytes_len as usize) }; @@ -316,12 +292,12 @@ pub unsafe extern "C" fn wasmer_instantiate( let new_instance = match result { Ok(instance) => instance, Err(error) => { - return wasmer_compile_result_t::WASMER_COMPILE_ERROR; + return wasmer_result_t::WASMER_ERROR; } }; unsafe { *instance = Box::into_raw(Box::new(new_instance)) as *mut wasmer_instance_t }; Box::into_raw(import_object); - wasmer_compile_result_t::WASMER_COMPILE_OK + wasmer_result_t::WASMER_OK } #[allow(clippy::cast_ptr_alignment)] @@ -333,17 +309,17 @@ pub unsafe extern "C" fn wasmer_instance_call( params_len: c_int, results: *mut wasmer_value_t, results_len: c_int, -) -> wasmer_call_result_t { +) -> wasmer_result_t { // TODO handle params and results if instance.is_null() { - return wasmer_call_result_t::WASMER_CALL_ERROR; + return wasmer_result_t::WASMER_ERROR; } if name.is_null() { - return wasmer_call_result_t::WASMER_CALL_ERROR; + return wasmer_result_t::WASMER_ERROR; } if params.is_null() { - return wasmer_call_result_t::WASMER_CALL_ERROR; + return wasmer_result_t::WASMER_ERROR; } let params: &[wasmer_value_t] = slice::from_raw_parts(params, params_len as usize); @@ -382,11 +358,11 @@ pub unsafe extern "C" fn wasmer_instance_call( }; results[0] = ret; } - wasmer_call_result_t::WASMER_CALL_OK + wasmer_result_t::WASMER_OK } Err(err) => { update_last_error(err); - wasmer_call_result_t::WASMER_CALL_ERROR + wasmer_result_t::WASMER_ERROR } } } diff --git a/lib/runtime-c-api/tests/test-import-function.c b/lib/runtime-c-api/tests/test-import-function.c index 13ce81cab..f0ca17504 100644 --- a/lib/runtime-c-api/tests/test-import-function.c +++ b/lib/runtime-c-api/tests/test-import-function.c @@ -39,15 +39,15 @@ int main() fclose(file); wasmer_instance_t *instance = NULL; - wasmer_compile_result_t compile_result = wasmer_instantiate(&instance, bytes, len, import_object); + wasmer_result_t compile_result = wasmer_instantiate(&instance, bytes, len, import_object); printf("Compile result: %d\n", compile_result); - assert(compile_result == WASMER_COMPILE_OK); + assert(compile_result == WASMER_OK); wasmer_value_t params[] = {}; wasmer_value_t results[] = {}; - wasmer_call_result_t call_result = wasmer_instance_call(instance, "hello_wasm", params, 0, results, 0); + wasmer_result_t call_result = wasmer_instance_call(instance, "hello_wasm", params, 0, results, 0); printf("Call result: %d\n", call_result); - assert(call_result == WASMER_CALL_OK); + assert(call_result == WASMER_OK); assert(print_str_called); assert(memory_len == 17); diff --git a/lib/runtime-c-api/tests/test-instantiate.c b/lib/runtime-c-api/tests/test-instantiate.c index 604f9544d..db24544f4 100644 --- a/lib/runtime-c-api/tests/test-instantiate.c +++ b/lib/runtime-c-api/tests/test-instantiate.c @@ -17,9 +17,9 @@ int main() fclose(file); wasmer_instance_t *instance = NULL; - wasmer_compile_result_t compile_result = wasmer_instantiate(&instance, bytes, len, import_object); + wasmer_result_t compile_result = wasmer_instantiate(&instance, bytes, len, import_object); printf("Compile result: %d\n", compile_result); - assert(compile_result == WASMER_COMPILE_OK); + assert(compile_result == WASMER_OK); wasmer_value_t param_one; param_one.tag = WASM_I32; @@ -32,16 +32,16 @@ int main() wasmer_value_t result_one; wasmer_value_t results[] = {result_one}; - wasmer_call_result_t call_result = wasmer_instance_call(instance, "sum", params, 2, results, 1); + wasmer_result_t call_result = wasmer_instance_call(instance, "sum", params, 2, results, 1); printf("Call result: %d\n", call_result); printf("Result: %d\n", results[0].value.I32); assert(results[0].value.I32 == 15); - assert(call_result == WASMER_CALL_OK); + assert(call_result == WASMER_OK); - wasmer_call_result_t call_result2 = wasmer_instance_call(instance, "sum", params, 1, results, 1); + wasmer_result_t call_result2 = wasmer_instance_call(instance, "sum", params, 1, results, 1); printf("Call result bad: %d\n", call_result2); - assert(call_result2 == WASMER_CALL_ERROR); + assert(call_result2 == WASMER_ERROR); int error_len = wasmer_last_error_length(); printf("Error len: `%d`\n", error_len); diff --git a/lib/runtime-c-api/tests/test-memory.c b/lib/runtime-c-api/tests/test-memory.c index d9379c78a..68ff27712 100644 --- a/lib/runtime-c-api/tests/test-memory.c +++ b/lib/runtime-c-api/tests/test-memory.c @@ -9,16 +9,16 @@ int main() wasmer_limits_t descriptor; descriptor.min = 10; descriptor.max = 15; - wasmer_memory_result_t memory_result = wasmer_memory_new(&memory, descriptor); + wasmer_result_t memory_result = wasmer_memory_new(&memory, descriptor); printf("Memory result: %d\n", memory_result); - assert(memory_result == WASMER_MEMORY_OK); + assert(memory_result == WASMER_OK); uint32_t len = wasmer_memory_length(memory); printf("Memory pages length: %d\n", len); assert(len == 10); - wasmer_memory_result_t grow_result = wasmer_memory_grow(memory, 2); - assert(grow_result == WASMER_MEMORY_OK); + wasmer_result_t grow_result = wasmer_memory_grow(memory, 2); + assert(grow_result == WASMER_OK); uint32_t new_len = wasmer_memory_length(memory); printf("Memory pages length: %d\n", new_len); @@ -29,8 +29,8 @@ int main() assert(bytes_len == 12 * 65536); // Err, grow beyond max - wasmer_memory_result_t grow_result2 = wasmer_memory_grow(memory, 10); - assert(grow_result2 == WASMER_MEMORY_ERROR); + wasmer_result_t grow_result2 = wasmer_memory_grow(memory, 10); + assert(grow_result2 == WASMER_ERROR); // int error_len = wasmer_last_error_length(); // char *error_str = malloc(error_len); // wasmer_last_error_message(error_str, error_len); @@ -42,7 +42,7 @@ int main() // wasmer_limits_t bad_descriptor; // bad_descriptor.min = 15; // bad_descriptor.max = 10; -// wasmer_memory_result_t bad_memory_result = wasmer_memory_new(&bad_memory, bad_descriptor); +// wasmer_result_t bad_memory_result = wasmer_memory_new(&bad_memory, bad_descriptor); // printf("Bad memory result: %d\n", bad_memory_result); // assert(memory_result == WASMER_MEMORY_ERROR); // diff --git a/lib/runtime-c-api/tests/test-tables.c b/lib/runtime-c-api/tests/test-tables.c index f50a5af5f..3f8c29805 100644 --- a/lib/runtime-c-api/tests/test-tables.c +++ b/lib/runtime-c-api/tests/test-tables.c @@ -9,23 +9,23 @@ int main() wasmer_limits_t descriptor; descriptor.min = 10; descriptor.max = 15; - wasmer_table_result_t table_result = wasmer_table_new(&table, descriptor); + wasmer_result_t table_result = wasmer_table_new(&table, descriptor); printf("Table result: %d\n", table_result); - assert(table_result == WASMER_TABLE_OK); + assert(table_result == WASMER_OK); uint32_t len = wasmer_table_length(table); printf("Table length: %d\n", len); assert(len == 15); - // wasmer_table_result_t grow_result1 = wasmer_table_grow(&table, 5); - // assert(grow_result1 == WASMER_TABLE_OK); + // wasmer_result_t grow_result1 = wasmer_table_grow(&table, 5); + // assert(grow_result1 == WASMER_OK); // uint32_t len_grow1 = wasmer_table_length(table); // printf("Table length: %d\n", len_grow1); // assert(len_grow1 == 15); // // Try to grow beyond max - // wasmer_table_result_t grow_result2 = wasmer_table_grow(&table, 1); - // assert(grow_result2 == WASMER_TABLE_ERROR); + // wasmer_result_t grow_result2 = wasmer_table_grow(&table, 1); + // assert(grow_result2 == WASMER_ERROR); // uint32_t len_grow2 = wasmer_table_length(table); // printf("Table length: %d\n", len_grow2); // assert(len_grow2 == 15); @@ -34,9 +34,9 @@ int main() // wasmer_limits_t bad_descriptor; // bad_descriptor.min = 15; // bad_descriptor.max = 10; -// wasmer_table_result_t table_bad_result = wasmer_table_new(&table_bad, bad_descriptor); +// wasmer_result_t table_bad_result = wasmer_table_new(&table_bad, bad_descriptor); // printf("Table result: %d\n", table_bad_result); -// assert(table_result == WASMER_TABLE_ERROR); +// assert(table_result == WASMER_ERROR); printf("Destroy table\n"); wasmer_table_destroy(table); diff --git a/lib/runtime-c-api/wasmer.h b/lib/runtime-c-api/wasmer.h index 3f4a34a94..1b53f3123 100644 --- a/lib/runtime-c-api/wasmer.h +++ b/lib/runtime-c-api/wasmer.h @@ -7,24 +7,9 @@ #include typedef enum { - WASMER_CALL_OK = 1, - WASMER_CALL_ERROR = 2, -} wasmer_call_result_t; - -typedef enum { - WASMER_COMPILE_OK = 1, - WASMER_COMPILE_ERROR = 2, -} wasmer_compile_result_t; - -typedef enum { - WASMER_MEMORY_OK = 1, - WASMER_MEMORY_ERROR = 2, -} wasmer_memory_result_t; - -typedef enum { - WASMER_TABLE_OK = 1, - WASMER_TABLE_ERROR = 2, -} wasmer_table_result_t; + WASMER_OK = 1, + WASMER_ERROR = 2, +} wasmer_result_t; enum wasmer_value_tag { WASM_I32, @@ -97,22 +82,22 @@ void wasmer_imports_set_import_func(wasmer_import_object_t *import_object, const wasmer_value_tag *returns, int returns_len); -wasmer_call_result_t wasmer_instance_call(wasmer_instance_t *instance, - const char *name, - const wasmer_value_t *params, - int params_len, - wasmer_value_t *results, - int results_len); +wasmer_result_t wasmer_instance_call(wasmer_instance_t *instance, + const char *name, + const wasmer_value_t *params, + int params_len, + wasmer_value_t *results, + int results_len); const wasmer_memory_t *wasmer_instance_context_memory(wasmer_instance_context_t *ctx, uint32_t memory_idx); void wasmer_instance_destroy(wasmer_instance_t *instance); -wasmer_compile_result_t wasmer_instantiate(wasmer_instance_t **instance, - uint8_t *wasm_bytes, - uint32_t wasm_bytes_len, - wasmer_import_object_t *import_object); +wasmer_result_t wasmer_instantiate(wasmer_instance_t **instance, + uint8_t *wasm_bytes, + uint32_t wasm_bytes_len, + wasmer_import_object_t *import_object); int wasmer_last_error_length(void); @@ -124,19 +109,19 @@ uint32_t wasmer_memory_data_length(wasmer_memory_t *mem); void wasmer_memory_destroy(wasmer_memory_t *memory); -wasmer_memory_result_t wasmer_memory_grow(wasmer_memory_t *memory, uint32_t delta); +wasmer_result_t wasmer_memory_grow(wasmer_memory_t *memory, uint32_t delta); uint32_t wasmer_memory_length(wasmer_memory_t *memory); -wasmer_memory_result_t wasmer_memory_new(wasmer_memory_t **memory, wasmer_limits_t limits); +wasmer_result_t wasmer_memory_new(wasmer_memory_t **memory, wasmer_limits_t limits); void wasmer_table_destroy(wasmer_table_t *table); -wasmer_table_result_t wasmer_table_grow(wasmer_table_t *table, uint32_t delta); +wasmer_result_t wasmer_table_grow(wasmer_table_t *table, uint32_t delta); uint32_t wasmer_table_length(wasmer_table_t *table); -wasmer_table_result_t wasmer_table_new(wasmer_table_t **table, wasmer_limits_t limits); +wasmer_result_t wasmer_table_new(wasmer_table_t **table, wasmer_limits_t limits); bool wasmer_validate(uint8_t *wasm_bytes, uint32_t wasm_bytes_len); diff --git a/lib/runtime-c-api/wasmer.hh b/lib/runtime-c-api/wasmer.hh index c7ddb5bdd..68b935202 100644 --- a/lib/runtime-c-api/wasmer.hh +++ b/lib/runtime-c-api/wasmer.hh @@ -5,24 +5,9 @@ #include #include -enum class wasmer_call_result_t { - WASMER_CALL_OK = 1, - WASMER_CALL_ERROR = 2, -}; - -enum class wasmer_compile_result_t { - WASMER_COMPILE_OK = 1, - WASMER_COMPILE_ERROR = 2, -}; - -enum class wasmer_memory_result_t { - WASMER_MEMORY_OK = 1, - WASMER_MEMORY_ERROR = 2, -}; - -enum class wasmer_table_result_t { - WASMER_TABLE_OK = 1, - WASMER_TABLE_ERROR = 2, +enum class wasmer_result_t { + WASMER_OK = 1, + WASMER_ERROR = 2, }; enum class wasmer_value_tag : uint32_t { @@ -97,22 +82,22 @@ void wasmer_imports_set_import_func(wasmer_import_object_t *import_object, const wasmer_value_tag *returns, int returns_len); -wasmer_call_result_t wasmer_instance_call(wasmer_instance_t *instance, - const char *name, - const wasmer_value_t *params, - int params_len, - wasmer_value_t *results, - int results_len); +wasmer_result_t wasmer_instance_call(wasmer_instance_t *instance, + const char *name, + const wasmer_value_t *params, + int params_len, + wasmer_value_t *results, + int results_len); const wasmer_memory_t *wasmer_instance_context_memory(wasmer_instance_context_t *ctx, uint32_t memory_idx); void wasmer_instance_destroy(wasmer_instance_t *instance); -wasmer_compile_result_t wasmer_instantiate(wasmer_instance_t **instance, - uint8_t *wasm_bytes, - uint32_t wasm_bytes_len, - wasmer_import_object_t *import_object); +wasmer_result_t wasmer_instantiate(wasmer_instance_t **instance, + uint8_t *wasm_bytes, + uint32_t wasm_bytes_len, + wasmer_import_object_t *import_object); int wasmer_last_error_length(); @@ -124,19 +109,19 @@ uint32_t wasmer_memory_data_length(wasmer_memory_t *mem); void wasmer_memory_destroy(wasmer_memory_t *memory); -wasmer_memory_result_t wasmer_memory_grow(wasmer_memory_t *memory, uint32_t delta); +wasmer_result_t wasmer_memory_grow(wasmer_memory_t *memory, uint32_t delta); uint32_t wasmer_memory_length(wasmer_memory_t *memory); -wasmer_memory_result_t wasmer_memory_new(wasmer_memory_t **memory, wasmer_limits_t limits); +wasmer_result_t wasmer_memory_new(wasmer_memory_t **memory, wasmer_limits_t limits); void wasmer_table_destroy(wasmer_table_t *table); -wasmer_table_result_t wasmer_table_grow(wasmer_table_t *table, uint32_t delta); +wasmer_result_t wasmer_table_grow(wasmer_table_t *table, uint32_t delta); uint32_t wasmer_table_length(wasmer_table_t *table); -wasmer_table_result_t wasmer_table_new(wasmer_table_t **table, wasmer_limits_t limits); +wasmer_result_t wasmer_table_new(wasmer_table_t **table, wasmer_limits_t limits); bool wasmer_validate(uint8_t *wasm_bytes, uint32_t wasm_bytes_len); From 34c45aee3d7047b112907e92b878dc9a008c8ad2 Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Mon, 11 Feb 2019 20:08:54 -0600 Subject: [PATCH 038/262] Update last error for every error result --- lib/runtime-c-api/src/lib.rs | 41 ++++++++++++++++++++++++--- lib/runtime-c-api/tests/test-memory.c | 11 +++---- 2 files changed, 43 insertions(+), 9 deletions(-) diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index 97267866d..319447d0c 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -5,6 +5,7 @@ use libc::{c_char, c_int, int32_t, int64_t, uint32_t, uint8_t}; use std::cell::RefCell; use std::error::Error; use std::ffi::CStr; +use std::fmt; use std::slice; use std::str; use std::sync::Arc; @@ -137,6 +138,9 @@ pub extern "C" fn wasmer_memory_grow( if let Some(_delta) = maybe_delta { wasmer_result_t::WASMER_OK } else { + update_last_error(CApiError { + msg: "unable to grow memory".to_string(), + }); wasmer_result_t::WASMER_ERROR } } @@ -184,6 +188,9 @@ pub extern "C" fn wasmer_table_grow( if let Some(_delta) = maybe_delta { wasmer_result_t::WASMER_OK } else { + update_last_error(CApiError { + msg: "unable to grow table".to_string(), + }); wasmer_result_t::WASMER_ERROR } } @@ -284,6 +291,9 @@ pub unsafe extern "C" fn wasmer_instantiate( ) -> wasmer_result_t { let import_object = unsafe { Box::from_raw(import_object as *mut ImportObject) }; if wasm_bytes.is_null() { + update_last_error(CApiError { + msg: "wasm bytes ptr is null".to_string(), + }); return wasmer_result_t::WASMER_ERROR; } let bytes: &[u8] = @@ -292,6 +302,11 @@ pub unsafe extern "C" fn wasmer_instantiate( let new_instance = match result { Ok(instance) => instance, Err(error) => { + // TODO the trait bound `wasmer_runtime::error::Error: std::error::Error` is not satisfied + //update_last_error(error); + update_last_error(CApiError { + msg: "error instantiating".to_string(), + }); return wasmer_result_t::WASMER_ERROR; } }; @@ -310,22 +325,27 @@ pub unsafe extern "C" fn wasmer_instance_call( results: *mut wasmer_value_t, results_len: c_int, ) -> wasmer_result_t { - // TODO handle params and results if instance.is_null() { + update_last_error(CApiError { + msg: "instance ptr is null".to_string(), + }); return wasmer_result_t::WASMER_ERROR; } if name.is_null() { + update_last_error(CApiError { + msg: "name ptr is null".to_string(), + }); return wasmer_result_t::WASMER_ERROR; } - if params.is_null() { + update_last_error(CApiError { + msg: "params ptr is null".to_string(), + }); return wasmer_result_t::WASMER_ERROR; } let params: &[wasmer_value_t] = slice::from_raw_parts(params, params_len as usize); - // TODO Fix this conversion and params let params: Vec = params.iter().cloned().map(|x| x.into()).collect(); - // let params= &[Value::I32(3), Value::I32(4)]; let func_name_c = unsafe { CStr::from_ptr(name) }; let func_name_r = func_name_c.to_str().unwrap(); @@ -576,3 +596,16 @@ pub unsafe extern "C" fn wasmer_last_error_message(buffer: *mut c_char, length: error_message.len() as c_int } + +#[derive(Debug)] +struct CApiError { + msg: String, +} + +impl fmt::Display for CApiError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", &self.msg) + } +} + +impl Error for CApiError {} diff --git a/lib/runtime-c-api/tests/test-memory.c b/lib/runtime-c-api/tests/test-memory.c index 68ff27712..d472c2b08 100644 --- a/lib/runtime-c-api/tests/test-memory.c +++ b/lib/runtime-c-api/tests/test-memory.c @@ -31,11 +31,12 @@ int main() // Err, grow beyond max wasmer_result_t grow_result2 = wasmer_memory_grow(memory, 10); assert(grow_result2 == WASMER_ERROR); -// int error_len = wasmer_last_error_length(); -// char *error_str = malloc(error_len); -// wasmer_last_error_message(error_str, error_len); -// assert(0 == strcmp(error_str, "Creation error")); -// free(error_str); + int error_len = wasmer_last_error_length(); + char *error_str = malloc(error_len); + wasmer_last_error_message(error_str, error_len); + printf("Error str: `%s`\n", error_str); + assert(0 == strcmp(error_str, "unable to grow memory")); + free(error_str); // wasmer_memory_t *bad_memory = NULL; From 5ee19e55a5adb0ffec3b27d6a51fd02f31a9f947 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Mon, 11 Feb 2019 19:34:04 -0800 Subject: [PATCH 039/262] Add some branching instructions --- Cargo.lock | 1 + lib/llvm-backend/Cargo.toml | 1 + lib/llvm-backend/src/code.rs | 387 ++++++++++++++++++++++++----- lib/llvm-backend/src/intrinsics.rs | 72 ++++-- lib/llvm-backend/src/lib.rs | 2 +- lib/llvm-backend/src/state.rs | 85 +++++-- 6 files changed, 454 insertions(+), 94 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 209d06782..6adb5581c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -359,6 +359,7 @@ version = "0.1.0" dependencies = [ "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "inkwell 0.1.0 (git+https://github.com/TheDan64/inkwell?branch=llvm7-0)", + "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-runtime-core 0.1.2", "wasmparser 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/lib/llvm-backend/Cargo.toml b/lib/llvm-backend/Cargo.toml index 000265b7d..bcf2175e2 100644 --- a/lib/llvm-backend/Cargo.toml +++ b/lib/llvm-backend/Cargo.toml @@ -9,6 +9,7 @@ wasmer-runtime-core = { path = "../runtime-core", version = "0.1.2" } wasmparser = "0.28.0" inkwell = { git = "https://github.com/TheDan64/inkwell", branch = "llvm7-0" } hashbrown = "0.1.8" +smallvec = "0.6.8" [dev-dependencies] wabt = "0.7.4" diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index 50a31065a..7a24f9fbf 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -1,13 +1,12 @@ -use hashbrown::HashMap; use inkwell::{ - basic_block::BasicBlock, builder::Builder, context::Context, module::Module, types::{BasicType, BasicTypeEnum, FunctionType}, - values::{AggregateValue, BasicValue, BasicValueEnum, FunctionValue}, - IntPredicate, + values::{BasicValue, FunctionValue}, + FloatPredicate, IntPredicate, }; +use smallvec::SmallVec; use wasmer_runtime_core::{ module::ModuleInfo, structures::{Map, SliceMap, TypedIndex}, @@ -19,20 +18,18 @@ use crate::intrinsics::Intrinsics; use crate::read_info::type_to_type; use crate::state::State; -fn func_sig_to_llvm(context: &Context, sig: &FuncSig) -> FunctionType { - let param_types: Vec<_> = sig - .params() - .iter() - .map(|&ty| type_to_llvm(context, ty)) - .collect(); +fn func_sig_to_llvm(context: &Context, intrinsics: &Intrinsics, sig: &FuncSig) -> FunctionType { + let user_param_types = sig.params().iter().map(|&ty| type_to_llvm(intrinsics, ty)); + + let param_types: Vec<_> = user_param_types.collect(); match sig.returns() { - [] => context.void_type().fn_type(¶m_types, false), - [single_value] => type_to_llvm(context, *single_value).fn_type(¶m_types, false), + [] => intrinsics.void_ty.fn_type(¶m_types, false), + [single_value] => type_to_llvm(intrinsics, *single_value).fn_type(¶m_types, false), returns @ _ => { let basic_types: Vec<_> = returns .iter() - .map(|&ty| type_to_llvm(context, ty)) + .map(|&ty| type_to_llvm(intrinsics, ty)) .collect(); context @@ -42,12 +39,12 @@ fn func_sig_to_llvm(context: &Context, sig: &FuncSig) -> FunctionType { } } -fn type_to_llvm(context: &Context, ty: Type) -> BasicTypeEnum { +fn type_to_llvm(intrinsics: &Intrinsics, ty: Type) -> BasicTypeEnum { match ty { - Type::I32 => context.i32_type().as_basic_type_enum(), - Type::I64 => context.i64_type().as_basic_type_enum(), - Type::F32 => context.f32_type().as_basic_type_enum(), - Type::F64 => context.f64_type().as_basic_type_enum(), + Type::I32 => intrinsics.i32_ty.as_basic_type_enum(), + Type::I64 => intrinsics.i64_ty.as_basic_type_enum(), + Type::F32 => intrinsics.f32_ty.as_basic_type_enum(), + Type::F64 => intrinsics.f64_ty.as_basic_type_enum(), } } @@ -64,7 +61,7 @@ pub fn parse_function_bodies( let signatures: Map = info .signatures .iter() - .map(|(_, sig)| func_sig_to_llvm(&context, sig)) + .map(|(_, sig)| func_sig_to_llvm(&context, &intrinsics, sig)) .collect(); let functions: Map = info .func_assoc @@ -72,7 +69,7 @@ pub fn parse_function_bodies( .skip(info.imported_functions.len()) .map(|(func_index, &sig_index)| { module.add_function( - &format!("fn:{}", func_index.index()), + &format!("fn{}", func_index.index()), signatures[sig_index], None, ) @@ -114,7 +111,9 @@ fn parse_function( locals_reader: LocalsReader, op_reader: OperatorsReader, ) -> Result<(), BinaryReaderError> { - let llvm_sig = &signatures[info.func_assoc[func_index.convert_up(info)]]; + let sig_index = info.func_assoc[func_index.convert_up(info)]; + let func_sig = &info.signatures[sig_index]; + let llvm_sig = &signatures[sig_index]; let function = functions[func_index]; let entry_block = context.append_basic_block(&function, "entry"); @@ -126,7 +125,7 @@ fn parse_function( locals.extend(function.get_param_iter().enumerate().map(|(index, param)| { let ty = param.get_type(); - let alloca = builder.build_alloca(ty, &state.var_name()); + let alloca = builder.build_alloca(ty, &format!("local{}", index)); builder.build_store(alloca, param); alloca })); @@ -136,15 +135,15 @@ fn parse_function( let wasmer_ty = type_to_type(ty)?; - let ty = type_to_llvm(context, wasmer_ty); + let ty = type_to_llvm(intrinsics, wasmer_ty); - let alloca = builder.build_alloca(ty, &state.var_name()); + let alloca = builder.build_alloca(ty, &format!("local{}", index)); let default_value = match wasmer_ty { - Type::I32 => context.i32_type().const_int(0, false).as_basic_value_enum(), - Type::I64 => context.i64_type().const_int(0, false).as_basic_value_enum(), - Type::F32 => context.f32_type().const_float(0.0).as_basic_value_enum(), - Type::F64 => context.f64_type().const_float(0.0).as_basic_value_enum(), + Type::I32 => intrinsics.i32_zero.as_basic_value_enum(), + Type::I64 => intrinsics.i64_zero.as_basic_value_enum(), + Type::F32 => intrinsics.f32_zero.as_basic_value_enum(), + Type::F64 => intrinsics.f64_zero.as_basic_value_enum(), }; builder.build_store(alloca, default_value); @@ -154,6 +153,149 @@ fn parse_function( for op in op_reader { match op? { + /*************************** + * Control Flow instructions. + * https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#control-flow-instructions + ***************************/ + Operator::Block { ty } => { + let current_block = builder.get_insert_block().ok_or(BinaryReaderError { + message: "not currently in a block", + offset: -1isize as usize, + })?; + + let end_block = context.append_basic_block(&function, &state.block_name()); + builder.position_at_end(&end_block); + + let phis = if let Ok(wasmer_ty) = type_to_type(ty) { + let llvm_ty = type_to_llvm(intrinsics, wasmer_ty); + [llvm_ty] + .iter() + .map(|&ty| builder.build_phi(ty, &state.var_name())) + .collect() + } else { + SmallVec::new() + }; + + state.push_block(end_block, phis); + builder.position_at_end(¤t_block); + } + Operator::Loop { ty } => { + + // let loop_body = context.append_basic_block(&function, &state.block_name()); + // let next = context.append_basic_block(&function, &state.block_name()); + // builder.build_unconditional_branch(&body); + // let num_return_values = if ty == wasmparser::Type::EmptyBlockType { 0 } else { 1 }; + // state.push_loop(loop_body, next, num_return_values); + } + Operator::Br { relative_depth } => { + let frame = state.frame_at_depth(relative_depth)?; + + let current_block = builder.get_insert_block().ok_or(BinaryReaderError { + message: "not currently in a block", + offset: -1isize as usize, + })?; + + let values = state.peekn(frame.phis().len())?; + + // For each result of the block we're branching to, + // pop a value off the value stack and load it into + // the corresponding phi. + for (phi, value) in frame.phis().iter().zip(values.iter()) { + phi.add_incoming(&[(value, ¤t_block)]); + } + + builder.build_unconditional_branch(frame.dest()); + + state.popn(frame.phis().len())?; + + builder.build_unreachable(); + } + Operator::BrIf { relative_depth } => { + let cond = state.pop1()?; + let frame = state.frame_at_depth(relative_depth)?; + + let current_block = builder.get_insert_block().ok_or(BinaryReaderError { + message: "not currently in a block", + offset: -1isize as usize, + })?; + + let param_stack = state.peekn(frame.phis().len())?; + + for (phi, value) in frame.phis().iter().zip(param_stack.iter()) { + phi.add_incoming(&[(value, ¤t_block)]); + } + + let false_block = context.append_basic_block(&function, &state.block_name()); + + let cond_value = builder.build_int_compare( + IntPredicate::NE, + cond.into_int_value(), + intrinsics.i32_zero, + &state.var_name(), + ); + builder.build_conditional_branch(cond_value, frame.dest(), &false_block); + builder.position_at_end(&false_block); + } + Operator::BrTable { ref table } => { + let current_block = builder.get_insert_block().ok_or(BinaryReaderError { + message: "not currently in a block", + offset: -1isize as usize, + })?; + + let (label_depths, default_depth) = table.read_table()?; + + let index = state.pop1()?; + + let default_frame = state.frame_at_depth(default_depth)?; + + let res_len = default_frame.phis().len(); + + let args = state.peekn(res_len)?; + + for (phi, value) in default_frame.phis().iter().zip(args.iter()) { + phi.add_incoming(&[(value, ¤t_block)]); + } + + let cases: Vec<_> = label_depths + .iter() + .enumerate() + .map(|(case_index, &depth)| { + let frame = state.frame_at_depth(depth)?; + let case_index_literal = + context.i32_type().const_int(case_index as u64, false); + + for (phi, value) in frame.phis().iter().zip(args.iter()) { + phi.add_incoming(&[(value, ¤t_block)]); + } + + Ok((case_index_literal, frame.dest())) + }) + .collect::>()?; + + builder.build_switch(index.into_int_value(), default_frame.dest(), &cases[..]); + + state.popn(res_len)?; + builder.build_unreachable(); + } + + Operator::End => { + let frame = state.pop_frame()?; + + // Push each phi value to the value stack. + for phi in frame.phis() { + state.push1(phi.as_basic_value()); + } + + state.reset_stack(&frame); + } + + Operator::Unreachable => { + // Emit an unreachable instruction. + // If llvm cannot prove that this is never touched, + // it will emit a `ud2` instruction on x86_64 arches. + builder.build_unreachable(); + } + /*************************** * Basic instructions. * https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#basic-instructions @@ -167,21 +309,21 @@ fn parse_function( // Generate const values. Operator::I32Const { value } => { - let i = context.i32_type().const_int(value as u64, false); + let i = intrinsics.i32_ty.const_int(value as u64, false); state.push1(i); } Operator::I64Const { value } => { - let i = context.i64_type().const_int(value as u64, false); + let i = intrinsics.i64_ty.const_int(value as u64, false); state.push1(i); } Operator::F32Const { value } => { - let f = context - .f32_type() + let f = intrinsics + .f32_ty .const_float(f64::from_bits(value.bits() as u64)); state.push1(f); } Operator::F64Const { value } => { - let f = context.f64_type().const_float(f64::from_bits(value.bits())); + let f = intrinsics.f64_ty.const_float(f64::from_bits(value.bits())); state.push1(f); } @@ -243,9 +385,7 @@ fn parse_function( } } } - LocalOrImport::Import(import_func_index) => { - // unimplemented!() - } + LocalOrImport::Import(import_func_index) => unimplemented!(), } } Operator::CallIndirect { index, table_index } => { @@ -339,7 +479,7 @@ fn parse_function( let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); let lhs = builder.build_left_shift(v1, v2, &state.var_name()); let rhs = { - let int_width = context.i32_type().const_int(32 as u64, false); + let int_width = intrinsics.i32_ty.const_int(32 as u64, false); let rhs = builder.build_int_sub(int_width, v2, &state.var_name()); builder.build_right_shift(v1, rhs, false, &state.var_name()) }; @@ -351,7 +491,7 @@ fn parse_function( let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); let lhs = builder.build_left_shift(v1, v2, &state.var_name()); let rhs = { - let int_width = context.i64_type().const_int(64 as u64, false); + let int_width = intrinsics.i64_ty.const_int(64 as u64, false); let rhs = builder.build_int_sub(int_width, v2, &state.var_name()); builder.build_right_shift(v1, rhs, false, &state.var_name()) }; @@ -363,7 +503,7 @@ fn parse_function( let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); let lhs = builder.build_right_shift(v1, v2, false, &state.var_name()); let rhs = { - let int_width = context.i32_type().const_int(32 as u64, false); + let int_width = intrinsics.i32_ty.const_int(32 as u64, false); let rhs = builder.build_int_sub(int_width, v2, &state.var_name()); builder.build_left_shift(v1, rhs, &state.var_name()) }; @@ -375,7 +515,7 @@ fn parse_function( let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); let lhs = builder.build_right_shift(v1, v2, false, &state.var_name()); let rhs = { - let int_width = context.i64_type().const_int(64 as u64, false); + let int_width = intrinsics.i64_ty.const_int(64 as u64, false); let rhs = builder.build_int_sub(int_width, v2, &state.var_name()); builder.build_left_shift(v1, rhs, &state.var_name()) }; @@ -384,8 +524,8 @@ fn parse_function( } Operator::I32Clz => { let input = state.pop1()?; - let ensure_defined_zero = context - .bool_type() + let ensure_defined_zero = intrinsics + .i1_ty .const_int(1 as u64, false) .as_basic_value_enum(); let res = builder @@ -401,8 +541,8 @@ fn parse_function( } Operator::I64Clz => { let input = state.pop1()?; - let ensure_defined_zero = context - .bool_type() + let ensure_defined_zero = intrinsics + .i1_ty .const_int(1 as u64, false) .as_basic_value_enum(); let res = builder @@ -418,8 +558,8 @@ fn parse_function( } Operator::I32Ctz => { let input = state.pop1()?; - let ensure_defined_zero = context - .bool_type() + let ensure_defined_zero = intrinsics + .i1_ty .const_int(1 as u64, false) .as_basic_value_enum(); let res = builder @@ -435,8 +575,8 @@ fn parse_function( } Operator::I64Ctz => { let input = state.pop1()?; - let ensure_defined_zero = context - .bool_type() + let ensure_defined_zero = intrinsics + .i1_ty .const_int(1 as u64, false) .as_basic_value_enum(); let res = builder @@ -470,16 +610,22 @@ fn parse_function( } Operator::I32Eqz => { let input = state.pop1()?.into_int_value(); - let zero = context.i32_type().const_int(0, false); - let res = - builder.build_int_compare(IntPredicate::EQ, input, zero, &state.var_name()); + let res = builder.build_int_compare( + IntPredicate::EQ, + input, + intrinsics.i32_zero, + &state.var_name(), + ); state.push1(res); } Operator::I64Eqz => { let input = state.pop1()?.into_int_value(); - let zero = context.i64_type().const_int(0, false); - let res = - builder.build_int_compare(IntPredicate::EQ, input, zero, &state.var_name()); + let res = builder.build_int_compare( + IntPredicate::EQ, + input, + intrinsics.i64_zero, + &state.var_name(), + ); state.push1(res); } @@ -493,7 +639,7 @@ fn parse_function( let res = builder.build_float_add(v1, v2, &state.var_name()); state.push1(res); } - Operator::F32Sub | Operator::F32Sub => { + Operator::F32Sub | Operator::F64Sub => { let (v1, v2) = state.pop2()?; let (v1, v2) = (v1.into_float_value(), v2.into_float_value()); let res = builder.build_float_sub(v1, v2, &state.var_name()); @@ -748,12 +894,133 @@ fn parse_function( * Floating-Point Comparison instructions. * https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#floating-point-comparison-instructions ***************************/ - Operator::Unreachable => { - // Emit an unreachable instruction. - // If llvm cannot prove that this is never touched, - // it will emit a `ud2` instruction on x86_64 arches. - builder.build_unreachable(); + Operator::F32Eq | Operator::F64Eq => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_float_value(), v2.into_float_value()); + let res = + builder.build_float_compare(FloatPredicate::OEQ, v1, v2, &state.var_name()); + state.push1(res); } + Operator::F32Ne | Operator::F64Ne => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_float_value(), v2.into_float_value()); + let res = + builder.build_float_compare(FloatPredicate::UNE, v1, v2, &state.var_name()); + state.push1(res); + } + Operator::F32Lt | Operator::F64Lt => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_float_value(), v2.into_float_value()); + let res = + builder.build_float_compare(FloatPredicate::OLT, v1, v2, &state.var_name()); + state.push1(res); + } + Operator::F32Le | Operator::F64Le => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_float_value(), v2.into_float_value()); + let res = + builder.build_float_compare(FloatPredicate::OLE, v1, v2, &state.var_name()); + state.push1(res); + } + Operator::F32Gt | Operator::F64Gt => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_float_value(), v2.into_float_value()); + let res = + builder.build_float_compare(FloatPredicate::OGT, v1, v2, &state.var_name()); + state.push1(res); + } + Operator::F32Ge | Operator::F64Ge => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_float_value(), v2.into_float_value()); + let res = + builder.build_float_compare(FloatPredicate::OGE, v1, v2, &state.var_name()); + state.push1(res); + } + + /*************************** + * Conversion instructions. + * https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#conversion-instructions + ***************************/ + Operator::I32WrapI64 => { + let v1 = state.pop1()?.into_int_value(); + let res = builder.build_int_truncate(v1, intrinsics.i32_ty, &state.var_name()); + state.push1(res); + } + Operator::I64ExtendSI32 => { + let v1 = state.pop1()?.into_int_value(); + let res = builder.build_int_s_extend(v1, intrinsics.i64_ty, &state.var_name()); + state.push1(res); + } + Operator::I64ExtendUI32 => { + let v1 = state.pop1()?.into_int_value(); + let res = builder.build_int_z_extend(v1, intrinsics.i64_ty, &state.var_name()); + state.push1(res); + } + Operator::I32TruncSF32 | Operator::I32TruncSF64 => { + let v1 = state.pop1()?.into_float_value(); + let res = + builder.build_float_to_signed_int(v1, intrinsics.i32_ty, &state.var_name()); + state.push1(res); + } + Operator::I64TruncSF32 | Operator::I64TruncSF64 => { + let v1 = state.pop1()?.into_float_value(); + let res = + builder.build_float_to_signed_int(v1, intrinsics.i64_ty, &state.var_name()); + state.push1(res); + } + Operator::I32TruncUF32 | Operator::I32TruncUF64 => { + let v1 = state.pop1()?.into_float_value(); + let res = + builder.build_float_to_unsigned_int(v1, intrinsics.i32_ty, &state.var_name()); + state.push1(res); + } + Operator::I64TruncUF32 | Operator::I64TruncUF64 => { + let v1 = state.pop1()?.into_float_value(); + let res = + builder.build_float_to_unsigned_int(v1, intrinsics.i64_ty, &state.var_name()); + state.push1(res); + } + Operator::F32DemoteF64 => { + let v1 = state.pop1()?.into_float_value(); + let res = builder.build_float_trunc(v1, intrinsics.f32_ty, &state.var_name()); + state.push1(res); + } + Operator::F64PromoteF32 => { + let v1 = state.pop1()?.into_float_value(); + let res = builder.build_float_ext(v1, intrinsics.f64_ty, &state.var_name()); + state.push1(res); + } + Operator::F32ConvertSI32 | Operator::F32ConvertSI64 => { + let v1 = state.pop1()?.into_int_value(); + let res = + builder.build_signed_int_to_float(v1, intrinsics.f32_ty, &state.var_name()); + state.push1(res); + } + Operator::F64ConvertSI32 | Operator::F64ConvertSI64 => { + let v1 = state.pop1()?.into_int_value(); + let res = + builder.build_signed_int_to_float(v1, intrinsics.f64_ty, &state.var_name()); + state.push1(res); + } + Operator::F32ConvertUI32 | Operator::F32ConvertUI64 => { + let v1 = state.pop1()?.into_int_value(); + let res = + builder.build_unsigned_int_to_float(v1, intrinsics.f32_ty, &state.var_name()); + state.push1(res); + } + Operator::F64ConvertUI32 | Operator::F64ConvertUI64 => { + let v1 = state.pop1()?.into_int_value(); + let res = + builder.build_unsigned_int_to_float(v1, intrinsics.f64_ty, &state.var_name()); + state.push1(res); + } + Operator::I32ReinterpretF32 + | Operator::F32ReinterpretI32 + | Operator::I64ReinterpretF64 + | Operator::F64ReinterpretI64 => { + unimplemented!("waiting on better bitcasting support in inkwell") + } + op @ _ => { println!("{}", module.print_to_string().to_string()); unimplemented!("{:?}", op); diff --git a/lib/llvm-backend/src/intrinsics.rs b/lib/llvm-backend/src/intrinsics.rs index 824317e8e..8eab37071 100644 --- a/lib/llvm-backend/src/intrinsics.rs +++ b/lib/llvm-backend/src/intrinsics.rs @@ -1,4 +1,9 @@ -use inkwell::{context::Context, module::Module, types::BasicType, values::FunctionValue}; +use inkwell::{ + context::Context, + module::Module, + types::{BasicType, FloatType, IntType, VoidType}, + values::{FloatValue, FunctionValue, IntValue}, +}; pub struct Intrinsics { pub ctlz_i32: FunctionValue, @@ -36,27 +41,53 @@ pub struct Intrinsics { pub copysign_f32: FunctionValue, pub copysign_f64: FunctionValue, + + pub void_ty: VoidType, + pub i1_ty: IntType, + pub i32_ty: IntType, + pub i64_ty: IntType, + pub f32_ty: FloatType, + pub f64_ty: FloatType, + + pub i1_zero: IntValue, + pub i32_zero: IntValue, + pub i64_zero: IntValue, + pub f32_zero: FloatValue, + pub f64_zero: FloatValue, } impl Intrinsics { pub fn declare(module: &Module, context: &Context) -> Self { - let i1_ty = context.bool_type().as_basic_type_enum(); - let i32_ty = context.i32_type().as_basic_type_enum(); - let i64_ty = context.i64_type().as_basic_type_enum(); - let f32_ty = context.f32_type().as_basic_type_enum(); - let f64_ty = context.f64_type().as_basic_type_enum(); + let void_ty = context.void_type(); + let i1_ty = context.bool_type(); + let i32_ty = context.i32_type(); + let i64_ty = context.i64_type(); + let f32_ty = context.f32_type(); + let f64_ty = context.f64_type(); - let ret_i32_take_i32_i1 = i32_ty.fn_type(&[i32_ty, i1_ty], false); - let ret_i64_take_i64_i1 = i64_ty.fn_type(&[i64_ty, i1_ty], false); + let i1_zero = i1_ty.const_int(0, false); + let i32_zero = i32_ty.const_int(0, false); + let i64_zero = i64_ty.const_int(0, false); + let f32_zero = f32_ty.const_float(0.0); + let f64_zero = f64_ty.const_float(0.0); - let ret_i32_take_i32 = i32_ty.fn_type(&[i32_ty], false); - let ret_i64_take_i64 = i64_ty.fn_type(&[i64_ty], false); + let i1_ty_basic = i1_ty.as_basic_type_enum(); + let i32_ty_basic = i32_ty.as_basic_type_enum(); + let i64_ty_basic = i64_ty.as_basic_type_enum(); + let f32_ty_basic = f32_ty.as_basic_type_enum(); + let f64_ty_basic = f64_ty.as_basic_type_enum(); - let ret_f32_take_f32 = f32_ty.fn_type(&[f32_ty], false); - let ret_f64_take_f64 = f64_ty.fn_type(&[f64_ty], false); + let ret_i32_take_i32_i1 = i32_ty.fn_type(&[i32_ty_basic, i1_ty_basic], false); + let ret_i64_take_i64_i1 = i64_ty.fn_type(&[i64_ty_basic, i1_ty_basic], false); - let ret_f32_take_f32_f32 = f32_ty.fn_type(&[f32_ty, f32_ty], false); - let ret_f64_take_f64_f64 = f64_ty.fn_type(&[f64_ty, f64_ty], false); + let ret_i32_take_i32 = i32_ty.fn_type(&[i32_ty_basic], false); + let ret_i64_take_i64 = i64_ty.fn_type(&[i64_ty_basic], false); + + let ret_f32_take_f32 = f32_ty.fn_type(&[f32_ty_basic], false); + let ret_f64_take_f64 = f64_ty.fn_type(&[f64_ty_basic], false); + + let ret_f32_take_f32_f32 = f32_ty.fn_type(&[f32_ty_basic, f32_ty_basic], false); + let ret_f64_take_f64_f64 = f64_ty.fn_type(&[f64_ty_basic, f64_ty_basic], false); Self { ctlz_i32: module.add_function("llvm.ctlz.i32", ret_i32_take_i32_i1, None), @@ -94,6 +125,19 @@ impl Intrinsics { copysign_f32: module.add_function("llvm.copysign.f32", ret_f32_take_f32_f32, None), copysign_f64: module.add_function("llvm.copysign.f64", ret_f64_take_f64_f64, None), + + void_ty, + i1_ty, + i32_ty, + i64_ty, + f32_ty, + f64_ty, + + i1_zero, + i32_zero, + i64_zero, + f32_zero, + f64_zero, } } } diff --git a/lib/llvm-backend/src/lib.rs b/lib/llvm-backend/src/lib.rs index 9b1b3eab6..69ed0fa0d 100644 --- a/lib/llvm-backend/src/lib.rs +++ b/lib/llvm-backend/src/lib.rs @@ -1,7 +1,7 @@ use wasmer_runtime_core::{ backend::{Compiler, Token}, error::CompileError, - module::{ModuleInfo, ModuleInner}, + module::ModuleInner, }; mod code; diff --git a/lib/llvm-backend/src/state.rs b/lib/llvm-backend/src/state.rs index 38b1178ce..e85c7a23c 100644 --- a/lib/llvm-backend/src/state.rs +++ b/lib/llvm-backend/src/state.rs @@ -1,25 +1,38 @@ use inkwell::{ basic_block::BasicBlock, - values::{BasicValue, BasicValueEnum}, + values::{BasicValue, BasicValueEnum, PhiValue}, }; +use smallvec::SmallVec; +use std::cell::Cell; use wasmparser::BinaryReaderError; -enum ControlFrame { - If { - dest: BasicBlock, - stack_size_snapshot: usize, - }, +pub enum ControlFrame { Block { - dest: BasicBlock, + end_label: BasicBlock, + phis: SmallVec<[PhiValue; 1]>, stack_size_snapshot: usize, - num_ret_values: usize, }, } +impl ControlFrame { + pub fn dest(&self) -> &BasicBlock { + match self { + ControlFrame::Block { ref end_label, .. } => end_label, + } + } + + pub fn phis(&self) -> &[PhiValue] { + match self { + ControlFrame::Block { ref phis, .. } => phis.as_slice(), + } + } +} + pub struct State { stack: Vec, control_stack: Vec, - value_counter: usize, + value_counter: Cell, + block_counter: Cell, } impl State { @@ -27,13 +40,47 @@ impl State { Self { stack: vec![], control_stack: vec![], - value_counter: 0, + value_counter: Cell::new(0), + block_counter: Cell::new(0), } } - pub fn var_name(&mut self) -> String { - let s = self.value_counter.to_string(); - self.value_counter += 1; + pub fn reset_stack(&mut self, frame: &ControlFrame) { + let stack_size_snapshot = match frame { + ControlFrame::Block { + stack_size_snapshot, + .. + } => *stack_size_snapshot, + }; + self.stack.truncate(stack_size_snapshot); + } + + pub fn frame_at_depth(&self, depth: u32) -> Result<&ControlFrame, BinaryReaderError> { + let index = self.control_stack.len() - 1 - (depth as usize); + self.control_stack.get(index).ok_or(BinaryReaderError { + message: "invalid control stack depth", + offset: -1isize as usize, + }) + } + + pub fn pop_frame(&mut self) -> Result { + self.control_stack.pop().ok_or(BinaryReaderError { + message: "cannot pop from control stack", + offset: -1isize as usize, + }) + } + + pub fn block_name(&self) -> String { + let counter = self.block_counter.get(); + let s = format!("block{}", counter); + self.block_counter.set(counter + 1); + s + } + + pub fn var_name(&self) -> String { + let counter = self.value_counter.get(); + let s = format!("s{}", counter); + self.value_counter.set(counter + 1); s } @@ -42,7 +89,7 @@ impl State { } pub fn pop1(&mut self) -> Result { - self.stack.pop().ok_or_else(|| BinaryReaderError { + self.stack.pop().ok_or(BinaryReaderError { message: "invalid value stack", offset: -1isize as usize, }) @@ -66,7 +113,7 @@ impl State { pub fn peek1(&self) -> Result { self.stack .get(self.stack.len() - 1) - .ok_or_else(|| BinaryReaderError { + .ok_or(BinaryReaderError { message: "invalid value stack", offset: -1isize as usize, }) @@ -76,7 +123,7 @@ impl State { pub fn peekn(&self, n: usize) -> Result<&[BasicValueEnum], BinaryReaderError> { self.stack .get(self.stack.len() - n..) - .ok_or_else(|| BinaryReaderError { + .ok_or(BinaryReaderError { message: "invalid value stack", offset: -1isize as usize, }) @@ -95,11 +142,11 @@ impl State { Ok(()) } - pub fn push_block(&mut self, dest: BasicBlock, num_ret_values: usize) { + pub fn push_block(&mut self, end_label: BasicBlock, phis: SmallVec<[PhiValue; 1]>) { self.control_stack.push(ControlFrame::Block { - dest, + end_label, + phis, stack_size_snapshot: self.stack.len(), - num_ret_values, }); } } From 27cbfc0b0bc87e877ad0b5ef4c58381818da1c51 Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Mon, 11 Feb 2019 23:14:32 -0600 Subject: [PATCH 040/262] Add documentation to API functions --- lib/runtime-c-api/src/lib.rs | 90 ++++++++++++++++++++++++++ lib/runtime-c-api/wasmer.h | 121 +++++++++++++++++++++++++++++++++++ lib/runtime-c-api/wasmer.hh | 71 ++++++++++++++++++++ 3 files changed, 282 insertions(+) diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index 319447d0c..d5443ba7f 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -85,6 +85,7 @@ pub struct wasmer_limits_t { pub max: uint32_t, } +/// Returns true for valid wasm bytes and false for invalid bytes #[allow(clippy::cast_ptr_alignment)] #[no_mangle] pub unsafe extern "C" fn wasmer_validate( @@ -99,11 +100,22 @@ pub unsafe extern "C" fn wasmer_validate( wasmer_runtime_core::validate(bytes) } +/// Creates a new ImportObject and returns a pointer to it. +/// The caller owns the object and should call `wasmer_import_object_destroy` to free it. #[no_mangle] pub extern "C" fn wasmer_import_object_new() -> *mut wasmer_import_object_t { Box::into_raw(Box::new(ImportObject::new())) as *mut wasmer_import_object_t } +/// Creates a new Memory for the given descriptor and initializes the given +/// pointer to pointer to a pointer to the new memory. +/// +/// The caller owns the object and should call `wasmer_memory_destroy` to free it. +/// +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. #[no_mangle] pub unsafe extern "C" fn wasmer_memory_new( mut memory: *mut *mut wasmer_memory_t, @@ -126,6 +138,12 @@ pub unsafe extern "C" fn wasmer_memory_new( wasmer_result_t::WASMER_OK } +/// Grows a Memory by the given number of pages. +/// +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. #[allow(clippy::cast_ptr_alignment)] #[no_mangle] pub extern "C" fn wasmer_memory_grow( @@ -145,6 +163,7 @@ pub extern "C" fn wasmer_memory_grow( } } +/// Returns the current length in pages of the given memory #[allow(clippy::cast_ptr_alignment)] #[no_mangle] pub extern "C" fn wasmer_memory_length(memory: *mut wasmer_memory_t) -> uint32_t { @@ -154,6 +173,15 @@ pub extern "C" fn wasmer_memory_length(memory: *mut wasmer_memory_t) -> uint32_t len } +/// Creates a new Table for the given descriptor and initializes the given +/// pointer to pointer to a pointer to the new Table. +/// +/// The caller owns the object and should call `wasmer_table_destroy` to free it. +/// +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. #[no_mangle] pub unsafe extern "C" fn wasmer_table_new( mut table: *mut *mut wasmer_table_t, @@ -176,6 +204,12 @@ pub unsafe extern "C" fn wasmer_table_new( wasmer_result_t::WASMER_OK } +/// Grows a Table by the given number of elements. +/// +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. #[allow(clippy::cast_ptr_alignment)] #[no_mangle] pub extern "C" fn wasmer_table_grow( @@ -195,6 +229,7 @@ pub extern "C" fn wasmer_table_grow( } } +/// Returns the current length of the given Table #[allow(clippy::cast_ptr_alignment)] #[no_mangle] pub extern "C" fn wasmer_table_length(table: *mut wasmer_table_t) -> uint32_t { @@ -204,6 +239,7 @@ pub extern "C" fn wasmer_table_length(table: *mut wasmer_table_t) -> uint32_t { len } +/// Frees memory for the given Table #[allow(clippy::cast_ptr_alignment)] #[no_mangle] pub extern "C" fn wasmer_table_destroy(table: *mut wasmer_table_t) { @@ -212,6 +248,8 @@ pub extern "C" fn wasmer_table_destroy(table: *mut wasmer_table_t) { } } +/// Creates a new Global and returns a pointer to it. +/// The caller owns the object and should call `wasmer_global_destroy` to free it. #[no_mangle] pub unsafe extern "C" fn wasmer_global_new( value: wasmer_value_t, @@ -225,6 +263,7 @@ pub unsafe extern "C" fn wasmer_global_new( unsafe { Box::into_raw(Box::new(global)) as *mut wasmer_global_t } } +/// Gets the value stored by the given Global #[allow(clippy::cast_ptr_alignment)] #[no_mangle] pub extern "C" fn wasmer_global_get(global: *mut wasmer_global_t) -> wasmer_value_t { @@ -234,6 +273,7 @@ pub extern "C" fn wasmer_global_get(global: *mut wasmer_global_t) -> wasmer_valu value } +/// Sets the value stored by the given Global #[allow(clippy::cast_ptr_alignment)] #[no_mangle] pub extern "C" fn wasmer_global_set(global: *mut wasmer_global_t, value: wasmer_value_t) { @@ -242,6 +282,7 @@ pub extern "C" fn wasmer_global_set(global: *mut wasmer_global_t, value: wasmer_ Box::into_raw(global); } +/// Returns a descriptor (type, mutability) of the given Global #[allow(clippy::cast_ptr_alignment)] #[no_mangle] pub extern "C" fn wasmer_global_get_descriptor( @@ -257,6 +298,7 @@ pub extern "C" fn wasmer_global_get_descriptor( desc } +/// Frees memory for the given Global #[allow(clippy::cast_ptr_alignment)] #[no_mangle] pub extern "C" fn wasmer_global_destroy(global: *mut wasmer_global_t) { @@ -265,6 +307,7 @@ pub extern "C" fn wasmer_global_destroy(global: *mut wasmer_global_t) { } } +/// Frees memory for the given ImportObject #[allow(clippy::cast_ptr_alignment)] #[no_mangle] pub extern "C" fn wasmer_import_object_destroy(import_object: *mut wasmer_import_object_t) { @@ -273,6 +316,7 @@ pub extern "C" fn wasmer_import_object_destroy(import_object: *mut wasmer_import } } +/// Frees memory for the given Memory #[allow(clippy::cast_ptr_alignment)] #[no_mangle] pub extern "C" fn wasmer_memory_destroy(memory: *mut wasmer_memory_t) { @@ -281,6 +325,12 @@ pub extern "C" fn wasmer_memory_destroy(memory: *mut wasmer_memory_t) { } } +/// Creates a new Instance from the given wasm bytes and imports. +/// +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. #[allow(clippy::cast_ptr_alignment)] #[no_mangle] pub unsafe extern "C" fn wasmer_instantiate( @@ -315,6 +365,13 @@ pub unsafe extern "C" fn wasmer_instantiate( wasmer_result_t::WASMER_OK } +/// Calls an instances exported function by `name` with the provided parameters. +/// Results are set using the provided `results` pointer. +/// +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. #[allow(clippy::cast_ptr_alignment)] #[no_mangle] pub unsafe extern "C" fn wasmer_instance_call( @@ -387,6 +444,12 @@ pub unsafe extern "C" fn wasmer_instance_call( } } +/// Registers a `func` with provided `name` and `namespace` into the ImportObject. +/// +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. #[allow(clippy::cast_ptr_alignment)] #[no_mangle] pub unsafe extern "C" fn wasmer_imports_set_import_func( @@ -428,6 +491,8 @@ pub unsafe extern "C" fn wasmer_imports_set_import_func( // }; } +/// Gets the memory within the context at the index `memory_idx`. +/// The index is always 0 until multiple memories are supported. #[allow(clippy::cast_ptr_alignment)] #[no_mangle] pub extern "C" fn wasmer_instance_context_memory( @@ -439,6 +504,7 @@ pub extern "C" fn wasmer_instance_context_memory( memory as *const Memory as *const wasmer_memory_t } +/// Gets the start pointer to the bytes within a Memory #[allow(clippy::cast_ptr_alignment)] #[no_mangle] pub extern "C" fn wasmer_memory_data(mem: *mut wasmer_memory_t) -> *mut uint8_t { @@ -447,6 +513,7 @@ pub extern "C" fn wasmer_memory_data(mem: *mut wasmer_memory_t) -> *mut uint8_t unsafe { ((*memory).view::()[..]).as_ptr() as *mut Cell as *mut u8 } } +/// Gets the size in bytes of a Memory #[allow(clippy::cast_ptr_alignment)] #[no_mangle] pub extern "C" fn wasmer_memory_data_length(mem: *mut wasmer_memory_t) -> uint32_t { @@ -455,6 +522,7 @@ pub extern "C" fn wasmer_memory_data_length(mem: *mut wasmer_memory_t) -> uint32 len as uint32_t } +/// Frees memory for the given Instance #[allow(clippy::cast_ptr_alignment)] #[no_mangle] pub extern "C" fn wasmer_instance_destroy(instance: *mut wasmer_instance_t) { @@ -555,6 +623,15 @@ fn take_last_error() -> Option> { LAST_ERROR.with(|prev| prev.borrow_mut().take()) } +/// Gets the length in bytes of the last error. +/// This can be used to dynamically allocate a buffer with the correct number of +/// bytes needed to store a message. +/// +/// # Example +/// ``` +/// int error_len = wasmer_last_error_length(); +/// char *error_str = malloc(error_len); +/// ``` #[no_mangle] pub extern "C" fn wasmer_last_error_length() -> c_int { LAST_ERROR.with(|prev| match *prev.borrow() { @@ -563,6 +640,19 @@ pub extern "C" fn wasmer_last_error_length() -> c_int { }) } +/// Stores the last error message into the provided buffer up to the given `length`. +/// The `length` parameter must be large enough to store the last error message. +/// +/// Returns the length of the string in bytes. +/// Returns `-1` if an error occurs. +/// +/// # Example +/// ``` +/// int error_len = wasmer_last_error_length(); +/// char *error_str = malloc(error_len); +/// wasmer_last_error_message(error_str, error_len); +/// printf("Error str: `%s`\n", error_str); +/// ``` #[no_mangle] pub unsafe extern "C" fn wasmer_last_error_message(buffer: *mut c_char, length: c_int) -> c_int { if buffer.is_null() { diff --git a/lib/runtime-c-api/wasmer.h b/lib/runtime-c-api/wasmer.h index 1b53f3123..6b855404a 100644 --- a/lib/runtime-c-api/wasmer.h +++ b/lib/runtime-c-api/wasmer.h @@ -59,20 +59,49 @@ typedef struct { } wasmer_table_t; +/** + * Frees memory for the given Global + */ void wasmer_global_destroy(wasmer_global_t *global); +/** + * Gets the value stored by the given Global + */ wasmer_value_t wasmer_global_get(wasmer_global_t *global); +/** + * Returns a descriptor (type, mutability) of the given Global + */ wasmer_global_descriptor_t wasmer_global_get_descriptor(wasmer_global_t *global); +/** + * Creates a new Global and returns a pointer to it. + * The caller owns the object and should call `wasmer_global_destroy` to free it. + */ wasmer_global_t *wasmer_global_new(wasmer_value_t value, bool mutable_); +/** + * Sets the value stored by the given Global + */ void wasmer_global_set(wasmer_global_t *global, wasmer_value_t value); +/** + * Frees memory for the given ImportObject + */ void wasmer_import_object_destroy(wasmer_import_object_t *import_object); +/** + * Creates a new ImportObject and returns a pointer to it. + * The caller owns the object and should call `wasmer_import_object_destroy` to free it. + */ wasmer_import_object_t *wasmer_import_object_new(void); +/** + * Registers a `func` with provided `name` and `namespace` into the ImportObject. + * Returns `wasmer_result_t::WASMER_OK` upon success. + * Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` + * and `wasmer_last_error_message` to get an error message. + */ void wasmer_imports_set_import_func(wasmer_import_object_t *import_object, const char *namespace_, const char *name, @@ -82,6 +111,13 @@ void wasmer_imports_set_import_func(wasmer_import_object_t *import_object, const wasmer_value_tag *returns, int returns_len); +/** + * Calls an instances exported function by `name` with the provided parameters. + * Results are set using the provided `results` pointer. + * Returns `wasmer_result_t::WASMER_OK` upon success. + * Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` + * and `wasmer_last_error_message` to get an error message. + */ wasmer_result_t wasmer_instance_call(wasmer_instance_t *instance, const char *name, const wasmer_value_t *params, @@ -89,40 +125,125 @@ wasmer_result_t wasmer_instance_call(wasmer_instance_t *instance, wasmer_value_t *results, int results_len); +/** + * Gets the memory within the context at the index `memory_idx`. + * The index is always 0 until multiple memories are supported. + */ const wasmer_memory_t *wasmer_instance_context_memory(wasmer_instance_context_t *ctx, uint32_t memory_idx); +/** + * Frees memory for the given Instance + */ void wasmer_instance_destroy(wasmer_instance_t *instance); +/** + * Creates a new Instance from the given wasm bytes and imports. + * Returns `wasmer_result_t::WASMER_OK` upon success. + * Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` + * and `wasmer_last_error_message` to get an error message. + */ wasmer_result_t wasmer_instantiate(wasmer_instance_t **instance, uint8_t *wasm_bytes, uint32_t wasm_bytes_len, wasmer_import_object_t *import_object); +/** + * Gets the length in bytes of the last error. + * This can be used to dynamically allocate a buffer with the correct number of + * bytes needed to store a message. + * # Example + * ``` + * int error_len = wasmer_last_error_length(); + * char *error_str = malloc(error_len); + * ``` + */ int wasmer_last_error_length(void); +/** + * Stores the last error message into the provided buffer up to the given `length`. + * The `length` parameter must be large enough to store the last error message. + * Returns the length of the string in bytes. + * Returns `-1` if an error occurs. + * # Example + * ``` + * int error_len = wasmer_last_error_length(); + * char *error_str = malloc(error_len); + * wasmer_last_error_message(error_str, error_len); + * printf("Error str: `%s`\n", error_str); + * ``` + */ int wasmer_last_error_message(char *buffer, int length); +/** + * Gets the start pointer to the bytes within a Memory + */ uint8_t *wasmer_memory_data(wasmer_memory_t *mem); +/** + * Gets the size in bytes of a Memory + */ uint32_t wasmer_memory_data_length(wasmer_memory_t *mem); +/** + * Frees memory for the given Memory + */ void wasmer_memory_destroy(wasmer_memory_t *memory); +/** + * Grows a Memory by the given number of pages. + * Returns `wasmer_result_t::WASMER_OK` upon success. + * Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` + * and `wasmer_last_error_message` to get an error message. + */ wasmer_result_t wasmer_memory_grow(wasmer_memory_t *memory, uint32_t delta); +/** + * Returns the current length in pages of the given memory + */ uint32_t wasmer_memory_length(wasmer_memory_t *memory); +/** + * Creates a new Memory for the given descriptor and initializes the given + * pointer to pointer to a pointer to the new memory. + * The caller owns the object and should call `wasmer_memory_destroy` to free it. + * Returns `wasmer_result_t::WASMER_OK` upon success. + * Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` + * and `wasmer_last_error_message` to get an error message. + */ wasmer_result_t wasmer_memory_new(wasmer_memory_t **memory, wasmer_limits_t limits); +/** + * Frees memory for the given Table + */ void wasmer_table_destroy(wasmer_table_t *table); +/** + * Grows a Table by the given number of elements. + * Returns `wasmer_result_t::WASMER_OK` upon success. + * Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` + * and `wasmer_last_error_message` to get an error message. + */ wasmer_result_t wasmer_table_grow(wasmer_table_t *table, uint32_t delta); +/** + * Returns the current length of the given Table + */ uint32_t wasmer_table_length(wasmer_table_t *table); +/** + * Creates a new Table for the given descriptor and initializes the given + * pointer to pointer to a pointer to the new Table. + * The caller owns the object and should call `wasmer_table_destroy` to free it. + * Returns `wasmer_result_t::WASMER_OK` upon success. + * Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` + * and `wasmer_last_error_message` to get an error message. + */ wasmer_result_t wasmer_table_new(wasmer_table_t **table, wasmer_limits_t limits); +/** + * Returns true for valid wasm bytes and false for invalid bytes + */ bool wasmer_validate(uint8_t *wasm_bytes, uint32_t wasm_bytes_len); #endif /* WASMER_H */ diff --git a/lib/runtime-c-api/wasmer.hh b/lib/runtime-c-api/wasmer.hh index 68b935202..24c4f3f14 100644 --- a/lib/runtime-c-api/wasmer.hh +++ b/lib/runtime-c-api/wasmer.hh @@ -59,20 +59,33 @@ struct wasmer_table_t { extern "C" { +/// Frees memory for the given Global void wasmer_global_destroy(wasmer_global_t *global); +/// Gets the value stored by the given Global wasmer_value_t wasmer_global_get(wasmer_global_t *global); +/// Returns a descriptor (type, mutability) of the given Global wasmer_global_descriptor_t wasmer_global_get_descriptor(wasmer_global_t *global); +/// Creates a new Global and returns a pointer to it. +/// The caller owns the object and should call `wasmer_global_destroy` to free it. wasmer_global_t *wasmer_global_new(wasmer_value_t value, bool mutable_); +/// Sets the value stored by the given Global void wasmer_global_set(wasmer_global_t *global, wasmer_value_t value); +/// Frees memory for the given ImportObject void wasmer_import_object_destroy(wasmer_import_object_t *import_object); +/// Creates a new ImportObject and returns a pointer to it. +/// The caller owns the object and should call `wasmer_import_object_destroy` to free it. wasmer_import_object_t *wasmer_import_object_new(); +/// Registers a `func` with provided `name` and `namespace` into the ImportObject. +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. void wasmer_imports_set_import_func(wasmer_import_object_t *import_object, const char *namespace_, const char *name, @@ -82,6 +95,11 @@ void wasmer_imports_set_import_func(wasmer_import_object_t *import_object, const wasmer_value_tag *returns, int returns_len); +/// Calls an instances exported function by `name` with the provided parameters. +/// Results are set using the provided `results` pointer. +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. wasmer_result_t wasmer_instance_call(wasmer_instance_t *instance, const char *name, const wasmer_value_t *params, @@ -89,40 +107,93 @@ wasmer_result_t wasmer_instance_call(wasmer_instance_t *instance, wasmer_value_t *results, int results_len); +/// Gets the memory within the context at the index `memory_idx`. +/// The index is always 0 until multiple memories are supported. const wasmer_memory_t *wasmer_instance_context_memory(wasmer_instance_context_t *ctx, uint32_t memory_idx); +/// Frees memory for the given Instance void wasmer_instance_destroy(wasmer_instance_t *instance); +/// Creates a new Instance from the given wasm bytes and imports. +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. wasmer_result_t wasmer_instantiate(wasmer_instance_t **instance, uint8_t *wasm_bytes, uint32_t wasm_bytes_len, wasmer_import_object_t *import_object); +/// Gets the length in bytes of the last error. +/// This can be used to dynamically allocate a buffer with the correct number of +/// bytes needed to store a message. +/// # Example +/// ``` +/// int error_len = wasmer_last_error_length(); +/// char *error_str = malloc(error_len); +/// ``` int wasmer_last_error_length(); +/// Stores the last error message into the provided buffer up to the given `length`. +/// The `length` parameter must be large enough to store the last error message. +/// Returns the length of the string in bytes. +/// Returns `-1` if an error occurs. +/// # Example +/// ``` +/// int error_len = wasmer_last_error_length(); +/// char *error_str = malloc(error_len); +/// wasmer_last_error_message(error_str, error_len); +/// printf("Error str: `%s`\n", error_str); +/// ``` int wasmer_last_error_message(char *buffer, int length); +/// Gets the start pointer to the bytes within a Memory uint8_t *wasmer_memory_data(wasmer_memory_t *mem); +/// Gets the size in bytes of a Memory uint32_t wasmer_memory_data_length(wasmer_memory_t *mem); +/// Frees memory for the given Memory void wasmer_memory_destroy(wasmer_memory_t *memory); +/// Grows a Memory by the given number of pages. +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. wasmer_result_t wasmer_memory_grow(wasmer_memory_t *memory, uint32_t delta); +/// Returns the current length in pages of the given memory uint32_t wasmer_memory_length(wasmer_memory_t *memory); +/// Creates a new Memory for the given descriptor and initializes the given +/// pointer to pointer to a pointer to the new memory. +/// The caller owns the object and should call `wasmer_memory_destroy` to free it. +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. wasmer_result_t wasmer_memory_new(wasmer_memory_t **memory, wasmer_limits_t limits); +/// Frees memory for the given Table void wasmer_table_destroy(wasmer_table_t *table); +/// Grows a Table by the given number of elements. +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. wasmer_result_t wasmer_table_grow(wasmer_table_t *table, uint32_t delta); +/// Returns the current length of the given Table uint32_t wasmer_table_length(wasmer_table_t *table); +/// Creates a new Table for the given descriptor and initializes the given +/// pointer to pointer to a pointer to the new Table. +/// The caller owns the object and should call `wasmer_table_destroy` to free it. +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. wasmer_result_t wasmer_table_new(wasmer_table_t **table, wasmer_limits_t limits); +/// Returns true for valid wasm bytes and false for invalid bytes bool wasmer_validate(uint8_t *wasm_bytes, uint32_t wasm_bytes_len); } // extern "C" From c40195cf77cdd2fef1147b81c443bf9dcdc96325 Mon Sep 17 00:00:00 2001 From: Syrus Date: Tue, 12 Feb 2019 10:04:11 -0800 Subject: [PATCH 041/262] Fixed spectests --- lib/clif-backend/src/func_env.rs | 8 ++++---- lib/clif-backend/src/trampoline.rs | 31 +++++++++++++++--------------- 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/lib/clif-backend/src/func_env.rs b/lib/clif-backend/src/func_env.rs index 723ab71d9..7f1f8b52f 100644 --- a/lib/clif-backend/src/func_env.rs +++ b/lib/clif-backend/src/func_env.rs @@ -32,10 +32,10 @@ impl<'env, 'module, 'isa> FuncEnv<'env, 'module, 'isa> { let mut signature = self.env.signatures[Converter(clif_sig_index).into()].clone(); // Add the vmctx parameter type to it - signature.params.insert(0, ir::AbiParam::special( - self.pointer_type(), - ir::ArgumentPurpose::VMContext, - )); + signature.params.insert( + 0, + ir::AbiParam::special(self.pointer_type(), ir::ArgumentPurpose::VMContext), + ); // Return signature signature diff --git a/lib/clif-backend/src/trampoline.rs b/lib/clif-backend/src/trampoline.rs index a30dfd114..b9d942ba1 100644 --- a/lib/clif-backend/src/trampoline.rs +++ b/lib/clif-backend/src/trampoline.rs @@ -229,22 +229,21 @@ fn generate_trampoline_signature() -> ir::Signature { fn generate_export_signature(func_sig: &FuncSig) -> ir::Signature { let mut export_clif_sig = ir::Signature::new(isa::CallConv::SystemV); - export_clif_sig.params = func_sig - .params() - .iter() - .map(|wasm_ty| ir::AbiParam { - value_type: wasm_ty_to_clif(*wasm_ty), - purpose: ir::ArgumentPurpose::Normal, - extension: ir::ArgumentExtension::None, - location: ir::ArgumentLoc::Unassigned, - }) - .chain(iter::once(ir::AbiParam { - value_type: ir::types::I64, - purpose: ir::ArgumentPurpose::VMContext, - extension: ir::ArgumentExtension::None, - location: ir::ArgumentLoc::Unassigned, - })) - .collect(); + let func_sig_iter = func_sig.params().iter().map(|wasm_ty| ir::AbiParam { + value_type: wasm_ty_to_clif(*wasm_ty), + purpose: ir::ArgumentPurpose::Normal, + extension: ir::ArgumentExtension::None, + location: ir::ArgumentLoc::Unassigned, + }); + + export_clif_sig.params = iter::once(ir::AbiParam { + value_type: ir::types::I64, + purpose: ir::ArgumentPurpose::VMContext, + extension: ir::ArgumentExtension::None, + location: ir::ArgumentLoc::Unassigned, + }) + .chain(func_sig_iter) + .collect(); export_clif_sig.returns = func_sig .returns() From 44d1a0d1f963b1cb13f4e4dbfc9bf844959846f5 Mon Sep 17 00:00:00 2001 From: Syrus Date: Tue, 12 Feb 2019 10:49:43 -0800 Subject: [PATCH 042/262] Fixed debug function context position --- lib/clif-backend/src/module_env.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/clif-backend/src/module_env.rs b/lib/clif-backend/src/module_env.rs index 6b22b4ce6..65bd5f839 100644 --- a/lib/clif-backend/src/module_env.rs +++ b/lib/clif-backend/src/module_env.rs @@ -419,8 +419,8 @@ impl<'module, 'isa, 'data> ModuleEnvironment<'data> for ModuleEnv<'module, 'isa> let signature = pos.func.import_signature(ir::Signature { call_conv: self.target_config().default_call_conv, params: vec![ - ir::AbiParam::new(ir::types::I32), ir::AbiParam::special(ir::types::I64, ir::ArgumentPurpose::VMContext), + ir::AbiParam::new(ir::types::I32), ], returns: vec![], }); @@ -457,8 +457,8 @@ impl<'module, 'isa, 'data> ModuleEnvironment<'data> for ModuleEnv<'module, 'isa> let signature = pos.func.import_signature(ir::Signature { call_conv: self.target_config().default_call_conv, params: vec![ - ir::AbiParam::new(ir::types::I32), ir::AbiParam::special(ir::types::I64, ir::ArgumentPurpose::VMContext), + ir::AbiParam::new(ir::types::I32), ], returns: vec![], }); @@ -476,8 +476,8 @@ impl<'module, 'isa, 'data> ModuleEnvironment<'data> for ModuleEnv<'module, 'isa> let signature = pos.func.import_signature(ir::Signature { call_conv: self.target_config().default_call_conv, params: vec![ - ir::AbiParam::new(ir::types::I64), ir::AbiParam::special(ir::types::I64, ir::ArgumentPurpose::VMContext), + ir::AbiParam::new(ir::types::I64), ], returns: vec![], }); @@ -495,8 +495,8 @@ impl<'module, 'isa, 'data> ModuleEnvironment<'data> for ModuleEnv<'module, 'isa> let signature = pos.func.import_signature(ir::Signature { call_conv: self.target_config().default_call_conv, params: vec![ - ir::AbiParam::new(ir::types::F32), ir::AbiParam::special(ir::types::I64, ir::ArgumentPurpose::VMContext), + ir::AbiParam::new(ir::types::F32), ], returns: vec![], }); @@ -514,8 +514,8 @@ impl<'module, 'isa, 'data> ModuleEnvironment<'data> for ModuleEnv<'module, 'isa> let signature = pos.func.import_signature(ir::Signature { call_conv: self.target_config().default_call_conv, params: vec![ - ir::AbiParam::new(ir::types::F64), ir::AbiParam::special(ir::types::I64, ir::ArgumentPurpose::VMContext), + ir::AbiParam::new(ir::types::F64), ], returns: vec![], }); From b7c3cc09d122f533415db830ce2c8ca62696e06c Mon Sep 17 00:00:00 2001 From: Syrus Date: Tue, 12 Feb 2019 11:14:20 -0800 Subject: [PATCH 043/262] Fixed typed func implementation --- lib/runtime-core/src/typed_func.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/runtime-core/src/typed_func.rs b/lib/runtime-core/src/typed_func.rs index 9989764c6..e16307d8e 100644 --- a/lib/runtime-core/src/typed_func.rs +++ b/lib/runtime-core/src/typed_func.rs @@ -138,9 +138,9 @@ impl WasmTypeList for (A,) { } #[allow(non_snake_case)] unsafe fn call(self, f: *const (), ctx: *mut Ctx) -> Rets { - let f: extern "C" fn(A, *mut Ctx) -> Rets = mem::transmute(f); + let f: extern "C" fn(*mut Ctx, A) -> Rets = mem::transmute(f); let (a,) = self; - f(a, ctx) + f(ctx, a) } } @@ -175,10 +175,10 @@ macro_rules! impl_traits { } #[allow(non_snake_case)] unsafe fn call(self, f: *const (), ctx: *mut Ctx) -> Rets { - let f: extern fn( $( $x, )* *mut Ctx) -> Rets::CStruct = mem::transmute(f); + let f: extern fn(*mut Ctx $( ,$x )*) -> Rets::CStruct = mem::transmute(f); #[allow(unused_parens)] let ( $( $x ),* ) = self; - let c_struct = f( $( $x, )* ctx); + let c_struct = f(ctx $( ,$x )*); Rets::from_c_struct(c_struct) } } From b6416068a8dc84039d6c8d96426d892daeffb296 Mon Sep 17 00:00:00 2001 From: Syrus Date: Tue, 12 Feb 2019 11:17:09 -0800 Subject: [PATCH 044/262] Use vec.push instead of .insert for vmctx arg --- lib/clif-backend/src/func_env.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/clif-backend/src/func_env.rs b/lib/clif-backend/src/func_env.rs index 7f1f8b52f..8670e0000 100644 --- a/lib/clif-backend/src/func_env.rs +++ b/lib/clif-backend/src/func_env.rs @@ -459,8 +459,8 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> { // Build a value list for the indirect call instruction containing the call_args // and the vmctx parameter. let mut args = Vec::with_capacity(call_args.len() + 1); + args.push(vmctx_ptr); args.extend(call_args.iter().cloned()); - args.insert(0, vmctx_ptr); Ok(pos.ins().call_indirect(sig_ref, func_ptr, &args)) } @@ -485,8 +485,8 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> { .expect("missing vmctx parameter"); let mut args = Vec::with_capacity(call_args.len() + 1); + args.push(vmctx); args.extend(call_args.iter().cloned()); - args.insert(0, vmctx); Ok(pos.ins().call(callee, &args)) } @@ -532,8 +532,8 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> { let sig_ref = pos.func.dfg.ext_funcs[callee].signature; let mut args = Vec::with_capacity(call_args.len() + 1); + args.push(imported_vmctx_addr); args.extend(call_args.iter().cloned()); - args.insert(0, imported_vmctx_addr); Ok(pos .ins() From 2572a0259b87e0852332b18026674dc178985313 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Tue, 12 Feb 2019 18:02:00 -0800 Subject: [PATCH 045/262] Get control flow working (fingers crossed) --- lib/llvm-backend/src/code.rs | 233 ++++++++++++++++++++++++++--- lib/llvm-backend/src/intrinsics.rs | 39 +++++ lib/llvm-backend/src/lib.rs | 29 ++-- lib/llvm-backend/src/read_info.rs | 7 +- lib/llvm-backend/src/state.rs | 121 +++++++++++++-- 5 files changed, 377 insertions(+), 52 deletions(-) diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index 7a24f9fbf..e177cc375 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -2,21 +2,22 @@ use inkwell::{ builder::Builder, context::Context, module::Module, + passes::PassManager, types::{BasicType, BasicTypeEnum, FunctionType}, - values::{BasicValue, FunctionValue}, + values::{BasicValue, FunctionValue, PhiValue}, FloatPredicate, IntPredicate, }; use smallvec::SmallVec; use wasmer_runtime_core::{ module::ModuleInfo, structures::{Map, SliceMap, TypedIndex}, - types::{FuncIndex, FuncSig, LocalFuncIndex, LocalOrImport, SigIndex, Type}, + types::{FuncIndex, MemoryIndex, FuncSig, LocalFuncIndex, LocalOrImport, SigIndex, Type, MemoryType}, }; use wasmparser::{BinaryReaderError, CodeSectionReader, LocalsReader, Operator, OperatorsReader}; use crate::intrinsics::Intrinsics; use crate::read_info::type_to_type; -use crate::state::State; +use crate::state::{ControlFrame, IfElseState, State}; fn func_sig_to_llvm(context: &Context, intrinsics: &Intrinsics, sig: &FuncSig) -> FunctionType { let user_param_types = sig.params().iter().map(|&ty| type_to_llvm(intrinsics, ty)); @@ -116,10 +117,37 @@ fn parse_function( let llvm_sig = &signatures[sig_index]; let function = functions[func_index]; - let entry_block = context.append_basic_block(&function, "entry"); - builder.position_at_end(&entry_block); - let mut state = State::new(); + let entry_block = context.append_basic_block(&function, "entry"); + + let return_block = context.append_basic_block(&function, "return"); + builder.position_at_end(&return_block); + + let phis: SmallVec<[PhiValue; 1]> = func_sig + .returns() + .iter() + .map(|&wasmer_ty| type_to_llvm(intrinsics, wasmer_ty)) + .map(|ty| builder.build_phi(ty, &state.var_name())) + .collect(); + + match phis.as_slice() { + // No returns. + &[] => { + builder.build_return(None); + } + &[one_value] => { + let value = one_value.as_basic_value(); + builder.build_return(Some(&value)); + } + returns @ _ => { + // let struct_ty = llvm_sig.get_return_type().as_struct_type(); + // let ret_struct = struct_ty.const_zero(); + unimplemented!("multi-value returns not yet implemented") + } + } + + state.push_block(return_block, phis); + builder.position_at_end(&entry_block); let mut locals = Vec::with_capacity(locals_reader.get_count() as usize); locals.extend(function.get_param_iter().enumerate().map(|(index, param)| { @@ -163,7 +191,7 @@ fn parse_function( offset: -1isize as usize, })?; - let end_block = context.append_basic_block(&function, &state.block_name()); + let end_block = context.append_basic_block(&function, "end"); builder.position_at_end(&end_block); let phis = if let Ok(wasmer_ty) = type_to_type(ty) { @@ -180,12 +208,24 @@ fn parse_function( builder.position_at_end(¤t_block); } Operator::Loop { ty } => { + let loop_body = context.append_basic_block(&function, "loop_body"); + let loop_next = context.append_basic_block(&function, "loop_outer"); - // let loop_body = context.append_basic_block(&function, &state.block_name()); - // let next = context.append_basic_block(&function, &state.block_name()); - // builder.build_unconditional_branch(&body); - // let num_return_values = if ty == wasmparser::Type::EmptyBlockType { 0 } else { 1 }; - // state.push_loop(loop_body, next, num_return_values); + builder.build_unconditional_branch(&loop_body); + + builder.position_at_end(&loop_next); + let phis = if let Ok(wasmer_ty) = type_to_type(ty) { + let llvm_ty = type_to_llvm(intrinsics, wasmer_ty); + [llvm_ty] + .iter() + .map(|&ty| builder.build_phi(ty, &state.var_name())) + .collect() + } else { + SmallVec::new() + }; + + builder.position_at_end(&loop_body); + state.push_loop(loop_body, loop_next, phis); } Operator::Br { relative_depth } => { let frame = state.frame_at_depth(relative_depth)?; @@ -195,7 +235,13 @@ fn parse_function( offset: -1isize as usize, })?; - let values = state.peekn(frame.phis().len())?; + let value_len = if frame.is_loop() { + 0 + } else { + frame.phis().len() + }; + + let values = state.peekn(value_len)?; // For each result of the block we're branching to, // pop a value off the value stack and load it into @@ -204,11 +250,10 @@ fn parse_function( phi.add_incoming(&[(value, ¤t_block)]); } - builder.build_unconditional_branch(frame.dest()); + builder.build_unconditional_branch(frame.br_dest()); - state.popn(frame.phis().len())?; - - builder.build_unreachable(); + state.popn(value_len)?; + state.reachable = false; } Operator::BrIf { relative_depth } => { let cond = state.pop1()?; @@ -219,13 +264,19 @@ fn parse_function( offset: -1isize as usize, })?; - let param_stack = state.peekn(frame.phis().len())?; + let value_len = if frame.is_loop() { + 0 + } else { + frame.phis().len() + }; + + let param_stack = state.peekn(value_len)?; for (phi, value) in frame.phis().iter().zip(param_stack.iter()) { phi.add_incoming(&[(value, ¤t_block)]); } - let false_block = context.append_basic_block(&function, &state.block_name()); + let else_block = context.append_basic_block(&function, "else"); let cond_value = builder.build_int_compare( IntPredicate::NE, @@ -233,8 +284,8 @@ fn parse_function( intrinsics.i32_zero, &state.var_name(), ); - builder.build_conditional_branch(cond_value, frame.dest(), &false_block); - builder.position_at_end(&false_block); + builder.build_conditional_branch(cond_value, frame.br_dest(), &else_block); + builder.position_at_end(&else_block); } Operator::BrTable { ref table } => { let current_block = builder.get_insert_block().ok_or(BinaryReaderError { @@ -268,25 +319,131 @@ fn parse_function( phi.add_incoming(&[(value, ¤t_block)]); } - Ok((case_index_literal, frame.dest())) + Ok((case_index_literal, frame.br_dest())) }) .collect::>()?; - builder.build_switch(index.into_int_value(), default_frame.dest(), &cases[..]); + builder.build_switch(index.into_int_value(), default_frame.br_dest(), &cases[..]); state.popn(res_len)?; builder.build_unreachable(); } + Operator::If { ty } => { + let current_block = builder.get_insert_block().ok_or(BinaryReaderError { + message: "not currently in a block", + offset: -1isize as usize, + })?; + let if_then_block = context.append_basic_block(&function, "if_then"); + let if_else_block = context.append_basic_block(&function, "if_else"); + let end_block = context.append_basic_block(&function, "if_end"); + + let end_phis = { + builder.position_at_end(&end_block); + + let phis = if let Ok(wasmer_ty) = type_to_type(ty) { + let llvm_ty = type_to_llvm(intrinsics, wasmer_ty); + [llvm_ty] + .iter() + .map(|&ty| builder.build_phi(ty, &state.var_name())) + .collect() + } else { + SmallVec::new() + }; + + builder.position_at_end(¤t_block); + phis + }; + + let cond = state.pop1()?; + + let cond_value = builder.build_int_compare( + IntPredicate::NE, + cond.into_int_value(), + intrinsics.i32_zero, + &state.var_name(), + ); + + builder.build_conditional_branch(cond_value, &if_then_block, &if_else_block); + builder.position_at_end(&if_then_block); + state.push_if(if_then_block, if_else_block, end_block, end_phis); + } + Operator::Else => { + if state.reachable { + let frame = state.frame_at_depth(0)?; + builder.build_unconditional_branch(frame.code_after()); + let current_block = builder.get_insert_block().ok_or(BinaryReaderError { + message: "not currently in a block", + offset: -1isize as usize, + })?; + + for phi in frame.phis().to_vec().iter().rev() { + let value = state.pop1()?; + phi.add_incoming(&[(&value, ¤t_block)]) + } + } + + let (if_else_block, if_else_state) = if let ControlFrame::IfElse { + if_else, + if_else_state, + .. + } = state.frame_at_depth_mut(0)? + { + (if_else, if_else_state) + } else { + unreachable!() + }; + + *if_else_state = IfElseState::Else; + + builder.position_at_end(if_else_block); + state.reachable = true; + } Operator::End => { let frame = state.pop_frame()?; + let current_block = builder.get_insert_block().ok_or(BinaryReaderError { + message: "not currently in a block", + offset: -1isize as usize, + })?; + + if state.reachable { + builder.build_unconditional_branch(frame.code_after()); + + for phi in frame.phis().iter().rev() { + let value = state.pop1()?; + phi.add_incoming(&[(&value, ¤t_block)]) + } + } + + if let ControlFrame::IfElse { + if_else, + next, + phis, + if_else_state, + .. + } = &frame + { + if let IfElseState::If = if_else_state { + builder.position_at_end(if_else); + builder.build_unconditional_branch(next); + } + } + + builder.position_at_end(frame.code_after()); + state.reset_stack(&frame); + + state.reachable = true; // Push each phi value to the value stack. for phi in frame.phis() { state.push1(phi.as_basic_value()); } + } + Operator::Return => { + let frame = state.outermost_frame()?; - state.reset_stack(&frame); + builder.build_unconditional_branch(frame.br_dest()); + state.reachable = false; } Operator::Unreachable => { @@ -294,6 +451,7 @@ fn parse_function( // If llvm cannot prove that this is never touched, // it will emit a `ud2` instruction on x86_64 arches. builder.build_unreachable(); + state.reachable = false; } /*************************** @@ -1021,6 +1179,26 @@ fn parse_function( unimplemented!("waiting on better bitcasting support in inkwell") } + Operator::MemoryGrow { reserved } => { + + let memory_grow_const = intrinsics.i32_ty.const_int(reserved as u64, false); + + let memory_index = MemoryIndex::new(reserved); + match memory_index.local_or_import(info) { + LocalOrImport::Local(local_mem_index) => { + let mem_desc = &info.memories[local_mem_index]; + match mem_desc.memory_type() { + MemoryType::Dynamic => { + + } + } + }, + LocalOrImport::Import(import_mem_index) => { + + }, + } + } + op @ _ => { println!("{}", module.print_to_string().to_string()); unimplemented!("{:?}", op); @@ -1028,5 +1206,12 @@ fn parse_function( } } + let pass_manager = PassManager::create_for_module(); + pass_manager.add_promote_memory_to_register_pass(); + pass_manager.add_cfg_simplification_pass(); + pass_manager.run_on_module(module); + + println!("{}", module.print_to_string().to_string()); + Ok(()) } diff --git a/lib/llvm-backend/src/intrinsics.rs b/lib/llvm-backend/src/intrinsics.rs index 8eab37071..ff6847b3b 100644 --- a/lib/llvm-backend/src/intrinsics.rs +++ b/lib/llvm-backend/src/intrinsics.rs @@ -54,6 +54,22 @@ pub struct Intrinsics { pub i64_zero: IntValue, pub f32_zero: FloatValue, pub f64_zero: FloatValue, + + // VM intrinsics. + pub memory_grow_dynamic_local: FunctionValue, + pub memory_grow_static_local: FunctionValue, + pub memory_grow_shared_local: FunctionValue, + pub memory_grow_dynamic_import: FunctionValue, + pub memory_grow_static_import: FunctionValue, + pub memory_grow_shared_import: FunctionValue, + + pub memory_size_dynamic_local: FunctionValue, + pub memory_size_static_local: FunctionValue, + pub memory_size_shared_local: FunctionValue, + pub memory_size_dynamic_import: FunctionValue, + pub memory_size_static_import: FunctionValue, + pub memory_size_shared_import: FunctionValue, + // pub ctx_ty: StructType, } impl Intrinsics { @@ -64,6 +80,7 @@ impl Intrinsics { let i64_ty = context.i64_type(); let f32_ty = context.f32_type(); let f64_ty = context.f64_type(); + // let ctx_ty = context.struct_type(&[], false); let i1_zero = i1_ty.const_int(0, false); let i32_zero = i32_ty.const_int(0, false); @@ -89,6 +106,9 @@ impl Intrinsics { let ret_f32_take_f32_f32 = f32_ty.fn_type(&[f32_ty_basic, f32_ty_basic], false); let ret_f64_take_f64_f64 = f64_ty.fn_type(&[f64_ty_basic, f64_ty_basic], false); + let ret_i32_take_i64_i32_i32 = i32_ty.fn_type(&[i64_ty, i32_ty, i32_ty], false); + let ret_i32_take_i64_i32 = i32_ty.fn_type(&[i64_ty, i32_ty], false); + Self { ctlz_i32: module.add_function("llvm.ctlz.i32", ret_i32_take_i32_i1, None), ctlz_i64: module.add_function("llvm.ctlz.i64", ret_i64_take_i64_i1, None), @@ -138,6 +158,25 @@ impl Intrinsics { i64_zero, f32_zero, f64_zero, + + // VM intrinsics. + memory_grow_dynamic_local: module.add_function("vm.memory.grow.dynamic.local", ret_i32_take_i64_i32_i32, None), + memory_grow_static_local: module.add_function("vm.memory.grow.static.local", ret_i32_take_i64_i32_i32, None), + memory_grow_shared_local: module.add_function("vm.memory.grow.shared.local", ret_i32_take_i64_i32_i32, None), + memory_grow_dynamic_import: module.add_function("vm.memory.grow.dynamic.import", ret_i32_take_i64_i32_i32, None), + memory_grow_static_import: module.add_function("vm.memory.grow.static.import", ret_i32_take_i64_i32_i32, None), + memory_grow_shared_import: module.add_function("vm.memory.grow.shared.import", ret_i32_take_i64_i32_i32, None), + + memory_size_dynamic_local: module.add_function("vm.memory.size.dynamic.local", ret_i32_take_i64_i32, None), + memory_size_static_local: module.add_function("vm.memory.size.static.local", ret_i32_take_i64_i32, None), + memory_size_shared_local: module.add_function("vm.memory.size.shared.local", ret_i32_take_i64_i32, None), + memory_size_dynamic_import: module.add_function("vm.memory.size.dynamic.import", ret_i32_take_i64_i32, None), + memory_size_static_import: module.add_function("vm.memory.size.static.import", ret_i32_take_i64_i32, None), + memory_size_shared_import: module.add_function("vm.memory.size.shared.import", ret_i32_take_i64_i32, None), } } } + +// pub struct CtxType { +// ctx_ty: StructType, +// } diff --git a/lib/llvm-backend/src/lib.rs b/lib/llvm-backend/src/lib.rs index 69ed0fa0d..b02b39cbf 100644 --- a/lib/llvm-backend/src/lib.rs +++ b/lib/llvm-backend/src/lib.rs @@ -30,21 +30,26 @@ impl Compiler for LLVMCompiler { #[test] fn test_read_module() { use wabt::wat2wasm; - let WAT: &'static str = r#" + let wat = r#" (module (type $t0 (func (param i32) (result i32))) - (import "env" "memory" (memory 1 1)) - (import "env" "table" (table 10 anyfunc)) - (import "env" "global" (global i32)) - (import "env" "print_i32" (func $print_i32 (type $t0))) - (func $identity (type $t0) (param $p0 i32) (result i32) - get_local $p0) - (func $print_num (export "print_num") (type $t0) (param $p0 i32) (result i32) - get_global 0 - call $identity - call $print_i32)) + (type $t1 (func (result i32))) + (func $foo (type $t0) (param i32) (result i32) + get_local 0 + (if + (then + i32.const 42 + set_local 0 + ) + (else + i32.const 24 + set_local 0 + ) + ) + get_local 0 + )) "#; - let wasm = wat2wasm(WAT).unwrap(); + let wasm = wat2wasm(wat).unwrap(); let (info, code_reader) = read_info::read_module(&wasm).unwrap(); diff --git a/lib/llvm-backend/src/read_info.rs b/lib/llvm-backend/src/read_info.rs index c1ac2cf6b..bed91aa90 100644 --- a/lib/llvm-backend/src/read_info.rs +++ b/lib/llvm-backend/src/read_info.rs @@ -285,7 +285,12 @@ pub fn type_to_type(ty: WpType) -> Result { offset: -1isize as usize, }); } - _ => panic!("broken invariant, invalid type"), + _ => { + return Err(BinaryReaderError { + message: "that type is not supported as a wasmer type", + offset: -1isize as usize, + }); + } }) } diff --git a/lib/llvm-backend/src/state.rs b/lib/llvm-backend/src/state.rs index e85c7a23c..674eee04c 100644 --- a/lib/llvm-backend/src/state.rs +++ b/lib/llvm-backend/src/state.rs @@ -6,33 +6,73 @@ use smallvec::SmallVec; use std::cell::Cell; use wasmparser::BinaryReaderError; +#[derive(Debug)] pub enum ControlFrame { Block { - end_label: BasicBlock, + next: BasicBlock, phis: SmallVec<[PhiValue; 1]>, stack_size_snapshot: usize, }, + Loop { + body: BasicBlock, + next: BasicBlock, + phis: SmallVec<[PhiValue; 1]>, + stack_size_snapshot: usize, + }, + IfElse { + if_then: BasicBlock, + if_else: BasicBlock, + next: BasicBlock, + phis: SmallVec<[PhiValue; 1]>, + stack_size_snapshot: usize, + if_else_state: IfElseState, + }, +} + +#[derive(Debug)] +pub enum IfElseState { + If, + Else, } impl ControlFrame { - pub fn dest(&self) -> &BasicBlock { + pub fn code_after(&self) -> &BasicBlock { match self { - ControlFrame::Block { ref end_label, .. } => end_label, + ControlFrame::Block { ref next, .. } + | ControlFrame::Loop { ref next, .. } + | ControlFrame::IfElse { ref next, .. } => next, + } + } + + pub fn br_dest(&self) -> &BasicBlock { + match self { + ControlFrame::Block { ref next, .. } | ControlFrame::IfElse { ref next, .. } => next, + ControlFrame::Loop { ref body, .. } => body, } } pub fn phis(&self) -> &[PhiValue] { match self { - ControlFrame::Block { ref phis, .. } => phis.as_slice(), + ControlFrame::Block { ref phis, .. } + | ControlFrame::Loop { ref phis, .. } + | ControlFrame::IfElse { ref phis, .. } => phis.as_slice(), + } + } + + pub fn is_loop(&self) -> bool { + match self { + ControlFrame::Loop { .. } => true, + _ => false, } } } +#[derive(Debug)] pub struct State { stack: Vec, control_stack: Vec, value_counter: Cell, - block_counter: Cell, + pub reachable: bool, } impl State { @@ -41,7 +81,7 @@ impl State { stack: vec![], control_stack: vec![], value_counter: Cell::new(0), - block_counter: Cell::new(0), + reachable: true, } } @@ -50,11 +90,26 @@ impl State { ControlFrame::Block { stack_size_snapshot, .. + } + | ControlFrame::Loop { + stack_size_snapshot, + .. + } + | ControlFrame::IfElse { + stack_size_snapshot, + .. } => *stack_size_snapshot, }; self.stack.truncate(stack_size_snapshot); } + pub fn outermost_frame(&self) -> Result<&ControlFrame, BinaryReaderError> { + self.control_stack.get(0).ok_or(BinaryReaderError { + message: "invalid control stack depth", + offset: -1isize as usize, + }) + } + pub fn frame_at_depth(&self, depth: u32) -> Result<&ControlFrame, BinaryReaderError> { let index = self.control_stack.len() - 1 - (depth as usize); self.control_stack.get(index).ok_or(BinaryReaderError { @@ -63,6 +118,17 @@ impl State { }) } + pub fn frame_at_depth_mut( + &mut self, + depth: u32, + ) -> Result<&mut ControlFrame, BinaryReaderError> { + let index = self.control_stack.len() - 1 - (depth as usize); + self.control_stack.get_mut(index).ok_or(BinaryReaderError { + message: "invalid control stack depth", + offset: -1isize as usize, + }) + } + pub fn pop_frame(&mut self) -> Result { self.control_stack.pop().ok_or(BinaryReaderError { message: "cannot pop from control stack", @@ -70,13 +136,6 @@ impl State { }) } - pub fn block_name(&self) -> String { - let counter = self.block_counter.get(); - let s = format!("block{}", counter); - self.block_counter.set(counter + 1); - s - } - pub fn var_name(&self) -> String { let counter = self.value_counter.get(); let s = format!("s{}", counter); @@ -129,6 +188,12 @@ impl State { }) } + pub fn popn_save(&mut self, n: usize) -> Result, BinaryReaderError> { + let v = self.peekn(n)?.to_vec(); + self.popn(n)?; + Ok(v) + } + pub fn popn(&mut self, n: usize) -> Result<(), BinaryReaderError> { if self.stack.len() < n { return Err(BinaryReaderError { @@ -142,11 +207,37 @@ impl State { Ok(()) } - pub fn push_block(&mut self, end_label: BasicBlock, phis: SmallVec<[PhiValue; 1]>) { + pub fn push_block(&mut self, next: BasicBlock, phis: SmallVec<[PhiValue; 1]>) { self.control_stack.push(ControlFrame::Block { - end_label, + next, phis, stack_size_snapshot: self.stack.len(), }); } + + pub fn push_loop(&mut self, body: BasicBlock, next: BasicBlock, phis: SmallVec<[PhiValue; 1]>) { + self.control_stack.push(ControlFrame::Loop { + body, + next, + phis, + stack_size_snapshot: self.stack.len(), + }); + } + + pub fn push_if( + &mut self, + if_then: BasicBlock, + if_else: BasicBlock, + next: BasicBlock, + phis: SmallVec<[PhiValue; 1]>, + ) { + self.control_stack.push(ControlFrame::IfElse { + if_then, + if_else, + next, + phis, + stack_size_snapshot: self.stack.len(), + if_else_state: IfElseState::If, + }); + } } From 93979aeae20db75eec41ab48e9220baf0d4e1ebc Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Wed, 13 Feb 2019 20:02:11 -0600 Subject: [PATCH 046/262] Add get exports from instance --- lib/runtime-c-api/src/lib.rs | 135 +++++++++++++++++- lib/runtime-c-api/tests/.gitignore | 1 + lib/runtime-c-api/tests/CMakeLists.txt | 4 + lib/runtime-c-api/tests/test-exports.c | 43 ++++++ .../tests/test-import-function.c | 10 +- lib/runtime-c-api/wasmer.h | 42 ++++++ lib/runtime-c-api/wasmer.hh | 31 ++++ 7 files changed, 261 insertions(+), 5 deletions(-) create mode 100644 lib/runtime-c-api/tests/test-exports.c diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index d5443ba7f..e6e82dc0d 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -5,6 +5,7 @@ use libc::{c_char, c_int, int32_t, int64_t, uint32_t, uint8_t}; use std::cell::RefCell; use std::error::Error; use std::ffi::CStr; +use std::ffi::CString; use std::fmt; use std::slice; use std::str; @@ -75,6 +76,10 @@ pub struct wasmer_memory_t(); #[derive(Clone)] pub struct wasmer_table_t(); +#[repr(C)] +#[derive(Clone)] +pub struct wasmer_func_t(); + #[repr(C)] #[derive(Clone)] pub struct wasmer_global_t(); @@ -85,6 +90,47 @@ pub struct wasmer_limits_t { pub max: uint32_t, } +#[repr(C)] +pub struct wasmer_func_signature { + pub params: *const wasmer_value_tag, + pub params_len: c_int, + pub returns: *const wasmer_value_tag, + pub returns_len: c_int, +} + +#[repr(C)] +#[derive(Clone)] +pub struct wasmer_import { + tag: wasmer_import_export_kind, + value: wasmer_import_export_value, +} + +#[repr(C)] +#[derive(Clone)] +pub struct wasmer_export_t; + +#[repr(C)] +#[derive(Clone)] +pub struct wasmer_exports_t; + +#[repr(u32)] +#[derive(Clone)] +pub enum wasmer_import_export_kind { + WASM_FUNCTION, + WASM_GLOBAL, + WASM_MEMORY, + WASM_TABLE, +} + +#[repr(C)] +#[derive(Clone, Copy)] +pub union wasmer_import_export_value { + func: *const wasmer_func_t, + table: *const wasmer_table_t, + memory: *const wasmer_memory_t, + global: *const wasmer_global_t, +} + /// Returns true for valid wasm bytes and false for invalid bytes #[allow(clippy::cast_ptr_alignment)] #[no_mangle] @@ -413,7 +459,6 @@ pub unsafe extern "C" fn wasmer_instance_call( Box::into_raw(instance); match result { Ok(results_vec) => { - println!("Call Res: {:?}", results_vec); if results_vec.len() > 0 { let ret = match results_vec[0] { Value::I32(x) => wasmer_value_t { @@ -444,6 +489,83 @@ pub unsafe extern "C" fn wasmer_instance_call( } } +/// Gets Exports for the given instance +/// +/// The caller owns the object and should call `wasmer_exports_destroy` to free it. +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub unsafe extern "C" fn wasmer_instance_exports( + instance: *mut wasmer_instance_t, + exports: *mut *mut wasmer_exports_t, +) { + let mut instance = unsafe { Box::from_raw(instance as *mut Instance) }; + let named_exports: Box = + Box::new(NamedExports(instance.exports().map(|e| e.into()).collect())); + unsafe { *exports = Box::into_raw(named_exports) as *mut wasmer_exports_t }; + Box::into_raw(instance); +} + +pub struct NamedExports(Vec); + +/// Frees the memory for the given exports +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub unsafe extern "C" fn wasmer_exports_destroy(exports: *mut wasmer_exports_t) { + if !exports.is_null() { + drop(unsafe { Box::from_raw(exports as *mut NamedExports) }); + } +} + +/// Gets the length of the exports +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub unsafe extern "C" fn wasmer_exports_len(exports: *mut wasmer_exports_t) -> c_int { + if exports.is_null() { + return 0; + } + (*(exports as *mut NamedExports)).0.len() as c_int +} + +/// Gets wasmer_export by index +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub unsafe extern "C" fn wasmer_exports_get( + exports: *mut wasmer_exports_t, + idx: c_int, +) -> *mut wasmer_export_t { + if exports.is_null() { + return ptr::null_mut(); + } + let mut named_exports = unsafe { Box::from_raw(exports as *mut NamedExports) }; + let ptr = &mut (*named_exports).0[idx as usize] as *mut NamedExport as *mut wasmer_export_t; + Box::into_raw(named_exports); + ptr +} + +/// Gets wasmer_export kind +#[no_mangle] +#[allow(clippy::cast_ptr_alignment)] +pub unsafe extern "C" fn wasmer_export_kind( + export: *mut wasmer_export_t, +) -> wasmer_import_export_kind { + let named_export = &*(export as *mut NamedExport); + match named_export.export { + Export::Table(_) => wasmer_import_export_kind::WASM_TABLE, + Export::Function { .. } => wasmer_import_export_kind::WASM_FUNCTION, + Export::Global(_) => wasmer_import_export_kind::WASM_GLOBAL, + Export::Memory(_) => wasmer_import_export_kind::WASM_MEMORY, + } +} + +///// Gets wasmer_export func +//#[no_mangle] +//pub unsafe extern "C" fn wasmer_export_name(export: *mut wasmer_export_t) { +// if exports.is_null() { +// return ptr::null_mut(); +// } +// let named_export = &*(export as *mut NamedExport); +//} + /// Registers a `func` with provided `name` and `namespace` into the ImportObject. /// /// Returns `wasmer_result_t::WASMER_OK` upon success. @@ -606,6 +728,12 @@ impl From for Type { } } +impl From<(std::string::String, wasmer_runtime_core::export::Export)> for NamedExport { + fn from((name, export): (String, Export)) -> Self { + NamedExport { name, export } + } +} + // Error reporting thread_local! { @@ -699,3 +827,8 @@ impl fmt::Display for CApiError { } impl Error for CApiError {} + +struct NamedExport { + name: String, + export: Export, +} diff --git a/lib/runtime-c-api/tests/.gitignore b/lib/runtime-c-api/tests/.gitignore index 6a96cd53f..c8dfca857 100644 --- a/lib/runtime-c-api/tests/.gitignore +++ b/lib/runtime-c-api/tests/.gitignore @@ -10,6 +10,7 @@ compile_commands.json CTestTestfile.cmake _deps test-globals +test-exports test-instantiate test-import-function test-memory diff --git a/lib/runtime-c-api/tests/CMakeLists.txt b/lib/runtime-c-api/tests/CMakeLists.txt index d15934df5..ce970d4bf 100644 --- a/lib/runtime-c-api/tests/CMakeLists.txt +++ b/lib/runtime-c-api/tests/CMakeLists.txt @@ -1,6 +1,7 @@ cmake_minimum_required (VERSION 2.6) project (WasmerCApiTests) +add_executable(test-exports test-exports.c) add_executable(test-globals test-globals.c) add_executable(test-instantiate test-instantiate.c) add_executable(test-import-function test-import-function.c) @@ -17,6 +18,8 @@ if(NOT WASMER_LIB) message(FATAL_ERROR "wasmer library not found") endif() +target_link_libraries(test-exports + general ${WASMER_LIB}) target_link_libraries(test-globals general ${WASMER_LIB}) target_link_libraries(test-instantiate @@ -31,6 +34,7 @@ target_link_libraries(test-tables general ${WASMER_LIB}) enable_testing() +add_test(test-exports test-exports) add_test(test-globals test-globals) add_test(test-instantiate test-instantiate) add_test(test-import-function test-import-function) diff --git a/lib/runtime-c-api/tests/test-exports.c b/lib/runtime-c-api/tests/test-exports.c new file mode 100644 index 000000000..8516d562b --- /dev/null +++ b/lib/runtime-c-api/tests/test-exports.c @@ -0,0 +1,43 @@ +#include +#include "../wasmer.h" +#include +#include + +int main() +{ + wasmer_import_object_t *import_object = wasmer_import_object_new(); + + // Read the wasm file bytes + FILE *file = fopen("sum.wasm", "r"); + fseek(file, 0, SEEK_END); + long len = ftell(file); + uint8_t *bytes = malloc(len); + fseek(file, 0, SEEK_SET); + fread(bytes, 1, len, file); + fclose(file); + + wasmer_instance_t *instance = NULL; + wasmer_result_t compile_result = wasmer_instantiate(&instance, bytes, len, import_object); + printf("Compile result: %d\n", compile_result); + assert(compile_result == WASMER_OK); + + wasmer_exports_t *exports = NULL; + wasmer_instance_exports(instance, &exports); + + int exports_len = wasmer_exports_len(exports); + printf("exports_len: %d\n", exports_len); + assert(exports_len == 1); + + wasmer_export_t *export = wasmer_exports_get(exports, 0); + + wasmer_import_export_kind kind = wasmer_export_kind(export); + assert(kind == WASM_FUNCTION); + + printf("Destroy instance\n"); + wasmer_instance_destroy(instance); + printf("Destroy import object\n"); + wasmer_import_object_destroy(import_object); + printf("Destroy exports\n"); + wasmer_exports_destroy(exports); + return 0; +} \ No newline at end of file diff --git a/lib/runtime-c-api/tests/test-import-function.c b/lib/runtime-c-api/tests/test-import-function.c index f0ca17504..b42817abc 100644 --- a/lib/runtime-c-api/tests/test-import-function.c +++ b/lib/runtime-c-api/tests/test-import-function.c @@ -8,11 +8,13 @@ static memory_len = 0; static ptr_len = 0; static char actual_str[14] = {}; -void print_str(int32_t ptr, int32_t len, wasmer_instance_context_t *ctx) { +void print_str(int32_t ptr, int32_t len, wasmer_instance_context_t *ctx) +{ wasmer_memory_t *memory = wasmer_instance_context_memory(ctx, 0); uint32_t mem_len = wasmer_memory_length(memory); uint8_t *mem_bytes = wasmer_memory_data(memory); - for(int32_t idx = 0; idx < len; idx++){ + for (int32_t idx = 0; idx < len; idx++) + { actual_str[idx] = mem_bytes[ptr + idx]; } actual_str[13] = '\0'; @@ -54,8 +56,8 @@ int main() assert(ptr_len == 13); assert(0 == strcmp(actual_str, "Hello, World!")); - printf("Destroy instance\n"); - wasmer_instance_destroy(instance); + // printf("Destroy instance\n"); + // wasmer_instance_destroy(instance); printf("Destroy import object\n"); wasmer_import_object_destroy(import_object); return 0; diff --git a/lib/runtime-c-api/wasmer.h b/lib/runtime-c-api/wasmer.h index 6b855404a..86230de1c 100644 --- a/lib/runtime-c-api/wasmer.h +++ b/lib/runtime-c-api/wasmer.h @@ -6,6 +6,14 @@ #include #include +enum wasmer_import_export_kind { + WASM_FUNCTION, + WASM_GLOBAL, + WASM_MEMORY, + WASM_TABLE, +}; +typedef uint32_t wasmer_import_export_kind; + typedef enum { WASMER_OK = 1, WASMER_ERROR = 2, @@ -27,6 +35,14 @@ typedef struct wasmer_instance_t wasmer_instance_t; typedef struct { +} wasmer_export_t; + +typedef struct { + +} wasmer_exports_t; + +typedef struct { + } wasmer_global_t; typedef union { @@ -59,6 +75,26 @@ typedef struct { } wasmer_table_t; +/** + * Gets wasmer_export kind + */ +wasmer_import_export_kind wasmer_export_kind(wasmer_export_t *export_); + +/** + * Frees the memory for the given exports + */ +void wasmer_exports_destroy(wasmer_exports_t *exports); + +/** + * Gets wasmer_export by index + */ +wasmer_export_t *wasmer_exports_get(wasmer_exports_t *exports, int idx); + +/** + * Gets the length of the exports + */ +int wasmer_exports_len(wasmer_exports_t *exports); + /** * Frees memory for the given Global */ @@ -137,6 +173,12 @@ const wasmer_memory_t *wasmer_instance_context_memory(wasmer_instance_context_t */ void wasmer_instance_destroy(wasmer_instance_t *instance); +/** + * Gets Exports for the given instance + * The caller owns the object and should call `wasmer_exports_destroy` to free it. + */ +void wasmer_instance_exports(wasmer_instance_t *instance, wasmer_exports_t **exports); + /** * Creates a new Instance from the given wasm bytes and imports. * Returns `wasmer_result_t::WASMER_OK` upon success. diff --git a/lib/runtime-c-api/wasmer.hh b/lib/runtime-c-api/wasmer.hh index 24c4f3f14..32b6e435f 100644 --- a/lib/runtime-c-api/wasmer.hh +++ b/lib/runtime-c-api/wasmer.hh @@ -5,6 +5,13 @@ #include #include +enum class wasmer_import_export_kind : uint32_t { + WASM_FUNCTION, + WASM_GLOBAL, + WASM_MEMORY, + WASM_TABLE, +}; + enum class wasmer_result_t { WASMER_OK = 1, WASMER_ERROR = 2, @@ -23,6 +30,14 @@ struct wasmer_instance_context_t; struct wasmer_instance_t; +struct wasmer_export_t { + +}; + +struct wasmer_exports_t { + +}; + struct wasmer_global_t { }; @@ -59,6 +74,18 @@ struct wasmer_table_t { extern "C" { +/// Gets wasmer_export kind +wasmer_import_export_kind wasmer_export_kind(wasmer_export_t *export_); + +/// Frees the memory for the given exports +void wasmer_exports_destroy(wasmer_exports_t *exports); + +/// Gets wasmer_export by index +wasmer_export_t *wasmer_exports_get(wasmer_exports_t *exports, int idx); + +/// Gets the length of the exports +int wasmer_exports_len(wasmer_exports_t *exports); + /// Frees memory for the given Global void wasmer_global_destroy(wasmer_global_t *global); @@ -115,6 +142,10 @@ const wasmer_memory_t *wasmer_instance_context_memory(wasmer_instance_context_t /// Frees memory for the given Instance void wasmer_instance_destroy(wasmer_instance_t *instance); +/// Gets Exports for the given instance +/// The caller owns the object and should call `wasmer_exports_destroy` to free it. +void wasmer_instance_exports(wasmer_instance_t *instance, wasmer_exports_t **exports); + /// Creates a new Instance from the given wasm bytes and imports. /// Returns `wasmer_result_t::WASMER_OK` upon success. /// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` From bfd5e21605be3db7b1a8eb1be9c0c5a2632efb67 Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Thu, 14 Feb 2019 00:00:39 -0600 Subject: [PATCH 047/262] Add export_name and export_func --- lib/runtime-c-api/src/lib.rs | 101 +++++++++++++++++++++++++ lib/runtime-c-api/tests/test-exports.c | 26 +++++++ lib/runtime-c-api/wasmer.h | 38 +++++++++- lib/runtime-c-api/wasmer.hh | 30 +++++++- 4 files changed, 190 insertions(+), 5 deletions(-) diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index e6e82dc0d..1931656e7 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -131,6 +131,12 @@ pub union wasmer_import_export_value { global: *const wasmer_global_t, } +#[repr(C)] +pub struct wasmer_byte_array { + bytes: *const uint8_t, + bytes_len: uint32_t, +} + /// Returns true for valid wasm bytes and false for invalid bytes #[allow(clippy::cast_ptr_alignment)] #[no_mangle] @@ -557,6 +563,101 @@ pub unsafe extern "C" fn wasmer_export_kind( } } +/// Gets func from wasm_export +#[no_mangle] +#[allow(clippy::cast_ptr_alignment)] +pub unsafe extern "C" fn wasmer_export_to_func( + export: *mut wasmer_export_t, +) -> *const wasmer_func_t { + let named_export = &*(export as *mut NamedExport); + &named_export.export as *const Export as *const wasmer_func_t +} + +/// Gets name from wasmer_export +#[no_mangle] +#[allow(clippy::cast_ptr_alignment)] +pub unsafe extern "C" fn wasmer_export_name(export: *mut wasmer_export_t) -> wasmer_byte_array { + let named_export = &*(export as *mut NamedExport); + wasmer_byte_array { + bytes: named_export.name.as_ptr(), + bytes_len: named_export.name.len() as u32, + } +} + +/// Calls a `func` with the provided parameters. +/// Results are set using the provided `results` pointer. +/// +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub unsafe extern "C" fn wasmer_func_call( + func: *mut wasmer_func_t, + params: *const wasmer_value_t, + params_len: c_int, + results: *mut wasmer_value_t, + results_len: c_int, +) -> wasmer_result_t { + if func.is_null() { + update_last_error(CApiError { + msg: "func ptr is null".to_string(), + }); + return wasmer_result_t::WASMER_ERROR; + } + if params.is_null() { + update_last_error(CApiError { + msg: "params ptr is null".to_string(), + }); + return wasmer_result_t::WASMER_ERROR; + } + + let params: &[wasmer_value_t] = slice::from_raw_parts(params, params_len as usize); + let params: Vec = params.iter().cloned().map(|x| x.into()).collect(); + + let export_func = unsafe { Box::from_raw(func as *mut Export) }; + + let results: &mut [wasmer_value_t] = slice::from_raw_parts_mut(results, results_len as usize); + // TODO implement func.call + update_last_error(CApiError { + msg: "wasmer_func_call not yet implemented".to_string(), + }); + return wasmer_result_t::WASMER_ERROR; + // let result = instance.call(func_name_r, ¶ms[..]); + // Box::into_raw(export_func); + // match result { + // Ok(results_vec) => { + // if results_vec.len() > 0 { + // let ret = match results_vec[0] { + // Value::I32(x) => wasmer_value_t { + // tag: wasmer_value_tag::WASM_I32, + // value: wasmer_value { I32: x }, + // }, + // Value::I64(x) => wasmer_value_t { + // tag: wasmer_value_tag::WASM_I64, + // value: wasmer_value { I64: x }, + // }, + // Value::F32(x) => wasmer_value_t { + // tag: wasmer_value_tag::WASM_F32, + // value: wasmer_value { F32: x }, + // }, + // Value::F64(x) => wasmer_value_t { + // tag: wasmer_value_tag::WASM_F64, + // value: wasmer_value { F64: x }, + // }, + // }; + // results[0] = ret; + // } + // wasmer_result_t::WASMER_OK + // } + // Err(err) => { + // update_last_error(err); + // wasmer_result_t::WASMER_ERROR + // } + // } +} + ///// Gets wasmer_export func //#[no_mangle] //pub unsafe extern "C" fn wasmer_export_name(export: *mut wasmer_export_t) { diff --git a/lib/runtime-c-api/tests/test-exports.c b/lib/runtime-c-api/tests/test-exports.c index 8516d562b..b00adb790 100644 --- a/lib/runtime-c-api/tests/test-exports.c +++ b/lib/runtime-c-api/tests/test-exports.c @@ -32,6 +32,32 @@ int main() wasmer_import_export_kind kind = wasmer_export_kind(export); assert(kind == WASM_FUNCTION); + wasmer_func_t *func = wasmer_export_to_func(export); + + wasmer_byte_array name_bytes = wasmer_export_name(export); + assert(name_bytes.bytes_len == 3); + char expected[] = {'s', 'u', 'm'}; + for(int idx = 0; idx < 3; idx++){ + printf("%c\n", name_bytes.bytes[idx]); + assert(name_bytes.bytes[idx] == expected[idx]); + } + +// wasmer_value_t param_one; +// param_one.tag = WASM_I32; +// param_one.value.I32 = 7; +// wasmer_value_t param_two; +// param_two.tag = WASM_I32; +// param_two.value.I32 = 8; +// wasmer_value_t params[] = {param_one, param_two}; +// wasmer_value_t result_one; +// wasmer_value_t results[] = {result_one}; +// +// wasmer_result_t call_result = wasmer_func_call(func, params, 2, results, 1); +// printf("Call result: %d\n", call_result); +// printf("Result: %d\n", results[0].value.I32); +// assert(results[0].value.I32 == 15); +// assert(call_result == WASMER_OK); + printf("Destroy instance\n"); wasmer_instance_destroy(instance); diff --git a/lib/runtime-c-api/wasmer.h b/lib/runtime-c-api/wasmer.h index 86230de1c..f55014bee 100644 --- a/lib/runtime-c-api/wasmer.h +++ b/lib/runtime-c-api/wasmer.h @@ -38,12 +38,17 @@ typedef struct { } wasmer_export_t; typedef struct { - -} wasmer_exports_t; + const uint8_t *bytes; + uint32_t bytes_len; +} wasmer_byte_array; typedef struct { -} wasmer_global_t; +} wasmer_func_t; + +typedef struct { + +} wasmer_exports_t; typedef union { int32_t I32; @@ -57,6 +62,10 @@ typedef struct { wasmer_value value; } wasmer_value_t; +typedef struct { + +} wasmer_global_t; + typedef struct { bool mutable_; wasmer_value_tag kind; @@ -80,6 +89,16 @@ typedef struct { */ wasmer_import_export_kind wasmer_export_kind(wasmer_export_t *export_); +/** + * Gets func from wasm_export + */ +wasmer_byte_array wasmer_export_name(wasmer_export_t *export_); + +/** + * Gets func from wasm_export + */ +const wasmer_func_t *wasmer_export_to_func(wasmer_export_t *export_); + /** * Frees the memory for the given exports */ @@ -95,6 +114,19 @@ wasmer_export_t *wasmer_exports_get(wasmer_exports_t *exports, int idx); */ int wasmer_exports_len(wasmer_exports_t *exports); +/** + * Calls a `func` with the provided parameters. + * Results are set using the provided `results` pointer. + * Returns `wasmer_result_t::WASMER_OK` upon success. + * Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` + * and `wasmer_last_error_message` to get an error message. + */ +wasmer_result_t wasmer_func_call(wasmer_func_t *func, + const wasmer_value_t *params, + int params_len, + wasmer_value_t *results, + int results_len); + /** * Frees memory for the given Global */ diff --git a/lib/runtime-c-api/wasmer.hh b/lib/runtime-c-api/wasmer.hh index 32b6e435f..02de6f52b 100644 --- a/lib/runtime-c-api/wasmer.hh +++ b/lib/runtime-c-api/wasmer.hh @@ -34,11 +34,16 @@ struct wasmer_export_t { }; -struct wasmer_exports_t { +struct wasmer_byte_array { + const uint8_t *bytes; + uint32_t bytes_len; +}; + +struct wasmer_func_t { }; -struct wasmer_global_t { +struct wasmer_exports_t { }; @@ -54,6 +59,10 @@ struct wasmer_value_t { wasmer_value value; }; +struct wasmer_global_t { + +}; + struct wasmer_global_descriptor_t { bool mutable_; wasmer_value_tag kind; @@ -77,6 +86,12 @@ extern "C" { /// Gets wasmer_export kind wasmer_import_export_kind wasmer_export_kind(wasmer_export_t *export_); +/// Gets func from wasm_export +wasmer_byte_array wasmer_export_name(wasmer_export_t *export_); + +/// Gets func from wasm_export +const wasmer_func_t *wasmer_export_to_func(wasmer_export_t *export_); + /// Frees the memory for the given exports void wasmer_exports_destroy(wasmer_exports_t *exports); @@ -86,6 +101,17 @@ wasmer_export_t *wasmer_exports_get(wasmer_exports_t *exports, int idx); /// Gets the length of the exports int wasmer_exports_len(wasmer_exports_t *exports); +/// Calls a `func` with the provided parameters. +/// Results are set using the provided `results` pointer. +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +wasmer_result_t wasmer_func_call(wasmer_func_t *func, + const wasmer_value_t *params, + int params_len, + wasmer_value_t *results, + int results_len); + /// Frees memory for the given Global void wasmer_global_destroy(wasmer_global_t *global); From 6a1fdb7f91ac25fec86663e283da646dcda5c554 Mon Sep 17 00:00:00 2001 From: Mackenzie Clark Date: Thu, 14 Feb 2019 09:58:33 -0800 Subject: [PATCH 048/262] add windows exception handling in C (#175) --- .appveyor.yml | 3 +- Cargo.lock | 290 +++++++++++++++++- Cargo.toml | 2 +- README.md | 10 +- lib/clif-backend/Cargo.toml | 6 +- lib/clif-backend/src/resolver.rs | 4 +- lib/clif-backend/src/signal/mod.rs | 12 + lib/clif-backend/src/signal/windows.rs | 114 ++++++- lib/clif-backend/src/trampoline.rs | 17 +- lib/runtime-core/src/sys/windows/memory.rs | 3 +- lib/runtime-core/src/vm.rs | 1 + lib/spectests/examples/simple/main.rs | 3 - lib/win-exception-handler/Cargo.toml | 18 ++ lib/win-exception-handler/build.rs | 11 + .../exception_handling/.gitignore | 1 + .../exception_handling/CMakeLists.txt | 6 + .../exception_handling/exception_handling.c | 74 +++++ .../exception_handling/exception_handling.h | 25 ++ .../src/exception_handling.rs | 55 ++++ lib/win-exception-handler/src/lib.rs | 5 + src/bin/wasmer.rs | 2 +- 21 files changed, 630 insertions(+), 32 deletions(-) create mode 100644 lib/win-exception-handler/Cargo.toml create mode 100644 lib/win-exception-handler/build.rs create mode 100644 lib/win-exception-handler/exception_handling/.gitignore create mode 100644 lib/win-exception-handler/exception_handling/CMakeLists.txt create mode 100644 lib/win-exception-handler/exception_handling/exception_handling.c create mode 100644 lib/win-exception-handler/exception_handling/exception_handling.h create mode 100644 lib/win-exception-handler/src/exception_handling.rs create mode 100644 lib/win-exception-handler/src/lib.rs diff --git a/.appveyor.yml b/.appveyor.yml index 8bcc3b4c7..5da647f54 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -29,4 +29,5 @@ build_script: test_script: - set RUST_BACKTRACE=1 - - cargo test --verbose + - cd ./lib/spectests && cargo test -- --test-threads 1 && cd ../.. + diff --git a/Cargo.lock b/Cargo.lock index d061df27b..5f55a2ea5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,3 +1,13 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "aho-corasick" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ansi_term" version = "0.11.0" @@ -21,6 +31,49 @@ name = "autocfg" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "backtrace" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "backtrace-sys" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "bindgen" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cexpr 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "clang-sys 0.26.4 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "which 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "bitflags" version = "1.0.4" @@ -65,11 +118,29 @@ name = "cc" version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "cexpr" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "nom 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "cfg-if" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "clang-sys" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "clap" version = "2.32.0" @@ -178,6 +249,18 @@ dependencies = [ "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "env_logger" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "errno" version = "0.2.4" @@ -202,6 +285,7 @@ name = "failure" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -276,6 +360,14 @@ dependencies = [ "unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "humantime" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "indexmap" version = "1.0.2" @@ -310,6 +402,15 @@ name = "libc" version = "0.2.48" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "libloading" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "lock_api" version = "0.1.5" @@ -327,6 +428,11 @@ dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "memchr" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "memmap" version = "0.7.0" @@ -360,6 +466,15 @@ dependencies = [ "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "nom" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "opaque-debug" version = "0.2.2" @@ -404,6 +519,19 @@ dependencies = [ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "peeking_take_while" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "proc-macro2" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "proc-macro2" version = "0.4.26" @@ -412,6 +540,19 @@ dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "quick-error" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "quote" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "quote" version = "0.6.11" @@ -547,6 +688,31 @@ dependencies = [ "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "regex" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "regex-syntax" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "rustc_version" version = "0.2.3" @@ -602,12 +768,12 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.85" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.13.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -669,6 +835,16 @@ dependencies = [ "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "syn" +version = "0.13.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "syn" version = "0.15.26" @@ -700,6 +876,14 @@ dependencies = [ "serde_json 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "termcolor" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "termion" version = "1.5.1" @@ -718,6 +902,14 @@ dependencies = [ "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "thread_local" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "time" version = "0.1.42" @@ -733,6 +925,11 @@ name = "typenum" version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "ucd-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "unicode-segmentation" version = "1.2.1" @@ -756,11 +953,21 @@ dependencies = [ "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "utf8-ranges" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "vec_map" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "version_check" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "void" version = "1.0.2" @@ -772,7 +979,7 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", "wabt-sys 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -815,10 +1022,12 @@ dependencies = [ "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", "serde-bench 0.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", "target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-runtime-core 0.1.2", + "wasmer-win-exception-handler 0.0.1", "wasmparser 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -860,7 +1069,7 @@ dependencies = [ "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", "serde-bench 0.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-clif-backend 0.1.2", "wasmparser 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -876,6 +1085,18 @@ dependencies = [ "wasmer-runtime-core 0.1.2", ] +[[package]] +name = "wasmer-win-exception-handler" +version = "0.0.1" +dependencies = [ + "bindgen 0.46.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cmake 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmer-runtime-core 0.1.2", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "wasmparser" version = "0.22.1" @@ -886,6 +1107,15 @@ name = "wasmparser" version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "which" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "winapi" version = "0.2.8" @@ -910,15 +1140,36 @@ name = "winapi-i686-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "winapi-util" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "wincolor" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [metadata] +"checksum aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1e9a933f4e58658d7b12defcf96dc5c720f20832deebe3e0a19efd3b6aaeeb9e" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" "checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799" +"checksum backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "b5b493b66e03090ebc4343eb02f94ff944e0cbc9ac6571491d170ba026741eb5" +"checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6" +"checksum bindgen 0.46.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8f7f7f0701772b17de73e4f5cbcb1dd6926f4706cba4c1ab62c5367f8bdc94e1" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" "checksum block-buffer 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "509de513cca6d92b6aacf9c61acfe7eaa160837323a81068d690cc1f8e5740da" "checksum block-padding 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d75255892aeb580d3c566f213a2b6fdc1c66667839f45719ee1d30ebf2aea591" @@ -926,7 +1177,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" "checksum cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "926013f2860c46252efceabb19f4a6b308197505082c609025aa6706c011d427" "checksum cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4a8b715cb4597106ea87c7c84b2f1d452c7492033765df7f32651e66fcf749" +"checksum cexpr 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "644d693ecfa91955ed32dcc7eda4914e1be97a641fb6f0645a37348e20b230da" "checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" +"checksum clang-sys 0.26.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6ef0c1bcf2e99c649104bd7a7012d8f8802684400e03db0ec0af48583c6fa0e4" "checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum cmake 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "6ec65ee4f9c9d16f335091d23693457ed4928657ba4982289d7fafee03bc614a" @@ -938,6 +1191,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum cranelift-native 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "474bee81d620a473bf43411a3d6f10ffbf7965141dc5e5b76d8d2151dde3285d" "checksum cranelift-wasm 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49723365dab9a48b354bdc24cb6d9d5719bc1d3b858ffd2ea179d0d7d885804a" "checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c" +"checksum env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "afb070faf94c85d17d50ca44f6ad076bce18ae92f0037d350947240a36e9d42e" "checksum errno 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c2a071601ed01b988f896ab14b95e67335d1eeb50190932a1320f7fe3cadc84e" "checksum errno-dragonfly 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "14ca354e36190500e1e1fb267c647932382b54053c50b14970856c0b00a35067" "checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" @@ -951,23 +1205,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" "checksum hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3bae29b6653b3412c2e71e9d486db9f9df5d701941d86683005efb9f2d28e3da" "checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" +"checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114" "checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d" "checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1" "checksum libc 0.2.48 (git+https://github.com/rust-lang/libc)" = "" "checksum libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)" = "e962c7641008ac010fa60a7dfdc1712449f29c44ef2d4702394aea943ee75047" +"checksum libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3ad660d7cb8c5822cd83d10897b0f1f1526792737a179e73896152f85b88c2" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" +"checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39" "checksum memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" "checksum nix 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "921f61dc817b379d0834e45d5ec45beaacfae97082090a49c2cf30dcbc30206f" "checksum nix 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46f0f3210768d796e8fa79ec70ee6af172dacbe7147f5e69be5240a47778302b" +"checksum nom 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b30adc557058ce00c9d0d7cb3c6e0b5bc6f36e2e2eabe74b0ba726d194abd588" "checksum opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "93f5bb2e8e8dec81642920ccff6b61f1eb94fa3020c5a325c9851ff604152409" "checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" "checksum page_size 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f89ef58b3d32420dbd1a43d2f38ae92f6239ef12bb556ab09ca55445f5a67242" "checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" "checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" +"checksum peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" +"checksum proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1b06e2f335f48d24442b35a19df506a835fb3547bc3c06ef27340da9acf5cae7" "checksum proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)" = "38fddd23d98b2144d197c0eca5705632d4fe2667d14a6be5df8934f8d74f1978" +"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" +"checksum quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9949cfe66888ffe1d53e6ec9d9f3b70714083854be20fd5e271b232a017401e8" "checksum quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cdd8e04bd9c52e0342b406469d494fcb033be4bdbe5c606016defbb1681411e1" "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" "checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" @@ -983,6 +1245,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" "checksum redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)" = "423e376fffca3dfa06c9e9790a9ccd282fafb3cc6e6397d01dbf64f9bacc6b85" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" +"checksum regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "37e7cbbd370869ce2e8dff25c7018702d10b21a20ef7135316f8daecd6c25b7f" +"checksum regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8c2f35eedad5295fdf00a63d7d4b238135723f92b434ec06774dad15c7ab0861" +"checksum rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "adacaae16d02b6ec37fdc7acfcddf365978de76d1983d3ee22afc260e1ca9619" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" @@ -991,7 +1256,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)" = "534b8b91a95e0f71bca3ed5824752d558da048d4248c91af873b63bd60519752" "checksum serde-bench 0.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "d733da87e79faaac25616e33d26299a41143fd4cd42746cbb0e91d8feea243fd" "checksum serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)" = "adb6e51a6b3696b301bc221d785f898b4457c619b51d7ce195a6d20baecb37b3" -"checksum serde_derive 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)" = "a915306b0f1ac5607797697148c223bedeaa36bcc2e28a01441cd638cc6567b4" +"checksum serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)" = "ac38f51a52a556cd17545798e29536885fb1a3fa63d6399f5ef650f4a7d35901" "checksum serde_json 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)" = "4b90a9fbe1211e57d3e1c15670f1cb00802988fb23a1a4aad7a2b63544f1920e" "checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d" "checksum smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "88aea073965ab29f6edb5493faf96ad662fb18aa9eeb186a3b7057951605ed15" @@ -999,25 +1264,34 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" "checksum structopt 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "670ad348dc73012fcf78c71f06f9d942232cdd4c859d4b6975e27836c3efc0c3" "checksum structopt-derive 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "ef98172b1a00b0bec738508d3726540edcbd186d50dfd326f2b1febbb3559f04" +"checksum syn 0.13.11 (registry+https://github.com/rust-lang/crates.io-index)" = "14f9bf6292f3a61d2c716723fdb789a41bbe104168e6f496dc6497e531ea1b9b" "checksum syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)" = "f92e629aa1d9c827b2bb8297046c1ccffc57c99b947a680d3ccff1f136a3bee9" "checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" "checksum target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4af5e2227f0b887d591d3724b796a96eff04226104d872f5b3883fcd427d64b9" +"checksum termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" "checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6" +"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" "checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" +"checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" "checksum unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa6024fc12ddfd1c6dbc14a80fa2324d4568849869b779f6bd37e5e4c03344d1" "checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" +"checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" +"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" "checksum wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "74e463a508e390cc7447e70f640fbf44ad52e1bd095314ace1fdf99516d32add" "checksum wabt-sys 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a6265b25719e82598d104b3717375e37661d41753e2c84cde3f51050c7ed7e3c" "checksum wasmparser 0.22.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f46e666ecb4a406483a59a49f9d0c17f327e70da53a128eccddae2eadb95865c" "checksum wasmparser 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b5e01c420bc7d36e778bd242e1167b079562ba8b34087122cc9057187026d060" +"checksum which 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b57acb10231b9493c8472b20cb57317d0679a49e0bdbee44b3b803a6473af164" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +"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.1 (registry+https://github.com/rust-lang/crates.io-index)" = "561ed901ae465d6185fa7864d63fbd5720d0ef718366c9a4dc83cf6170d7e9ba" diff --git a/Cargo.toml b/Cargo.toml index b570c9b09..9d96e28cd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,7 +27,7 @@ wasmer-runtime-core = { path = "lib/runtime-core" } wasmer-emscripten = { path = "lib/emscripten" } [workspace] -members = ["lib/clif-backend", "lib/runtime", "lib/runtime-core", "lib/emscripten", "lib/spectests"] +members = ["lib/clif-backend", "lib/runtime", "lib/runtime-core", "lib/emscripten", "lib/spectests", "lib/win-exception-handler"] [build-dependencies] wabt = "0.7.2" diff --git a/README.md b/README.md index 2aae6e086..df4ac0186 100644 --- a/README.md +++ b/README.md @@ -47,10 +47,10 @@ Wasmer is structured into different directories: Building wasmer requires [rustup](https://rustup.rs/). -To install on Windows, download and run [`rustup-init.exe`](https://win.rustup.rs/) +To build on Windows, download and run [`rustup-init.exe`](https://win.rustup.rs/) then follow the onscreen instructions. -To install on other systems, run: +To build on other systems, run: ```sh curl https://sh.rustup.rs -sSf | sh @@ -86,8 +86,8 @@ sudo apt install cmake #### Windows (MSVC) -Right now Windows support is _highly experimental_. -We are working on this so Wasmer can soon be released for Windows. +Windows support is _highly experimental_. Only simple wasm programs may be run, and no syscalls are allowed. This means +nginx and lua do not work on Windows. See [this issue for ongoing Emscripten syscall polyfills for Windows](https://github.com/wasmerio/wasmer/pull/176). 1. Install Python for Windows (https://www.python.org/downloads/release/python-2714/). The Windows x86-64 MSI installer is fine. You should change the installation to install the "Add python.exe to Path" feature. @@ -95,6 +95,8 @@ We are working on this so Wasmer can soon be released for Windows. 2. Install Git for Windows (https://git-scm.com/download/win). DO allow it to add git.exe to the PATH (default settings for the installer are fine). +3. Install CMake (https://cmake.org/download/). Ensure CMake is in the PATH. + ## Building Wasmer is built with [Cargo](https://crates.io/), the Rust package manager. diff --git a/lib/clif-backend/Cargo.toml b/lib/clif-backend/Cargo.toml index 5b565676b..becb71a04 100644 --- a/lib/clif-backend/Cargo.toml +++ b/lib/clif-backend/Cargo.toml @@ -37,6 +37,10 @@ optional = true version = "0.0.7" optional = true +[target.'cfg(windows)'.dependencies] +winapi = { version = "0.3", features = ["errhandlingapi", "minwindef", "minwinbase", "winnt"] } +wasmer-win-exception-handler = { path = "../win-exception-handler", version = "0.0.1" } + [features] cache = ["serde", "serde_derive", "serde_bytes", "serde-bench", "wasmer-runtime-core/cache"] -debug = ["wasmer-runtime-core/debug"] \ No newline at end of file +debug = ["wasmer-runtime-core/debug"] diff --git a/lib/clif-backend/src/resolver.rs b/lib/clif-backend/src/resolver.rs index 91e6102ef..48ea5c7e5 100644 --- a/lib/clif-backend/src/resolver.rs +++ b/lib/clif-backend/src/resolver.rs @@ -223,9 +223,9 @@ impl FuncResolverBuilder { LibCall::TruncF64 => libcalls::truncf64 as isize, LibCall::NearestF64 => libcalls::nearbyintf64 as isize, #[cfg(all(target_pointer_width = "64", target_os = "windows"))] - Probestack => __chkstk as isize, + LibCall::Probestack => __chkstk as isize, #[cfg(not(target_os = "windows"))] - Probestack => __rust_probestack as isize, + LibCall::Probestack => __rust_probestack as isize, }, RelocationType::Intrinsic(ref name) => match name.as_str() { "i32print" => i32_print as isize, diff --git a/lib/clif-backend/src/signal/mod.rs b/lib/clif-backend/src/signal/mod.rs index eab9e62e7..31dbb44dd 100644 --- a/lib/clif-backend/src/signal/mod.rs +++ b/lib/clif-backend/src/signal/mod.rs @@ -110,6 +110,7 @@ impl ProtectedCaller for Caller { .lookup(sig_index) .expect("that trampoline doesn't exist"); + #[cfg(not(target_os = "windows"))] call_protected(&self.handler_data, || unsafe { // Leap of faith. trampoline( @@ -120,6 +121,17 @@ impl ProtectedCaller for Caller { ); })?; + // the trampoline is called from C on windows + #[cfg(target_os = "windows")] + call_protected( + &self.handler_data, + trampoline, + vmctx_ptr, + func_ptr, + param_vec.as_ptr(), + return_vec.as_mut_ptr(), + )?; + Ok(return_vec .iter() .zip(signature.returns().iter()) diff --git a/lib/clif-backend/src/signal/windows.rs b/lib/clif-backend/src/signal/windows.rs index b715c616d..191085d91 100644 --- a/lib/clif-backend/src/signal/windows.rs +++ b/lib/clif-backend/src/signal/windows.rs @@ -1,10 +1,116 @@ +use crate::relocation::{TrapCode, TrapData}; use crate::signal::HandlerData; -use wasmer_runtime_core::error::RuntimeResult; +use crate::trampoline::Trampoline; +use std::cell::Cell; +use std::ffi::c_void; +use std::ptr; +use wasmer_runtime_core::vm::Ctx; +use wasmer_runtime_core::vm::Func; +use wasmer_runtime_core::{ + error::{RuntimeError, RuntimeResult}, + structures::TypedIndex, + types::{MemoryIndex, TableIndex}, +}; +use wasmer_win_exception_handler::CallProtectedData; +pub use wasmer_win_exception_handler::_call_protected; +use winapi::shared::minwindef::DWORD; +use winapi::um::minwinbase::{ + EXCEPTION_ACCESS_VIOLATION, EXCEPTION_FLT_DENORMAL_OPERAND, EXCEPTION_FLT_DIVIDE_BY_ZERO, + EXCEPTION_FLT_INEXACT_RESULT, EXCEPTION_FLT_INVALID_OPERATION, EXCEPTION_FLT_OVERFLOW, + EXCEPTION_FLT_STACK_CHECK, EXCEPTION_FLT_UNDERFLOW, EXCEPTION_ILLEGAL_INSTRUCTION, + EXCEPTION_INT_DIVIDE_BY_ZERO, EXCEPTION_INT_OVERFLOW, EXCEPTION_STACK_OVERFLOW, +}; -pub fn call_protected(handler_data: &HandlerData, f: impl FnOnce() -> T) -> RuntimeResult { - unimplemented!("TODO"); +thread_local! { + pub static CURRENT_EXECUTABLE_BUFFER: Cell<*const c_void> = Cell::new(ptr::null()); +} + +pub fn call_protected( + handler_data: &HandlerData, + trampoline: Trampoline, + ctx: *mut Ctx, + func: *const Func, + param_vec: *const u64, + return_vec: *mut u64, +) -> RuntimeResult<()> { + // TODO: trap early + // user code error + // if let Some(msg) = super::TRAP_EARLY_DATA.with(|cell| cell.replace(None)) { + // return Err(RuntimeError::User { msg }); + // } + + let result = _call_protected(trampoline, ctx, func, param_vec, return_vec); + + if let Ok(_) = result { + return Ok(()); + } + + let CallProtectedData { + code: signum, + exceptionAddress: exception_address, + instructionPointer: instruction_pointer, + } = result.unwrap_err(); + + if let Some(TrapData { + trapcode, + srcloc: _, + }) = handler_data.lookup(instruction_pointer as _) + { + Err(match signum as DWORD { + EXCEPTION_ACCESS_VIOLATION => RuntimeError::OutOfBoundsAccess { + memory: MemoryIndex::new(0), + addr: None, + }, + EXCEPTION_ILLEGAL_INSTRUCTION => match trapcode { + TrapCode::BadSignature => RuntimeError::IndirectCallSignature { + table: TableIndex::new(0), + }, + TrapCode::IndirectCallToNull => RuntimeError::IndirectCallToNull { + table: TableIndex::new(0), + }, + TrapCode::HeapOutOfBounds => RuntimeError::OutOfBoundsAccess { + memory: MemoryIndex::new(0), + addr: None, + }, + TrapCode::TableOutOfBounds => RuntimeError::TableOutOfBounds { + table: TableIndex::new(0), + }, + _ => RuntimeError::Unknown { + msg: "unknown trap".to_string(), + }, + }, + EXCEPTION_STACK_OVERFLOW => RuntimeError::Unknown { + msg: "unknown trap".to_string(), + }, + EXCEPTION_INT_DIVIDE_BY_ZERO => RuntimeError::IllegalArithmeticOperation, + EXCEPTION_INT_OVERFLOW => RuntimeError::IllegalArithmeticOperation, + _ => RuntimeError::Unknown { + msg: "unknown trap".to_string(), + }, + } + .into()) + } else { + let signal = match signum as DWORD { + EXCEPTION_FLT_DENORMAL_OPERAND + | EXCEPTION_FLT_DIVIDE_BY_ZERO + | EXCEPTION_FLT_INEXACT_RESULT + | EXCEPTION_FLT_INVALID_OPERATION + | EXCEPTION_FLT_OVERFLOW + | EXCEPTION_FLT_STACK_CHECK + | EXCEPTION_FLT_UNDERFLOW => "floating-point exception", + EXCEPTION_ILLEGAL_INSTRUCTION => "illegal instruction", + EXCEPTION_ACCESS_VIOLATION => "segmentation violation", + _ => "unkown trapped signal", + }; + + Err(RuntimeError::Unknown { + msg: format!("trap at {} - {}", exception_address, signal), + } + .into()) + } } pub unsafe fn trigger_trap() -> ! { - unimplemented!("TODO"); + // TODO + unimplemented!(); } diff --git a/lib/clif-backend/src/trampoline.rs b/lib/clif-backend/src/trampoline.rs index b9d942ba1..76fb521d6 100644 --- a/lib/clif-backend/src/trampoline.rs +++ b/lib/clif-backend/src/trampoline.rs @@ -7,6 +7,7 @@ use cranelift_codegen::{ isa, Context, }; use hashbrown::HashMap; +use std::ffi::c_void; use std::{iter, mem}; use wasmer_runtime_core::{ backend::sys::{Memory, Protect}, @@ -23,6 +24,9 @@ impl RelocSink for NullRelocSink { fn reloc_jt(&mut self, _: u32, _: Reloc, _: ir::JumpTable) {} } +pub type Trampoline = + unsafe extern "C" fn(*mut vm::Ctx, *const vm::Func, *const u64, *mut u64) -> c_void; + pub struct Trampolines { memory: Memory, offsets: HashMap, @@ -138,10 +142,7 @@ impl Trampolines { } } - pub fn lookup( - &self, - sig_index: SigIndex, - ) -> Option { + pub fn lookup(&self, sig_index: SigIndex) -> Option { let offset = *self.offsets.get(&sig_index)?; let ptr = unsafe { self.memory.as_ptr().add(offset) }; @@ -212,7 +213,9 @@ fn wasm_ty_to_clif(ty: Type) -> ir::types::Type { } fn generate_trampoline_signature() -> ir::Signature { - let mut sig = ir::Signature::new(isa::CallConv::SystemV); + let isa = super::get_isa(); + let call_convention = isa.default_call_conv(); + let mut sig = ir::Signature::new(call_convention); let ptr_param = ir::AbiParam { value_type: ir::types::I64, @@ -227,7 +230,9 @@ fn generate_trampoline_signature() -> ir::Signature { } fn generate_export_signature(func_sig: &FuncSig) -> ir::Signature { - let mut export_clif_sig = ir::Signature::new(isa::CallConv::SystemV); + let isa = super::get_isa(); + let call_convention = isa.default_call_conv(); + let mut export_clif_sig = ir::Signature::new(call_convention); let func_sig_iter = func_sig.params().iter().map(|wasm_ty| ir::AbiParam { value_type: wasm_ty_to_clif(*wasm_ty), diff --git a/lib/runtime-core/src/sys/windows/memory.rs b/lib/runtime-core/src/sys/windows/memory.rs index baf4d27a5..c8fd197eb 100644 --- a/lib/runtime-core/src/sys/windows/memory.rs +++ b/lib/runtime-core/src/sys/windows/memory.rs @@ -150,7 +150,8 @@ impl Drop for Memory { fn drop(&mut self) { if !self.ptr.is_null() { let success = unsafe { VirtualFree(self.ptr as _, self.size, MEM_DECOMMIT) }; - assert_eq!(success, 0, "failed to unmap memory: {}", errno::errno()); + // If the function succeeds, the return value is nonzero. + assert_eq!(success, 1, "failed to unmap memory: {}", errno::errno()); } } } diff --git a/lib/runtime-core/src/vm.rs b/lib/runtime-core/src/vm.rs index 8cb9f0986..faee819be 100644 --- a/lib/runtime-core/src/vm.rs +++ b/lib/runtime-core/src/vm.rs @@ -169,6 +169,7 @@ enum InnerFunc {} /// Used to provide type safety (ish) for passing around function pointers. /// The typesystem ensures this cannot be dereferenced since an /// empty enum cannot actually exist. +#[repr(C)] pub struct Func(InnerFunc); /// An imported function, which contains the vmctx that owns this function. diff --git a/lib/spectests/examples/simple/main.rs b/lib/spectests/examples/simple/main.rs index e418c9abe..029cec1ac 100644 --- a/lib/spectests/examples/simple/main.rs +++ b/lib/spectests/examples/simple/main.rs @@ -1,8 +1,6 @@ -use std::fs::remove_file; use wabt::wat2wasm; use wasmer_clif_backend::CraneliftCompiler; use wasmer_runtime_core::{ - cache::Cache, error, global::Global, memory::Memory, @@ -15,7 +13,6 @@ use wasmer_runtime_core::{ static EXAMPLE_WASM: &'static [u8] = include_bytes!("simple.wasm"); fn main() -> error::Result<()> { - let compiler = CraneliftCompiler::new(); let wasm_binary = wat2wasm(IMPORT_MODULE.as_bytes()).expect("WAST not valid or malformed"); let inner_module = wasmer_runtime_core::compile_with(&wasm_binary, &CraneliftCompiler::new())?; diff --git a/lib/win-exception-handler/Cargo.toml b/lib/win-exception-handler/Cargo.toml new file mode 100644 index 000000000..043dc3c59 --- /dev/null +++ b/lib/win-exception-handler/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "wasmer-win-exception-handler" +version = "0.0.1" +description = "Wasmer runtime exception handling for Windows" +license = "MIT" +authors = ["The Wasmer Engineering Team "] +repository = "https://github.com/wasmerio/wasmer" +edition = "2018" + +[target.'cfg(windows)'.dependencies] +wasmer-runtime-core = { path = "../runtime-core", version = "0.1.2" } +winapi = { version = "0.3", features = ["winbase", "errhandlingapi", "minwindef", "minwinbase", "winnt"] } +libc = "0.2.48" + +[build-dependencies] +cmake = "0.1.35" +bindgen = "0.46.0" +regex = "1.0.6" diff --git a/lib/win-exception-handler/build.rs b/lib/win-exception-handler/build.rs new file mode 100644 index 000000000..7376c6329 --- /dev/null +++ b/lib/win-exception-handler/build.rs @@ -0,0 +1,11 @@ +use cmake::Config; + +fn main() { + #[cfg(target_os = "windows")] + { + let project_name = "exception_handling"; + let dst = Config::new(project_name).build(); + println!("cargo:rustc-link-search=native={}", dst.display()); + println!("cargo:rustc-link-lib=static={}", project_name); + } +} diff --git a/lib/win-exception-handler/exception_handling/.gitignore b/lib/win-exception-handler/exception_handling/.gitignore new file mode 100644 index 000000000..8eee68fef --- /dev/null +++ b/lib/win-exception-handler/exception_handling/.gitignore @@ -0,0 +1 @@ +cmake-build-* diff --git a/lib/win-exception-handler/exception_handling/CMakeLists.txt b/lib/win-exception-handler/exception_handling/CMakeLists.txt new file mode 100644 index 000000000..47376c78f --- /dev/null +++ b/lib/win-exception-handler/exception_handling/CMakeLists.txt @@ -0,0 +1,6 @@ +cmake_minimum_required(VERSION 3.0) +project(exception_handling C) + +add_library(exception_handling STATIC exception_handling.c) + +install(TARGETS exception_handling DESTINATION .) diff --git a/lib/win-exception-handler/exception_handling/exception_handling.c b/lib/win-exception-handler/exception_handling/exception_handling.c new file mode 100644 index 000000000..3284034cc --- /dev/null +++ b/lib/win-exception-handler/exception_handling/exception_handling.c @@ -0,0 +1,74 @@ +#include +#include +#include "exception_handling.h" + +#define CALL_FIRST 1 + +__declspec(thread) jmp_buf jmpBuf; +__declspec(thread) PVOID caughtExceptionAddress; +__declspec(thread) DWORD64 caughtInstructionPointer; +__declspec(thread) PVOID savedStackPointer; +__declspec(thread) BOOL exceptionHandlerInstalled = FALSE; +__declspec(thread) BOOL alreadyHandlingException = FALSE; + +void longjmpOutOfHere() { + longjmp(jmpBuf, 1); +} + +/// Get the current address that we use to jmp, the no inline is important +static __declspec(noinline) void *get_callee_frame_address(void) { + return _AddressOfReturnAddress(); +} + +static LONG WINAPI +exceptionHandler(struct _EXCEPTION_POINTERS *ExceptionInfo) { + EXCEPTION_RECORD* pExceptionRecord = ExceptionInfo->ExceptionRecord; + PCONTEXT pCONTEXT = ExceptionInfo->ContextRecord; + caughtExceptionAddress = pExceptionRecord->ExceptionAddress; + caughtInstructionPointer = pCONTEXT->Rip; + if (alreadyHandlingException == TRUE) { + return EXCEPTION_CONTINUE_SEARCH; + } + alreadyHandlingException = TRUE; + + // Basically, here, we coerce the os to resume us into a context that calls `longjmp` instead of just continuing. + // Presumably, we cannot `longjmp` out of the signal/exception context, like we can on unix. + pCONTEXT->Rip = (uintptr_t)(&longjmpOutOfHere); + pCONTEXT->Rsp = (uintptr_t)(savedStackPointer); + return EXCEPTION_CONTINUE_EXECUTION; +} + +uint8_t callProtected(trampoline_t trampoline, + const struct wasmer_instance_context_t* ctx, + const struct func_t* func, + const uint64_t* param_vec, + uint64_t* return_vec, + struct call_protected_result_t* out_result) { + + // install exception handler + if (exceptionHandlerInstalled == FALSE) { + exceptionHandlerInstalled = TRUE; + AddVectoredExceptionHandler(CALL_FIRST, exceptionHandler); + } + + // jmp jmp jmp! + int signum = setjmp(jmpBuf); + if (signum == 0) { + // save the stack pointer + savedStackPointer = get_callee_frame_address(); + trampoline(ctx, func, param_vec, return_vec); + out_result->code = 0; + out_result->exceptionAddress = 0; + out_result->instructionPointer = 0; + return TRUE; + } + + out_result->code = (uint64_t)signum; + out_result->exceptionAddress = (uint64_t)caughtExceptionAddress; + out_result->instructionPointer = caughtInstructionPointer; + + caughtExceptionAddress = 0; + caughtInstructionPointer = 0; + + return FALSE; +} diff --git a/lib/win-exception-handler/exception_handling/exception_handling.h b/lib/win-exception-handler/exception_handling/exception_handling.h new file mode 100644 index 000000000..cd5472149 --- /dev/null +++ b/lib/win-exception-handler/exception_handling/exception_handling.h @@ -0,0 +1,25 @@ +#ifndef WASMER_EXCEPTION_HANDLING_H +#define WASMER_EXCEPTION_HANDLING_H + +#include + +struct func_t; +struct wasmer_instance_context_t; + +typedef void(*trampoline_t)(struct wasmer_instance_context_t*, const struct func_t*, const uint64_t*, uint64_t*); + +struct call_protected_result_t { + uint64_t code; + uint64_t exceptionAddress; + uint64_t instructionPointer; +}; + +uint8_t callProtected( + trampoline_t trampoline, + const struct wasmer_instance_context_t* ctx, + const struct func_t* func, + const uint64_t* param_vec, + uint64_t* return_vec, + struct call_protected_result_t* out_result); + +#endif //WASMER_EXCEPTION_HANDLING_H diff --git a/lib/win-exception-handler/src/exception_handling.rs b/lib/win-exception-handler/src/exception_handling.rs new file mode 100644 index 000000000..82992e721 --- /dev/null +++ b/lib/win-exception-handler/src/exception_handling.rs @@ -0,0 +1,55 @@ +use std::ffi::c_void; +use wasmer_runtime_core::vm::{Ctx, Func}; + +type Trampoline = unsafe extern "C" fn(*mut Ctx, *const Func, *const u64, *mut u64) -> c_void; +type CallProtectedResult = Result<(), CallProtectedData>; + +#[repr(C)] +pub struct CallProtectedData { + pub code: u64, + pub exceptionAddress: u64, + pub instructionPointer: u64, +} + +extern "C" { + #[link_name = "callProtected"] + pub fn __call_protected( + trampoline: Trampoline, + ctx: *mut Ctx, + func: *const Func, + param_vec: *const u64, + return_vec: *mut u64, + out_result: *mut CallProtectedData, + ) -> u8; +} + +pub fn _call_protected( + trampoline: Trampoline, + ctx: *mut Ctx, + func: *const Func, + param_vec: *const u64, + return_vec: *mut u64, +) -> CallProtectedResult { + let mut out_result = CallProtectedData { + code: 0, + exceptionAddress: 0, + instructionPointer: 0, + }; + let result = unsafe { + __call_protected( + trampoline, + ctx, + func, + param_vec, + return_vec, + &mut out_result, + ) + }; + println!("result from __call_protected: {}", result); + if result == 1 { + Ok(()) + } else { + println!("returning error from _call_protected"); + Err(out_result) + } +} diff --git a/lib/win-exception-handler/src/lib.rs b/lib/win-exception-handler/src/lib.rs new file mode 100644 index 000000000..bc4a142b5 --- /dev/null +++ b/lib/win-exception-handler/src/lib.rs @@ -0,0 +1,5 @@ +#[cfg(windows)] +mod exception_handling; + +#[cfg(windows)] +pub use self::exception_handling::*; diff --git a/src/bin/wasmer.rs b/src/bin/wasmer.rs index 4ebfb76d3..63f6e20e2 100644 --- a/src/bin/wasmer.rs +++ b/src/bin/wasmer.rs @@ -69,7 +69,7 @@ fn execute_wasm(options: &Run) -> Result<(), String> { let module = webassembly::compile(&wasm_binary[..]) .map_err(|e| format!("Can't compile module: {:?}", e))?; - let (_abi, import_object, em_globals) = if wasmer_emscripten::is_emscripten_module(&module) { + let (_abi, import_object, _em_globals) = if wasmer_emscripten::is_emscripten_module(&module) { let mut emscripten_globals = wasmer_emscripten::EmscriptenGlobals::new(&module); ( InstanceABI::Emscripten, From 0c7532b1ba1218b83ff4ca3506ed21c26b250d2b Mon Sep 17 00:00:00 2001 From: Mackenzie Clark Date: Thu, 14 Feb 2019 11:11:35 -0800 Subject: [PATCH 049/262] remove unnecessary print statements (#177) --- lib/win-exception-handler/src/exception_handling.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/win-exception-handler/src/exception_handling.rs b/lib/win-exception-handler/src/exception_handling.rs index 82992e721..04c3c7f2e 100644 --- a/lib/win-exception-handler/src/exception_handling.rs +++ b/lib/win-exception-handler/src/exception_handling.rs @@ -45,11 +45,9 @@ pub fn _call_protected( &mut out_result, ) }; - println!("result from __call_protected: {}", result); if result == 1 { Ok(()) } else { - println!("returning error from _call_protected"); Err(out_result) } } From 8827830aba96b5f9a99cf98f8b94eff2a7e5f6f5 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Thu, 14 Feb 2019 15:13:58 -0800 Subject: [PATCH 050/262] implement load* and store* instructions --- Cargo.lock | 126 ++++---- lib/llvm-backend/src/code.rs | 463 +++++++++++++++++++++++++++-- lib/llvm-backend/src/intrinsics.rs | 334 +++++++++++++++++++-- lib/llvm-backend/src/lib.rs | 19 +- lib/llvm-backend/src/state.rs | 1 + 5 files changed, 811 insertions(+), 132 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6adb5581c..758c7ac56 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3,7 +3,7 @@ name = "aho-corasick" version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "memchr 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -70,7 +70,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cc" -version = "1.0.28" +version = "1.0.29" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -105,7 +105,7 @@ name = "cmake" version = "0.1.35" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -232,7 +232,7 @@ name = "failure_derive" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -249,17 +249,8 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "fuchsia-zircon" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "fuchsia-zircon-sys" -version = "0.3.3" +name = "fuchsia-cprng" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -287,7 +278,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -306,7 +297,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "inkwell" version = "0.1.0" -source = "git+https://github.com/TheDan64/inkwell?branch=llvm7-0#83b9188bad1e098f97e6aad8f6d45becb6d1ccdd" +source = "git+https://github.com/TheDan64/inkwell?branch=llvm7-0#715423bc67f46518ec489343b52455a27c1ff761" dependencies = [ "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "enum-methods 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -318,7 +309,7 @@ dependencies = [ [[package]] name = "inkwell_internal_macros" version = "0.1.0" -source = "git+https://github.com/TheDan64/inkwell?branch=llvm7-0#83b9188bad1e098f97e6aad8f6d45becb6d1ccdd" +source = "git+https://github.com/TheDan64/inkwell?branch=llvm7-0#715423bc67f46518ec489343b52455a27c1ff761" dependencies = [ "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", @@ -346,12 +337,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" version = "0.2.48" -source = "git+https://github.com/rust-lang/libc#42cd3ba27254c423e03f6f4324de57075047f6a0" +source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.48" -source = "registry+https://github.com/rust-lang/crates.io-index" +version = "0.2.49" +source = "git+https://github.com/rust-lang/libc#9a9e2e05c9532557362e5b24b0622259851392fa" [[package]] name = "llvm-backend" @@ -370,7 +361,7 @@ name = "llvm-sys" version = "70.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -396,12 +387,8 @@ dependencies = [ [[package]] name = "memchr" -version = "2.1.3" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "memmap" @@ -418,7 +405,7 @@ version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -430,7 +417,7 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -482,7 +469,7 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "0.4.26" +version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -498,7 +485,7 @@ name = "quote" version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -512,8 +499,8 @@ dependencies = [ "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_jitter 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_os 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -559,7 +546,7 @@ dependencies = [ [[package]] name = "rand_jitter" -version = "0.1.0" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", @@ -569,13 +556,13 @@ dependencies = [ [[package]] name = "rand_os" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (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.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -603,7 +590,7 @@ version = "6.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -634,7 +621,7 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -681,7 +668,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.85" +version = "1.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -690,7 +677,7 @@ version = "0.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -698,27 +685,27 @@ name = "serde_bytes" version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_derive" -version = "1.0.85" +version = "1.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_json" -version = "1.0.37" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -765,7 +752,7 @@ version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -785,7 +772,7 @@ name = "syn" version = "0.15.26" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -803,7 +790,7 @@ name = "synstructure" version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -816,7 +803,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -913,9 +900,9 @@ name = "wabt" version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", "wabt-sys 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -924,7 +911,7 @@ name = "wabt-sys" version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", "cmake 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -954,10 +941,10 @@ dependencies = [ "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "nix 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "serde-bench 0.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-runtime-core 0.1.2", "wasmparser 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -969,7 +956,7 @@ version = "0.1.0" dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (git+https://github.com/rust-lang/libc)", + "libc 0.2.49 (git+https://github.com/rust-lang/libc)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-clif-backend 0.1.2", @@ -999,10 +986,10 @@ dependencies = [ "nix 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "page_size 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "serde-bench 0.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-clif-backend 0.1.2", "wasmparser 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1073,7 +1060,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" "checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" "checksum cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "926013f2860c46252efceabb19f4a6b308197505082c609025aa6706c011d427" -"checksum cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4a8b715cb4597106ea87c7c84b2f1d452c7492033765df7f32651e66fcf749" +"checksum cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)" = "4390a3b5f4f6bce9c1d0c00128379df433e53777fdd30e92f16a529332baec4e" "checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" "checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" @@ -1094,8 +1081,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" "checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" "checksum field-offset 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "64e9bc339e426139e02601fa69d101e96a92aee71b58bc01697ec2a63a5c9e68" -"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" -"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" +"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" "checksum gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)" = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" "checksum generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c0f28c2f5bfb5960175af447a2da7c18900693738343dc896ffbcabd9839592" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" @@ -1107,12 +1093,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1" -"checksum libc 0.2.48 (git+https://github.com/rust-lang/libc)" = "" "checksum libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)" = "e962c7641008ac010fa60a7dfdc1712449f29c44ef2d4702394aea943ee75047" +"checksum libc 0.2.49 (git+https://github.com/rust-lang/libc)" = "" "checksum llvm-sys 70.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60a9ee82fe0fa72ae6ef6d018b407296085863836451c7a97384f84ed7e26b9f" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" -"checksum memchr 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e1dd4eaac298c32ce07eb6ed9242eda7d82955b9170b7d6db59b2e02cc63fcb8" +"checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39" "checksum memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" "checksum nix 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "921f61dc817b379d0834e45d5ec45beaacfae97082090a49c2cf30dcbc30206f" "checksum nix 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46f0f3210768d796e8fa79ec70ee6af172dacbe7147f5e69be5240a47778302b" @@ -1121,7 +1107,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum page_size 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f89ef58b3d32420dbd1a43d2f38ae92f6239ef12bb556ab09ca55445f5a67242" "checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" "checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" -"checksum proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)" = "38fddd23d98b2144d197c0eca5705632d4fe2667d14a6be5df8934f8d74f1978" +"checksum proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" "checksum quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cdd8e04bd9c52e0342b406469d494fcb033be4bdbe5c606016defbb1681411e1" "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" @@ -1130,8 +1116,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" "checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" "checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" -"checksum rand_jitter 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f47842851e13bd803b506bdd1345328e0a1394733ee58e627b5e39332b9afafe" -"checksum rand_os 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f46fbd5550acf75b0c2730f5dd1873751daf9beb8f11b44027778fae50d7feca" +"checksum rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b9ea758282efe12823e0d952ddb269d2e1897227e464919a554f2a03ef1b832" +"checksum rand_os 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b7c690732391ae0abafced5015ffb53656abfaec61b342290e5eb56b286a679d" "checksum rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "086bd09a33c7044e56bb44d5bdde5a60e7f119a9e95b0775f545de759a32fe05" "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" "checksum raw-cpuid 6.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "30a9d219c32c9132f7be513c18be77c9881c7107d2ab5569d205a6a0f0e6dc7d" @@ -1145,11 +1131,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)" = "534b8b91a95e0f71bca3ed5824752d558da048d4248c91af873b63bd60519752" +"checksum serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)" = "2e20fde37801e83c891a2dc4ebd3b81f0da4d1fb67a9e0a2a3b921e2536a58ee" "checksum serde-bench 0.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "d733da87e79faaac25616e33d26299a41143fd4cd42746cbb0e91d8feea243fd" "checksum serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)" = "adb6e51a6b3696b301bc221d785f898b4457c619b51d7ce195a6d20baecb37b3" -"checksum serde_derive 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)" = "a915306b0f1ac5607797697148c223bedeaa36bcc2e28a01441cd638cc6567b4" -"checksum serde_json 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)" = "4b90a9fbe1211e57d3e1c15670f1cb00802988fb23a1a4aad7a2b63544f1920e" +"checksum serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)" = "633e97856567e518b59ffb2ad7c7a4fd4c5d91d9c7f32dd38a27b2bf7e8114ea" +"checksum serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)" = "27dce848e7467aa0e2fcaf0a413641499c0b745452aaca1194d24dedde9e13c9" "checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d" "checksum smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "88aea073965ab29f6edb5493faf96ad662fb18aa9eeb186a3b7057951605ed15" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index e177cc375..fb9e53520 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -3,30 +3,35 @@ use inkwell::{ context::Context, module::Module, passes::PassManager, - types::{BasicType, BasicTypeEnum, FunctionType}, - values::{BasicValue, FunctionValue, PhiValue}, + types::{BasicType, BasicTypeEnum, FunctionType, PointerType}, + values::{BasicValue, FunctionValue, PhiValue, PointerValue}, FloatPredicate, IntPredicate, }; use smallvec::SmallVec; use wasmer_runtime_core::{ + memory::MemoryType, module::ModuleInfo, structures::{Map, SliceMap, TypedIndex}, - types::{FuncIndex, MemoryIndex, FuncSig, LocalFuncIndex, LocalOrImport, SigIndex, Type, MemoryType}, + types::{FuncIndex, FuncSig, LocalFuncIndex, LocalOrImport, MemoryIndex, SigIndex, Type}, +}; +use wasmparser::{ + BinaryReaderError, CodeSectionReader, LocalsReader, MemoryImmediate, Operator, OperatorsReader, }; -use wasmparser::{BinaryReaderError, CodeSectionReader, LocalsReader, Operator, OperatorsReader}; -use crate::intrinsics::Intrinsics; +use crate::intrinsics::{CtxType, Intrinsics}; use crate::read_info::type_to_type; use crate::state::{ControlFrame, IfElseState, State}; fn func_sig_to_llvm(context: &Context, intrinsics: &Intrinsics, sig: &FuncSig) -> FunctionType { let user_param_types = sig.params().iter().map(|&ty| type_to_llvm(intrinsics, ty)); - let param_types: Vec<_> = user_param_types.collect(); + let param_types: Vec<_> = std::iter::once(intrinsics.ctx_ptr_ty.as_basic_type_enum()) + .chain(user_param_types) + .collect(); match sig.returns() { - [] => intrinsics.void_ty.fn_type(¶m_types, false), - [single_value] => type_to_llvm(intrinsics, *single_value).fn_type(¶m_types, false), + &[] => intrinsics.void_ty.fn_type(¶m_types, false), + &[single_value] => type_to_llvm(intrinsics, single_value).fn_type(¶m_types, false), returns @ _ => { let basic_types: Vec<_> = returns .iter() @@ -149,14 +154,22 @@ fn parse_function( state.push_block(return_block, phis); builder.position_at_end(&entry_block); - let mut locals = Vec::with_capacity(locals_reader.get_count() as usize); - locals.extend(function.get_param_iter().enumerate().map(|(index, param)| { - let ty = param.get_type(); + let mut ctx = intrinsics.ctx(info, builder, &function); - let alloca = builder.build_alloca(ty, &format!("local{}", index)); - builder.build_store(alloca, param); - alloca - })); + let mut locals = Vec::with_capacity(locals_reader.get_count() as usize); + locals.extend( + function + .get_param_iter() + .skip(1) + .enumerate() + .map(|(index, param)| { + let ty = param.get_type(); + + let alloca = builder.build_alloca(ty, &format!("local{}", index)); + builder.build_store(alloca, param); + alloca + }), + ); for (index, local) in locals_reader.into_iter().enumerate().skip(locals.len()) { let (_, ty) = local?; @@ -520,11 +533,13 @@ fn parse_function( LocalOrImport::Local(local_func_index) => { let func_sig = &info.signatures[sigindex]; let func_value = functions[local_func_index]; - let call_site = builder.build_call( - func_value, - &state.peekn(func_sig.params().len())?.to_vec(), - &state.var_name(), - ); + let params: Vec<_> = [ctx.basic()] + .iter() + .chain(state.peekn(func_sig.params().len())?.iter()) + .map(|v| *v) + .collect(); + + let call_site = builder.build_call(func_value, ¶ms, &state.var_name()); if let Some(basic_value) = call_site.try_as_basic_value().left() { match func_sig.returns().len() { 1 => state.push1(basic_value), @@ -1179,24 +1194,378 @@ fn parse_function( unimplemented!("waiting on better bitcasting support in inkwell") } + /*************************** + * Load and Store instructions. + * https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#load-and-store-instructions + ***************************/ + Operator::I32Load { memarg } => { + let effective_address = resolve_memory_ptr( + builder, + intrinsics, + &mut state, + &mut ctx, + memarg, + intrinsics.i32_ptr_ty, + )?; + let result = builder.build_load(effective_address, &state.var_name()); + state.push1(result); + } + Operator::I64Load { memarg } => { + let effective_address = resolve_memory_ptr( + builder, + intrinsics, + &mut state, + &mut ctx, + memarg, + intrinsics.i64_ptr_ty, + )?; + let result = builder.build_load(effective_address, &state.var_name()); + state.push1(result); + } + Operator::F32Load { memarg } => { + let effective_address = resolve_memory_ptr( + builder, + intrinsics, + &mut state, + &mut ctx, + memarg, + intrinsics.i32_ptr_ty, + )?; + let result = builder.build_load(effective_address, &state.var_name()); + state.push1(result); + } + Operator::F64Load { memarg } => { + let effective_address = resolve_memory_ptr( + builder, + intrinsics, + &mut state, + &mut ctx, + memarg, + intrinsics.f64_ptr_ty, + )?; + let result = builder.build_load(effective_address, &state.var_name()); + state.push1(result); + } + + Operator::I32Store { memarg } => { + let value = state.pop1()?; + let effective_address = resolve_memory_ptr( + builder, + intrinsics, + &mut state, + &mut ctx, + memarg, + intrinsics.i32_ptr_ty, + )?; + builder.build_store(effective_address, value); + } + Operator::I64Store { memarg } => { + let value = state.pop1()?; + let effective_address = resolve_memory_ptr( + builder, + intrinsics, + &mut state, + &mut ctx, + memarg, + intrinsics.i64_ptr_ty, + )?; + builder.build_store(effective_address, value); + } + Operator::F32Store { memarg } => { + let value = state.pop1()?; + let effective_address = resolve_memory_ptr( + builder, + intrinsics, + &mut state, + &mut ctx, + memarg, + intrinsics.f32_ptr_ty, + )?; + builder.build_store(effective_address, value); + } + Operator::F64Store { memarg } => { + let value = state.pop1()?; + let effective_address = resolve_memory_ptr( + builder, + intrinsics, + &mut state, + &mut ctx, + memarg, + intrinsics.f64_ptr_ty, + )?; + builder.build_store(effective_address, value); + } + + Operator::I32Load8S { memarg } => { + let effective_address = resolve_memory_ptr( + builder, + intrinsics, + &mut state, + &mut ctx, + memarg, + intrinsics.i8_ptr_ty, + )?; + let narrow_result = builder + .build_load(effective_address, &state.var_name()) + .into_int_value(); + let result = + builder.build_int_s_extend(narrow_result, intrinsics.i32_ty, &state.var_name()); + state.push1(result); + } + Operator::I32Load16S { memarg } => { + let effective_address = resolve_memory_ptr( + builder, + intrinsics, + &mut state, + &mut ctx, + memarg, + intrinsics.i16_ptr_ty, + )?; + let narrow_result = builder + .build_load(effective_address, &state.var_name()) + .into_int_value(); + let result = + builder.build_int_s_extend(narrow_result, intrinsics.i32_ty, &state.var_name()); + state.push1(result); + } + Operator::I64Load8S { memarg } => { + let effective_address = resolve_memory_ptr( + builder, + intrinsics, + &mut state, + &mut ctx, + memarg, + intrinsics.i8_ptr_ty, + )?; + let narrow_result = builder + .build_load(effective_address, &state.var_name()) + .into_int_value(); + let result = + builder.build_int_s_extend(narrow_result, intrinsics.i64_ty, &state.var_name()); + state.push1(result); + } + Operator::I64Load16S { memarg } => { + let effective_address = resolve_memory_ptr( + builder, + intrinsics, + &mut state, + &mut ctx, + memarg, + intrinsics.i16_ptr_ty, + )?; + let narrow_result = builder + .build_load(effective_address, &state.var_name()) + .into_int_value(); + let result = + builder.build_int_s_extend(narrow_result, intrinsics.i64_ty, &state.var_name()); + state.push1(result); + } + Operator::I64Load32S { memarg } => { + let effective_address = resolve_memory_ptr( + builder, + intrinsics, + &mut state, + &mut ctx, + memarg, + intrinsics.i32_ptr_ty, + )?; + let narrow_result = builder + .build_load(effective_address, &state.var_name()) + .into_int_value(); + let result = + builder.build_int_s_extend(narrow_result, intrinsics.i64_ty, &state.var_name()); + state.push1(result); + } + + Operator::I32Load8U { memarg } => { + let effective_address = resolve_memory_ptr( + builder, + intrinsics, + &mut state, + &mut ctx, + memarg, + intrinsics.i8_ptr_ty, + )?; + let narrow_result = builder + .build_load(effective_address, &state.var_name()) + .into_int_value(); + let result = + builder.build_int_z_extend(narrow_result, intrinsics.i32_ty, &state.var_name()); + state.push1(result); + } + Operator::I32Load16U { memarg } => { + let effective_address = resolve_memory_ptr( + builder, + intrinsics, + &mut state, + &mut ctx, + memarg, + intrinsics.i16_ptr_ty, + )?; + let narrow_result = builder + .build_load(effective_address, &state.var_name()) + .into_int_value(); + let result = + builder.build_int_z_extend(narrow_result, intrinsics.i32_ty, &state.var_name()); + state.push1(result); + } + Operator::I64Load8U { memarg } => { + let effective_address = resolve_memory_ptr( + builder, + intrinsics, + &mut state, + &mut ctx, + memarg, + intrinsics.i8_ptr_ty, + )?; + let narrow_result = builder + .build_load(effective_address, &state.var_name()) + .into_int_value(); + let result = + builder.build_int_z_extend(narrow_result, intrinsics.i64_ty, &state.var_name()); + state.push1(result); + } + Operator::I64Load16U { memarg } => { + let effective_address = resolve_memory_ptr( + builder, + intrinsics, + &mut state, + &mut ctx, + memarg, + intrinsics.i16_ptr_ty, + )?; + let narrow_result = builder + .build_load(effective_address, &state.var_name()) + .into_int_value(); + let result = + builder.build_int_z_extend(narrow_result, intrinsics.i64_ty, &state.var_name()); + state.push1(result); + } + Operator::I64Load32U { memarg } => { + let effective_address = resolve_memory_ptr( + builder, + intrinsics, + &mut state, + &mut ctx, + memarg, + intrinsics.i32_ptr_ty, + )?; + let narrow_result = builder + .build_load(effective_address, &state.var_name()) + .into_int_value(); + let result = + builder.build_int_z_extend(narrow_result, intrinsics.i64_ty, &state.var_name()); + state.push1(result); + } + + Operator::I32Store8 { memarg } | Operator::I64Store8 { memarg } => { + let value = state.pop1()?.into_int_value(); + let effective_address = resolve_memory_ptr( + builder, + intrinsics, + &mut state, + &mut ctx, + memarg, + intrinsics.i8_ptr_ty, + )?; + let narrow_value = + builder.build_int_truncate(value, intrinsics.i8_ty, &state.var_name()); + builder.build_store(effective_address, narrow_value); + } + Operator::I32Store16 { memarg } | Operator::I64Store16 { memarg } => { + let value = state.pop1()?.into_int_value(); + let effective_address = resolve_memory_ptr( + builder, + intrinsics, + &mut state, + &mut ctx, + memarg, + intrinsics.i16_ptr_ty, + )?; + let narrow_value = + builder.build_int_truncate(value, intrinsics.i16_ty, &state.var_name()); + builder.build_store(effective_address, narrow_value); + } + Operator::I64Store32 { memarg } => { + let value = state.pop1()?.into_int_value(); + let effective_address = resolve_memory_ptr( + builder, + intrinsics, + &mut state, + &mut ctx, + memarg, + intrinsics.i32_ptr_ty, + )?; + let narrow_value = + builder.build_int_truncate(value, intrinsics.i32_ty, &state.var_name()); + builder.build_store(effective_address, narrow_value); + } + Operator::MemoryGrow { reserved } => { - - let memory_grow_const = intrinsics.i32_ty.const_int(reserved as u64, false); - - let memory_index = MemoryIndex::new(reserved); - match memory_index.local_or_import(info) { + let memory_index = MemoryIndex::new(reserved as usize); + let func_value = match memory_index.local_or_import(info) { LocalOrImport::Local(local_mem_index) => { let mem_desc = &info.memories[local_mem_index]; match mem_desc.memory_type() { - MemoryType::Dynamic => { - - } + MemoryType::Dynamic => intrinsics.memory_grow_dynamic_local, + MemoryType::Static => intrinsics.memory_grow_static_local, + MemoryType::SharedStatic => intrinsics.memory_grow_shared_local, } - }, + } LocalOrImport::Import(import_mem_index) => { + let mem_desc = &info.imported_memories[import_mem_index].1; + match mem_desc.memory_type() { + MemoryType::Dynamic => intrinsics.memory_grow_dynamic_import, + MemoryType::Static => intrinsics.memory_grow_static_import, + MemoryType::SharedStatic => intrinsics.memory_grow_shared_import, + } + } + }; - }, - } + let memory_index_const = intrinsics + .i32_ty + .const_int(reserved as u64, false) + .as_basic_value_enum(); + let delta = state.pop1()?; + + let result = builder.build_call( + func_value, + &[ctx.basic(), memory_index_const, delta], + &state.var_name(), + ); + state.push1(result.try_as_basic_value().left().unwrap()); + } + Operator::MemorySize { reserved } => { + let memory_index = MemoryIndex::new(reserved as usize); + let func_value = match memory_index.local_or_import(info) { + LocalOrImport::Local(local_mem_index) => { + let mem_desc = &info.memories[local_mem_index]; + match mem_desc.memory_type() { + MemoryType::Dynamic => intrinsics.memory_size_dynamic_local, + MemoryType::Static => intrinsics.memory_size_static_local, + MemoryType::SharedStatic => intrinsics.memory_size_shared_local, + } + } + LocalOrImport::Import(import_mem_index) => { + let mem_desc = &info.imported_memories[import_mem_index].1; + match mem_desc.memory_type() { + MemoryType::Dynamic => intrinsics.memory_size_dynamic_import, + MemoryType::Static => intrinsics.memory_size_static_import, + MemoryType::SharedStatic => intrinsics.memory_size_shared_import, + } + } + }; + + let memory_index_const = intrinsics + .i32_ty + .const_int(reserved as u64, false) + .as_basic_value_enum(); + let result = builder.build_call( + func_value, + &[ctx.basic(), memory_index_const], + &state.var_name(), + ); + state.push1(result.try_as_basic_value().left().unwrap()); } op @ _ => { @@ -1209,9 +1578,41 @@ fn parse_function( let pass_manager = PassManager::create_for_module(); pass_manager.add_promote_memory_to_register_pass(); pass_manager.add_cfg_simplification_pass(); + pass_manager.add_instruction_combining_pass(); + // pass_manager.add_aggressive_inst_combiner_pass(); + // pass_manager.add_merged_load_store_motion_pass(); + // pass_manager.add_sccp_pass(); + pass_manager.add_gvn_pass(); + pass_manager.add_new_gvn_pass(); + pass_manager.add_aggressive_dce_pass(); pass_manager.run_on_module(module); println!("{}", module.print_to_string().to_string()); Ok(()) } + +fn resolve_memory_ptr( + builder: &Builder, + intrinsics: &Intrinsics, + state: &mut State, + ctx: &mut CtxType, + memarg: MemoryImmediate, + ptr_ty: PointerType, +) -> Result { + // Ignore alignment hint for the time being. + let imm_offset = intrinsics.i64_ty.const_int(memarg.offset as u64, false); + let var_offset_i32 = state.pop1()?.into_int_value(); + let var_offset = + builder.build_int_z_extend(var_offset_i32, intrinsics.i64_ty, &state.var_name()); + let effective_offset = builder.build_int_add(var_offset, imm_offset, &state.var_name()); + let (mem_base, mem_bound) = ctx.memory(MemoryIndex::new(0)); + let mem_base_int = builder.build_ptr_to_int(mem_base, intrinsics.i64_ty, &state.var_name()); + let effective_address_int = + builder.build_int_add(mem_base_int, effective_offset, &state.var_name()); + Ok(builder.build_int_to_ptr( + effective_address_int, + intrinsics.i32_ptr_ty, + &state.var_name(), + )) +} diff --git a/lib/llvm-backend/src/intrinsics.rs b/lib/llvm-backend/src/intrinsics.rs index ff6847b3b..f2e681f38 100644 --- a/lib/llvm-backend/src/intrinsics.rs +++ b/lib/llvm-backend/src/intrinsics.rs @@ -1,8 +1,18 @@ +use hashbrown::HashMap; use inkwell::{ + builder::Builder, context::Context, module::Module, - types::{BasicType, FloatType, IntType, VoidType}, - values::{FloatValue, FunctionValue, IntValue}, + types::{BasicType, FloatType, IntType, PointerType, StructType, VoidType}, + values::{BasicValue, BasicValueEnum, FloatValue, FunctionValue, IntValue, PointerValue}, + AddressSpace, +}; +use std::marker::PhantomData; +use wasmer_runtime_core::{ + memory::MemoryType, + module::ModuleInfo, + structures::TypedIndex, + types::{LocalOrImport, MemoryIndex}, }; pub struct Intrinsics { @@ -44,11 +54,20 @@ pub struct Intrinsics { pub void_ty: VoidType, pub i1_ty: IntType, + pub i8_ty: IntType, + pub i16_ty: IntType, pub i32_ty: IntType, pub i64_ty: IntType, pub f32_ty: FloatType, pub f64_ty: FloatType, + pub i8_ptr_ty: PointerType, + pub i16_ptr_ty: PointerType, + pub i32_ptr_ty: PointerType, + pub i64_ptr_ty: PointerType, + pub f32_ptr_ty: PointerType, + pub f64_ptr_ty: PointerType, + pub i1_zero: IntValue, pub i32_zero: IntValue, pub i64_zero: IntValue, @@ -69,18 +88,30 @@ pub struct Intrinsics { pub memory_size_dynamic_import: FunctionValue, pub memory_size_static_import: FunctionValue, pub memory_size_shared_import: FunctionValue, - // pub ctx_ty: StructType, + + ctx_ty: StructType, + pub ctx_ptr_ty: PointerType, } impl Intrinsics { pub fn declare(module: &Module, context: &Context) -> Self { let void_ty = context.void_type(); let i1_ty = context.bool_type(); + let i8_ty = context.i8_type(); + let i16_ty = context.i16_type(); let i32_ty = context.i32_type(); let i64_ty = context.i64_type(); let f32_ty = context.f32_type(); let f64_ty = context.f64_type(); - // let ctx_ty = context.struct_type(&[], false); + + let i8_ptr_ty = i8_ty.ptr_type(AddressSpace::Generic); + let i16_ptr_ty = i16_ty.ptr_type(AddressSpace::Generic); + let i32_ptr_ty = i32_ty.ptr_type(AddressSpace::Generic); + let i64_ptr_ty = i64_ty.ptr_type(AddressSpace::Generic); + let f32_ptr_ty = f32_ty.ptr_type(AddressSpace::Generic); + let f64_ptr_ty = f64_ty.ptr_type(AddressSpace::Generic); + + let opaque_ptr_ty = void_ty.ptr_type(AddressSpace::Generic); let i1_zero = i1_ty.const_int(0, false); let i32_zero = i32_ty.const_int(0, false); @@ -93,6 +124,53 @@ impl Intrinsics { let i64_ty_basic = i64_ty.as_basic_type_enum(); let f32_ty_basic = f32_ty.as_basic_type_enum(); let f64_ty_basic = f64_ty.as_basic_type_enum(); + let i8_ptr_ty_basic = i8_ptr_ty.as_basic_type_enum(); + let opaque_ptr_ty_basic = opaque_ptr_ty.as_basic_type_enum(); + + let ctx_ty = context.opaque_struct_type("ctx"); + let ctx_ptr_ty = ctx_ty.ptr_type(AddressSpace::Generic); + + let local_memory_ty = + context.struct_type(&[i8_ptr_ty_basic, i64_ty_basic, opaque_ptr_ty_basic], false); + let local_table_ty = local_memory_ty; + let local_global_ty = i64_ty; + let imported_func_ty = context.struct_type( + &[opaque_ptr_ty_basic, ctx_ptr_ty.as_basic_type_enum()], + false, + ); + ctx_ty.set_body( + &[ + local_memory_ty + .ptr_type(AddressSpace::Generic) + .ptr_type(AddressSpace::Generic) + .as_basic_type_enum(), + local_table_ty + .ptr_type(AddressSpace::Generic) + .ptr_type(AddressSpace::Generic) + .as_basic_type_enum(), + local_global_ty + .ptr_type(AddressSpace::Generic) + .ptr_type(AddressSpace::Generic) + .as_basic_type_enum(), + local_memory_ty + .ptr_type(AddressSpace::Generic) + .ptr_type(AddressSpace::Generic) + .as_basic_type_enum(), + local_table_ty + .ptr_type(AddressSpace::Generic) + .ptr_type(AddressSpace::Generic) + .as_basic_type_enum(), + local_global_ty + .ptr_type(AddressSpace::Generic) + .ptr_type(AddressSpace::Generic) + .as_basic_type_enum(), + imported_func_ty + .ptr_type(AddressSpace::Generic) + .ptr_type(AddressSpace::Generic) + .as_basic_type_enum(), + ], + false, + ); let ret_i32_take_i32_i1 = i32_ty.fn_type(&[i32_ty_basic, i1_ty_basic], false); let ret_i64_take_i64_i1 = i64_ty.fn_type(&[i64_ty_basic, i1_ty_basic], false); @@ -106,8 +184,9 @@ impl Intrinsics { let ret_f32_take_f32_f32 = f32_ty.fn_type(&[f32_ty_basic, f32_ty_basic], false); let ret_f64_take_f64_f64 = f64_ty.fn_type(&[f64_ty_basic, f64_ty_basic], false); - let ret_i32_take_i64_i32_i32 = i32_ty.fn_type(&[i64_ty, i32_ty, i32_ty], false); - let ret_i32_take_i64_i32 = i32_ty.fn_type(&[i64_ty, i32_ty], false); + let ret_i32_take_i64_i32_i32 = + i32_ty.fn_type(&[i64_ty_basic, i32_ty_basic, i32_ty_basic], false); + let ret_i32_take_i64_i32 = i32_ty.fn_type(&[i64_ty_basic, i32_ty_basic], false); Self { ctlz_i32: module.add_function("llvm.ctlz.i32", ret_i32_take_i32_i1, None), @@ -148,11 +227,20 @@ impl Intrinsics { void_ty, i1_ty, + i8_ty, + i16_ty, i32_ty, i64_ty, f32_ty, f64_ty, + i8_ptr_ty, + i16_ptr_ty, + i32_ptr_ty, + i64_ptr_ty, + f32_ptr_ty, + f64_ptr_ty, + i1_zero, i32_zero, i64_zero, @@ -160,23 +248,229 @@ impl Intrinsics { f64_zero, // VM intrinsics. - memory_grow_dynamic_local: module.add_function("vm.memory.grow.dynamic.local", ret_i32_take_i64_i32_i32, None), - memory_grow_static_local: module.add_function("vm.memory.grow.static.local", ret_i32_take_i64_i32_i32, None), - memory_grow_shared_local: module.add_function("vm.memory.grow.shared.local", ret_i32_take_i64_i32_i32, None), - memory_grow_dynamic_import: module.add_function("vm.memory.grow.dynamic.import", ret_i32_take_i64_i32_i32, None), - memory_grow_static_import: module.add_function("vm.memory.grow.static.import", ret_i32_take_i64_i32_i32, None), - memory_grow_shared_import: module.add_function("vm.memory.grow.shared.import", ret_i32_take_i64_i32_i32, None), + memory_grow_dynamic_local: module.add_function( + "vm.memory.grow.dynamic.local", + ret_i32_take_i64_i32_i32, + None, + ), + memory_grow_static_local: module.add_function( + "vm.memory.grow.static.local", + ret_i32_take_i64_i32_i32, + None, + ), + memory_grow_shared_local: module.add_function( + "vm.memory.grow.shared.local", + ret_i32_take_i64_i32_i32, + None, + ), + memory_grow_dynamic_import: module.add_function( + "vm.memory.grow.dynamic.import", + ret_i32_take_i64_i32_i32, + None, + ), + memory_grow_static_import: module.add_function( + "vm.memory.grow.static.import", + ret_i32_take_i64_i32_i32, + None, + ), + memory_grow_shared_import: module.add_function( + "vm.memory.grow.shared.import", + ret_i32_take_i64_i32_i32, + None, + ), - memory_size_dynamic_local: module.add_function("vm.memory.size.dynamic.local", ret_i32_take_i64_i32, None), - memory_size_static_local: module.add_function("vm.memory.size.static.local", ret_i32_take_i64_i32, None), - memory_size_shared_local: module.add_function("vm.memory.size.shared.local", ret_i32_take_i64_i32, None), - memory_size_dynamic_import: module.add_function("vm.memory.size.dynamic.import", ret_i32_take_i64_i32, None), - memory_size_static_import: module.add_function("vm.memory.size.static.import", ret_i32_take_i64_i32, None), - memory_size_shared_import: module.add_function("vm.memory.size.shared.import", ret_i32_take_i64_i32, None), + memory_size_dynamic_local: module.add_function( + "vm.memory.size.dynamic.local", + ret_i32_take_i64_i32, + None, + ), + memory_size_static_local: module.add_function( + "vm.memory.size.static.local", + ret_i32_take_i64_i32, + None, + ), + memory_size_shared_local: module.add_function( + "vm.memory.size.shared.local", + ret_i32_take_i64_i32, + None, + ), + memory_size_dynamic_import: module.add_function( + "vm.memory.size.dynamic.import", + ret_i32_take_i64_i32, + None, + ), + memory_size_static_import: module.add_function( + "vm.memory.size.static.import", + ret_i32_take_i64_i32, + None, + ), + memory_size_shared_import: module.add_function( + "vm.memory.size.shared.import", + ret_i32_take_i64_i32, + None, + ), + + ctx_ty, + ctx_ptr_ty, + } + } + + pub fn ctx<'a>( + &'a self, + info: &'a ModuleInfo, + builder: &'a Builder, + func_value: &'a FunctionValue, + ) -> CtxType<'a> { + CtxType { + ctx_ty: self.ctx_ty, + ctx_ptr_ty: self.ctx_ptr_ty, + + ctx_ptr_value: func_value.get_nth_param(0).unwrap().into_pointer_value(), + + builder, + intrinsics: self, + info, + + cached_memories: HashMap::new(), + + _phantom: PhantomData, } } } -// pub struct CtxType { -// ctx_ty: StructType, +enum MemoryCache { + /// The memory moves around. + Dynamic { + ptr_to_base_ptr: PointerValue, + ptr_to_bounds: PointerValue, + }, + /// The memory is always in the same place. + Static { + base_ptr: PointerValue, + bounds: IntValue, + }, +} + +pub struct CtxType<'a> { + ctx_ty: StructType, + ctx_ptr_ty: PointerType, + + ctx_ptr_value: PointerValue, + + builder: &'a Builder, + intrinsics: &'a Intrinsics, + info: &'a ModuleInfo, + + cached_memories: HashMap, + + _phantom: PhantomData<&'a FunctionValue>, +} + +impl<'a> CtxType<'a> { + pub fn basic(&self) -> BasicValueEnum { + self.ctx_ptr_value.as_basic_value_enum() + } + + pub fn memory(&mut self, index: MemoryIndex) -> (PointerValue, IntValue) { + let (cached_memories, builder, info, ctx_ptr_value, intrinsics) = ( + &mut self.cached_memories, + self.builder, + self.info, + self.ctx_ptr_value, + self.intrinsics, + ); + + let memory_cache = cached_memories.entry(index).or_insert_with(|| { + let (memory_array_ptr_ptr, index, memory_type) = match index.local_or_import(info) { + LocalOrImport::Local(local_mem_index) => ( + unsafe { builder.build_struct_gep(ctx_ptr_value, 0, "memory_array_ptr_ptr") }, + local_mem_index.index() as u64, + info.memories[local_mem_index].memory_type(), + ), + LocalOrImport::Import(import_mem_index) => ( + unsafe { builder.build_struct_gep(ctx_ptr_value, 3, "memory_array_ptr_ptr") }, + import_mem_index.index() as u64, + info.imported_memories[import_mem_index].1.memory_type(), + ), + }; + + let memory_array_ptr = builder + .build_load(memory_array_ptr_ptr, "memory_array_ptr") + .into_pointer_value(); + let const_index = intrinsics.i32_ty.const_int(index, false); + let memory_ptr_ptr = unsafe { + builder.build_in_bounds_gep(memory_array_ptr, &[const_index], "memory_ptr_ptr") + }; + let memory_ptr = builder + .build_load(memory_ptr_ptr, "memory_ptr") + .into_pointer_value(); + + let (ptr_to_base_ptr, ptr_to_bounds) = unsafe { + ( + builder.build_struct_gep(memory_ptr, 0, "base_ptr"), + builder.build_struct_gep(memory_ptr, 1, "bounds_ptr"), + ) + }; + + match memory_type { + MemoryType::Dynamic => MemoryCache::Dynamic { + ptr_to_base_ptr, + ptr_to_bounds, + }, + MemoryType::Static | MemoryType::SharedStatic => MemoryCache::Static { + base_ptr: builder + .build_load(ptr_to_base_ptr, "base") + .into_pointer_value(), + bounds: builder.build_load(ptr_to_bounds, "bounds").into_int_value(), + }, + } + }); + + match memory_cache { + MemoryCache::Dynamic { + ptr_to_base_ptr, + ptr_to_bounds, + } => { + let base = builder + .build_load(*ptr_to_base_ptr, "base") + .into_pointer_value(); + let bounds = builder + .build_load(*ptr_to_bounds, "bounds") + .into_int_value(); + + (base, bounds) + } + MemoryCache::Static { base_ptr, bounds } => (*base_ptr, *bounds), + } + } +} + +// pub struct Ctx { +// /// A pointer to an array of locally-defined memories, indexed by `MemoryIndex`. +// pub(crate) memories: *mut *mut LocalMemory, + +// /// A pointer to an array of locally-defined tables, indexed by `TableIndex`. +// pub(crate) tables: *mut *mut LocalTable, + +// /// A pointer to an array of locally-defined globals, indexed by `GlobalIndex`. +// pub(crate) globals: *mut *mut LocalGlobal, + +// /// A pointer to an array of imported memories, indexed by `MemoryIndex, +// pub(crate) imported_memories: *mut *mut LocalMemory, + +// /// A pointer to an array of imported tables, indexed by `TableIndex`. +// pub(crate) imported_tables: *mut *mut LocalTable, + +// /// A pointer to an array of imported globals, indexed by `GlobalIndex`. +// pub(crate) imported_globals: *mut *mut LocalGlobal, + +// /// A pointer to an array of imported functions, indexed by `FuncIndex`. +// pub(crate) imported_funcs: *mut ImportedFunc, + +// local_backing: *mut LocalBacking, +// import_backing: *mut ImportBacking, +// module: *const ModuleInner, + +// pub data: *mut c_void, +// pub data_finalizer: Option, // } diff --git a/lib/llvm-backend/src/lib.rs b/lib/llvm-backend/src/lib.rs index b02b39cbf..e691acebb 100644 --- a/lib/llvm-backend/src/lib.rs +++ b/lib/llvm-backend/src/lib.rs @@ -34,19 +34,16 @@ fn test_read_module() { (module (type $t0 (func (param i32) (result i32))) (type $t1 (func (result i32))) + (memory 1) (func $foo (type $t0) (param i32) (result i32) get_local 0 - (if - (then - i32.const 42 - set_local 0 - ) - (else - i32.const 24 - set_local 0 - ) - ) - get_local 0 + i32.load offset=16 + i32.const 1 + memory.grow + drop + i32.const 0 + i32.load offset=4 + i32.add )) "#; let wasm = wat2wasm(wat).unwrap(); diff --git a/lib/llvm-backend/src/state.rs b/lib/llvm-backend/src/state.rs index 674eee04c..47da54a6d 100644 --- a/lib/llvm-backend/src/state.rs +++ b/lib/llvm-backend/src/state.rs @@ -72,6 +72,7 @@ pub struct State { stack: Vec, control_stack: Vec, value_counter: Cell, + pub reachable: bool, } From 5948fa1d203a757abb9f43bccd30a2cc6172759f Mon Sep 17 00:00:00 2001 From: Mackenzie Clark Date: Thu, 14 Feb 2019 15:30:42 -0800 Subject: [PATCH 051/262] Fix/windows installer (#178) --- .appveyor.yml | 30 ++++++++++++++----- installer/wasmer.iss | 71 ++++++++++++++++++++++++++++++++++++++++++++ src/bin/wasmer.rs | 5 ++++ 3 files changed, 98 insertions(+), 8 deletions(-) create mode 100644 installer/wasmer.iss diff --git a/.appveyor.yml b/.appveyor.yml index 5da647f54..16432ed6b 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -1,11 +1,10 @@ -branches: - except: - - master - version: "{build} ~ {branch}" os: Visual Studio 2017 +# Do not build feature branch with open Pull Requests +skip_branch_with_pr: true + environment: matrix: - CHANNEL: stable @@ -20,10 +19,6 @@ install: - rustc -vV - cargo -vV -artifacts: - - path: target\debug\wasmer.exe - name: wasmer.exe - build_script: - cargo build --verbose @@ -31,3 +26,22 @@ test_script: - set RUST_BACKTRACE=1 - cd ./lib/spectests && cargo test -- --test-threads 1 && cd ../.. +before_deploy: + - cd installer + - iscc wasmer.iss + - copy /y .\WasmerInstaller.exe ..\WasmerInstaller-%APPVEYOR_REPO_TAG_NAME%.exe + - appveyor PushArtifact WasmerInstaller-%APPVEYOR_REPO_TAG_NAME%.exe + +artifacts: + - path: WasmerInstaller-%APPVEYOR_REPO_TAG_NAME%.exe + name: WasmerInstaller.exe + +deploy: + description: 'WasmerInstaller' + artifact: /.*\.exe/ + auth_token: + secure: CaKtncy7S1PWxzDUQ0p2264pe3HwxzDn5VIyRizDaa72/SVfskNcoMjwwRh0ut22 + provider: GitHub + on: + branch: master + appveyor_repo_tag: true diff --git a/installer/wasmer.iss b/installer/wasmer.iss new file mode 100644 index 000000000..04850eb7a --- /dev/null +++ b/installer/wasmer.iss @@ -0,0 +1,71 @@ +[Setup] +AppName=Wasmer +AppVersion=1.5 +DefaultDirName={pf}\Wasmer +DefaultGroupName=Wasmer +Compression=lzma2 +SolidCompression=yes +OutputDir=.\ +DisableProgramGroupPage=yes +ChangesEnvironment=yes +OutputBaseFilename=WasmerInstaller + +[Files] +Source: "..\target\release\wasmer.exe"; DestDir: "{app}\bin" + +[Code] +const EnvironmentKey = 'SYSTEM\CurrentControlSet\Control\Session Manager\Environment'; + +procedure EnvAddPath(Path: string); +var + Paths: string; +begin + { Retrieve current path (use empty string if entry not exists) } + if not RegQueryStringValue(HKEY_LOCAL_MACHINE, EnvironmentKey, 'Path', Paths) + then Paths := ''; + + { Skip if string already found in path } + if Pos(';' + Uppercase(Path) + ';', ';' + Uppercase(Paths) + ';') > 0 then exit; + + { App string to the end of the path variable } + Paths := Paths + ';'+ Path +';' + + { Overwrite (or create if missing) path environment variable } + if RegWriteStringValue(HKEY_LOCAL_MACHINE, EnvironmentKey, 'Path', Paths) + then Log(Format('The [%s] added to PATH: [%s]', [Path, Paths])) + else Log(Format('Error while adding the [%s] to PATH: [%s]', [Path, Paths])); +end; + +procedure EnvRemovePath(Path: string); +var + Paths: string; + P: Integer; +begin + { Skip if registry entry not exists } + if not RegQueryStringValue(HKEY_LOCAL_MACHINE, EnvironmentKey, 'Path', Paths) then + exit; + + { Skip if string not found in path } + P := Pos(';' + Uppercase(Path) + ';', ';' + Uppercase(Paths) + ';'); + if P = 0 then exit; + + { Update path variable } + Delete(Paths, P - 1, Length(Path) + 1); + + { Overwrite path environment variable } + if RegWriteStringValue(HKEY_LOCAL_MACHINE, EnvironmentKey, 'Path', Paths) + then Log(Format('The [%s] removed from PATH: [%s]', [Path, Paths])) + else Log(Format('Error while removing the [%s] from PATH: [%s]', [Path, Paths])); +end; + +procedure CurStepChanged(CurStep: TSetupStep); +begin + if CurStep = ssPostInstall + then EnvAddPath(ExpandConstant('{app}') +'\bin'); +end; + +procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep); +begin + if CurUninstallStep = usPostUninstall + then EnvRemovePath(ExpandConstant('{app}') +'\bin'); +end; \ No newline at end of file diff --git a/src/bin/wasmer.rs b/src/bin/wasmer.rs index 63f6e20e2..2ec707f83 100644 --- a/src/bin/wasmer.rs +++ b/src/bin/wasmer.rs @@ -113,6 +113,11 @@ fn main() { let options = CLIOptions::from_args(); match options { CLIOptions::Run(options) => run(options), + #[cfg(not(target_os = "windows"))] CLIOptions::SelfUpdate => update::self_update(), + #[cfg(target_os = "windows")] + CLIOptions::SelfUpdate => { + println!("Self update is not supported on Windows. Use install instructions on the Wasmer homepage: https://wasmer.io"); + } } } From 73b4f7d33796a3318968752ae792e0e54e666531 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Thu, 14 Feb 2019 18:08:20 -0800 Subject: [PATCH 052/262] Implement memory and global operations --- Cargo.lock | 1358 ++++++++++++++++++++++++++++ lib/llvm-backend/src/code.rs | 171 +++- lib/llvm-backend/src/intrinsics.rs | 190 +++- lib/llvm-backend/src/lib.rs | 11 +- 4 files changed, 1665 insertions(+), 65 deletions(-) create mode 100644 Cargo.lock diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 000000000..065209f0b --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,1358 @@ +[[package]] +name = "aho-corasick" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ansi_term" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "atty" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "autocfg" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "backtrace" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "backtrace-sys" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "bindgen" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cexpr 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "clang-sys 0.26.4 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "which 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "bitflags" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "block-buffer" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-padding 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "block-padding" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "byte-tools" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "byteorder" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "cast" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "cc" +version = "1.0.29" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "cexpr" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "nom 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cfg-if" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "clang-sys" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "clap" +version = "2.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cloudabi" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cmake" +version = "0.1.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cranelift-bforest" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cranelift-entity 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cranelift-codegen" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cranelift-bforest 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-codegen-meta 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-entity 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cranelift-codegen-meta" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cranelift-entity 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cranelift-entity" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "cranelift-frontend" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cranelift-codegen 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cranelift-native" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cranelift-codegen 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "raw-cpuid 6.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cranelift-wasm" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-codegen 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-entity 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-frontend 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmparser 0.22.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "digest" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "either" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "enum-methods" +version = "0.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "env_logger" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "errno" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "errno-dragonfly 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "failure" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "failure_derive" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", + "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "fake-simd" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "field-offset" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "fuchsia-cprng" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "gcc" +version = "0.3.55" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "generic-array" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "glob" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "hashbrown" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "heck" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "humantime" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "indexmap" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "inkwell" +version = "0.1.0" +source = "git+https://github.com/TheDan64/inkwell?branch=llvm7-0#715423bc67f46518ec489343b52455a27c1ff761" +dependencies = [ + "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "enum-methods 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "inkwell_internal_macros 0.1.0 (git+https://github.com/TheDan64/inkwell?branch=llvm7-0)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "llvm-sys 70.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "inkwell_internal_macros" +version = "0.1.0" +source = "git+https://github.com/TheDan64/inkwell?branch=llvm7-0#715423bc67f46518ec489343b52455a27c1ff761" +dependencies = [ + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "itoa" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "kernel32-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "lazy_static" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "libc" +version = "0.2.48" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "libc" +version = "0.2.49" +source = "git+https://github.com/rust-lang/libc#9a9e2e05c9532557362e5b24b0622259851392fa" + +[[package]] +name = "libloading" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "llvm-backend" +version = "0.1.0" +dependencies = [ + "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "inkwell 0.1.0 (git+https://github.com/TheDan64/inkwell?branch=llvm7-0)", + "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmer-runtime-core 0.1.2", + "wasmparser 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "llvm-sys" +version = "70.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "lock_api" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "log" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "memchr" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "memmap" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "nix" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "nix" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "nom" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "opaque-debug" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "owning_ref" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "page_size" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parking_lot" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parking_lot_core" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "peeking_take_while" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "proc-macro2" +version = "0.4.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "quick-error" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "quote" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "quote" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_chacha" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_core" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rand_hc" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_isaac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_jitter" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_os" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (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.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_pcg" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_xorshift" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "raw-cpuid" +version = "6.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rdrand" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "redox_syscall" +version = "0.1.51" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "redox_termios" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "regex" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "regex-syntax" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ryu" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "scopeguard" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "serde" +version = "1.0.87" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "serde-bench" +version = "0.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_bytes" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_derive" +version = "1.0.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_json" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "sha2" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-buffer 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "smallvec" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "stable_deref_trait" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "strsim" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "structopt" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", + "structopt-derive 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "structopt-derive" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "syn" +version = "0.11.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "syn" +version = "0.15.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "synom" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "synstructure" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "target-lexicon" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "termcolor" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "termion" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "textwrap" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "thread_local" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "time" +version = "0.1.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "typenum" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "ucd-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unicode-segmentation" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unicode-width" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unicode-xid" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unicode-xid" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unreachable" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "utf8-ranges" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "vec_map" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "version_check" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "wabt" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", + "wabt-sys 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wabt-sys" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "cmake 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", + "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasmer" +version = "0.1.4" +dependencies = [ + "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "structopt 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", + "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmer-clif-backend 0.1.2", + "wasmer-emscripten 0.1.0", + "wasmer-runtime 0.1.4", + "wasmer-runtime-core 0.1.2", +] + +[[package]] +name = "wasmer-clif-backend" +version = "0.1.2" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-codegen 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-entity 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-native 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-wasm 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "nix 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde-bench 0.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmer-runtime-core 0.1.2", + "wasmer-win-exception-handler 0.0.1", + "wasmparser 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasmer-emscripten" +version = "0.1.0" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (git+https://github.com/rust-lang/libc)", + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmer-clif-backend 0.1.2", + "wasmer-runtime-core 0.1.2", +] + +[[package]] +name = "wasmer-runtime" +version = "0.1.4" +dependencies = [ + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmer-clif-backend 0.1.2", + "wasmer-runtime-core 0.1.2", +] + +[[package]] +name = "wasmer-runtime-core" +version = "0.1.2" +dependencies = [ + "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)", + "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "nix 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "page_size 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde-bench 0.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmer-clif-backend 0.1.2", + "wasmparser 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasmer-spectests" +version = "0.1.2" +dependencies = [ + "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmer-clif-backend 0.1.2", + "wasmer-runtime-core 0.1.2", +] + +[[package]] +name = "wasmer-win-exception-handler" +version = "0.0.1" +dependencies = [ + "bindgen 0.46.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cmake 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmer-runtime-core 0.1.2", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasmparser" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "wasmparser" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "wasmparser" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "which" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winapi" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winapi-build" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-util" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "wincolor" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[metadata] +"checksum aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1e9a933f4e58658d7b12defcf96dc5c720f20832deebe3e0a19efd3b6aaeeb9e" +"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" +"checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" +"checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799" +"checksum backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "b5b493b66e03090ebc4343eb02f94ff944e0cbc9ac6571491d170ba026741eb5" +"checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6" +"checksum bindgen 0.46.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8f7f7f0701772b17de73e4f5cbcb1dd6926f4706cba4c1ab62c5367f8bdc94e1" +"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" +"checksum block-buffer 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49665c62e0e700857531fa5d3763e91b539ff1abeebd56808d378b495870d60d" +"checksum block-padding 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d75255892aeb580d3c566f213a2b6fdc1c66667839f45719ee1d30ebf2aea591" +"checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" +"checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" +"checksum cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "926013f2860c46252efceabb19f4a6b308197505082c609025aa6706c011d427" +"checksum cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)" = "4390a3b5f4f6bce9c1d0c00128379df433e53777fdd30e92f16a529332baec4e" +"checksum cexpr 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "644d693ecfa91955ed32dcc7eda4914e1be97a641fb6f0645a37348e20b230da" +"checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" +"checksum clang-sys 0.26.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6ef0c1bcf2e99c649104bd7a7012d8f8802684400e03db0ec0af48583c6fa0e4" +"checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e" +"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" +"checksum cmake 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "6ec65ee4f9c9d16f335091d23693457ed4928657ba4982289d7fafee03bc614a" +"checksum cranelift-bforest 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "40f8ff24e9a6c89b8a846b14df9a34d2cac17cea7bdb5c81ed6b4744ee0e38bf" +"checksum cranelift-codegen 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "42f5b809bd885c368e01aeec8fe04f21dcb07569834b907d75b4a7bed8d067eb" +"checksum cranelift-codegen-meta 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "014c23ed3ebdc8377d41540af638245207dd169f421df042dfccc867465734ed" +"checksum cranelift-entity 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4df40e26c0cf7b4d86919cb995bb412ee3001cc18e4f3c83a903f30b7007d8b" +"checksum cranelift-frontend 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "789907218eeebebcea8122c2053d71affac91c96ce72cea35ebfdbbf547e82af" +"checksum cranelift-native 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "474bee81d620a473bf43411a3d6f10ffbf7965141dc5e5b76d8d2151dde3285d" +"checksum cranelift-wasm 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49723365dab9a48b354bdc24cb6d9d5719bc1d3b858ffd2ea179d0d7d885804a" +"checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c" +"checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0" +"checksum enum-methods 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7798e7da2d4cb0d6d6fc467e8d6b5bf247e9e989f786dde1732d79899c32bb10" +"checksum env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "afb070faf94c85d17d50ca44f6ad076bce18ae92f0037d350947240a36e9d42e" +"checksum errno 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c2a071601ed01b988f896ab14b95e67335d1eeb50190932a1320f7fe3cadc84e" +"checksum errno-dragonfly 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "14ca354e36190500e1e1fb267c647932382b54053c50b14970856c0b00a35067" +"checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" +"checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" +"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" +"checksum field-offset 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "64e9bc339e426139e02601fa69d101e96a92aee71b58bc01697ec2a63a5c9e68" +"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" +"checksum gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)" = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" +"checksum generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c0f28c2f5bfb5960175af447a2da7c18900693738343dc896ffbcabd9839592" +"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" +"checksum hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3bae29b6653b3412c2e71e9d486db9f9df5d701941d86683005efb9f2d28e3da" +"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" +"checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114" +"checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d" +"checksum inkwell 0.1.0 (git+https://github.com/TheDan64/inkwell?branch=llvm7-0)" = "" +"checksum inkwell_internal_macros 0.1.0 (git+https://github.com/TheDan64/inkwell?branch=llvm7-0)" = "" +"checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" +"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +"checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1" +"checksum libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)" = "e962c7641008ac010fa60a7dfdc1712449f29c44ef2d4702394aea943ee75047" +"checksum libc 0.2.49 (git+https://github.com/rust-lang/libc)" = "" +"checksum libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3ad660d7cb8c5822cd83d10897b0f1f1526792737a179e73896152f85b88c2" +"checksum llvm-sys 70.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60a9ee82fe0fa72ae6ef6d018b407296085863836451c7a97384f84ed7e26b9f" +"checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" +"checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" +"checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39" +"checksum memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" +"checksum nix 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "921f61dc817b379d0834e45d5ec45beaacfae97082090a49c2cf30dcbc30206f" +"checksum nix 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46f0f3210768d796e8fa79ec70ee6af172dacbe7147f5e69be5240a47778302b" +"checksum nom 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b30adc557058ce00c9d0d7cb3c6e0b5bc6f36e2e2eabe74b0ba726d194abd588" +"checksum opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "93f5bb2e8e8dec81642920ccff6b61f1eb94fa3020c5a325c9851ff604152409" +"checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" +"checksum page_size 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f89ef58b3d32420dbd1a43d2f38ae92f6239ef12bb556ab09ca55445f5a67242" +"checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" +"checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" +"checksum peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" +"checksum proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915" +"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" +"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" +"checksum quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cdd8e04bd9c52e0342b406469d494fcb033be4bdbe5c606016defbb1681411e1" +"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" +"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" +"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +"checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" +"checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" +"checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" +"checksum rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b9ea758282efe12823e0d952ddb269d2e1897227e464919a554f2a03ef1b832" +"checksum rand_os 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b7c690732391ae0abafced5015ffb53656abfaec61b342290e5eb56b286a679d" +"checksum rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "086bd09a33c7044e56bb44d5bdde5a60e7f119a9e95b0775f545de759a32fe05" +"checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" +"checksum raw-cpuid 6.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "30a9d219c32c9132f7be513c18be77c9881c7107d2ab5569d205a6a0f0e6dc7d" +"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" +"checksum redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)" = "423e376fffca3dfa06c9e9790a9ccd282fafb3cc6e6397d01dbf64f9bacc6b85" +"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" +"checksum regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "37e7cbbd370869ce2e8dff25c7018702d10b21a20ef7135316f8daecd6c25b7f" +"checksum regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8c2f35eedad5295fdf00a63d7d4b238135723f92b434ec06774dad15c7ab0861" +"checksum rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "adacaae16d02b6ec37fdc7acfcddf365978de76d1983d3ee22afc260e1ca9619" +"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +"checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7" +"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" +"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" +"checksum serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)" = "2e20fde37801e83c891a2dc4ebd3b81f0da4d1fb67a9e0a2a3b921e2536a58ee" +"checksum serde-bench 0.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "d733da87e79faaac25616e33d26299a41143fd4cd42746cbb0e91d8feea243fd" +"checksum serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)" = "adb6e51a6b3696b301bc221d785f898b4457c619b51d7ce195a6d20baecb37b3" +"checksum serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)" = "633e97856567e518b59ffb2ad7c7a4fd4c5d91d9c7f32dd38a27b2bf7e8114ea" +"checksum serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)" = "27dce848e7467aa0e2fcaf0a413641499c0b745452aaca1194d24dedde9e13c9" +"checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d" +"checksum smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "88aea073965ab29f6edb5493faf96ad662fb18aa9eeb186a3b7057951605ed15" +"checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" +"checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" +"checksum structopt 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "670ad348dc73012fcf78c71f06f9d942232cdd4c859d4b6975e27836c3efc0c3" +"checksum structopt-derive 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "ef98172b1a00b0bec738508d3726540edcbd186d50dfd326f2b1febbb3559f04" +"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" +"checksum syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)" = "f92e629aa1d9c827b2bb8297046c1ccffc57c99b947a680d3ccff1f136a3bee9" +"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" +"checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" +"checksum target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4af5e2227f0b887d591d3724b796a96eff04226104d872f5b3883fcd427d64b9" +"checksum termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f" +"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" +"checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6" +"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" +"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" +"checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" +"checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" +"checksum unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa6024fc12ddfd1c6dbc14a80fa2324d4568849869b779f6bd37e5e4c03344d1" +"checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" +"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" +"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" +"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" +"checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737" +"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" +"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" +"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" +"checksum wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "74e463a508e390cc7447e70f640fbf44ad52e1bd095314ace1fdf99516d32add" +"checksum wabt-sys 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a6265b25719e82598d104b3717375e37661d41753e2c84cde3f51050c7ed7e3c" +"checksum wasmparser 0.22.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f46e666ecb4a406483a59a49f9d0c17f327e70da53a128eccddae2eadb95865c" +"checksum wasmparser 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b5e01c420bc7d36e778bd242e1167b079562ba8b34087122cc9057187026d060" +"checksum wasmparser 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)" = "40f426b1929bd26517fb10702e2a8e520d1845c49567aa4d244f426f10b206c1" +"checksum which 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b57acb10231b9493c8472b20cb57317d0679a49e0bdbee44b3b803a6473af164" +"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" +"checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" +"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" +"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +"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.1 (registry+https://github.com/rust-lang/crates.io-index)" = "561ed901ae465d6185fa7864d63fbd5720d0ef718366c9a4dc83cf6170d7e9ba" diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index fb9e53520..48aac8dc2 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -5,20 +5,22 @@ use inkwell::{ passes::PassManager, types::{BasicType, BasicTypeEnum, FunctionType, PointerType}, values::{BasicValue, FunctionValue, PhiValue, PointerValue}, - FloatPredicate, IntPredicate, + AddressSpace, FloatPredicate, IntPredicate, }; use smallvec::SmallVec; use wasmer_runtime_core::{ memory::MemoryType, module::ModuleInfo, structures::{Map, SliceMap, TypedIndex}, - types::{FuncIndex, FuncSig, LocalFuncIndex, LocalOrImport, MemoryIndex, SigIndex, Type}, + types::{ + FuncIndex, FuncSig, GlobalIndex, LocalFuncIndex, LocalOrImport, MemoryIndex, SigIndex, Type, + }, }; use wasmparser::{ BinaryReaderError, CodeSectionReader, LocalsReader, MemoryImmediate, Operator, OperatorsReader, }; -use crate::intrinsics::{CtxType, Intrinsics}; +use crate::intrinsics::{CtxType, GlobalCache, Intrinsics}; use crate::read_info::type_to_type; use crate::state::{ControlFrame, IfElseState, State}; @@ -515,8 +517,32 @@ fn parse_function( builder.build_store(pointer_value, v); } - Operator::GetGlobal { global_index } => unimplemented!(), - Operator::SetGlobal { global_index } => unimplemented!(), + Operator::GetGlobal { global_index } => { + let index = GlobalIndex::new(global_index as usize); + let global_cache = ctx.global_cache(index); + match global_cache { + GlobalCache::Const { value } => { + state.push1(value.as_basic_value_enum()); + } + GlobalCache::Mut { ptr_to_value } => { + let value = builder.build_load(ptr_to_value, "global_value"); + state.push1(value); + } + } + } + Operator::SetGlobal { global_index } => { + let value = state.pop1()?; + let index = GlobalIndex::new(global_index as usize); + let global_cache = ctx.global_cache(index); + match global_cache { + GlobalCache::Mut { ptr_to_value } => { + builder.build_store(ptr_to_value, value); + } + GlobalCache::Const { value: _ } => { + unreachable!("cannot set non-mutable globals") + } + } + } Operator::Select => { let (v1, v2, cond) = state.pop3()?; @@ -528,10 +554,10 @@ fn parse_function( let func_index = FuncIndex::new(function_index as usize); let sigindex = info.func_assoc[func_index]; let llvm_sig = signatures[sigindex]; + let func_sig = &info.signatures[sig_index]; - match func_index.local_or_import(info) { + let call_site = match func_index.local_or_import(info) { LocalOrImport::Local(local_func_index) => { - let func_sig = &info.signatures[sigindex]; let func_value = functions[local_func_index]; let params: Vec<_> = [ctx.basic()] .iter() @@ -539,26 +565,45 @@ fn parse_function( .map(|v| *v) .collect(); - let call_site = builder.build_call(func_value, ¶ms, &state.var_name()); - if let Some(basic_value) = call_site.try_as_basic_value().left() { - match func_sig.returns().len() { - 1 => state.push1(basic_value), - count @ _ => { - // This is a multi-value return. - let struct_value = basic_value.into_struct_value(); - for i in 0..(count as u32) { - let value = builder.build_extract_value( - struct_value, - i, - &state.var_name(), - ); - state.push1(value); - } - } + builder.build_call(func_value, ¶ms, &state.var_name()) + } + LocalOrImport::Import(import_func_index) => { + let (func_ptr_untyped, ctx_ptr) = ctx.imported_func(import_func_index); + let params: Vec<_> = [ctx_ptr.as_basic_value_enum()] + .iter() + .chain(state.peekn(func_sig.params().len())?.iter()) + .map(|v| *v) + .collect(); + + let func_ptr_ty = llvm_sig.ptr_type(AddressSpace::Generic); + + // Once we can just bitcast between pointer types, remove this. + let func_ptr = { + let ptr_int = builder.build_ptr_to_int( + func_ptr_untyped, + intrinsics.i64_ty, + "func_ptr_int", + ); + builder.build_int_to_ptr(ptr_int, func_ptr_ty, "typed_func_ptr") + }; + + builder.build_call(func_ptr, ¶ms, &state.var_name()) + } + }; + + if let Some(basic_value) = call_site.try_as_basic_value().left() { + match func_sig.returns().len() { + 1 => state.push1(basic_value), + count @ _ => { + // This is a multi-value return. + let struct_value = basic_value.into_struct_value(); + for i in 0..(count as u32) { + let value = + builder.build_extract_value(struct_value, i, &state.var_name()); + state.push1(value); } } } - LocalOrImport::Import(import_func_index) => unimplemented!(), } } Operator::CallIndirect { index, table_index } => { @@ -1129,25 +1174,37 @@ fn parse_function( let res = builder.build_int_z_extend(v1, intrinsics.i64_ty, &state.var_name()); state.push1(res); } - Operator::I32TruncSF32 | Operator::I32TruncSF64 => { + Operator::I32TruncSF32 + | Operator::I32TruncSF64 + | Operator::I32TruncSSatF32 + | Operator::I32TruncSSatF64 => { let v1 = state.pop1()?.into_float_value(); let res = builder.build_float_to_signed_int(v1, intrinsics.i32_ty, &state.var_name()); state.push1(res); } - Operator::I64TruncSF32 | Operator::I64TruncSF64 => { + Operator::I64TruncSF32 + | Operator::I64TruncSF64 + | Operator::I64TruncSSatF32 + | Operator::I64TruncSSatF64 => { let v1 = state.pop1()?.into_float_value(); let res = builder.build_float_to_signed_int(v1, intrinsics.i64_ty, &state.var_name()); state.push1(res); } - Operator::I32TruncUF32 | Operator::I32TruncUF64 => { + Operator::I32TruncUF32 + | Operator::I32TruncUF64 + | Operator::I32TruncUSatF32 + | Operator::I32TruncUSatF64 => { let v1 = state.pop1()?.into_float_value(); let res = builder.build_float_to_unsigned_int(v1, intrinsics.i32_ty, &state.var_name()); state.push1(res); } - Operator::I64TruncUF32 | Operator::I64TruncUF64 => { + Operator::I64TruncUF32 + | Operator::I64TruncUF64 + | Operator::I64TruncUSatF32 + | Operator::I64TruncUSatF64 => { let v1 = state.pop1()?.into_float_value(); let res = builder.build_float_to_unsigned_int(v1, intrinsics.i64_ty, &state.var_name()); @@ -1194,6 +1251,51 @@ fn parse_function( unimplemented!("waiting on better bitcasting support in inkwell") } + /*************************** + * Sign-extension operators. + * https://github.com/WebAssembly/sign-extension-ops/blob/master/proposals/sign-extension-ops/Overview.md + ***************************/ + Operator::I32Extend8S => { + let value = state.pop1()?.into_int_value(); + let narrow_value = + builder.build_int_truncate(value, intrinsics.i8_ty, &state.var_name()); + let extended_value = + builder.build_int_s_extend(narrow_value, intrinsics.i32_ty, &state.var_name()); + state.push1(extended_value); + } + Operator::I32Extend16S => { + let value = state.pop1()?.into_int_value(); + let narrow_value = + builder.build_int_truncate(value, intrinsics.i16_ty, &state.var_name()); + let extended_value = + builder.build_int_s_extend(narrow_value, intrinsics.i32_ty, &state.var_name()); + state.push1(extended_value); + } + Operator::I64Extend8S => { + let value = state.pop1()?.into_int_value(); + let narrow_value = + builder.build_int_truncate(value, intrinsics.i8_ty, &state.var_name()); + let extended_value = + builder.build_int_s_extend(narrow_value, intrinsics.i64_ty, &state.var_name()); + state.push1(extended_value); + } + Operator::I64Extend16S => { + let value = state.pop1()?.into_int_value(); + let narrow_value = + builder.build_int_truncate(value, intrinsics.i16_ty, &state.var_name()); + let extended_value = + builder.build_int_s_extend(narrow_value, intrinsics.i64_ty, &state.var_name()); + state.push1(extended_value); + } + Operator::I64Extend32S => { + let value = state.pop1()?.into_int_value(); + let narrow_value = + builder.build_int_truncate(value, intrinsics.i32_ty, &state.var_name()); + let extended_value = + builder.build_int_s_extend(narrow_value, intrinsics.i64_ty, &state.var_name()); + state.push1(extended_value); + } + /*************************** * Load and Store instructions. * https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#load-and-store-instructions @@ -1566,15 +1668,15 @@ fn parse_function( &state.var_name(), ); state.push1(result.try_as_basic_value().left().unwrap()); - } - - op @ _ => { - println!("{}", module.print_to_string().to_string()); - unimplemented!("{:?}", op); - } + } // op @ _ => { + // println!("{}", module.print_to_string().to_string()); + // unimplemented!("{:?}", op); + // } } } + println!("finished translating"); + let pass_manager = PassManager::create_for_module(); pass_manager.add_promote_memory_to_register_pass(); pass_manager.add_cfg_simplification_pass(); @@ -1585,6 +1687,7 @@ fn parse_function( pass_manager.add_gvn_pass(); pass_manager.add_new_gvn_pass(); pass_manager.add_aggressive_dce_pass(); + pass_manager.add_verifier_pass(); pass_manager.run_on_module(module); println!("{}", module.print_to_string().to_string()); diff --git a/lib/llvm-backend/src/intrinsics.rs b/lib/llvm-backend/src/intrinsics.rs index f2e681f38..6ffbb6ea6 100644 --- a/lib/llvm-backend/src/intrinsics.rs +++ b/lib/llvm-backend/src/intrinsics.rs @@ -12,9 +12,18 @@ use wasmer_runtime_core::{ memory::MemoryType, module::ModuleInfo, structures::TypedIndex, - types::{LocalOrImport, MemoryIndex}, + types::{GlobalIndex, ImportedFuncIndex, LocalOrImport, MemoryIndex, TableIndex, Type}, }; +fn type_to_llvm_ptr(intrinsics: &Intrinsics, ty: Type) -> PointerType { + match ty { + Type::I32 => intrinsics.i32_ptr_ty, + Type::I64 => intrinsics.i64_ptr_ty, + Type::F32 => intrinsics.f32_ptr_ty, + Type::F64 => intrinsics.f64_ptr_ty, + } +} + pub struct Intrinsics { pub ctlz_i32: FunctionValue, pub ctlz_i64: FunctionValue, @@ -111,8 +120,6 @@ impl Intrinsics { let f32_ptr_ty = f32_ty.ptr_type(AddressSpace::Generic); let f64_ptr_ty = f64_ty.ptr_type(AddressSpace::Generic); - let opaque_ptr_ty = void_ty.ptr_type(AddressSpace::Generic); - let i1_zero = i1_ty.const_int(0, false); let i32_zero = i32_ty.const_int(0, false); let i64_zero = i64_ty.const_int(0, false); @@ -125,19 +132,16 @@ impl Intrinsics { let f32_ty_basic = f32_ty.as_basic_type_enum(); let f64_ty_basic = f64_ty.as_basic_type_enum(); let i8_ptr_ty_basic = i8_ptr_ty.as_basic_type_enum(); - let opaque_ptr_ty_basic = opaque_ptr_ty.as_basic_type_enum(); let ctx_ty = context.opaque_struct_type("ctx"); let ctx_ptr_ty = ctx_ty.ptr_type(AddressSpace::Generic); let local_memory_ty = - context.struct_type(&[i8_ptr_ty_basic, i64_ty_basic, opaque_ptr_ty_basic], false); + context.struct_type(&[i8_ptr_ty_basic, i64_ty_basic, i8_ptr_ty_basic], false); let local_table_ty = local_memory_ty; let local_global_ty = i64_ty; - let imported_func_ty = context.struct_type( - &[opaque_ptr_ty_basic, ctx_ptr_ty.as_basic_type_enum()], - false, - ); + let imported_func_ty = + context.struct_type(&[i8_ptr_ty_basic, ctx_ptr_ty.as_basic_type_enum()], false); ctx_ty.set_body( &[ local_memory_ty @@ -184,9 +188,12 @@ impl Intrinsics { let ret_f32_take_f32_f32 = f32_ty.fn_type(&[f32_ty_basic, f32_ty_basic], false); let ret_f64_take_f64_f64 = f64_ty.fn_type(&[f64_ty_basic, f64_ty_basic], false); - let ret_i32_take_i64_i32_i32 = - i32_ty.fn_type(&[i64_ty_basic, i32_ty_basic, i32_ty_basic], false); - let ret_i32_take_i64_i32 = i32_ty.fn_type(&[i64_ty_basic, i32_ty_basic], false); + let ret_i32_take_ctx_i32_i32 = i32_ty.fn_type( + &[ctx_ptr_ty.as_basic_type_enum(), i32_ty_basic, i32_ty_basic], + false, + ); + let ret_i32_take_ctx_i32 = + i32_ty.fn_type(&[ctx_ptr_ty.as_basic_type_enum(), i32_ty_basic], false); Self { ctlz_i32: module.add_function("llvm.ctlz.i32", ret_i32_take_i32_i1, None), @@ -250,63 +257,63 @@ impl Intrinsics { // VM intrinsics. memory_grow_dynamic_local: module.add_function( "vm.memory.grow.dynamic.local", - ret_i32_take_i64_i32_i32, + ret_i32_take_ctx_i32_i32, None, ), memory_grow_static_local: module.add_function( "vm.memory.grow.static.local", - ret_i32_take_i64_i32_i32, + ret_i32_take_ctx_i32_i32, None, ), memory_grow_shared_local: module.add_function( "vm.memory.grow.shared.local", - ret_i32_take_i64_i32_i32, + ret_i32_take_ctx_i32_i32, None, ), memory_grow_dynamic_import: module.add_function( "vm.memory.grow.dynamic.import", - ret_i32_take_i64_i32_i32, + ret_i32_take_ctx_i32_i32, None, ), memory_grow_static_import: module.add_function( "vm.memory.grow.static.import", - ret_i32_take_i64_i32_i32, + ret_i32_take_ctx_i32_i32, None, ), memory_grow_shared_import: module.add_function( "vm.memory.grow.shared.import", - ret_i32_take_i64_i32_i32, + ret_i32_take_ctx_i32_i32, None, ), memory_size_dynamic_local: module.add_function( "vm.memory.size.dynamic.local", - ret_i32_take_i64_i32, + ret_i32_take_ctx_i32, None, ), memory_size_static_local: module.add_function( "vm.memory.size.static.local", - ret_i32_take_i64_i32, + ret_i32_take_ctx_i32, None, ), memory_size_shared_local: module.add_function( "vm.memory.size.shared.local", - ret_i32_take_i64_i32, + ret_i32_take_ctx_i32, None, ), memory_size_dynamic_import: module.add_function( "vm.memory.size.dynamic.import", - ret_i32_take_i64_i32, + ret_i32_take_ctx_i32, None, ), memory_size_static_import: module.add_function( "vm.memory.size.static.import", - ret_i32_take_i64_i32, + ret_i32_take_ctx_i32, None, ), memory_size_shared_import: module.add_function( "vm.memory.size.shared.import", - ret_i32_take_i64_i32, + ret_i32_take_ctx_i32, None, ), @@ -332,6 +339,9 @@ impl Intrinsics { info, cached_memories: HashMap::new(), + cached_tables: HashMap::new(), + cached_globals: HashMap::new(), + cached_imported_functions: HashMap::new(), _phantom: PhantomData, } @@ -351,6 +361,22 @@ enum MemoryCache { }, } +struct TableCache { + ptr_to_base_ptr: PointerValue, + ptr_to_bounds: PointerValue, +} + +#[derive(Clone, Copy)] +pub enum GlobalCache { + Mut { ptr_to_value: PointerValue }, + Const { value: IntValue }, +} + +struct ImportedFuncCache { + func_ptr: PointerValue, + ctx_ptr: PointerValue, +} + pub struct CtxType<'a> { ctx_ty: StructType, ctx_ptr_ty: PointerType, @@ -362,6 +388,9 @@ pub struct CtxType<'a> { info: &'a ModuleInfo, cached_memories: HashMap, + cached_tables: HashMap, + cached_globals: HashMap, + cached_imported_functions: HashMap, _phantom: PhantomData<&'a FunctionValue>, } @@ -443,6 +472,119 @@ impl<'a> CtxType<'a> { MemoryCache::Static { base_ptr, bounds } => (*base_ptr, *bounds), } } + + pub fn global_cache(&mut self, index: GlobalIndex) -> GlobalCache { + let (cached_globals, builder, ctx_ptr_value, info, intrinsics) = ( + &mut self.cached_globals, + self.builder, + self.ctx_ptr_value, + self.info, + self.intrinsics, + ); + + *cached_globals.entry(index).or_insert_with(|| { + let (globals_array_ptr_ptr, index, mutable, wasmer_ty) = + match index.local_or_import(info) { + LocalOrImport::Local(local_global_index) => { + let desc = info.globals[local_global_index].desc; + ( + unsafe { + builder.build_struct_gep(ctx_ptr_value, 2, "globals_array_ptr_ptr") + }, + local_global_index.index() as u64, + desc.mutable, + desc.ty, + ) + } + LocalOrImport::Import(import_global_index) => { + let desc = info.imported_globals[import_global_index].1; + ( + unsafe { + builder.build_struct_gep(ctx_ptr_value, 5, "globals_array_ptr_ptr") + }, + import_global_index.index() as u64, + desc.mutable, + desc.ty, + ) + } + }; + + let llvm_ptr_ty = type_to_llvm_ptr(intrinsics, wasmer_ty); + + let global_array_ptr = builder + .build_load(globals_array_ptr_ptr, "global_array_ptr") + .into_pointer_value(); + let const_index = intrinsics.i32_ty.const_int(index, false); + let global_ptr_ptr = unsafe { + builder.build_in_bounds_gep(global_array_ptr, &[const_index], "global_ptr_ptr") + }; + let global_ptr = builder + .build_load(global_ptr_ptr, "global_ptr") + .into_pointer_value(); + + let global_ptr_typed = { + let int = builder.build_ptr_to_int(global_ptr, intrinsics.i64_ty, "global_ptr_int"); + builder.build_int_to_ptr(int, llvm_ptr_ty, "global_ptr_typed") + }; + println!("global_ptr: {:?}", global_ptr_typed); + + if mutable { + GlobalCache::Mut { + ptr_to_value: global_ptr_typed, + } + } else { + GlobalCache::Const { + value: builder + .build_load(global_ptr_typed, "global_value") + .into_int_value(), + } + } + }) + } + + pub fn imported_func(&mut self, index: ImportedFuncIndex) -> (PointerValue, PointerValue) { + let (cached_imported_functions, builder, ctx_ptr_value, intrinsics) = ( + &mut self.cached_imported_functions, + self.builder, + self.ctx_ptr_value, + self.intrinsics, + ); + + let imported_func_cache = cached_imported_functions.entry(index).or_insert_with(|| { + let func_array_ptr_ptr = unsafe { + builder.build_struct_gep(ctx_ptr_value, 6, "imported_func_array_ptr_ptr") + }; + let func_array_ptr = builder + .build_load(func_array_ptr_ptr, "func_array_ptr") + .into_pointer_value(); + let const_index = intrinsics.i32_ty.const_int(index.index() as u64, false); + let imported_func_ptr_ptr = unsafe { + builder.build_in_bounds_gep(func_array_ptr, &[const_index], "imported_func_ptr_ptr") + }; + let imported_func_ptr = builder + .build_load(imported_func_ptr_ptr, "imported_func_ptr") + .into_pointer_value(); + let (func_ptr_ptr, ctx_ptr_ptr) = unsafe { + ( + builder.build_struct_gep(imported_func_ptr, 0, "func_ptr_ptr"), + builder.build_struct_gep(imported_func_ptr, 1, "ctx_ptr_ptr"), + ) + }; + + let func_ptr = builder + .build_load(func_ptr_ptr, "func_ptr") + .into_pointer_value(); + let ctx_ptr = builder + .build_load(ctx_ptr_ptr, "ctx_ptr") + .into_pointer_value(); + + ImportedFuncCache { func_ptr, ctx_ptr } + }); + + (imported_func_cache.func_ptr, imported_func_cache.ctx_ptr) + } + + // pub fn table(&mut self, table_index: TableIndex, elem_index: IntValue) -> } // pub struct Ctx { diff --git a/lib/llvm-backend/src/lib.rs b/lib/llvm-backend/src/lib.rs index e691acebb..cd43c6aef 100644 --- a/lib/llvm-backend/src/lib.rs +++ b/lib/llvm-backend/src/lib.rs @@ -30,20 +30,17 @@ impl Compiler for LLVMCompiler { #[test] fn test_read_module() { use wabt::wat2wasm; + // let wasm = include_bytes!("../../spectests/examples/simple/simple.wasm") as &[u8]; let wat = r#" (module (type $t0 (func (param i32) (result i32))) (type $t1 (func (result i32))) (memory 1) + (global $g0 (mut i32) (i32.const 0)) (func $foo (type $t0) (param i32) (result i32) get_local 0 - i32.load offset=16 - i32.const 1 - memory.grow - drop - i32.const 0 - i32.load offset=4 - i32.add + set_global $g0 + get_global $g0 )) "#; let wasm = wat2wasm(wat).unwrap(); From 24d028e2a2eeb332c03f5b8c84fde085d4c9edc4 Mon Sep 17 00:00:00 2001 From: Mackenzie Clark Date: Thu, 14 Feb 2019 18:19:18 -0800 Subject: [PATCH 053/262] impl error trait for ResolveError (#179) --- lib/runtime-core/src/error.rs | 26 ++++++++++++++++++++++++++ lib/runtime-core/src/types.rs | 24 ++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/lib/runtime-core/src/error.rs b/lib/runtime-core/src/error.rs index b72c74242..734e11cff 100644 --- a/lib/runtime-core/src/error.rs +++ b/lib/runtime-core/src/error.rs @@ -1,6 +1,7 @@ use crate::types::{ FuncSig, GlobalDescriptor, MemoryDescriptor, MemoryIndex, TableDescriptor, TableIndex, Type, }; +use core::borrow::Borrow; use std::sync::Arc; pub type Result = std::result::Result; @@ -135,6 +136,31 @@ impl PartialEq for ResolveError { } } +impl std::fmt::Display for ResolveError { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + ResolveError::ExportNotFound { name } => write!(f, "Export not found: {}", name), + ResolveError::ExportWrongType { name } => write!(f, "Export wrong type: {}", name), + ResolveError::Signature { expected, found } => { + let found = found + .as_slice() + .iter() + .map(|p| p.to_string()) + .collect::>() + .join(", "); + let expected: &FuncSig = expected.borrow(); + write!( + f, + "Parameters of type [{}] did not match signature {}", + found, expected + ) + } + } + } +} + +impl std::error::Error for ResolveError {} + /// This error type is produced by calling a wasm function /// exported from a module. /// diff --git a/lib/runtime-core/src/types.rs b/lib/runtime-core/src/types.rs index c6b3f0a2b..fd57bf12c 100644 --- a/lib/runtime-core/src/types.rs +++ b/lib/runtime-core/src/types.rs @@ -15,6 +15,12 @@ pub enum Type { F64, } +impl std::fmt::Display for Type { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "{:?}", self) + } +} + /// Represents a WebAssembly value. /// /// As the number of types in WebAssembly expand, @@ -292,6 +298,24 @@ impl FuncSig { } } +impl std::fmt::Display for FuncSig { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + let params = self + .params + .iter() + .map(|p| p.to_string()) + .collect::>() + .join(", "); + let returns = self + .returns + .iter() + .map(|p| p.to_string()) + .collect::>() + .join(", "); + write!(f, "[{}] -> [{}]", params, returns) + } +} + pub trait LocalImport { type Local: TypedIndex; type Import: TypedIndex; From 6e876761607fa0c0e87d6da293d7a0121613b4ae Mon Sep 17 00:00:00 2001 From: Mackenzie Clark Date: Thu, 14 Feb 2019 18:40:52 -0800 Subject: [PATCH 054/262] Impl error for link error (#182) --- lib/runtime-core/src/error.rs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/lib/runtime-core/src/error.rs b/lib/runtime-core/src/error.rs index 734e11cff..9e1eba8fe 100644 --- a/lib/runtime-core/src/error.rs +++ b/lib/runtime-core/src/error.rs @@ -76,6 +76,31 @@ impl PartialEq for LinkError { } } +impl std::fmt::Display for LinkError { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + LinkError::ImportNotFound {namespace, name} => write!(f, "Import not found, namespace: {}, name: {}", namespace, name), + LinkError::IncorrectGlobalDescriptor {namespace, name,expected,found} => { + write!(f, "Incorrect global descriptor, namespace: {}, name: {}, expected global descriptor: {:?}, found global descriptor: {:?}", namespace, name, expected, found) + }, + LinkError::IncorrectImportSignature{namespace, name,expected,found} => { + write!(f, "Incorrect import signature, namespace: {}, name: {}, expected signature: {}, found signature: {}", namespace, name, expected, found) + } + LinkError::IncorrectImportType{namespace, name,expected,found} => { + write!(f, "Incorrect import type, namespace: {}, name: {}, expected type: {}, found type: {}", namespace, name, expected, found) + } + LinkError::IncorrectMemoryDescriptor{namespace, name,expected,found} => { + write!(f, "Incorrect memory descriptor, namespace: {}, name: {}, expected memory descriptor: {:?}, found memory descriptor: {:?}", namespace, name, expected, found) + }, + LinkError::IncorrectTableDescriptor{namespace, name,expected,found} => { + write!(f, "Incorrect table descriptor, namespace: {}, name: {}, expected table descriptor: {:?}, found table descriptor: {:?}", namespace, name, expected, found) + }, + } + } +} + +impl std::error::Error for LinkError {} + /// This is the error type returned when calling /// a webassembly function. /// From 09ba27390cad6313738e4e5b87e2a2d43baf619e Mon Sep 17 00:00:00 2001 From: Mackenzie Clark Date: Thu, 14 Feb 2019 19:22:19 -0800 Subject: [PATCH 055/262] Implement Error for Creation Error (#180) --- lib/runtime-core/src/error.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/lib/runtime-core/src/error.rs b/lib/runtime-core/src/error.rs index 9e1eba8fe..539f94e42 100644 --- a/lib/runtime-core/src/error.rs +++ b/lib/runtime-core/src/error.rs @@ -219,6 +219,17 @@ impl PartialEq for CreationError { } } +impl std::fmt::Display for CreationError { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + CreationError::UnableToCreateMemory => write!(f, "Unable to Create Memory"), + CreationError::UnableToCreateTable => write!(f, "Unable to Create Table"), + } + } +} + +impl std::error::Error for CreationError {} + /// The amalgamation of all errors that can occur /// during the compilation, instantiation, or execution /// of a webassembly module. From 39ef47ebb1152529f3759ac9a6ec6f637963bd44 Mon Sep 17 00:00:00 2001 From: Mackenzie Clark Date: Thu, 14 Feb 2019 21:08:35 -0800 Subject: [PATCH 056/262] Implement Error for CompilerError (#181) --- lib/runtime-core/src/error.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/lib/runtime-core/src/error.rs b/lib/runtime-core/src/error.rs index 539f94e42..ac14e4fc1 100644 --- a/lib/runtime-core/src/error.rs +++ b/lib/runtime-core/src/error.rs @@ -28,6 +28,19 @@ impl PartialEq for CompileError { } } +impl std::fmt::Display for CompileError { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + CompileError::InternalError { msg } => { + write!(f, "Internal compiler error: \"{}\"", msg) + } + CompileError::ValidationError { msg } => write!(f, "Validation error \"{}\"", msg), + } + } +} + +impl std::error::Error for CompileError {} + /// This is returned when the runtime is unable to /// correctly link the module with the provided imports. /// From 3ebb80e50e8049da79a270880d8dcd070d63df43 Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Fri, 15 Feb 2019 09:40:28 -0600 Subject: [PATCH 057/262] Update imports and add func_new --- lib/runtime-c-api/src/lib.rs | 93 +++++++++++++++++-- lib/runtime-c-api/tests/test-exports.c | 7 +- .../tests/test-import-function.c | 41 +++++++- lib/runtime-c-api/tests/test-instantiate.c | 6 +- lib/runtime-c-api/wasmer.h | 42 +++++++-- lib/runtime-c-api/wasmer.hh | 38 ++++++-- 6 files changed, 196 insertions(+), 31 deletions(-) diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index 1931656e7..511f4304a 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -3,6 +3,7 @@ extern crate wasmer_runtime_core; use libc::{c_char, c_int, int32_t, int64_t, uint32_t, uint8_t}; use std::cell::RefCell; +use std::collections::HashMap; use std::error::Error; use std::ffi::CStr; use std::ffi::CString; @@ -99,8 +100,9 @@ pub struct wasmer_func_signature { } #[repr(C)] -#[derive(Clone)] -pub struct wasmer_import { +pub struct wasmer_import_t { + module_name: wasmer_byte_array, + import_name: wasmer_byte_array, tag: wasmer_import_export_kind, value: wasmer_import_export_value, } @@ -389,18 +391,63 @@ pub unsafe extern "C" fn wasmer_instantiate( mut instance: *mut *mut wasmer_instance_t, wasm_bytes: *mut uint8_t, wasm_bytes_len: uint32_t, - import_object: *mut wasmer_import_object_t, + imports: *mut wasmer_import_t, + imports_len: c_int, ) -> wasmer_result_t { - let import_object = unsafe { Box::from_raw(import_object as *mut ImportObject) }; if wasm_bytes.is_null() { update_last_error(CApiError { msg: "wasm bytes ptr is null".to_string(), }); return wasmer_result_t::WASMER_ERROR; } + let imports: &[wasmer_import_t] = slice::from_raw_parts(imports, imports_len as usize); + let mut import_object = ImportObject::new(); + let mut namespaces = HashMap::new(); + for import in imports { + let module_name = slice::from_raw_parts( + import.module_name.bytes, + import.module_name.bytes_len as usize, + ); + let module_name = if let Ok(s) = std::str::from_utf8(module_name) { + s + } else { + update_last_error(CApiError { + msg: "error converting module name to string".to_string(), + }); + return wasmer_result_t::WASMER_ERROR; + }; + let import_name = slice::from_raw_parts( + import.import_name.bytes, + import.import_name.bytes_len as usize, + ); + let import_name = if let Ok(s) = std::str::from_utf8(import_name) { + s + } else { + update_last_error(CApiError { + msg: "error converting import_name to string".to_string(), + }); + return wasmer_result_t::WASMER_ERROR; + }; + + let namespace = namespaces + .entry(module_name) + .or_insert_with(|| Namespace::new()); + + let export = match import.tag { + wasmer_import_export_kind::WASM_MEMORY => import.value.memory as *mut Export, + wasmer_import_export_kind::WASM_FUNCTION => import.value.func as *mut Export, + wasmer_import_export_kind::WASM_GLOBAL => import.value.global as *mut Export, + wasmer_import_export_kind::WASM_TABLE => import.value.table as *mut Export, + }; + namespace.insert(import_name, unsafe { *Box::from_raw(export) }); + } + for (module_name, namespace) in namespaces.into_iter() { + import_object.register(module_name, namespace); + } + let bytes: &[u8] = unsafe { ::std::slice::from_raw_parts_mut(wasm_bytes, wasm_bytes_len as usize) }; - let result = wasmer_runtime::instantiate(bytes, &*import_object); + let result = wasmer_runtime::instantiate(bytes, &import_object); let new_instance = match result { Ok(instance) => instance, Err(error) => { @@ -413,7 +460,7 @@ pub unsafe extern "C" fn wasmer_instantiate( } }; unsafe { *instance = Box::into_raw(Box::new(new_instance)) as *mut wasmer_instance_t }; - Box::into_raw(import_object); + Box::into_raw(Box::new(import_object)); wasmer_result_t::WASMER_OK } @@ -563,6 +610,40 @@ pub unsafe extern "C" fn wasmer_export_kind( } } +/// Creates new func +/// +/// The caller owns the object and should call `wasmer_func_destroy` to free it. +#[no_mangle] +#[allow(clippy::cast_ptr_alignment)] +pub unsafe extern "C" fn wasmer_func_new( + func: extern "C" fn(data: *mut c_void), + params: *const wasmer_value_tag, + params_len: c_int, + returns: *const wasmer_value_tag, + returns_len: c_int, +) -> *const wasmer_func_t { + let params: &[wasmer_value_tag] = slice::from_raw_parts(params, params_len as usize); + let params: Vec = params.iter().cloned().map(|x| x.into()).collect(); + let returns: &[wasmer_value_tag] = slice::from_raw_parts(returns, returns_len as usize); + let returns: Vec = returns.iter().cloned().map(|x| x.into()).collect(); + + let export = Box::new(Export::Function { + func: unsafe { FuncPointer::new(func as _) }, + ctx: Context::Internal, + signature: Arc::new(FuncSig::new(params, returns)), + }); + Box::into_raw(export) as *mut wasmer_func_t +} + +/// Frees memory for the given Func +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub extern "C" fn wasmer_func_destroy(func: *mut wasmer_func_t) { + if !func.is_null() { + drop(unsafe { Box::from_raw(func as *mut Export) }); + } +} + /// Gets func from wasm_export #[no_mangle] #[allow(clippy::cast_ptr_alignment)] diff --git a/lib/runtime-c-api/tests/test-exports.c b/lib/runtime-c-api/tests/test-exports.c index b00adb790..c0c6a4a7b 100644 --- a/lib/runtime-c-api/tests/test-exports.c +++ b/lib/runtime-c-api/tests/test-exports.c @@ -5,7 +5,7 @@ int main() { - wasmer_import_object_t *import_object = wasmer_import_object_new(); +// wasmer_import_object_t *import_object = wasmer_import_object_new(); // Read the wasm file bytes FILE *file = fopen("sum.wasm", "r"); @@ -16,8 +16,9 @@ int main() fread(bytes, 1, len, file); fclose(file); + wasmer_import_t imports[] = {}; wasmer_instance_t *instance = NULL; - wasmer_result_t compile_result = wasmer_instantiate(&instance, bytes, len, import_object); + wasmer_result_t compile_result = wasmer_instantiate(&instance, bytes, len, imports, 0); printf("Compile result: %d\n", compile_result); assert(compile_result == WASMER_OK); @@ -61,8 +62,6 @@ int main() printf("Destroy instance\n"); wasmer_instance_destroy(instance); - printf("Destroy import object\n"); - wasmer_import_object_destroy(import_object); printf("Destroy exports\n"); wasmer_exports_destroy(exports); return 0; diff --git a/lib/runtime-c-api/tests/test-import-function.c b/lib/runtime-c-api/tests/test-import-function.c index b42817abc..2c241be55 100644 --- a/lib/runtime-c-api/tests/test-import-function.c +++ b/lib/runtime-c-api/tests/test-import-function.c @@ -2,6 +2,7 @@ #include "../wasmer.h" #include #include +#include static print_str_called = false; static memory_len = 0; @@ -26,10 +27,32 @@ void print_str(int32_t ptr, int32_t len, wasmer_instance_context_t *ctx) int main() { - wasmer_import_object_t *import_object = wasmer_import_object_new(); +// wasmer_import_object_t *import_object = wasmer_import_object_new(); wasmer_value_tag params_sig[] = {WASM_I32, WASM_I32}; wasmer_value_tag returns_sig[] = {}; - wasmer_imports_set_import_func(import_object, "env", "print_str", print_str, params_sig, 2, returns_sig, 0); + + printf("Creating new func\n"); + wasmer_func_t *func = wasmer_func_new(print_str, params_sig, 2, returns_sig, 0); + wasmer_import_t import; + + char *module_name = "env"; + wasmer_byte_array module_name_bytes; + module_name_bytes.bytes = module_name; + module_name_bytes.bytes_len = strlen(module_name); + char *import_name = "print_str"; + wasmer_byte_array import_name_bytes; + import_name_bytes.bytes = import_name; + import_name_bytes.bytes_len = strlen(import_name); + + import.module_name = module_name_bytes; + import.import_name = import_name_bytes; + import.tag = WASM_FUNCTION; + import.value.func = func; + wasmer_import_t imports[] = {import}; + + +// wasmer_imports_set_import_func(import_object, "env", "print_str", print_str, params_sig, 2, returns_sig, 0); + // Read the wasm file bytes FILE *file = fopen("wasm_sample_app.wasm", "r"); @@ -40,9 +63,15 @@ int main() fread(bytes, 1, len, file); fclose(file); + printf("Instantiating\n"); wasmer_instance_t *instance = NULL; - wasmer_result_t compile_result = wasmer_instantiate(&instance, bytes, len, import_object); + wasmer_result_t compile_result = wasmer_instantiate(&instance, bytes, len, imports, 1); printf("Compile result: %d\n", compile_result); + int error_len = wasmer_last_error_length(); + printf("Error len: `%d`\n", error_len); + char *error_str = malloc(error_len); + wasmer_last_error_message(error_str, error_len); + printf("Error str: `%s`\n", error_str); assert(compile_result == WASMER_OK); wasmer_value_t params[] = {}; @@ -56,9 +85,11 @@ int main() assert(ptr_len == 13); assert(0 == strcmp(actual_str, "Hello, World!")); + printf("Destroying func\n"); + // wasmer_func_destroy(func); // printf("Destroy instance\n"); // wasmer_instance_destroy(instance); - printf("Destroy import object\n"); - wasmer_import_object_destroy(import_object); +// printf("Destroy import object\n"); +// wasmer_import_object_destroy(import_object); return 0; } \ No newline at end of file diff --git a/lib/runtime-c-api/tests/test-instantiate.c b/lib/runtime-c-api/tests/test-instantiate.c index db24544f4..63adf11c1 100644 --- a/lib/runtime-c-api/tests/test-instantiate.c +++ b/lib/runtime-c-api/tests/test-instantiate.c @@ -5,7 +5,6 @@ int main() { - wasmer_import_object_t *import_object = wasmer_import_object_new(); // Read the wasm file bytes FILE *file = fopen("sum.wasm", "r"); @@ -16,8 +15,9 @@ int main() fread(bytes, 1, len, file); fclose(file); + wasmer_import_t imports[] = {}; wasmer_instance_t *instance = NULL; - wasmer_result_t compile_result = wasmer_instantiate(&instance, bytes, len, import_object); + wasmer_result_t compile_result = wasmer_instantiate(&instance, bytes, len, imports, 0); printf("Compile result: %d\n", compile_result); assert(compile_result == WASMER_OK); @@ -53,7 +53,5 @@ int main() printf("Destroy instance\n"); wasmer_instance_destroy(instance); - printf("Destroy import object\n"); - wasmer_import_object_destroy(import_object); return 0; } \ No newline at end of file diff --git a/lib/runtime-c-api/wasmer.h b/lib/runtime-c-api/wasmer.h index f55014bee..efc840400 100644 --- a/lib/runtime-c-api/wasmer.h +++ b/lib/runtime-c-api/wasmer.h @@ -75,22 +75,36 @@ typedef struct { } wasmer_memory_t; +typedef struct { + +} wasmer_table_t; + +typedef union { + const wasmer_func_t *func; + const wasmer_table_t *table; + const wasmer_memory_t *memory; + const wasmer_global_t *global; +} wasmer_import_export_value; + +typedef struct { + wasmer_byte_array module_name; + wasmer_byte_array import_name; + wasmer_import_export_kind tag; + wasmer_import_export_value value; +} wasmer_import_t; + typedef struct { uint32_t min; uint32_t max; } wasmer_limits_t; -typedef struct { - -} wasmer_table_t; - /** * Gets wasmer_export kind */ wasmer_import_export_kind wasmer_export_kind(wasmer_export_t *export_); /** - * Gets func from wasm_export + * Gets name from wasmer_export */ wasmer_byte_array wasmer_export_name(wasmer_export_t *export_); @@ -127,6 +141,21 @@ wasmer_result_t wasmer_func_call(wasmer_func_t *func, wasmer_value_t *results, int results_len); +/** + * Frees memory for the given Func + */ +void wasmer_func_destroy(wasmer_func_t *func); + +/** + * Creates new func + * The caller owns the object and should call `wasmer_func_destroy` to free it. + */ +const wasmer_func_t *wasmer_func_new(void (*func)(void *data), + const wasmer_value_tag *params, + int params_len, + const wasmer_value_tag *returns, + int returns_len); + /** * Frees memory for the given Global */ @@ -220,7 +249,8 @@ void wasmer_instance_exports(wasmer_instance_t *instance, wasmer_exports_t **exp wasmer_result_t wasmer_instantiate(wasmer_instance_t **instance, uint8_t *wasm_bytes, uint32_t wasm_bytes_len, - wasmer_import_object_t *import_object); + wasmer_import_t *imports, + int imports_len); /** * Gets the length in bytes of the last error. diff --git a/lib/runtime-c-api/wasmer.hh b/lib/runtime-c-api/wasmer.hh index 02de6f52b..0192e8555 100644 --- a/lib/runtime-c-api/wasmer.hh +++ b/lib/runtime-c-api/wasmer.hh @@ -72,21 +72,35 @@ struct wasmer_memory_t { }; +struct wasmer_table_t { + +}; + +union wasmer_import_export_value { + const wasmer_func_t *func; + const wasmer_table_t *table; + const wasmer_memory_t *memory; + const wasmer_global_t *global; +}; + +struct wasmer_import_t { + wasmer_byte_array module_name; + wasmer_byte_array import_name; + wasmer_import_export_kind tag; + wasmer_import_export_value value; +}; + struct wasmer_limits_t { uint32_t min; uint32_t max; }; -struct wasmer_table_t { - -}; - extern "C" { /// Gets wasmer_export kind wasmer_import_export_kind wasmer_export_kind(wasmer_export_t *export_); -/// Gets func from wasm_export +/// Gets name from wasmer_export wasmer_byte_array wasmer_export_name(wasmer_export_t *export_); /// Gets func from wasm_export @@ -112,6 +126,17 @@ wasmer_result_t wasmer_func_call(wasmer_func_t *func, wasmer_value_t *results, int results_len); +/// Frees memory for the given Func +void wasmer_func_destroy(wasmer_func_t *func); + +/// Creates new func +/// The caller owns the object and should call `wasmer_func_destroy` to free it. +const wasmer_func_t *wasmer_func_new(void (*func)(void *data), + const wasmer_value_tag *params, + int params_len, + const wasmer_value_tag *returns, + int returns_len); + /// Frees memory for the given Global void wasmer_global_destroy(wasmer_global_t *global); @@ -179,7 +204,8 @@ void wasmer_instance_exports(wasmer_instance_t *instance, wasmer_exports_t **exp wasmer_result_t wasmer_instantiate(wasmer_instance_t **instance, uint8_t *wasm_bytes, uint32_t wasm_bytes_len, - wasmer_import_object_t *import_object); + wasmer_import_t *imports, + int imports_len); /// Gets the length in bytes of the last error. /// This can be used to dynamically allocate a buffer with the correct number of From b68b109b7de1d27a334591fdeeda475c808c812a Mon Sep 17 00:00:00 2001 From: Mackenzie Clark Date: Fri, 15 Feb 2019 08:15:57 -0800 Subject: [PATCH 058/262] Implement error for remaining errors and the amalgamation error (#184) --- lib/runtime-core/src/error.rs | 50 +++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/lib/runtime-core/src/error.rs b/lib/runtime-core/src/error.rs index ac14e4fc1..98f0198f4 100644 --- a/lib/runtime-core/src/error.rs +++ b/lib/runtime-core/src/error.rs @@ -150,6 +150,39 @@ impl PartialEq for RuntimeError { } } +impl std::fmt::Display for RuntimeError { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + RuntimeError::IndirectCallSignature { table } => write!( + f, + "Indirect call signature error with Table Index \"{:?}\"", + table + ), + RuntimeError::IndirectCallToNull { table } => { + write!(f, "Indirect call to null with table index \"{:?}\"", table) + } + RuntimeError::IllegalArithmeticOperation => write!(f, "Illegal arithmetic operation"), + RuntimeError::OutOfBoundsAccess { memory, addr } => match addr { + Some(addr) => write!( + f, + "Out-of-bounds access with memory index {:?} and address {}", + memory, addr + ), + None => write!(f, "Out-of-bounds access with memory index {:?}", memory), + }, + RuntimeError::TableOutOfBounds { table } => { + write!(f, "Table out of bounds with table index \"{:?}\"", table) + } + RuntimeError::Unknown { msg } => { + write!(f, "Unknown runtime error with message: \"{}\"", msg) + } + RuntimeError::User { msg } => write!(f, "User runtime error with message: \"{}\"", msg), + } + } +} + +impl std::error::Error for RuntimeError {} + /// This error type is produced by resolving a wasm function /// given its name. /// @@ -218,6 +251,15 @@ impl PartialEq for CallError { } } +impl std::fmt::Display for CallError { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + CallError::Resolve(resolve_error) => write!(f, "Call error: {}", resolve_error), + CallError::Runtime(runtime_error) => write!(f, "Call error: {}", runtime_error), + } + } +} + /// This error type is produced when creating something, /// like a `Memory` or a `Table`. #[derive(Debug, Clone)] @@ -311,3 +353,11 @@ impl From for CallError { CallError::Resolve(resolve_err) } } + +impl std::fmt::Display for Error { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "{}", self) + } +} + +impl std::error::Error for Error {} From 2d2d708500a670eb07b414c3b6fcd0fc55edecdd Mon Sep 17 00:00:00 2001 From: Mackenzie Clark Date: Fri, 15 Feb 2019 13:14:42 -0800 Subject: [PATCH 059/262] Validate descriptor max on creating new table or memory (#186) --- lib/runtime-core/src/error.rs | 6 ++++++ lib/runtime-core/src/memory/mod.rs | 9 +++++++++ lib/runtime-core/src/table/mod.rs | 8 ++++++++ 3 files changed, 23 insertions(+) diff --git a/lib/runtime-core/src/error.rs b/lib/runtime-core/src/error.rs index 98f0198f4..e88a5692c 100644 --- a/lib/runtime-core/src/error.rs +++ b/lib/runtime-core/src/error.rs @@ -266,6 +266,7 @@ impl std::fmt::Display for CallError { pub enum CreationError { UnableToCreateMemory, UnableToCreateTable, + InvalidDescriptor(String), } impl PartialEq for CreationError { @@ -279,6 +280,11 @@ impl std::fmt::Display for CreationError { match self { CreationError::UnableToCreateMemory => write!(f, "Unable to Create Memory"), CreationError::UnableToCreateTable => write!(f, "Unable to Create Table"), + CreationError::InvalidDescriptor(msg) => write!( + f, + "Unable to create because the supplied descriptor is invalid: \"{}\"", + msg + ), } } } diff --git a/lib/runtime-core/src/memory/mod.rs b/lib/runtime-core/src/memory/mod.rs index 30fab393e..56d4c643b 100644 --- a/lib/runtime-core/src/memory/mod.rs +++ b/lib/runtime-core/src/memory/mod.rs @@ -63,6 +63,15 @@ impl Memory { /// # } /// ``` pub fn new(desc: MemoryDescriptor) -> Result { + if let Some(max) = desc.maximum { + if max < desc.minimum { + return Err(CreationError::InvalidDescriptor( + "Max number of memory pages is less than the minimum number of pages" + .to_string(), + )); + } + } + let variant = if !desc.shared { MemoryVariant::Unshared(UnsharedMemory::new(desc)?) } else { diff --git a/lib/runtime-core/src/table/mod.rs b/lib/runtime-core/src/table/mod.rs index db4b943c8..1bad9a3c4 100644 --- a/lib/runtime-core/src/table/mod.rs +++ b/lib/runtime-core/src/table/mod.rs @@ -50,6 +50,14 @@ impl Table { /// # } /// ``` pub fn new(desc: TableDescriptor) -> Result { + if let Some(max) = desc.maximum { + if max < desc.minimum { + return Err(CreationError::InvalidDescriptor( + "Max table size is less than the minimum size".to_string(), + )); + } + } + let mut local = vm::LocalTable { base: ptr::null_mut(), count: 0, From cb29261ec7db6fbf007e2bbce39d1782cddc542f Mon Sep 17 00:00:00 2001 From: Christopher Serr Date: Sat, 16 Feb 2019 00:11:06 +0100 Subject: [PATCH 060/262] Use repr(transparent) for single element structs (#187) The ABI of aggregates such as single element structs is not required to be the same as the single elements themselves. This is especially true for f64 vs. #[repr(c)] struct F(f64); on Windows. Therefore the macro has been tweaked so S1 uses repr(transparent) which is made for exactly for this use case. Closes #183 --- lib/runtime-core/src/typed_func.rs | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/lib/runtime-core/src/typed_func.rs b/lib/runtime-core/src/typed_func.rs index e16307d8e..19efcbe4e 100644 --- a/lib/runtime-core/src/typed_func.rs +++ b/lib/runtime-core/src/typed_func.rs @@ -154,8 +154,8 @@ where } macro_rules! impl_traits { - ( $struct_name:ident, $( $x:ident ),* ) => { - #[repr(C)] + ( [$repr:ident] $struct_name:ident, $( $x:ident ),* ) => { + #[repr($repr)] pub struct $struct_name <$( $x ),*> ( $( $x ),* ); impl< $( $x: WasmExternType, )* > WasmTypeList for ( $( $x ),* ) { @@ -234,18 +234,18 @@ macro_rules! impl_traits { }; } -impl_traits!(S0,); -impl_traits!(S1, A); -impl_traits!(S2, A, B); -impl_traits!(S3, A, B, C); -impl_traits!(S4, A, B, C, D); -impl_traits!(S5, A, B, C, D, E); -impl_traits!(S6, A, B, C, D, E, F); -impl_traits!(S7, A, B, C, D, E, F, G); -impl_traits!(S8, A, B, C, D, E, F, G, H); -impl_traits!(S9, A, B, C, D, E, F, G, H, I); -impl_traits!(S10, A, B, C, D, E, F, G, H, I, J); -impl_traits!(S11, A, B, C, D, E, F, G, H, I, J, K); +impl_traits!([C] S0,); +impl_traits!([transparent] S1, A); +impl_traits!([C] S2, A, B); +impl_traits!([C] S3, A, B, C); +impl_traits!([C] S4, A, B, C, D); +impl_traits!([C] S5, A, B, C, D, E); +impl_traits!([C] S6, A, B, C, D, E, F); +impl_traits!([C] S7, A, B, C, D, E, F, G); +impl_traits!([C] S8, A, B, C, D, E, F, G, H); +impl_traits!([C] S9, A, B, C, D, E, F, G, H, I); +impl_traits!([C] S10, A, B, C, D, E, F, G, H, I, J); +impl_traits!([C] S11, A, B, C, D, E, F, G, H, I, J, K); impl<'a, Args, Rets, Safety> IsExport for Func<'a, Args, Rets, Safety> where From 108973dabecf0dabef3f5ba36ce81a9ad69a074c Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Fri, 15 Feb 2019 16:02:20 -0800 Subject: [PATCH 061/262] Start producing object files with llvm --- Cargo.lock | 39 +++++++++++++++++ lib/llvm-backend/Cargo.toml | 1 + lib/llvm-backend/src/backend.rs | 45 ++++++++++++++++++++ lib/llvm-backend/src/code.rs | 45 ++++++++++---------- lib/llvm-backend/src/lib.rs | 75 +++++++++++++++++++++++++++++++-- lib/runtime-core/src/types.rs | 2 +- 6 files changed, 180 insertions(+), 27 deletions(-) create mode 100644 lib/llvm-backend/src/backend.rs diff --git a/Cargo.lock b/Cargo.lock index 065209f0b..402ff214c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -345,6 +345,16 @@ name = "glob" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "goblin" +version = "0.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "plain 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "scroll 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "hashbrown" version = "0.1.8" @@ -439,6 +449,7 @@ dependencies = [ name = "llvm-backend" version = "0.1.0" dependencies = [ + "goblin 0.0.20 (registry+https://github.com/rust-lang/crates.io-index)", "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "inkwell 0.1.0 (git+https://github.com/TheDan64/inkwell?branch=llvm7-0)", "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -572,6 +583,11 @@ name = "peeking_take_while" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "plain" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "proc-macro2" version = "0.4.27" @@ -768,6 +784,25 @@ name = "scopeguard" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "scroll" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "scroll_derive 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "scroll_derive" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "semver" version = "0.9.0" @@ -1259,6 +1294,7 @@ dependencies = [ "checksum gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)" = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" "checksum generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c0f28c2f5bfb5960175af447a2da7c18900693738343dc896ffbcabd9839592" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" +"checksum goblin 0.0.20 (registry+https://github.com/rust-lang/crates.io-index)" = "84473a5302fa5094d3d9911c2f312f522f9a37462a777f195f63fae1bf7faf4d" "checksum hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3bae29b6653b3412c2e71e9d486db9f9df5d701941d86683005efb9f2d28e3da" "checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" "checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114" @@ -1285,6 +1321,7 @@ dependencies = [ "checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" "checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" "checksum peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" +"checksum plain 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" "checksum proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" @@ -1309,6 +1346,8 @@ dependencies = [ "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" +"checksum scroll 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2f84d114ef17fd144153d608fba7c446b0145d038985e7a8cc5d08bb0ce20383" +"checksum scroll_derive 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8f1aa96c45e7f5a91cb7fabe7b279f02fea7126239fc40b732316e8b6a2d0fcb" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" "checksum serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)" = "2e20fde37801e83c891a2dc4ebd3b81f0da4d1fb67a9e0a2a3b921e2536a58ee" diff --git a/lib/llvm-backend/Cargo.toml b/lib/llvm-backend/Cargo.toml index bcf2175e2..8ffac375f 100644 --- a/lib/llvm-backend/Cargo.toml +++ b/lib/llvm-backend/Cargo.toml @@ -10,6 +10,7 @@ wasmparser = "0.28.0" inkwell = { git = "https://github.com/TheDan64/inkwell", branch = "llvm7-0" } hashbrown = "0.1.8" smallvec = "0.6.8" +goblin = "0.0.20" [dev-dependencies] wabt = "0.7.4" diff --git a/lib/llvm-backend/src/backend.rs b/lib/llvm-backend/src/backend.rs new file mode 100644 index 000000000..9821eabf6 --- /dev/null +++ b/lib/llvm-backend/src/backend.rs @@ -0,0 +1,45 @@ +use inkwell::{ + module::Module, + execution_engine::{ExecutionEngine, JitFunction}, +}; +use crate::intrinsics::Intrinsics; +use std::ptr::NonNull; +use wasmer_runtime_core::{ + module::ModuleInner, + types::LocalFuncIndex, + structures::TypedIndex, + backend::{FuncResolver, vm}, +}; + +pub struct LLVMBackend { + exec_engine: ExecutionEngine, +} + +impl LLVMBackend { + pub fn new(module: Module, intrinsics: Intrinsics) -> Self { + let exec_engine = module.create_jit_execution_engine(OptimizationLevel::Default).unwrap(); + + exec_engine.add_global_mapping(&intrinsics.memory_grow_dynamic_local, vmcalls::local_dynamic_memory_grow as usize); + exec_engine.add_global_mapping(&intrinsics.memory_grow_static_local, vmcalls::local_static_memory_grow as usize); + exec_engine.add_global_mapping(&intrinsics.memory_grow_dynamic_import, vmcalls::imported_dynamic_memory_grow as usize); + exec_engine.add_global_mapping(&intrinsics.memory_grow_static_import, vmcalls::imported_static_memory_grow as usize); + exec_engine.add_global_mapping(&intrinsics.memory_size_dynamic_local, vmcalls::local_dynamic_memory_size as usize); + exec_engine.add_global_mapping(&intrinsics.memory_size_static_local, vmcalls::local_static_memory_size as usize); + exec_engine.add_global_mapping(&intrinsics.memory_size_dynamic_import, vmcalls::imported_dynamic_memory_size as usize); + exec_engine.add_global_mapping(&intrinsics.memory_size_static_import, vmcalls::imported_static_memory_size as usize); + + Self { exec_engine } + } +} + +impl FuncResolver for LLVMBackend { + fn get(&self, module: &ModuleInner, local_func_index: LocalFuncIndex) -> Option> { + let index = module.info.imported_functions.len() + local_func_index.index(); + let name = format!("fn{}", index); + + unsafe { + let func: JitFunction = self.exec_engine.get_function(&name).ok()?; + + } + } +} \ No newline at end of file diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index 48aac8dc2..48c477f4a 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -59,7 +59,7 @@ fn type_to_llvm(intrinsics: &Intrinsics, ty: Type) -> BasicTypeEnum { pub fn parse_function_bodies( info: &ModuleInfo, code_reader: CodeSectionReader, -) -> Result<(), BinaryReaderError> { +) -> Result<(Module, Intrinsics), BinaryReaderError> { let context = Context::create(); let module = context.create_module("module"); let builder = context.create_builder(); @@ -104,7 +104,22 @@ pub fn parse_function_bodies( )?; } - Ok(()) + let pass_manager = PassManager::create_for_module(); + pass_manager.add_promote_memory_to_register_pass(); + pass_manager.add_cfg_simplification_pass(); + pass_manager.add_instruction_combining_pass(); + // pass_manager.add_aggressive_inst_combiner_pass(); + // pass_manager.add_merged_load_store_motion_pass(); + // pass_manager.add_sccp_pass(); + pass_manager.add_gvn_pass(); + pass_manager.add_new_gvn_pass(); + pass_manager.add_aggressive_dce_pass(); + pass_manager.add_verifier_pass(); + pass_manager.run_on_module(&module); + + println!("{}", module.print_to_string().to_string()); + + Ok((module, intrinsics)) } fn parse_function( @@ -1668,30 +1683,14 @@ fn parse_function( &state.var_name(), ); state.push1(result.try_as_basic_value().left().unwrap()); - } // op @ _ => { - // println!("{}", module.print_to_string().to_string()); - // unimplemented!("{:?}", op); - // } + } + op @ _ => { + println!("{}", module.print_to_string().to_string()); + unimplemented!("{:?}", op); + } } } - println!("finished translating"); - - let pass_manager = PassManager::create_for_module(); - pass_manager.add_promote_memory_to_register_pass(); - pass_manager.add_cfg_simplification_pass(); - pass_manager.add_instruction_combining_pass(); - // pass_manager.add_aggressive_inst_combiner_pass(); - // pass_manager.add_merged_load_store_motion_pass(); - // pass_manager.add_sccp_pass(); - pass_manager.add_gvn_pass(); - pass_manager.add_new_gvn_pass(); - pass_manager.add_aggressive_dce_pass(); - pass_manager.add_verifier_pass(); - pass_manager.run_on_module(module); - - println!("{}", module.print_to_string().to_string()); - Ok(()) } diff --git a/lib/llvm-backend/src/lib.rs b/lib/llvm-backend/src/lib.rs index cd43c6aef..6279aa8e1 100644 --- a/lib/llvm-backend/src/lib.rs +++ b/lib/llvm-backend/src/lib.rs @@ -3,11 +3,17 @@ use wasmer_runtime_core::{ error::CompileError, module::ModuleInner, }; +use inkwell::{ + execution_engine::JitFunction, + targets::{TargetMachine, Target, RelocMode, CodeModel, InitializationConfig, FileType}, + OptimizationLevel, +}; mod code; mod intrinsics; mod read_info; mod state; +// mod backend; pub struct LLVMCompiler { _private: (), @@ -29,6 +35,7 @@ impl Compiler for LLVMCompiler { #[test] fn test_read_module() { + use wasmer_runtime_core::vmcalls; use wabt::wat2wasm; // let wasm = include_bytes!("../../spectests/examples/simple/simple.wasm") as &[u8]; let wat = r#" @@ -39,13 +46,75 @@ fn test_read_module() { (global $g0 (mut i32) (i32.const 0)) (func $foo (type $t0) (param i32) (result i32) get_local 0 - set_global $g0 - get_global $g0 + call $foobar + memory.grow + ) + (func $foobar (type $t0) + get_local 0 + ) + (func $bar (type $t0) (param i32) (result i32) + get_local 0 + call $foo )) "#; let wasm = wat2wasm(wat).unwrap(); let (info, code_reader) = read_info::read_module(&wasm).unwrap(); - code::parse_function_bodies(&info, code_reader).unwrap(); + let (module, intrinsics) = code::parse_function_bodies(&info, code_reader).unwrap(); + + { + Target::initialize_x86(&InitializationConfig { + asm_parser: true, + asm_printer: true, + base: true, + disassembler: true, + info: true, + machine_code: true, + }); + let triple = TargetMachine::get_default_triple().to_string(); + let target = Target::from_triple(&triple).unwrap(); + let target_machine = target.create_target_machine( + &triple, + &TargetMachine::get_host_cpu_name().to_string(), + &TargetMachine::get_host_cpu_features().to_string(), + OptimizationLevel::Default, + RelocMode::PIC, + CodeModel::Default, + ).unwrap(); + + let memory_buffer = target_machine.write_to_memory_buffer(&module, FileType::Object).unwrap(); + // std::fs::write("memory_buffer", memory_buffer.as_slice()).unwrap(); + let mem_buf_slice = memory_buffer.as_slice(); + + let macho = goblin::mach::MachO::parse(mem_buf_slice, 0).unwrap(); + let symbols = macho.symbols.as_ref().unwrap(); + let relocations = macho.relocations().unwrap(); + for (_, reloc_iter, section) in relocations.into_iter() { + println!("section: {:#?}", section); + for reloc_info in reloc_iter { + let reloc_info = reloc_info.unwrap(); + println!("\treloc_info: {:#?}", reloc_info); + println!("\tsymbol: {:#?}", symbols.get(reloc_info.r_symbolnum()).unwrap()); + } + } + } + + + let exec_engine = module.create_jit_execution_engine(OptimizationLevel::Default).unwrap(); + + exec_engine.add_global_mapping(&intrinsics.memory_grow_dynamic_local, vmcalls::local_dynamic_memory_grow as usize); + exec_engine.add_global_mapping(&intrinsics.memory_grow_static_local, vmcalls::local_static_memory_grow as usize); + exec_engine.add_global_mapping(&intrinsics.memory_grow_dynamic_import, vmcalls::imported_dynamic_memory_grow as usize); + exec_engine.add_global_mapping(&intrinsics.memory_grow_static_import, vmcalls::imported_static_memory_grow as usize); + exec_engine.add_global_mapping(&intrinsics.memory_size_dynamic_local, vmcalls::local_dynamic_memory_size as usize); + exec_engine.add_global_mapping(&intrinsics.memory_size_static_local, vmcalls::local_static_memory_size as usize); + exec_engine.add_global_mapping(&intrinsics.memory_size_dynamic_import, vmcalls::imported_dynamic_memory_size as usize); + exec_engine.add_global_mapping(&intrinsics.memory_size_static_import, vmcalls::imported_static_memory_size as usize); + + // unsafe { + // let func: JitFunction i32> = exec_engine.get_function("fn0").unwrap(); + // let result = func.call(0 as _, 0); + // println!("result: {}", result); + // } } diff --git a/lib/runtime-core/src/types.rs b/lib/runtime-core/src/types.rs index bec1500b6..d3cd937bc 100644 --- a/lib/runtime-core/src/types.rs +++ b/lib/runtime-core/src/types.rs @@ -1,6 +1,6 @@ use crate::{ memory::MemoryType, - module::{ModuleInfo, ModuleInner}, + module::ModuleInfo, structures::TypedIndex, units::Pages, }; From 9ee86138b961ec682697c0e69ba792ba4ea6d848 Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Fri, 15 Feb 2019 19:16:19 -0600 Subject: [PATCH 062/262] Impl Error for CallError --- lib/runtime-core/src/error.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/runtime-core/src/error.rs b/lib/runtime-core/src/error.rs index e88a5692c..33c9fd15f 100644 --- a/lib/runtime-core/src/error.rs +++ b/lib/runtime-core/src/error.rs @@ -260,6 +260,8 @@ impl std::fmt::Display for CallError { } } +impl std::error::Error for CallError {} + /// This error type is produced when creating something, /// like a `Memory` or a `Table`. #[derive(Debug, Clone)] From 56079ad58937be68ba9188bd56135544bc36c6ff Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Fri, 15 Feb 2019 19:47:00 -0600 Subject: [PATCH 063/262] Add compile Module function --- lib/runtime-c-api/src/lib.rs | 41 ++++++++++++++++++- lib/runtime-c-api/tests/.gitignore | 1 + lib/runtime-c-api/tests/CMakeLists.txt | 4 ++ .../tests/test-import-function.c | 13 +++--- lib/runtime-c-api/tests/test-instantiate.c | 2 +- lib/runtime-c-api/tests/test-module.c | 27 ++++++++++++ lib/runtime-c-api/wasmer.h | 17 ++++++++ lib/runtime-c-api/wasmer.hh | 13 ++++++ 8 files changed, 111 insertions(+), 7 deletions(-) create mode 100644 lib/runtime-c-api/tests/test-module.c diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index 511f4304a..733e10fb8 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -12,7 +12,7 @@ use std::slice; use std::str; use std::sync::Arc; use std::{ffi::c_void, mem, ptr}; -use wasmer_runtime::{Ctx, Global, ImportObject, Instance, Memory, Table, Value}; +use wasmer_runtime::{Ctx, Global, ImportObject, Instance, Memory, Module, Table, Value}; use wasmer_runtime_core::export::{Context, Export, FuncPointer}; use wasmer_runtime_core::import::{LikeNamespace, Namespace}; use wasmer_runtime_core::types::{ @@ -23,6 +23,9 @@ use wasmer_runtime_core::units::{Bytes, Pages}; #[allow(non_camel_case_types)] pub struct wasmer_import_object_t(); +#[allow(non_camel_case_types)] +pub struct wasmer_module_t(); + #[allow(non_camel_case_types)] pub struct wasmer_instance_t(); @@ -379,6 +382,42 @@ pub extern "C" fn wasmer_memory_destroy(memory: *mut wasmer_memory_t) { } } +/// Creates a new Module from the given wasm bytes. +/// +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub unsafe extern "C" fn wasmer_compile( + mut module: *mut *mut wasmer_module_t, + wasm_bytes: *mut uint8_t, + wasm_bytes_len: uint32_t, +) -> wasmer_result_t { + let bytes: &[u8] = + unsafe { ::std::slice::from_raw_parts_mut(wasm_bytes, wasm_bytes_len as usize) }; + let result = wasmer_runtime::compile(bytes); + let new_module = match result { + Ok(instance) => instance, + Err(error) => { + update_last_error(error); + return wasmer_result_t::WASMER_ERROR; + } + }; + unsafe { *module = Box::into_raw(Box::new(new_module)) as *mut wasmer_module_t }; + wasmer_result_t::WASMER_OK +} + +/// Frees memory for the given Module +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub extern "C" fn wasmer_module_destroy(module: *mut wasmer_module_t) { + if !module.is_null() { + drop(unsafe { Box::from_raw(module as *mut Module) }); + } +} + /// Creates a new Instance from the given wasm bytes and imports. /// /// Returns `wasmer_result_t::WASMER_OK` upon success. diff --git a/lib/runtime-c-api/tests/.gitignore b/lib/runtime-c-api/tests/.gitignore index c8dfca857..6ea57c28d 100644 --- a/lib/runtime-c-api/tests/.gitignore +++ b/lib/runtime-c-api/tests/.gitignore @@ -14,6 +14,7 @@ test-exports test-instantiate test-import-function test-memory +test-module test-tables test-validate rust-build \ No newline at end of file diff --git a/lib/runtime-c-api/tests/CMakeLists.txt b/lib/runtime-c-api/tests/CMakeLists.txt index ce970d4bf..788ee1c6a 100644 --- a/lib/runtime-c-api/tests/CMakeLists.txt +++ b/lib/runtime-c-api/tests/CMakeLists.txt @@ -6,6 +6,7 @@ add_executable(test-globals test-globals.c) add_executable(test-instantiate test-instantiate.c) add_executable(test-import-function test-import-function.c) add_executable(test-memory test-memory.c) +add_executable(test-module test-module.c) add_executable(test-validate test-validate.c) add_executable(test-tables test-tables.c) @@ -28,6 +29,8 @@ target_link_libraries(test-import-function general ${WASMER_LIB}) target_link_libraries(test-memory general ${WASMER_LIB}) +target_link_libraries(test-module + general ${WASMER_LIB}) target_link_libraries(test-validate general ${WASMER_LIB}) target_link_libraries(test-tables @@ -39,6 +42,7 @@ add_test(test-globals test-globals) add_test(test-instantiate test-instantiate) add_test(test-import-function test-import-function) add_test(test-memory test-memory) +add_test(test-module test-module) add_test(test-validate test-validate) add_test(test-tables test-tables) diff --git a/lib/runtime-c-api/tests/test-import-function.c b/lib/runtime-c-api/tests/test-import-function.c index 2c241be55..54390b863 100644 --- a/lib/runtime-c-api/tests/test-import-function.c +++ b/lib/runtime-c-api/tests/test-import-function.c @@ -67,17 +67,20 @@ int main() wasmer_instance_t *instance = NULL; wasmer_result_t compile_result = wasmer_instantiate(&instance, bytes, len, imports, 1); printf("Compile result: %d\n", compile_result); - int error_len = wasmer_last_error_length(); - printf("Error len: `%d`\n", error_len); - char *error_str = malloc(error_len); - wasmer_last_error_message(error_str, error_len); - printf("Error str: `%s`\n", error_str); + assert(compile_result == WASMER_OK); wasmer_value_t params[] = {}; wasmer_value_t results[] = {}; wasmer_result_t call_result = wasmer_instance_call(instance, "hello_wasm", params, 0, results, 0); printf("Call result: %d\n", call_result); + + int error_len = wasmer_last_error_length(); + printf("Error len: `%d`\n", error_len); + char *error_str = malloc(error_len); + wasmer_last_error_message(error_str, error_len); + printf("Error str: `%s`\n", error_str); + assert(call_result == WASMER_OK); assert(print_str_called); diff --git a/lib/runtime-c-api/tests/test-instantiate.c b/lib/runtime-c-api/tests/test-instantiate.c index 63adf11c1..f276b8dee 100644 --- a/lib/runtime-c-api/tests/test-instantiate.c +++ b/lib/runtime-c-api/tests/test-instantiate.c @@ -48,7 +48,7 @@ int main() char *error_str = malloc(error_len); wasmer_last_error_message(error_str, error_len); printf("Error str: `%s`\n", error_str); - assert(0 == strcmp(error_str, "Call error")); + assert(0 == strcmp(error_str, "Call error: Parameters of type [I32] did not match signature [I32, I32] -> [I32]")); free(error_str); printf("Destroy instance\n"); diff --git a/lib/runtime-c-api/tests/test-module.c b/lib/runtime-c-api/tests/test-module.c new file mode 100644 index 000000000..5948fd26b --- /dev/null +++ b/lib/runtime-c-api/tests/test-module.c @@ -0,0 +1,27 @@ +#include +#include "../wasmer.h" +#include +#include + +int main() +{ + // Read the wasm file bytes + FILE *file = fopen("sum.wasm", "r"); + fseek(file, 0, SEEK_END); + long len = ftell(file); + uint8_t *bytes = malloc(len); + fseek(file, 0, SEEK_SET); + fread(bytes, 1, len, file); + fclose(file); + + wasmer_module_t *module = NULL; + wasmer_result_t compile_result = wasmer_compile(&module, bytes, len); + printf("Compile result: %d\n", compile_result); + assert(compile_result == WASMER_OK); + + // TODO add module exports + + printf("Destroy module\n"); + wasmer_module_destroy(module); + return 0; +} \ No newline at end of file diff --git a/lib/runtime-c-api/wasmer.h b/lib/runtime-c-api/wasmer.h index efc840400..3434d1a10 100644 --- a/lib/runtime-c-api/wasmer.h +++ b/lib/runtime-c-api/wasmer.h @@ -33,6 +33,8 @@ typedef struct wasmer_instance_context_t wasmer_instance_context_t; typedef struct wasmer_instance_t wasmer_instance_t; +typedef struct wasmer_module_t wasmer_module_t; + typedef struct { } wasmer_export_t; @@ -98,6 +100,16 @@ typedef struct { uint32_t max; } wasmer_limits_t; +/** + * Creates a new Module from the given wasm bytes. + * Returns `wasmer_result_t::WASMER_OK` upon success. + * Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` + * and `wasmer_last_error_message` to get an error message. + */ +wasmer_result_t wasmer_compile(wasmer_module_t **module, + uint8_t *wasm_bytes, + uint32_t wasm_bytes_len); + /** * Gets wasmer_export kind */ @@ -317,6 +329,11 @@ uint32_t wasmer_memory_length(wasmer_memory_t *memory); */ wasmer_result_t wasmer_memory_new(wasmer_memory_t **memory, wasmer_limits_t limits); +/** + * Frees memory for the given Module + */ +void wasmer_module_destroy(wasmer_module_t *module); + /** * Frees memory for the given Table */ diff --git a/lib/runtime-c-api/wasmer.hh b/lib/runtime-c-api/wasmer.hh index 0192e8555..3b6ca9551 100644 --- a/lib/runtime-c-api/wasmer.hh +++ b/lib/runtime-c-api/wasmer.hh @@ -30,6 +30,8 @@ struct wasmer_instance_context_t; struct wasmer_instance_t; +struct wasmer_module_t; + struct wasmer_export_t { }; @@ -97,6 +99,14 @@ struct wasmer_limits_t { extern "C" { +/// Creates a new Module from the given wasm bytes. +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +wasmer_result_t wasmer_compile(wasmer_module_t **module, + uint8_t *wasm_bytes, + uint32_t wasm_bytes_len); + /// Gets wasmer_export kind wasmer_import_export_kind wasmer_export_kind(wasmer_export_t *export_); @@ -256,6 +266,9 @@ uint32_t wasmer_memory_length(wasmer_memory_t *memory); /// and `wasmer_last_error_message` to get an error message. wasmer_result_t wasmer_memory_new(wasmer_memory_t **memory, wasmer_limits_t limits); +/// Frees memory for the given Module +void wasmer_module_destroy(wasmer_module_t *module); + /// Frees memory for the given Table void wasmer_table_destroy(wasmer_table_t *table); From a9b1c6c85e97a9b7a9b16f20c0849de7870bc1b4 Mon Sep 17 00:00:00 2001 From: David McNeil Date: Sun, 10 Feb 2019 15:24:04 -0700 Subject: [PATCH 064/262] Fix emscripten environment (#172) Dynamically determine abortOnCannotGrowMemory and add _emscripten_get_heap_size and _emscripten_resize_heap --- Cargo.lock | 1 + lib/emscripten/Cargo.toml | 1 + lib/emscripten/emtests/FS_exports.wasm | Bin 22094 -> 22032 bytes lib/emscripten/emtests/clock_gettime.wasm | Bin 45371 -> 45309 bytes lib/emscripten/emtests/closebitcasts.wasm | Bin 46013 -> 45951 bytes lib/emscripten/emtests/dyncall.wasm | Bin 22190 -> 22128 bytes lib/emscripten/emtests/dyncall_specific.wasm | Bin 22180 -> 22118 bytes .../emscripten_get_compiler_setting.wasm | Bin 45752 -> 45690 bytes lib/emscripten/emtests/env.wasm | Bin 46217 -> 46155 bytes lib/emscripten/emtests/getValue_setValue.wasm | Bin 22007 -> 21945 bytes .../legacy_exported_runtime_numbers.wasm | Bin 21966 -> 21904 bytes lib/emscripten/emtests/localtime.wasm | Bin 45609 -> 45547 bytes .../emtests/modularize_closure_pre.wasm | Bin 21950 -> 21888 bytes lib/emscripten/emtests/printf.wasm | Bin 47042 -> 46980 bytes lib/emscripten/emtests/puts.wasm | Bin 23716 -> 23654 bytes lib/emscripten/emtests/stackAlloc.wasm | Bin 22912 -> 22850 bytes lib/emscripten/emtests/stack_overflow.wasm | Bin 45898 -> 45836 bytes .../emtests/test_addr_of_stacked.wasm | Bin 45426 -> 45364 bytes lib/emscripten/emtests/test_alloca.wasm | Bin 45765 -> 45703 bytes lib/emscripten/emtests/test_alloca_stack.wasm | Bin 45559 -> 45497 bytes lib/emscripten/emtests/test_array2.wasm | Bin 45559 -> 45497 bytes lib/emscripten/emtests/test_array2b.wasm | Bin 45471 -> 45409 bytes lib/emscripten/emtests/test_atoX.wasm | Bin 47524 -> 47462 bytes lib/emscripten/emtests/test_atomic.wasm | Bin 45747 -> 45685 bytes lib/emscripten/emtests/test_atomic_cxx.wasm | Bin 87513 -> 87451 bytes lib/emscripten/emtests/test_bsearch.wasm | Bin 46089 -> 46027 bytes lib/emscripten/emtests/test_ccall.wasm | Bin 21861 -> 21799 bytes lib/emscripten/emtests/test_complex.wasm | Bin 60388 -> 60326 bytes .../emtests/test_demangle_stacks.wasm | Bin 22098 -> 22036 bytes .../test_demangle_stacks_noassert.wasm | Bin 22037 -> 21975 bytes .../emtests/test_dlmalloc_partial_2.wasm | Bin 7728 -> 7647 bytes .../emtests/test_double_varargs.wasm | Bin 46051 -> 45989 bytes lib/emscripten/emtests/test_em_asm.wasm | Bin 48055 -> 47993 bytes lib/emscripten/emtests/test_em_asm_2.wasm | Bin 55472 -> 55411 bytes .../emtests/test_em_asm_parameter_pack.wasm | Bin 22274 -> 22212 bytes .../emtests/test_em_asm_signatures.wasm | Bin 46362 -> 46300 bytes .../emtests/test_em_asm_unicode.wasm | Bin 21942 -> 21880 bytes .../emtests/test_em_asm_unused_arguments.wasm | Bin 45421 -> 45359 bytes lib/emscripten/emtests/test_em_js.wasm | Bin 48354 -> 48293 bytes .../emtests/test_emscripten_api.wasm | Bin 78408 -> 78346 bytes .../test_emulate_function_pointer_casts.wasm | Bin 46873 -> 46811 bytes lib/emscripten/emtests/test_erf.wasm | Bin 48761 -> 48699 bytes lib/emscripten/emtests/test_errar.wasm | Bin 45928 -> 45866 bytes lib/emscripten/emtests/test_exceptions_2.wasm | Bin 50281 -> 50219 bytes .../emtests/test_exceptions_convert.wasm | Bin 344256 -> 344186 bytes .../test_exceptions_destroy_virtual.wasm | Bin 327017 -> 326896 bytes .../emtests/test_exceptions_libcxx.wasm | Bin 325856 -> 325750 bytes .../emtests/test_exceptions_multi.wasm | Bin 49781 -> 49719 bytes .../test_exceptions_multiple_inherit.wasm | Bin 55239 -> 55170 bytes ...t_exceptions_multiple_inherit_rethrow.wasm | Bin 324016 -> 323921 bytes .../emtests/test_exceptions_primary.wasm | Bin 325780 -> 325685 bytes .../emtests/test_exceptions_refcount.wasm | Bin 49382 -> 49320 bytes .../emtests/test_exceptions_resume.wasm | Bin 57559 -> 57494 bytes .../emtests/test_exceptions_rethrow.wasm | Bin 344720 -> 344648 bytes .../emtests/test_exceptions_simplify_cfg.wasm | Bin 53402 -> 53338 bytes .../emtests/test_exceptions_std.wasm | Bin 49623 -> 49561 bytes .../test_exceptions_virtual_inheritance.wasm | Bin 327012 -> 326885 bytes .../emtests/test_exceptions_white_list.wasm | Bin 49450 -> 49388 bytes lib/emscripten/emtests/test_fast_math.wasm | Bin 59793 -> 59731 bytes .../emtests/test_flexarray_struct.wasm | Bin 45438 -> 45376 bytes .../emtests/test_float32_precise.wasm | Bin 45679 -> 45617 bytes .../emtests/test_float_builtins.wasm | Bin 48662 -> 48600 bytes lib/emscripten/emtests/test_frexp.wasm | Bin 45900 -> 45838 bytes lib/emscripten/emtests/test_funcptr.wasm | Bin 46998 -> 46936 bytes .../emtests/test_funcptr_namecollide.wasm | Bin 24131 -> 24069 bytes lib/emscripten/emtests/test_funcptrfunc.wasm | Bin 45451 -> 45389 bytes lib/emscripten/emtests/test_funcs.wasm | Bin 45418 -> 45356 bytes .../test_functionpointer_libfunc_varargs.wasm | Bin 47604 -> 47542 bytes lib/emscripten/emtests/test_fwrite_0.wasm | Bin 48914 -> 48852 bytes lib/emscripten/emtests/test_getgep.wasm | Bin 45462 -> 45400 bytes lib/emscripten/emtests/test_getloadavg.wasm | Bin 45780 -> 45718 bytes lib/emscripten/emtests/test_getopt.wasm | Bin 50592 -> 50530 bytes lib/emscripten/emtests/test_getopt_long.wasm | Bin 52928 -> 52866 bytes .../emtests/test_globaldoubles.wasm | Bin 45649 -> 45587 bytes lib/emscripten/emtests/test_globals.wasm | Bin 45416 -> 45354 bytes lib/emscripten/emtests/test_gmtime.wasm | Bin 45895 -> 45833 bytes lib/emscripten/emtests/test_hello_world.wasm | Bin 45340 -> 45278 bytes .../emtests/test_i16_emcc_intrinsic.wasm | Bin 45690 -> 45628 bytes .../emtests/test_i32_mul_precise.wasm | Bin 45432 -> 45370 bytes lib/emscripten/emtests/test_i64.wasm | Bin 45955 -> 45893 bytes lib/emscripten/emtests/test_i64_4.wasm | Bin 45500 -> 45438 bytes lib/emscripten/emtests/test_i64_7z.wasm | Bin 45706 -> 45644 bytes lib/emscripten/emtests/test_i64_cmp2.wasm | Bin 45593 -> 45531 bytes lib/emscripten/emtests/test_i64_i16.wasm | Bin 45456 -> 45394 bytes lib/emscripten/emtests/test_i64_llabs.wasm | Bin 45441 -> 45379 bytes lib/emscripten/emtests/test_i64_precise.wasm | Bin 46563 -> 46501 bytes .../emtests/test_i64_precise_needed.wasm | Bin 45407 -> 45345 bytes .../emtests/test_i64_precise_unneeded.wasm | Bin 45533 -> 45471 bytes lib/emscripten/emtests/test_i64_qdouble.wasm | Bin 45508 -> 45446 bytes lib/emscripten/emtests/test_i64_umul.wasm | Bin 45451 -> 45389 bytes lib/emscripten/emtests/test_i64_varargs.wasm | Bin 46011 -> 45949 bytes lib/emscripten/emtests/test_i64_zextneg.wasm | Bin 45500 -> 45438 bytes lib/emscripten/emtests/test_if.wasm | Bin 45360 -> 45298 bytes lib/emscripten/emtests/test_if_else.wasm | Bin 45385 -> 45323 bytes lib/emscripten/emtests/test_indirectbr.wasm | Bin 45608 -> 45546 bytes .../emtests/test_indirectbr_many.wasm | Bin 191435 -> 191374 bytes .../emtests/test_intentional_fault.wasm | Bin 21940 -> 21878 bytes lib/emscripten/emtests/test_isnan.wasm | Bin 45811 -> 45749 bytes lib/emscripten/emtests/test_libcextra.wasm | Bin 45463 -> 45401 bytes lib/emscripten/emtests/test_libgen.wasm | Bin 47612 -> 47550 bytes .../emtests/test_literal_negative_zero.wasm | Bin 45521 -> 45459 bytes lib/emscripten/emtests/test_llrint.wasm | Bin 45677 -> 45615 bytes lib/emscripten/emtests/test_llvm_fabs.wasm | Bin 45718 -> 45656 bytes .../emtests/test_llvm_intrinsics.wasm | Bin 52152 -> 52090 bytes lib/emscripten/emtests/test_llvmswitch.wasm | Bin 45753 -> 45691 bytes lib/emscripten/emtests/test_longjmp.wasm | Bin 52195 -> 52165 bytes lib/emscripten/emtests/test_longjmp2.wasm | Bin 52480 -> 52450 bytes lib/emscripten/emtests/test_longjmp3.wasm | Bin 52637 -> 52607 bytes lib/emscripten/emtests/test_longjmp4.wasm | Bin 52329 -> 52299 bytes lib/emscripten/emtests/test_longjmp_exc.wasm | Bin 52164 -> 52134 bytes .../emtests/test_longjmp_funcptr.wasm | Bin 51754 -> 51724 bytes .../emtests/test_longjmp_repeat.wasm | Bin 51781 -> 51751 bytes .../emtests/test_longjmp_stacked.wasm | Bin 52731 -> 52701 bytes .../emtests/test_longjmp_throw.wasm | Bin 56374 -> 56330 bytes .../emtests/test_longjmp_unwind.wasm | Bin 52942 -> 52912 bytes lib/emscripten/emtests/test_loop.wasm | Bin 45520 -> 45458 bytes .../emtests/test_lower_intrinsics.wasm | Bin 22318 -> 22256 bytes .../test_main_module_static_align.wasm | Bin 22485 -> 22423 bytes .../test_main_thread_async_em_asm.wasm | Bin 45532 -> 45470 bytes lib/emscripten/emtests/test_mainenv.wasm | Bin 45354 -> 45292 bytes lib/emscripten/emtests/test_mathfuncptr.wasm | Bin 47917 -> 47855 bytes lib/emscripten/emtests/test_memcpy2.wasm | Bin 46023 -> 45961 bytes lib/emscripten/emtests/test_memcpy3.wasm | Bin 64602 -> 64540 bytes .../emtests/test_memcpy_memcmp.wasm | Bin 46998 -> 46936 bytes lib/emscripten/emtests/test_memmove.wasm | Bin 23929 -> 23867 bytes lib/emscripten/emtests/test_memmove2.wasm | Bin 46011 -> 45949 bytes lib/emscripten/emtests/test_memmove3.wasm | Bin 23962 -> 23900 bytes lib/emscripten/emtests/test_memorygrowth.wasm | Bin 46425 -> 46363 bytes .../emtests/test_memorygrowth_2.wasm | Bin 46494 -> 46432 bytes .../emtests/test_memorygrowth_3.wasm | Bin 46942 -> 46880 bytes .../test_memorygrowth_wasm_mem_max.wasm | Bin 45652 -> 45590 bytes lib/emscripten/emtests/test_memset.wasm | Bin 64062 -> 64000 bytes lib/emscripten/emtests/test_mmap.wasm | Bin 50747 -> 50685 bytes .../emtests/test_negative_zero.wasm | Bin 47380 -> 47318 bytes .../emtests/test_nested_struct_varargs.wasm | Bin 46093 -> 46031 bytes lib/emscripten/emtests/test_nl_types.wasm | Bin 45442 -> 45380 bytes lib/emscripten/emtests/test_perrar.wasm | Bin 28112 -> 28050 bytes lib/emscripten/emtests/test_phiundef.wasm | Bin 45493 -> 45431 bytes lib/emscripten/emtests/test_poll.wasm | Bin 46611 -> 46549 bytes lib/emscripten/emtests/test_posixtime.wasm | Bin 46883 -> 46821 bytes lib/emscripten/emtests/test_printf_2.wasm | Bin 45568 -> 45506 bytes lib/emscripten/emtests/test_printf_more.wasm | Bin 47994 -> 47932 bytes lib/emscripten/emtests/test_regex.wasm | Bin 115265 -> 115192 bytes .../test_relocatable_void_function.wasm | Bin 23709 -> 23647 bytes lib/emscripten/emtests/test_rounding.wasm | Bin 48991 -> 48929 bytes .../emtests/test_runtime_stacksave.wasm | Bin 22209 -> 22147 bytes lib/emscripten/emtests/test_set_align.wasm | Bin 46169 -> 46107 bytes lib/emscripten/emtests/test_siglongjmp.wasm | Bin 29956 -> 29926 bytes lib/emscripten/emtests/test_sintvars.wasm | Bin 45921 -> 45859 bytes lib/emscripten/emtests/test_sizeof.wasm | Bin 46414 -> 46352 bytes lib/emscripten/emtests/test_sscanf.wasm | Bin 79801 -> 79739 bytes lib/emscripten/emtests/test_sscanf_3.wasm | Bin 76713 -> 76651 bytes lib/emscripten/emtests/test_sscanf_4.wasm | Bin 76468 -> 76406 bytes lib/emscripten/emtests/test_sscanf_5.wasm | Bin 76533 -> 76471 bytes lib/emscripten/emtests/test_sscanf_6.wasm | Bin 77211 -> 77149 bytes lib/emscripten/emtests/test_sscanf_caps.wasm | Bin 76515 -> 76453 bytes lib/emscripten/emtests/test_sscanf_float.wasm | Bin 76849 -> 76787 bytes lib/emscripten/emtests/test_sscanf_hex.wasm | Bin 82108 -> 82044 bytes lib/emscripten/emtests/test_sscanf_n.wasm | Bin 76828 -> 76766 bytes .../emtests/test_sscanf_other_whitespace.wasm | Bin 76694 -> 76632 bytes lib/emscripten/emtests/test_sscanf_skip.wasm | Bin 76584 -> 76522 bytes .../emtests/test_sscanf_whitespace.wasm | Bin 76632 -> 76570 bytes lib/emscripten/emtests/test_stack_align.wasm | Bin 45827 -> 45765 bytes .../emtests/test_stack_varargs.wasm | Bin 46274 -> 46212 bytes lib/emscripten/emtests/test_stack_void.wasm | Bin 50566 -> 50504 bytes lib/emscripten/emtests/test_statvfs.wasm | Bin 46625 -> 46563 bytes lib/emscripten/emtests/test_std_cout_new.wasm | Bin 322459 -> 322319 bytes lib/emscripten/emtests/test_strcasecmp.wasm | Bin 48844 -> 48782 bytes lib/emscripten/emtests/test_strcmp_uni.wasm | Bin 46634 -> 46572 bytes lib/emscripten/emtests/test_strftime.wasm | Bin 52228 -> 52166 bytes lib/emscripten/emtests/test_strings.wasm | Bin 80264 -> 80202 bytes lib/emscripten/emtests/test_strndup.wasm | Bin 45859 -> 45797 bytes .../emtests/test_strptime_days.wasm | Bin 46120 -> 46058 bytes .../emtests/test_strptime_reentrant.wasm | Bin 46730 -> 46668 bytes lib/emscripten/emtests/test_strstr.wasm | Bin 51369 -> 51307 bytes lib/emscripten/emtests/test_strtod.wasm | Bin 60733 -> 60671 bytes lib/emscripten/emtests/test_strtok.wasm | Bin 48253 -> 48191 bytes lib/emscripten/emtests/test_strtol_bin.wasm | Bin 50336 -> 50274 bytes lib/emscripten/emtests/test_strtol_dec.wasm | Bin 50501 -> 50439 bytes lib/emscripten/emtests/test_strtol_hex.wasm | Bin 50509 -> 50447 bytes lib/emscripten/emtests/test_strtol_oct.wasm | Bin 50503 -> 50441 bytes lib/emscripten/emtests/test_strtold.wasm | Bin 60735 -> 60673 bytes lib/emscripten/emtests/test_strtoll_bin.wasm | Bin 50348 -> 50286 bytes lib/emscripten/emtests/test_strtoll_dec.wasm | Bin 50514 -> 50452 bytes lib/emscripten/emtests/test_strtoll_hex.wasm | Bin 50530 -> 50468 bytes lib/emscripten/emtests/test_strtoll_oct.wasm | Bin 50516 -> 50454 bytes .../emtests/test_struct_varargs.wasm | Bin 46403 -> 46341 bytes lib/emscripten/emtests/test_time_c.wasm | Bin 45558 -> 45496 bytes lib/emscripten/emtests/test_tracing.wasm | Bin 21917 -> 21855 bytes lib/emscripten/emtests/test_transtrcase.wasm | Bin 24210 -> 24148 bytes lib/emscripten/emtests/test_trickystring.wasm | Bin 45434 -> 45372 bytes lib/emscripten/emtests/test_uname.wasm | Bin 45692 -> 45630 bytes .../emtests/test_unary_literal.wasm | Bin 45550 -> 45488 bytes lib/emscripten/emtests/test_utf.wasm | Bin 45880 -> 45818 bytes lib/emscripten/emtests/test_varargs.wasm | Bin 49742 -> 49680 bytes .../emtests/test_varargs_multi.wasm | Bin 45886 -> 45824 bytes lib/emscripten/emtests/test_vprintf.wasm | Bin 45463 -> 45401 bytes lib/emscripten/emtests/test_vsnprintf.wasm | Bin 47707 -> 47645 bytes lib/emscripten/emtests/test_wprintf.wasm | Bin 64670 -> 64609 bytes .../emtests/test_write_stdout_fileno.wasm | Bin 22394 -> 22332 bytes .../emtests/test_zero_multiplication.wasm | Bin 45595 -> 45533 bytes lib/emscripten/emtests/test_zerodiv.wasm | Bin 45725 -> 45663 bytes lib/emscripten/src/lib.rs | 44 ++++++++++++++++-- lib/emscripten/src/memory.rs | 23 ++++++++- lib/runtime-core/src/lib.rs | 2 + 205 files changed, 67 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5f55a2ea5..6d301f57f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1036,6 +1036,7 @@ version = "0.1.0" dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.48 (git+https://github.com/rust-lang/libc)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/lib/emscripten/Cargo.toml b/lib/emscripten/Cargo.toml index 36831f87d..648817eec 100644 --- a/lib/emscripten/Cargo.toml +++ b/lib/emscripten/Cargo.toml @@ -10,6 +10,7 @@ build = "build/mod.rs" [dependencies] wasmer-runtime-core = { path = "../runtime-core", version = "0.1.0" } +lazy_static = "1.2.0" libc = { git = "https://github.com/rust-lang/libc" } byteorder = "1" time = "0.1.41" diff --git a/lib/emscripten/emtests/FS_exports.wasm b/lib/emscripten/emtests/FS_exports.wasm index 5c65988e014f0d0fd166676736646ddd1fb7d9b8..255839e4ddb17591f532be0b716b02a0e2cd6ebc 100644 GIT binary patch delta 1727 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 LIoBXwKi~Xc*IGc& diff --git a/lib/emscripten/emtests/closebitcasts.wasm b/lib/emscripten/emtests/closebitcasts.wasm index 89ed015d5bf2bd2aa0749c8177532d1a4ede98e6..82d90c281ace13188bb1ce904056f7b159692d22 100644 GIT binary patch delta 3554 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 delta 1837 zcmZuxYitx%6uxI3JF|1Q?6jp6cH8CL&i3JgZm~RkK-i(Q0<{m)qQ)4v+jR?Vm))|v zEjD7dA^6Wk%|vO!9}^Oz5e;UIF)>jLK9K&vh=~ayU{Ip|zz|JLeEjg-Esy?Sk~#OD z@1FNL_uf1O@4pAHM)oo&k3yM^D&;cmv@(6P630dvTjH7Wt`=4^x!IabE}JUs&-7;w z<_mL7mDq~?nbJtUl*--)y$_&yef6j=HI^@whD)jR)ZlEUFrLjHW}4LDxtVOXcP5uk zPE0WEwL|sgDqM31o}G{fQq)K$li7TF>XssL#Z0NEP#DNBAvF@2E2dM~?1qhwR@%1_WtZpojw3L>C;n*hBTXz?z>P(&IxhezD*zLCKpwag^% zuky)$_bCsRo`(d2su_l&f(DF%3QPml1TcxweSTnyFI`&(N8v`%DRxUxaQ(AHTgCKR|6Q1(_)na(P*pRB0lgV-X`cKAxQ^9$>9{a=ehqur+$} zU}_@A8Vy>rB*<3NE^{zFJ;yq#JE|kQPfr%d3R5g*JvW!@COO%Vb%8rfx9r3EJAAb* z_t$5NrPNqT1-!c1-`Un~u0N=4RglJ$`Th0I~r;2l*v%MXO&acqi* z92aWp=ERa(=SOcF)E!qr;Nr z<90-xGVzq@1~w~{r~o`?Myp4Eh2d?5GWIS!`YSAWA8-AJ=+SLmuu%DE+c*%@y!|Dj zC$~RI^xy5rh|VYC&Vs_ZjxU2S@o%7#(oRCSpx`lOw>YlgaqqjtA59AidBj#13Ze~7 zSDO^=*p6)yT&Vo$nkw1*ZRZo@F41#L8@I$g3eV9LK4k9JNeUb~6ebi@?6pEgAF47T zANuTo&``6Rg^n^aJ;+b!kdUq1L7nWpJqgswP8x*Ro_7pO*l63$-laWGEUYG!1cqI< zON20_B?7=v$MBShqEE)$imlRZ8-~61zReK!p6#0?16|lf1}^kDg#6j}AzEkz`Dp-K z`mH0sxXdq-->)A}8-A*mpVT(=ceGfj1$h_vq`b^cTgrFMxHKBIODMSCH`s=I znVhUxhSUW4FAB7iAMdS!2d!3Np(UER?ReJ)b_7~v1w}}wfeLw@gX@~xL?bq$uOL?A zYGLT;69&hSybo(|jraWE7KnPM2c2-6Kturnx-QIa5dwvjX(gu3`+X2;{DVXPg;WOo zXAQJ6D(?IlR(%f;sPlFuy7z=)Xzm%Rk?wsuysC0}n1k;bl66e)#>m>Zt%TfwZMx+k zcg*UL*gylKqP9m%*mMQx&7cF2(?fFJ!~1qM(B+{jF&AvgNWM0%V*9)|_FeiPpO%{E diff --git a/lib/emscripten/emtests/dyncall_specific.wasm b/lib/emscripten/emtests/dyncall_specific.wasm index d7781255b6536d3db8893daa483fe36cb5c3d10f..d08d0a861e318eb35ae0154ad67dd735ef002e8a 100644 GIT binary patch delta 1799 zcmZuxZ){Ul6u;-bKYi`%=%b@-?bhyGUI*pRV7NK|jnG%zuw>K+H|&?IX(ojqL6lyWnbY%%?8wvs-S9iK^; zbI)hpGhjzrmM)jF60ch@n469QxSzm2cN0$ybi_bcJX{9_7y}&`D7pc1u4-OjT%WM2 zU~`j%Vjc%ul|m!cVRwc5B^OnKZgxoQ=Glwfd=a)W`tFRL&mgdzj*~5wiqkTMB&+y%UZSc;qhFNt@O}XAVbzdv+Uu_%rUmQKBJ7YHCnnnQJP{2 z-!sRG+sH2cFqLSne^H}?<=DDAYQ2E#o3rK0_(UOBKD4(oo|)P^GoHz^74CaVcXdO! ztE;1}E7H}qk-iZ9zOTBJpyRLd01 zVFB~|B3w2kdfB*_t9C&x00e6ZJ+9C&><#EN91I9;^8(lK3oaJ8i3{9egW?LuE1V+# z+z=_eWQajOXj0iGl_zka_Q47;$or%A7*V=cqi>KLi!G2`-*JHCs~vws!hIQ!L*m@O z2#~1#Cp^%S5Z6__t~%90aYMx$DsAzNY9-vLebh*ZA6180iQ3!t4;FEs=$-H+f--NW z6&2?VJa0JuK28S}fR~MUed&)jc$d?OU0?stFz^1}{}stkxAee#?bj`nK+4lwUmr*8Ak|#-CNN%#{xoK+n8VCdb0!k^(B!u%EPx2k&G{@6!lk*$QznO{wshXdEvga^OVOUEVQh4H?+%M7g3Tti4liw7j4+4 zCjDTdhLI@|N8M5Lq7yr1JgYI{PVDM~i2K&AJQ4I@4-xo=Y(h2;eT+f$1k4WsEE$k& zWn2;vTFm9c8IMj0^O9R(IAI1+4VXQk%Nm>=UO5z%r)wOxDyV6wSoPlbgDjH(=W2)w z+E6%B&t3pnE?1iGvl)!cfZ>)#R_}-i4>nV}D7r;whdRT1n#odOXB`03s-3xz--Z8}Nmbl2`ix(7RV{}aBYf?7rHoVdv9 zuK@xz#j*&p+Sr~mJVc%17?l!9t1eqBC84{Q_O!bj_Wh|JAYWT|*Y5A=LdCKoj^EOp yYQVIbDA5Y4Lu%4)G?zx}0oq?pN*nj+{_P=pejLK9K%^h>3|IU{HMgz!*(TeEjg-Esy?Sk~#OD z@1FNL_x^MW-gp;Yj_hSn9)&U+Rmx@BX=VCoC60|Uw!|~#9WAV8aznO+TZ zIktHT3*5mrZCrx*9jN}Ml%JrP+>$?U6+}SyHUWAw(BfT!p@=kY4v)CqeItWIYMDvi zU*(hi?h_s=Jr4*3RWl4l1q~Pj6_^I931AYV`~1KZU%Ivoj>3tkl4z3X-s?(({|Gof zPQ;L$_lXiHKM&oEK7MO8zJ=Oa3NlkDKH5#;LNsz6kUFKkVdX9BecT`7qkDe@!6{c9sdS))yO>(j!>jJl#ZrO+RxA|&Y z?yb)hOR2H!MDakiwZqe?bcU_ug_+z?zE~R0l!~m~Bp6Kt9CyDm0{Rd)RFCKx| z$+HL$t9&L5XpD&~8eY-da<90m;Z==XT+-~Acdg~H857qvm)WsO%K5=2+dUh{j1Ehd zkJ}M(%EVKq8`!K+q5|-o8Lb}u6^6GI%GkT`@Gr37eYo{2qDQxN!9wMOZR0>p^Y#~r zp4|R8(SNreBRZdmI|~ZuI=%?P#J_<`N;?VRf`Z4C-Qu`{$Gxu;e>5#9`Aj3LqfK42X(UZ)+A6TJ82MNd)_uIVWVv~d*AJGVqrC*Brxo< zT_S`bEfD~YI)_}#_t8Ql$WH^< z(r+F4#bthx{C@dp+VE4g{G_&_zoW%MEy%mTC*@^^^P_z-H;R&Gd`hTx#Cxv4DNa|! zz1To~1lcN*pi%t@pjI;VcX9JY|1@xK%Rt-iurRQm>Opb&Zz|t0TOjJ49(2NO0ucoS=(;ewMF5ANI5K$nNA#9Xi`Bl+66itY1W+jsGQ5GI<* diff --git a/lib/emscripten/emtests/emscripten_get_compiler_setting.wasm b/lib/emscripten/emtests/emscripten_get_compiler_setting.wasm index 3af77a61817e81cc50d2cfdc954b54d9374bb560..5151cc3a8d0c0c69347cb159bade043412a98be3 100644 GIT binary patch delta 3555 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 diff --git a/lib/emscripten/emtests/getValue_setValue.wasm b/lib/emscripten/emtests/getValue_setValue.wasm index cab7b6cb665d1b01d5c2bd692d7a75b3385fb680..a826f008c5d9fe0a2798414c14463fe1b8cd838e 100644 GIT binary patch delta 1669 zcmZuxUu=_A6u;+w|GIwN`q47Fwktb#UkjUm;&h0HKhh5n9I#C@&}16Au6~nlT|3&& zWd_qdjA#srf9}Ibcrek#NFdRqyby`O2jd)xFFg37Vo-u67>$Xd#s|;W4q2jK(sR%G z-QPXuoJ~FExYf)tH#?K5``Dn~&) z8d*yyyWUQN!@#>qBs*RzSBHyxvc+Ply1!hS8+4~j<#`5j4i3v(u)D7_4l37F;J_HD zz<{edc)DT$)5onE*xV$cm?ywi%@cBrcgR!RPxW*dVSCx?MJH@ ztMLJ}t)ukZa=BRYN}8?aOGOqlG7}Sp*~&2{w9G`=by>TXna<{mENswPAR=2&nme7F znP+xGqYkj-HZ4;bFHfmk5 zIzyHWnf}ItkPMsaK=B-Khgp8X92PXM7h&1wVaq;pXEnSwd^wiI>Jha75UMX~NrjfP zzMxLa#Wta}uW$`N1DJ228>`OMbeviZZoN|*B+kb#1IlSX@lF^<0 zuv8!1IRRu`cQ_c)**d7-O>Zo{E)ls*6LPgbz3JtwGYeDmj z25GMyyQv#}Yr4^AG5N{BSwj~VT2@pZKVaVzQ_?(*F^4@N;uu%c0WeX+*px`3?x>R@ zg{dCS#3qc%j}L5xnEdU)Bsu8EesVBz&?e-ygBLJ_M$r5a!1CgHLxpSNBE>y=C}(I? zhZZ`ve5j`uLN#digYNNlWX{6aLBWx$X@@3lN+{G3%Bq=UO@M~fl*U*Fz-xy9=i7E_ zT+`r4Q}_|UI&UZZ-{>ZWMG(U@n$!;FBqxO|4ITwUelfUdAR-J5Q{gCqJMJ8siI!E@ zK^pkgh~KwcigSy?wyi;0g62&Qn<=u~IrNZU2tWEo!nC^N{Lt<|!Yj3iYBW<(`PtCD ziEa_W2HIP&V@EhhZ~Qbm{p7MGzTH~s-?Bz?UA delta 1768 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 delta 1768 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 diff --git a/lib/emscripten/emtests/modularize_closure_pre.wasm b/lib/emscripten/emtests/modularize_closure_pre.wasm index 2eae20cd9e5c09c0969cc379eea8a734543f1daf..a2f6a5507fa187da60d8e25752b827b5a505d75e 100644 GIT binary patch delta 1669 zcmZuxUuauZ7(d^+f0E{=&0VrCP13C2=}orQKUnRYvOg|&o15L%R_UftWoa63UD`D1 zlGIX}+&*+DGVsrN=wJ_uia1tqkiCdw%m=Y{;L9F-(G4at1w|12iw}M`>0CiCxNMBOF1TZiex$K6#>P~aK5+RDO7zWz4woxV=|!V7TPz-! zE#ySH`FPqI4%lWA$!yv2b)E=)?hRSPaJY>F_&lQUgZtG);=ecz~w!Mi3 z?_v+9w>7bbx8~V3RtvFaOU-z47j$>Vvd(lhUn$JgoKp4$rEosg7B@&J#woB=m-Q*Uo)N3^%MH}KQDkmvz$t*`(qjBGL$w!(I3(w;f#X;x%N%^)+Gfed}gzJl1N}=Vv zKcv(0ahuTESGk6tak0t`TqSo0#5IoB(2@wMAPDiiZ@i-Js@tXcvGc(uB&ER&UerG)8adoE}gFb z(fzGSzQ67t_w|ImR1GsOmi@Tww}aa`r6d4X{Hey)ZwdI2Q*Lr%=l8HAhj)EJGPb)P zmg5De5XJ|$A9+v=o9 zW4ebku?6Gu%AxHLm%kpGBnSQ2PYxyyTZFuJ_!5TE7cwpam|k3OsBm3eq`1eAgfK#*N$p^EYEsDZ;BoNDF9){_M1>C{R5(iDjys!XqGio> zhz5Qw;`{BUVlPwJwslBL$hgg6D@B&OhaL(D5x{^*8fKTAAKDvCdZiXIjbK$m^b`!DsgD|5kPrx*h+K@L=+IDx53P$5GXuOnv8CFdKl>i zd@%fX?6wN3i`-tg${J4>0l68BBdcG2@*J1hk#?DUs#Cr?^1D7tOiP!ik9OUUirE&o ugC;$bkYO5BXa&_HYQ|~~l}7um6pea89C`idHiP~FsUpkvwM;N delta 1768 zcmZuxT}&KR6uxKvc9^@c1C#>0T{xFnx>%y6La9j+8E8=`e+k4IW3nvk(z0xKad&A$ zQk|OCw;F3ErX)4-rzV<|2b1+lqp2|_SYC|wv9^gn(N|4sqA}5Pcfs<|dHC)<-#vf# zoO9>G4fx^)Txl6+;LU@_<`vJQ9U+@%Y+m!|15dfHwyNpe+1hk2n=G74Po~f03u{b~ zT-~X3X)a$%W_L(G2T`wb)R0`r7fQ3GWNLZ(Y`U!msWS5GkE6tl-Nv6`QffrVDGx=g^ zHeD*Rm`U#DP8ZVWSfl@_+T$H)?(UAZwsd!QTNkfGvhoz=4c87nLCi79HC2LLP5peCsZ_0mAM;e*j#9+*Lz+?5d8s_#ss0wz_ghRj}{=;9V?A>IpyY{Jcny%Q06yXs{13KtAc_wwVwgh%ag{31nZbwp<(hT_m8!R05(#&D7%_%;|FeB8j|`Q{~t8jhPy#Q z>UJ@~5dT$yxJ*)+dfe&|7Fr_8ZS)7HhJ)?0jv}nnXodaDQ{7QVG-ERw1<`^OSVuzy zIELlRXvJ3l_S6v&esJ1}I06v`1nJ>0yIlwrQm2yy#~+_Y%6)nIpRme+|Ez)Lq2gY+ z$tv$1fd-?ld|~FA64l(BY?;P^M#eQu1wy-mEv14m%1_L4FkT>Q$MnbM+7H@F*bUkN u*9&pStQ6V?s=12VxHe?d^Ps;39e^A+((~V%>*MsWsBX*!Tla6zZTtuQ_=aTw diff --git a/lib/emscripten/emtests/printf.wasm b/lib/emscripten/emtests/printf.wasm index c3f19ab96f8195cbf12286b3e19df425e3d495f7..b466aa9e70a122028a28db3602b109bb122b8c6b 100644 GIT binary patch delta 3854 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 diff --git a/lib/emscripten/emtests/puts.wasm b/lib/emscripten/emtests/puts.wasm index c01c5d8b7c6039738b18e5aed060d83166f5947f..6c7e1d91e8e68bbe5d6485a59329a3bb9d6784b1 100644 GIT binary patch delta 2100 zcmZuyU2IfU5I%G6-*)fPz1>oFyY04fdfU>nK&wTfQeba^D*p%t6iAj*7wNLyE!!3- zpo_7Z7)eA8#57ar7Lo1lq2X#xb}Ut-i4f8x)Bb9SjT%1w68nK?6a zX6BnYd+vSs`aL)q5l~>ed7%J>-Hd*;W4rYNeM-Rils4yulzZ6ca|3|w6igIJHW*f<&{=qB@S+r(IkyXzFM5& zct##g{7l+eFG|jy^?VvJr&eww=DU>>dLbn4P)!?s!bIkErzu8g;|dz?LP|!$sFE;(_E`fG3ZEW=r*j6novJB%JWPvjTAZ|4f<2;v+}Edt{C@RG%M=be zPDDPn#+?_{5g3Yi*hwbYT}c zIK0*+$;)fs!4O(O`vQQY0#c2NGXg?~$>DVamO&M(AhXZcwGD+(587Q|Dt(pu@!e}x z(t5(9?%gjm!j94{XI~ItP^(g8glYg3a00wnYY5^pLya7?F9KAllj=L%o?AZ*mb|gP zH8e+9SWWe#a6jRIWKfK3SOc+XPaa)Sam#Dap3-1GsmNWM8vy0e%~w~1kzqJ3YO!`c zV4TdlcVjI+k8g%+F zNOzhxH4#N;p+$;SqQW2^vR>f;h2#?zHdX}fs_CMht8p~%JXN-GhJ+Np;V`$rDbh84 zcl%p}AN?X`JFa}DuO|>w?IdaqO14&B?TbU}sjahvwJJ`k&nmiAcN(O-wG*0U-&VJ~ zRUo2(06h@Qi3x#1skRW)Dw?o`^qWe6Q#!Pl=OD1TeUNj@1(n2Td2@8%BDbWM41 zXX66GWLDG*IP`P{ZO2dWX{fK$6K;8~6=ngtj2eY>s`v(T+ ByUqXr delta 2198 zcmZuxU2I&%6`nKqckgU`$95C1cVq7v-}Mg!CpHd|N*%H{AqJc{aj{7%g1T|sHL<hLpQdLN4T#1KP>O)(o0;TYRsy-lrc<7m3 zr-@YV!?|<5IsZTN(XZi^x8TLhG=s)zXt2|~(V!DicG_;xM+{^9FIL7XSD)Heu2vS3 zC(ASCbG76W;|A+^vRt39)fXzaKs^h6jn-Ay!kJo9pQ|q{t{#7?oGevp7nx;rM0LGV znOd(dmX?>>$hJF>TbNfWl`6Hx)h!+3*2?w6Nph^VrDKpwYl{n&%J|+fX15}2V-K{! zeQhv(TkyWUZAjdPwuDlItXJFq^mb4>f!Tgz(x01;4;`65K5I3Y;ZrTXG!uVI{}v8U z4iOkw<6M_&ywB z^od)4?>fj%3ap$Y)tV{BLVdYbWm&JZv{YGNJIjWh(o#|`v+Yjl+`@8|b$j%$kRbaS zoyzAH&tGD@S|_RW5ok>>NXz-m&)k7p_>c2bvKgL-me$PwRj$Vnv_;~Q_>rfa0Xhea6C_uJS2%;bkSK{**%qbGb z>>@I034~BMEDA#5GGv871g#%JL5MCErDHZ_BnxRmwh3`RIL4++#$?N8%Tg@KQas5N zN2V+UWye=i@~&)~qFV@J7K)oyxb7S6>;C_%H$Sy1073JVQ?TfF*$-X%z1X3g@lEdF zJ6vsYft#G-Q8zf=;1t#GeRU9j=c}nSIEFc7n1^t)d9xdQ(*7{lPbRh1_X1JfcZ2A+ z`yVIzR{s|;s^7>z4WmCFM}X1hy~=~0QT3jU@7Zx1wlPyQ}?7&5TRQ=PA znH+7tJMe)d+s%nH-bi4oCuCM#^YNM=r}uFdGX;3vFSM>c%fYLhGS>UQ@iA=Zp~*iG z{rBVqY%~k|mw=dOANUc`&I2cjE+4o;^wR@-q75#DgU^BT@pDiqb21QaaJ<4FQCB%$ z)y3j}c5ZO;h=VaCY6$(I3xvXf1F++0~0tw2KFC` z2w6Dt1_tPb;#UCD`0XOUc!yskzxN$o^n9vTiqw8`bYvhvI}{V(8hMl9<~%m|0#HvpZ6>HZ2gduPtm2>oJasH;bL*iH4IxZdS} zq|p5P%rxxV-S+9xg7q1DF(5~fd8(;}{2^1zIA4$R>r_vw<<)jhdf?HoH&pAAW?Ukp zj4fFp8A*faD9<4l&4Fg))@6tx@#tYNMLD`8*r`$u@lcH$7ifN{AOcgNNNr_zJI|PA z_jL|AljqK@g%n#)gIQ?(#A9O+>E|E2nGTSL;vWDRlGUBx{Oi!B1@{=e-N@-3P{-~QKbRdJ z>1+oJ@hjV<8(*X5blicYL-8*T!zPx$J$i32tO5*FpOAw(Gj}kp%;c%8Lq4*4X>M0x z#P~!vQ5npbBD$tvSrbby_8z84ZHfBLxiJ{hAI(LRBMK1}r0KO`QYnSXhz=4nq6Tn~ zu`7gbj&^~|f#BjG#oz#%D2_{YUs3`sV%@aR3FkoUf z13)XMI>?53XO%!<;^7hnc7(!WAU?FgZXk~@zs*`NHqt1`ZOscOU*>&w{5FlTLlDG% zJs~PvG*eHM+q~;>0qzr|9r^nHQ~5oTXXCW=;zlSUzqQ$t-f0?0d)h8aM*i(0U4U76 XlGD$e+AD1HY^P{`rK8_D^|Sv1uV2Dr diff --git a/lib/emscripten/emtests/stackAlloc.wasm b/lib/emscripten/emtests/stackAlloc.wasm index 0787b9ecc623ac0439ce5d63675f3b289ad7bf70..1b891078607f68d366f1598fe2286637ed5bf667 100644 GIT binary patch delta 1670 zcmZuxZD?Cn7(Va0A4zl5<}O*6=A+wtdXuj81FM}=_Th53x!G-Pm39hMmZtI6rA?DA zNiCJh?T-#c27a6$9qgaNa4=BJ{)j`SAl452vmgG^O{Ox1i6Z!kKYVY}xq@EEd*1gs z&w1bTew-}U;p6w6Raan+>{T>gU+eSNXR<%&~!-YCr#iwEXP z`D~%U8c6FpS*Yf7#p3!C|T#1MzTl zJ)z=wI}Hv4?y@+v>9Rh+1f`W`{(Y4Ja?HJFTy@=hY0UEaERQOE zZqKIP-egC#x3@R&h9qWJt{*Gns)9GBjp|Lx#?f zrNTy_u^^-(#s*M42i#_6Krowyj2k6b@q5^cpWK-ZuMJUy8cJk zHzxW1vVX$Y6ZTRy%(%GV#|wTtxSdl<0&vBjYHa&9oV!pAr#b6@vf?)Zu*6asu>d+dUw`B##s$A zUOV&5B89rGPKh+8 zdpHx_7?&R&+75B~>!B%f(2xD(VDhj<$Sa30ViEm^Q3AK!*)$U^Ypz2y z@M{sjO`3{*i^8_8Ls~+{O%7WrvfMrNKtPB921KV}ZjlQ^dxM=`sYOhqnTp9zhwkp| z5>bqzUJ)JGA$%I@!e?O28~!+zI5hkapgcHiCAtJ63JB8MU}mQfC_GM@j4pX<80iI^ z8~!_XQw7yUZZBSDji-x%+ziH%)h|7Mmdor&yX<@-DPJD>T^}Q+rOQ*JTkb{0Y>V4L tlb%V)FbyiSg6a`9V>O3Lqy1KjM!g`8ygItgpnpKB2(!WD_3+V>`VZi6u#&E&Ewsn^MJO%3I#Ap|~=)yRzG$vJJf@Nd0%i0>P(S;jLYN9dGb7#P^=v#dEp6{N& zd(OG>D8Q_b4QNPP0y$vlX6{EPENYd`QO8_L+w#eR9#m< z1;#)Drh;Ms7$j%`U`D#Z14rQmssv4f?kAN!b?3k_I6**4{+bf>UWO4yAKzXB8(=q3 zYMEj&Uy$WUm6r;676~L57jvtnQ>;@@E*3KxwpUM{PA%ox?f|VhQe=B*mpPqYSz}$* z9aWF*)03rz;xda{FRtZBNKba4JNUoQw?y(IO_@?TwUApXovJo(b|sb0utr{7&Ce7{ z<=ITR#9}77n>$s^oMlb^qiT=0zd4bJwzeb^3G2c&h;{>bjwQgckY!_*W4WQMyYiCU zIebbRLT0NRA;fj&SRrmOWHF0d)deBOc_VXzE*q7au^=(^oHu|feJU=q>jiUJi2s;} z4O4O(O(un~tC6byUE5YGx78egRTl z#IJQAK)iw?0L^i6N5eas>y3)L8s60?#CMt<_Xj)AnsM>7Mt6xZ84Kr3f`ZEF_D0F2%apYH6_jeC`O?YRZ7uG9{Pc8xpYlE*5 z{yTVr@WfLW32#4jz*$!~*YOev6aNBHCwG#ybk->|$07&|+uB5gZonTo2jc~@c1(Y4uH%5Mgx#PW vaJ>+B%xa-+pqi_wjcY?TJrDXz&;iJCBR&7Exjs%0i|WQ)u=UEVxxDrtV55h6 diff --git a/lib/emscripten/emtests/stack_overflow.wasm b/lib/emscripten/emtests/stack_overflow.wasm index 515a51e0db64829c6b9fc88c9973010a99a79238..5cc7a479140b0a3e7d240f31a615ba593d7c3950 100644 GIT binary patch delta 3675 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 diff --git a/lib/emscripten/emtests/test_addr_of_stacked.wasm b/lib/emscripten/emtests/test_addr_of_stacked.wasm index fce82c17ac022d9b5e106ac743804c990d221215..12c763c0326f93a1313a6b33c900fb43d67357f9 100644 GIT binary patch delta 3587 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 diff --git a/lib/emscripten/emtests/test_alloca.wasm b/lib/emscripten/emtests/test_alloca.wasm index f623c9f2dd2601e7e64388cc3268c5cb21f4bf7a..acbc0b1800b9aacef6b2b69f4e8f9fb0a1483706 100644 GIT binary patch delta 3693 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 delta 3778 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 diff --git a/lib/emscripten/emtests/test_alloca_stack.wasm b/lib/emscripten/emtests/test_alloca_stack.wasm index 98985f34a16e6f65fb4dcd3d0b89c349f0f7987c..d50dc3802d0331bc4555c7a30c794d2e9cb8b5e9 100644 GIT binary patch delta 3580 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 JUp{u}{{Wc!KCS=& delta 3559 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 diff --git a/lib/emscripten/emtests/test_array2.wasm b/lib/emscripten/emtests/test_array2.wasm index 6d3f8434faa6bdfdfe7b8fdde24ca326153c0faf..320c7f100804e6cb81e3638cfc3c455f19433e38 100644 GIT binary patch delta 3600 zcmZuz4RBP|6~5=b_jWgVOWw!X>)2^@ZD$;62M3u_m`-(yopw4ZQ)vC2PN&izi$6VgHlE590ii zmZOFHclkOu4@8GLhB~`?SM3T%w?+nbGp=5k{W~L()}8%bq3-UKX2vwl|8?$AC=?m! z>YehTSu8x%5{<4LnDSAY;aFE^Br?CYI?gl|dd75RT}tP@sasf^QkgeZQ$}f|+1Y<{ zy}VGkFV+?99vlkyhqi@>LfgZggP~aW-Z0bELOIjl_l5i9qc9`jpRSCCm37jO!T54cr5swDfdlYTg-4CyNXKO_^#I*>1Mu z5acEa%^ZQCu7p8ThuswNY3`3Vv#FobPb^HzpPl9AerQrJzJ9u22P>0~AC5-*2UN;C zhq?#)S)Mzzb!%j2Y&*Nn2yKmq!)&G%ibQtxg*L}_Q!ct|7O(~*)YsYF&wOrrM#z0UMb3)UWtZ;0ob91CSwmn%g9fO@+ zVU{VM(W?7evsbLh_vfrwu_FD2^L)u1fOya+Am~HZQ{oHy9IM9}+@VIntd)8LGMkwQ zmT9n{&oW&MS&7d~Pd*Szvdl}seQ`cQF*3=yIvFGB=~UZHuF(&{a`}!PC|e%D%o3l& zEc4I(aKWP%z2G4adzy!Bv&1YT0^my=a+PTGm`t-=^f+q?WBx^M;CU`CauY9dhqa1J z94~R&;yI6K#MeEd)eDB2G^xo7yqNH1gNM9l7S5uOvS!v3B+t#dNb>Qbdr5v+^j~O_ z*Kh=ye$*)dni89f-QaH$@9Oxj?!;Tgdpf?S(-Oba?It-I-0f)+f6*OgHzmFbUbQLq z)!NPOIX;yj)6NqwdhkV$dh-qu3_YOsa^^xYLC&G=ofpby=a zISF8^bydOQvkQv-4!$ z%7QAo1kRh~gd-@Z$bw4s3_zxuWPQsrTUHK&TfV)rG$%*6F^lp+`?{W~nQ{GqLH8js z_xm9a6v*#AeW*N}bE0+%q#;AF3sf2{^Sd1UDtayzi>{L6ob||;Cpz;c(gfAIF5HeG z{DimPF4bBON7F;Ma0|9znO#g(#pwE}Oet+TrYo%+?l=X-vS4iy$)#(zKu|ujc84ey^KqU7 zJp>2C8ix<{h+3>wehYD7(y!*8{bee_M4qiGdv*hzmg{k325M&N#BTy*s}0t#x^!ph z6e9L)RdCKPC^nrzMN~=B>{%%nD|Jk6mkNT*GQBByz&ToA5iuDmoOe}z;W-`Vs(e%t zR99eHNn8P{31edzZjrqktGwj|mRkf3%6U+p-uM!!H{3T$@{ji|Y6z;mQysR@m1lN^ ziIqY#v5K(OEc3l`?VmiJaUcogXPnkKo1)AV-JK<-l&kN567mus-%s^fDW3|pL0RI1 z(8oZJ%bhm>=E^s_VkDclRFi7wmfrxM^vmY0Z^OJqVB1F=suM=fv*61UZveiLyoKih z&x2he&-DHfYUIX9Gc1%7k$a&^-iSN_^W~wwdRQQT)%O#ql{@>7lTF6J1{!Z0SPYek ziGf@o)vJR$Rx98tu-vZ1#m?xc9uuDe;a`na_;YiCl%jA`4Hz_Rf|+%3hF|1;a*vwUDM*32ZXxZ zA8HhGQlA!bQm2rA-B+JqCqB{e6RnYTh!Gs2q`;Hn5gi}V?YhL$ks8QU`Od*?N;gBF zquG^mbid!K!J}M+47{P?q-GZ;PVavK2=g`ZpVK)LX`?T|eC7BD4WA?z)KkE2Pa?^2 z8*V2Yzk}zrUeQfvXEf}lz}FtYBIT9PuqWlD;O$SMtDO4nnndtH>b}EC!X9=CZx?%U zFWux}x%i{Sl)6W1TlfF!M?&OdbsYVN8YIrVz#@>FiY!|inRU5D={ zd@j?tQkIQ(klZ)kO!~9q6{P=Ud;@7(j&xGZKX>F1>1$*&Y4*r6k`uC)Y~Ge#G`{ud z7P2{cv>-qT(~>F$$BB3xOf7j_qa`mN#UdZxVVOR~-v!I96lm$|P1 z}8@DXOn%gpzk)KTQx8#S40jEq*|lwT>ts<<;kljTy(j<@v&&q+SD@;RIU%_ zPmu-XiraJOlDdeubxXpjdGNlhJ~dM}1IQ9Br%v!f)p0ySQId92<_<+En>sOiuP_o{ zJZpmMUeMz~m&`a_G?%*3jDX{{>66eh?Q{yQp?;U%5KMglt|9^M0|0eqmqb_x$Iad(L;xy)R#8pIv50JsAqb+90O1u~>{|M3pv0d8o4bMm7?Ikv1(xKZvn+ zRF4|$+mjsZ3$=%L1vdnD_lJiSCV45lg3- zwS-HOJsjz14~4F;u2m8|*EL>E^(@P{#+nmKBF<3XtbWl9Ts#dec~YaJb+c99w0UET z8dKytDX|W0u(pWL!GG)ORlrnTXP|sVsPknZa1~Vxdboxf2NxKIbs`UwP1;H=bXtnr_-h|r zbV%PmgJ;@yl8Wz!`6`6{<80CAn=hjJvs>F~fAc!1xR^aE6g@{0)Y0h*uV5 z!%Y001>hjL-{<7f$KvzcBSi1ZdxL0e{x+h|<^Ko#;wj3v|M6lD;E$IS*l7?I-VCCC z?_P(Wzpq(}>5sqey=;=MC#!eZ7dvH)3^R*Ak;ly%fGyO$TDP5NAfMbd0BW{dlqY9U*^+SEe| zs<4U_EW5=^oZD`B5uIpv8|MK`X*Z4R;yi4isfyAK9d-vrD~UckwqbFB6E(L{1vV)! zPdM7vB+sV#ECO;bSIsQ(rwut3R0r14GRh;!RFMRM@D+emxk&#WGfSEW2r^U6#lB2# z$8?GZ`GufMd7aF(Bm!wU8>KM|1|{O%hHF+kSjTeQ##;axBreoDXL6I~%wBWAB2Zld z@JNa5AN|ojqry@-Z$6a=1!DK9-|8Mz&?DBK&d>Kqq-SELJd`{nc_dNe<^?WICz-L+ zT~IIne!9fA37k^N*IUY=NG#o2NN2cpYe{A?uP2{fJ-h)MWETAB#}czx9NC%y#p1_X zA0xVMTRzdQZ95@fyt!?V=4)~itfR9sEryDYY63EDBlWv;mzg%} z6va7Z9>?W2K44HH9m_kj%(;X+(aCcSvqWq=Q|ICmL_ABUqh*OF&y*FG%A=w!%suGg zb{%cpZeW(Qz6cljsT*k~iqFne!eX)b5$~!}j)>G{s3j;S=N!2dEuuv!FTf&_FW^8a zGf_?qDlm%t0S1}UpF@v)Wk0OL3Yy2^o-vmDng-X=f>#hGF2OwPT>=7M%l05#CtliK zL0;R@&WohiMdFj~FA)3jyGDr?2A2DZqz7K~N@vNgflE1c+6n>@VdT%H>ZdH0vL9p@ z{eqF5>Dl%?+efFVD~pE%Q;-#}ZKFac7az1YL2kTi#}%LC)GQbKBbgpr zS(W$^!+#JwOu4s&rnLENB$Gb45IF#q;^ye4{HuWXGKz;4<2IMgz^fo@=NrIpfP!>Y z{4|Sn%^=27v<9UDuG9e34k;tVoTdFABK*RDxEzb~lq07t_)=)R( zil>LJlNZ2HrcSv3WM3IO>JoW(chKVAyZ6w}7k2|R6wmbvbG2-R*3amgq7t6ft)Ob& zB)g#7cpD&1+FeKq8fEigRlD5=9G+T5#E)^FvDHgMH=qH*VJC#O=7R8 z*iCtU>LBLJui`59T(jIaXLuL(nKkhb52}#1FL6KYvvSw*VH~FRu}^$`=u7P&;6d@# zeR&x)DR1KAfa4Mn2Z68DX{X}wTG$ugbGX^AjWZk<7mpTX(4?h_kI7q-B*z)wq~mz} z>d}`ORK;HwDUiTuA|m3gV-kiR9@|6*U3q*v_lU*PYvNgDOG$-TMC7 zKF8?>;hM~V^@vMcxxIbSXfh{MYTRz=Jd=82rlr$E&l*h@!7Y1h*6WPNAE&l2g25i0)w3yc+3zCHB=_*5HDeF;1ST~3&y)eR>&tzGa%d}fD zx8Zdpo-ihmX%)5gv?;4k^U(&#w++dOytCDYCSRUOiUp=Fwx8V?&w1_=#Gg4kV2^+G Rybst9GQ@%NwIce0|G#SgBKZIS diff --git a/lib/emscripten/emtests/test_array2b.wasm b/lib/emscripten/emtests/test_array2b.wasm index 6511dbd2c196d437e99653613bf58eac47f1284a..c110764577b64455c46d52be48efe5d6cc40e08d 100644 GIT binary patch delta 3609 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 delta 3493 zcmZuz4RBP|6@KTww?Emp)f2^R?R_k;+PV3a-K+oMo$+Ygw zo_p@O=bm%!Ip00^UH*Wb_>eu~^(c^Rg{0ETl1bu-Dy@q0Xm#x}Hk^dvRxL?CNV0cS zuNv;#H6z>?X^U+SH-~pbV}lBlvdrz_#Kvf%E%KF6?1#eE^ipl(;74^}JIcv3a zNK!l)?`Vre=GQJ#(lYlA*}~dMk$yuorIbOEfxb!mq6N5k8rBs_i_Q%jt<_B%Z(FA( z6*0wetSh7Fx6&bpn{?R1Nv(!fTAfHv(usFG-UQar@G8N=YW>qH#lVdlYMs8^DUMTYIEC-jy!shT@%V9bqL) zj}7##i^dZh!il(IImz6{u2^`tk}U?+>SRM+W8*Aueq&>!>*RS>Hya@7cX9B$Q0Xak z`CXRLW9{shoL_Iz0;rg(j$r6E#qTn7yMjuoOLwIQgi>A4R{U;DStB(|-6WZz>rVq1 z(r6}G!?e+~DGSMz@MvoxAX>G$ihvI@OI?;?=pXdK1*hC`!AV=pX|-|YaxY?vrEtIt&eHVK=LPT-qqB(Yy1&A>xLWsXqUTrCz}WT2uAyemuKb(ZCxx?Y4Y-P~4MDy$t7ixxH19qt|PdL)rB+sS=EJAEAS52RIwRzS& z0=#vplIjSuRHQ*5d>J51PIA7%O-9R3g3M4$c_5!VFo*I%aUs~GzKz_hODEEDHA-g| z^iw8PLw8SF2kWf@Lw^&%L+awgJ0}V=rrh2Lz#>px0`N+WtH=M~m{4J^rH&^7B^VJlyyNB0fy{tkIgIHmfi|A$#l#9{Lj}x7}rI={LmTgchp54+r={e<}``h(Eq}qLI!s2M+;mx zaTmIHp>9@)WhYj-xdajS+309K@!*L$rIqriXpeC(dbz`fcJ9#8C%wM?ED|So zj+4&P{!PUHuzv|ur6&5lK%y(L{)~l$$~jnRR*Adf`Cgh?)%Xd+zY{!6xpot=wD|pa zK5ck1elJvuip2Wj>wxz$%7>NYcDG%}>mcvWHNa~?NxCk^6SH&|+6{ef`i_aW6D5^? zpKj>S0p!YpnvrzDXZYUH725y!Qz(Br@aDQ=V4trA< z*M>T1(th_YTKV1G0QKcly~11}TcPy|^vEkbX9wq!>=3dM5dMLMk)#7Z#{j z)MVBkE^+X&N^Z_*)7+fV$jyO~`ZScI+Yxci}m;mv@ue%PMwLo%ip7~ljr4Cle1PQd9&FV|ZDVE;r{~Vl4NxU$zn*_@vd?jPLAWL>U|rJ1#2sxj&$>CG zQsWNG#`CEs=36%UqO;DrMR3#Zg)4a`W*U0Vq%|!aVyV0)hQ4wN;e^-!`D_#SoGQqi zO9!!2qoW(7Dj*&|RRveX#Z$R3BlYpAW2{i4Zr4jMsJwd4M2x7Jrrt!1+f%2W&|%|u zK}-6b@7amKNph(*m>r z^4o^=#I+}DeVY98%up;ascq9sd^`{6d%>w6%1gcS>}5zb|0L>2J@#AxSc6CKGmAv- H^UePSnEE5n diff --git a/lib/emscripten/emtests/test_atoX.wasm b/lib/emscripten/emtests/test_atoX.wasm index 5588c91a0520a622a380af27d1dee980873302aa..a36b2a59f7c918957aa783d2ee73738259ca3594 100644 GIT binary patch delta 3922 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 CfiC|5 delta 3503 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 delta 4640 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 delta 3816 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 delta 1660 zcmZuwO>9(E6u#%a-@ZF#UOTk3GyOTYZ>B%Gpwfbg5|{^qw530>6E%cnTE;1~9cFMk zg*0LYle#0(&BE+C~(Y3x(s$#awoNev@h3 z!93!eY&KgcHSP5VKs|jHg;asxnM*IXfP{s6K&X!<`+#4a))p7y}N> z0B!@=B$y5`JJ(c&fC~acgQ>w%Y2MOs83J1nI9gJtc%=F&9A)&0N2hZeqD_=mzFaPr zbSq{n^Q9tdcd~PHh2^Dl46W>3IiF{{o$Pt)LMg{$bjzR5U07j3{YD*QNh`Z_ro6~f z-b*XRqok+1-W%B#NbHN{m(;I3)-KA+#i`O#WjbG3Vm&U|XU>)Lmsqp1jlpVv%fLWl zPwT+IfcMKg(9sW24Lk{fhioC~1zs3k2rs;>Z-JOF)5v^7AVh`50xv3ThAim`uYMpT zg=l6$BxJ|6W->xdqY&Q|;f|}l-f_vFUw2z~7WzIIwd+O!z^nOI(x79%8@1^;wo6(q z8{EQAx!m9aH#j+!_c-2Duf!6tQM(ocm-OCBbdj<8sN)U76P@=6V_l~Ri(P*~O3im) zhSc@%y8%+Q2k6kDewHnSR?j6jCGVRd^Ha6eo^O5fb#Ca4)9>lxgx@Z2x_HwKBL_GO znFPG!ChNa`Pr&<}ict@r`T^F|S5Mz1eD~lGtku3eI0q!854}$K*`XH*yAH1sUO&7y zSmQ!icon3Je}Zh#H%;Lh$5lQeuW`JlemnfIV~tZpOodREz37JKg6zXS?A7F2%?MqC z{6(I5p2FpxSvBW8`QM(>fLv)K3lA<(;?U2Tozr%@h}R#6^nx(^$@Nsap+X zmO0tqg(rP)vc-BDmMLxeVWt*SNWOly*`hJ5#I@`Q4zTHJ@J8d#6WY@O#Ac-=uy)T Y&U3sU(EFiAu@HPqt!J+O3tJ#>ng9R* diff --git a/lib/emscripten/emtests/test_complex.wasm b/lib/emscripten/emtests/test_complex.wasm index d8996ad842e18da1fea74f02f1ab91915ccad791..bddd1b919b3d6e986ce7a41cf6d506e7e36f4db8 100644 GIT binary patch delta 5027 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 XjhkTq&%4bazn{zx+?vDpyx02wzVWC_ delta 5269 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 diff --git a/lib/emscripten/emtests/test_demangle_stacks.wasm b/lib/emscripten/emtests/test_demangle_stacks.wasm index e040a3a44d908dad16c5afa51c9fe11a2c7b1622..dd91254a4ddf2c6876df33a6542d2522dc65df69 100644 GIT binary patch delta 1784 zcmZuxO>9(E6u#%aziHo;dCau7ote^edDBjz5~{7Z5W>77D7Lf^KqAphr{k+kJ51}F zDTpZ<7PwIp(Q7OT3r$di1|nftn7CnM#InmL)V_O!n@Cx?Cz#?R?Kub;ygv^#!>Y3U4>6xywwr2gK<$O?>kuO0@vVGaA z_@(SCekFUv&&_1Zh1Y#%$P$S719#;R_-d!_!{FUQ2Y`GF4!p+)cXTAd;HG8)2gbkv z2Hem=t+fy^bKI$d%WV>xJqNC?gh8gqR)qY33u?J{xl>`6KfK26ldyx)_dr`;z?!vm zIX?(W)2gAlN@2Rhl2&$NqBvVV!dxRe5%@l9HL^!@g%WGFNEgYGJwhx0Xny7d>#DEH zeuZ@#+46WW#nO#0pD67hzw8DgtS7u|73gCdVt%=j8!r~hN9y$NpULHY7L$`&Uv*nK=$)A0_;L+chuuJ1fd@?_`Vke09E z9Hh_xfdJ{+Jz+s>THMs}rtVdDiCa3}(y3A3>rPrWyT?Om@r&*;CtZ{7&kp52J}_>D zqN<0slaxO_6>F*+_Y!b{(`_Vdy$kd5*R9`@yt=I)=4*GiO#m6A+utDh!}dcYH)T$f zypq}M&U4!~@NEzwybq#5trUdw98dGz;w;CrQulsK&hsstVV4Ji=*EzzPl`0Av0H)j zwdi0-qkM^-&r`Wz=V^T+Djw2Q8$-fG=53u6fY8GglicYbE=|-ZlV_sogosw%NeBZ& zsVEu|`{ND-xK{GhwjN!1$C% zp{dT?gFCvSt<15V7xYNK+m8 zioyLwvfa(uM6BPCj~70p1jVVkfFG=*hjyPEYlb?)=g zCt0ucp-=_xR$QwS8wr;Ch~#JxxZ@9q7k{f-WL6}fln8ms>T5Qz1rII`NI zedl-!je-}d1SFlhY^wyqlwa;kO83B@=3$C;O^F9PH=*W4;$GOHcM`FkFwKdE`mmmH g7pKRd{WVmdnod5lba23?zbo~KdEjt)>EI{-0$?1Dx&QzG delta 1860 zcmZuxO>9(E6u#&E&%0CRmA15Cb@GYHL{lVIEk1THC2QIi@q<4TNSBPn#@4-3Nvj6yK(WMQIl;d!qhP2ergz31HT ze&^ovop;||fuC03?IxFjI{_}6kX)B$ESRtf#a(hKsJQfjE4`*f)6>%|h}3L|+>7bybUI(m&aNXkdF5PXpi~+uzVl_>^F2%nj_HRN%h^mm z|9D^jdMtcD_GI6BDA>IYy9){tXufctUrPrkWvUl~ZQc;Hdgo!Z%}-&BjXV2?##5uR z%X~i+_~~KisP`uf^lxngN!Bz)2N@Ux378C$3ZRms7{Ih_tqZoq$;iG@e4~0rsUfrk zw#LcmzURFuh22+SKckP|8}(JNYU!l8QmIh%tC6Wp7YnRaPftzd=gY@gTuo1vayizd zrsp!#1=gU`m?t1>q*-n*dt#Aw1~V!i>r&I@$}ER$s8fVRc4zJt}$eBlbgYS5a)a|v%?NM z;3MNmh5#Xo!d7F z)v8f39H-p;*8;2>KJ%*aAa!*?$pe_xn`&I9Ary*eG&Dzq+OQ_6_?;xyB#vtmomE_s z@QRnJkHK1XwjK<^&9$`AX75bvTVz|>u8_Um_5#^`TmONCw+ELX@!{79kf>e|Iy5H4 zbp@|0j(b4dQ1FIA*T1S*3Gdpr1tTGDDGsv|)uZ-r7IE+Ho7B5ZzlPju6)Og=7*4of zVh$64t42In`YQ&XNOU*v(yrfO+53F=WwMKVdSSWx*`6sNr+)A2WZ&ES9N9a2Pm^6p zK4vdVoU3>Sgn@s92>CNVgv%11mJW-v5}x%gC+`sY8z)L+KRbp@&M!|rOU}-L(@KLW z9#T#3hr?TTwFwzDl>MV>s99Vns8}sRMgPodgr8F(>C3T?)acnDUJr>U20zt9!a~bx z@qQe%x5wn9l*E|B4v8p6m1Gz=su-IUanu}TMzmvlm&8N|#=N$neu#NThGvMM7ki1| z(vVG&KZd?S6ZHuH0>JX~ZhlD9eEW1(H>eIF+SWDP<(jBOc<*{cYRH^Z6GK8mNl7}? z!m~mqMd()RmvjZFNTLM&9tK|y0nP^vB;2|qA@%G9fLed0?!oLF>qG?WsOw1%=EP@& z_xIwk5q?{OPRi`PKk|eb z7bcpbm0R1qYa{!@!Y{Rms?<|auQRoywOuq~BWfklgiS(MQ4>1HsNej}*z6TkJHhro zPT8?`frtXa^lvar2!X=Kw3E~B-AW;yT^s#3Dl_0W6;NE1oKqKB@Gc;rWJRj6XU<8j zigS^QsZt0Wqf#Pk1-7YD5?b}@7>Dr}X}4|o8WV`#8tN_j0|rq>ICK(aYK)SSw4|sL uwsgmhaN7t(v4HfEQ5mE~!qYoL3*fgT;k=$BeVqO^swi{7qPP0UNB;rt7@BGT diff --git a/lib/emscripten/emtests/test_demangle_stacks_noassert.wasm b/lib/emscripten/emtests/test_demangle_stacks_noassert.wasm index 0ddaf5d4374d8d5c492491aebaf217dac083c860..3a85b778c04515bc7162803ef8ad50f6380c27bd 100644 GIT binary patch delta 1807 zcmZuxU2IfE6rMBpx1FVXy9L{Be>l^--IfwVu?0;8+1pAHT3Ss(BQM+SdMn#*w{>?5 zVrrI{YC=M^=EjtS2OoIRNTOzWGcg!{g5}A-=nG&l1`?woK4?^8JhN?Wquhsc=6o~f zd~<&0zHt%0eFqjBN>E~ByhLh@u`x!93^t~h=2uinZSn84dd<(Bh@{46^2O0&Dm^uF z!p~1+XHGJ%HbibNn;n?TrIVS=3bJVfvW8j7WHLLGo?7)GtKgT4`}6tXnN=qRohqbL z+3e2VZlJ#*SFq4JwySpq66?_Fp(;Y=a_f9%vT}Q-tEi1hf4Y#)XJ%`QelGc} zUrZkNQ?toJ<^?|(1~*#2wy(DHzQQXf7`&co0SKnyNN^MS`dga8;HG8)2gbkv2Hem= ztu-5%IqsCe<${DJ=E2pKFv#@Sx(J@-<77HJ;5Bj#nB!I-5%SED{W9-KA~yU0p4W z4P9Mb)jwZ==1zc;8Np**%v2&Rl_$immT;MYI z*nqss@hYdhKDK2aeq_sm5E#nnSH=NcF2A%HZ1P@cZl#dHg_hSy_OvdO{JZrS$)~se z3Gv_v&O`jd7YGn9e<>}fkIU;iUe~?SfV`pO4V@^y(w%s4r|qO2mp|$rbK>P0_Xme! zkM@pRoe@=4;WWvMHeR&7&~DDCQh-sQg&bm#ud0!{>8I3iue1YPZHhm{sny^BJWXnfwnY}d3z@5;?T)er@7Ni zy*5!(37Kd*Hnm-MqS8Q>nGqJ}4M?a~_E9IhH#EJQn*PwCw=GjT=s3~f_93?`swH>= zqaJ%qHer*V2!TKYqf;`5rn+-Gwkz5=MuT00yCE862PY{&5B5-iYlAK!FmwqcXobal z0FL5SQ~uv!`(`L@8C0z*a@%*fvn_&pSoEySw#xAI*r3WyPk1!?Q&Mx9f-{GkchJl6 zPH&+;f@+nT^RV~;pjH`m_n`Uu@GMxt{^9t+25Dg()r0P}=IqfxRILUIi`tbHcnez` z%{xmZH5-tsu(-vcgLr~V!w*!q$!e^YEyBUz&TwC-RaHm+$$pwf($+!ahqI;h!R5dT$s};B}#RsoeVd)JAyR+Esx)AyrqL) zLhhZu%qqVK1nPPyimcr8#ChIAqu|-aJV~b_8;W_F65YE@g)_=OjS4W2Q2^Hr?jG5C zKWa`*)C)QEbi%?BG%OnGLwdqp86kuAH_;`i@^mIRbhKB{FPI9&JaBk$=IGgf01Gsf ASO5S3 delta 1773 zcmZuxT})h65I%GNxo2T71%?ry8>j+Zi1bE%7C&Y-S%cz!XL zJG7XeO3%!&3R1lVxsTcDbUIg-#;o|3Y$9tJkNmIc~3sad~ZcqQf zCKh>sJ=VVoRZefZ-E*oUr^WmOek)zcRCa?eUxl%DMedAG1P6yFQe%3^lwDP^(<8xi z@&_0k*wGG}Zdry6Ixq$rFdZ}#z$C+PfLT+uA@~|6p(|l1ValUgL)9|)7AIjVOU`SN z@MSp2=;QZSdmX%5$}w9k<_oG0nbJ%l&sy#D^mJ}<;S}@D^mH+sWsPR~bY>>c>TOzc z}>gj23Y3}LianFAM?FoR;cLn$^ve~%nyFqj|n14xW zJ|8ub$UL1RM7ha)H_9!BEbel*vLM7c-^Tn%zz!+Tc!ZE@&JTm7IBg>HDx4Ljz*9_e zP4_z+(2lzSi}E4O31OLhIr-uiU-We87@b|!Ch|DNOkL!&&!4GnL|UG*{8C?Bo|hx~?G+v%`8)%FI-Kih7Q zyx#si$@U$0At9S_84~ZmjR1-AC1KMd-|J`~d9CBDlMuI!fO&~>zyFg*TuuEa?1Zc8 z#l2Q>)xoPy5E;-|zy#pB6R&Lj5rdC3x{JK>#4oTaU*G#3$z%KaV72_(zG)!i*C$^g zd1n7{lHc!NAvvDh?XPN_n|J|)gMWdjQksHrRl^l+NLOlYWiZ9+#2b#);N zEsqNW4KF54R5vrD{IUs2)uaQ|quwp;?4@@8GxV`tB|P-JnEdpJzcZ#MwIs#@_Oxih z79$w}jwZ(DL>w)Zb0>DHuw59FcaID}Ozs(;C4xTeBZ4c#J|W)@e}OLAQT`c#r{ZpV z$QZr*%#`g=wW{ctF_P$T(TMWC%@I{MJU2P4?q(zd8tOTrd#!SGq;)sFiQrrV^$}F7 z$b-i9OMqHs)IB83J0tTnGVW;CP_wYHj_N^qRoy%MfF_{PsNF;%SZVOA-~t7y*@8r( z{AUfiDUMtkebn`Zi>_$no{-l@4@6K^P_&pdP%TnV?P`mQMr=f@D4MWI*d|)S=GdYp zy&0S3aO!dBkmpl=EG`gHK!hFw^H2yB%BPczxcoYWl>5!p-z_==e#-zOL@hYC#wtGm z1nPWE`Oes7%{GEHs*x!#j&GNfN9*PF@jKQFZeC)!%P-=&! diff --git a/lib/emscripten/emtests/test_dlmalloc_partial_2.wasm b/lib/emscripten/emtests/test_dlmalloc_partial_2.wasm index 4791dc760263af8492ea64f7874847ca21a96641..5a4dbcc3cdc117b616672f010961befafe859122 100644 GIT binary patch delta 1087 zcmZuvy>DDa5Z~GN>D#-!=lAaX?%vt)Ox_)_LO~#rQ51?>TZ)K~Xd)51<6_Rr`5W6v zSOQ%NM^I28wz!BCbdZ7~;E0CiN}%9hpbQccNECbsgqXe9;DRT;+4=4MW@dMO^YDf5 zuYR!TeB@L=zw#=WFJMVGb8w}{KL`OX2#~H1>^lJn|5iMNLMk?ndK(JY8jqnC{~2>l z(vY{t^LB6i@mQ*NU|I0@?;3mxmFaG`+uz;Y+U{;_uk`i@+gla|XT9#~ zZoe-Que;eBY>DZB*9|6$n7#hy%FcnniMQ9^7gT!vU~8GryMuu^S7t!Rh;fnj_x5|Y zHU@jQZ|wJ0)^F_eR{A0`iF0w-O55#5t=ew4OYdIJ7XXGuLQo_q)>=uC=x9yvykWf} zecA1xh=oFklqZTLQocaZN>pjGAhc3-9vqv%;mCNBU=pTd8zue++K2T@DY~ zejPqjjHFT?z7G`QA3#&qvs*Zlcqp&aJ&E^BKJ^Q;E2W&1EtEos!LyZD7`#_Gbk8Id zp1PpPlex=va?nR-Q3~y&9|z>38_$r3VJkr|QujUR*rzRV;Kkz>nDyjKm@((l;zI6p zWCwFCUZf^A-A)-4dYG?M3w`abQ5)L}QqWVFo9%QFa`Q>L!=YKVVE=0MQ6s@1QV#)Q zTf{1aCq=@VWggTPh6%cnx&*$Z_$c(9*Iput((PzgYMq=ov$uZoh#`SzrJ2ZD2HR!= z{h$^p^#n*{y}kmNwkPSSf;I=I~P2!Jtg zfpKts0G}}@0Ol_hMv!qy;8<`icqZbd+`EwZk|40moZ$J2&-3 z-g;+ked*$GWxdBLL1%e+?dsqXoANr#{ce{fUgyfil^!bww62km70BvdS=zY99vNGM z?vQ2T^=rKaI`6Ekux9=tAv&FO2j&h>s5f!&;eq*=-|>nM8=BN3kR6Gh|I6#dtwz zN?BxCUb7dhvYDry2`O9PSf36#i^o34o^)(IvBwpl(-it27Rh-CtuXi>p=OF{5f{wI zPC6kpCGb}YJDlX^uJapgnO*lQ!gst=u(kK8w+uu|!41Og;8nsugH6J>!zZ#WE~SU> zg9`C)P&sSaE!^U`$xo}B9B-O?;UA>_GFKyK-{(Sy$WQt6M4q15bdLxX9?H<%D>P=S z%0VBUInK0?ejF$l-MFkg44VSINN#)3wojXW{;*$o3}C5>_t_> zn%mBUL=V%;s)@dKSJgC5&v2%WV``?7IY`apm$1< zl=lfo>ep?6f;~wN1*93#Xgiyz2oq{J)tTw$sxn`fZk#Tu023++Wt)58=%Gv7)xtrn zPfD?)Z&AP_hjzk9{>q_6G0jJlPl_oeP^gBC8|H_}`Fvf)7^|8`vr;oN<;NPR%2-Cf zuPRtkfrq{dB-Us;RTZmdqx=*cGdtxhMTLk8@|@-|t}BJgYNm;x`K62?Oi=l^<}i>y tyWozH>+Ab${4*dRkL6yyy3HG|-lsBpv;{gG_6g%LR)&4$?|qv}{vY$J;8*|v diff --git a/lib/emscripten/emtests/test_double_varargs.wasm b/lib/emscripten/emtests/test_double_varargs.wasm index b5fd215874fa4377a3f351b8589560ea0920a3f6..1b33500eed3dd89160e3e27cef4a0faeb4cb2b5d 100644 GIT binary patch delta 3646 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 delta 3637 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 bjMhH*21E}$)&T4`nIiRMP4v5ykE{O!1pxtw delta 4567 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 E09kGR=l}o! diff --git a/lib/emscripten/emtests/test_em_asm_2.wasm b/lib/emscripten/emtests/test_em_asm_2.wasm index 6325ba5c8b36b00c04e5b42a5da2d19546a9030a..677cf87035e5d90d04f26429fb48461ef2b728fd 100644 GIT binary patch delta 5430 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 F`6ul2gd_j} diff --git a/lib/emscripten/emtests/test_em_asm_parameter_pack.wasm b/lib/emscripten/emtests/test_em_asm_parameter_pack.wasm index 872d966a34a8721f21b24ce1b4754d861738536e..5a028d06bf1aa05faefda0fffbbd4ffdeeb78ffe 100644 GIT binary patch delta 1872 zcmZuxZ){Ul6u;-bKka%8@6l1Vc3XGvUiXKhV=_Pu1N%lc{%mX$2qt{#y4tyJT|3%N zoI;8Q6aSDXxg;Zy$OkoOL^Mu~#>6ZJ4Gur>!RU94!4MM@6EP|uJhuf|;$HI3J?FgN z`JMaDIrqMB8Lqq!uh$DGlTlhOLwQs$Q@5c-}TI(?$POtp0GX_lMKX8UJz zsYE72DxOu#JokK_L?V&Rr>3e1hE_3M>MIn6@^@pDXReq^X0s1%?jo9EUbWn}wd(WV z_ibt2T=iAhs)DG!! zPHe(BSj-?!z+xuhBpP78%EBR9%XWgH2uzH$D+HA=*TyiH2+E1jI0)SZdtKNCcZ}L~ zYNf7b*N3?o4YVMj zO~n#rdn^cl3vJP#Y~=E78S``mR8yGUEG~KZC9mt>N(t5* z_*M1S_~~{7yhHI{N~JGxetI5E@4RNj42zvNAg;>ai>>NfHcVYMk-zPI*JBEs+jc}=7;s`? zEl%S+?2_H0fj8)JKQM0a@RW#h)72+MD{t+fM6~g+{B>X}grze$i3Hue8wt(~I_UXq z@M9j}9*cblV5_`p{Q0uH9P^&qm+}}`hZ+pKy|1Gsz;%mtgQ@T)C+>;S0i1HG$8kW( zl+f&E86Rrgh)2p@3}S~sH9?&Ni+usGMj5p$qEyY zbC<|sYpNQ!SAw?Yeuqg`FZ19S-=xrvdF0gaCSRNIai3^nc2r&*?)A5*3W|_{qY{#T z3~zvTDMr?MLuzQlSgP$K4@0Y*9dUZv1?OCVA7`4_EkbaiFs*2`ix%FBH$#g615HOM z3?~FP`8mHGRTJE5C8=w(jb6N{vBk8r>PygJOu!mY>8(;yyd*IO!}v@5c{R1l^d z*xx8WJ^1JT!x-zBs)2~Zn+XR8$9pfwyJYtfu3^^;xC70$!>-@f-Ll2(RX9x=*9Y~u fQ=KsbzgxIzYz<;09NNtA^2SOMyo{)fANuNF0AHCV delta 2007 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 M2p}ghn%DyW1wchu3IG5A delta 3806 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 Ze{r_Q8Mj}k1D2aD-g==X{!-ir{{dB+TvPx6 diff --git a/lib/emscripten/emtests/test_em_asm_unicode.wasm b/lib/emscripten/emtests/test_em_asm_unicode.wasm index bf21149de7eaf194e2dc603171b6f671d56aa3cf..6313244ca438200df71e24e18912fd26aa29a94c 100644 GIT binary patch delta 1669 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 I_Vlv<0utmV0ssI2 delta 3700 zcmZuz4RBP|6@KTw_jWh?HhC|>{FCI|Y(g*rmY;~wfaF0EAu$jW)D(ebi5rs5vP(7# z6pU<8pjdSTuRs7T#s8|5bk^xitL@N1IzVa%t9ANgCAB(MtyL>^6k6@MyC|93&E&j$ z&pr3tbIy0px%c>+?1MMio`Mnu5^Er#tYL`+jkE;)=u0zYjiT(GQ#+FlCSZ_#rWUHf z$fnF-BpisX3$_N=M`K$QCV5%wg7M|icp&^0Q#=hNYf?)&fwj?Cydxgy>RYxc80!v4 zH!G^#V?;KF!%Z6_UH;zQG$(T$=PRDm@ArqJU457L&}<+WZ;Zv3Miq7M%M+Tllu44k zWuPk%4$r8at)zIKE4*uJ(=6i(>#|S=aW+QM`o%Or5rJ~?YiKK#T3sE>?L{rim$j)0 zMb0x)bAPMdDGFKRjq~RLQymTsR8SOPK>wNwplFK5ob**(8Ia*N4De`~S*EElrfHf} z%4#|&j;`zkc$q;&l|(ZV;utH)7zD4wAmS7wEH^O-4a()8aR)4t!>_;2KSFjk*&mF> zB2gKmK)g2^QHq`Z?(Xo$fgYt=_jkvFK_$=hhr^rJ`_~R^4s7uE&YGz#(*5fLy%FUq zCw;@TRmr7MaDCT?ElNXbL_t;>^>+Wj+E|~`dcKrjtm@w!dJp`cRXHr%NXLWN=EC|-}P zG)c({4{ zjLbXf;tTPYF5ct;T}~Fs$@Msz+YIT#(8V37*z-bUI80^|NoGwX zEFGvyhaBjz46dPO6>%MMdF=iZ*{R+&+4(*Ru=OjEYj*dV4#l0eY^r4(wR!El=e)*Vo}>N8;V6= zONbQA!dax?^%gG_KXAiy=tie$i~v~Do}6!HsCe~;E~ks4m_fU)Yn^PkQ8SHM;E=%d zx8{-F-K`USR5A8gHNgoIF`3S$@jO7boJ{yXT3>11K$+CAbW(i*cj5#J3z>nSOL?6f zZcD|}b}y0fw4t8@s+xu;tsU%Fi%sJkK&~|6*sY@_8JCZ}Vt`G#H3m>1B~Cs3C+DaN zQ{?!w!=>OA`47FS7odU#;-iPk$_ivzkq$+oNWqg_HwBxxV%fJJ z;Z+1{kqseUMpl&BEFR*BD5W^^lvK`&+vpD1yrLhf#JelXh-Tb+$6`0x2hv=Mu(gPy z!n6b`I;yE0GmY%8BJ@_Z<*@%wh-8i9cueCR23699)8C)zu9hb862qD-v?B{WVenpHls+KEnHDXp#)hgbcW*sZIFi2i2vwe^+K0xx={v2?D1 zQ#e(akJ62@>3p^NFP6yK27`3W=Zwxdk#70v_I!dmy=e3wg5uGYFpc8?S4ogxikCpCct74t^rnqd^mc%TNvS@=9oBWSz1lBO!B9VtWulTlsN1%X)7~_3VrjW9!`nNOyjwk>RW0edmEQ& z@vcfLN3?M&M>JA-(@-7E6?=yYVQ%u7p;?eE!<&b>6kP>#Y}N9K54Y!=v++U3{W@M! zaYVJgmCU{KX&{JC-1QUkHu;?$PeVd({Jn~YXbWm-9D7p0F4&`x=Pv+h0TcTlaSo=ehj>s)f7*_YnV)0}aG^ z=Rg%vbGVjd8iu=Q{M7JmB$Ih?VuE0&BV|B_DS2#6A33a2OwJNYl)ipsi}^tn52_Rc zdN%nDz69S@DW{j1Mh;^M*hVQq_WnG59py@v%o3T5VAZ9Q@j^B|qP1M`y^zW};S&m1nH%amDVT#4^e{#hwPvl}q8um3Xdz`5$%)gC*A{8=iJYO>V9`ZDuYjX@px8q$<6vHL d*Rj7qGXIIFGueH-9@yes@$vE5;*F6T{|lhzQ;Yxr diff --git a/lib/emscripten/emtests/test_em_js.wasm b/lib/emscripten/emtests/test_em_js.wasm index 0f8b21682d3f56f6e58bab542279d958c910a9a6..ce044115e47bf6e7fd55577aac97cce898c8ac86 100644 GIT binary patch delta 4302 zcmZu!3viUx75>lv*xlq`vVS(O%_bq|W)t$@6-Z1#Y{?&z2tj!yNFY2mn`D7JNW$(0 z1{>HY2}tSG#|6T}#|Vm*(vfzl)mj`{)FRZe533G}qP1gHY#Fguq=P+oH)(b{%}nmS z=ey^gd+&E1_umh%%THdHAINk;SZa~OVF-Bc`wsnoJAt~q&)dm8KdPmm?WNWa^*WEp%yi`(@FqxhZ4^|LJn0*|(r91}dk(?|!m6TM;LK-#zMW`xiAX(asFnDC08bu!fkE##wONxtM zRkYE6Yq&-l{Ua^&X_VV4B6Ph$5pNl|1|pYMLuAb$me_=hOL3H7jFU+_8dP z9erLh7?etQsg{;GDQ$dVe@}nV-yWMS=4-X|@KjgaY|tN|DDLwGe4*ZeG$mO~1p+<2 zBG7%Ij@}-r(&}BeuDd_DL0YAG*9H83X{N*5-Mx9Ew>7wh!mFcfrnFY`ZuE8ZNTpWl zyJ@L3gGT<1ZGBrMZ*)YNBDHAVU~Ax(F3FeJzO`o_DT;J!wT}xVwx#%kAzy2EM{q+l zQ5*YwZGH*4X( zWJo%KL)Rpa)1g}=l=7W=VzfiZPtollM-74xL78pVx~}fw+K_CN~YB?n1*Sn33EG&F-^dVdA4{o;ZmxMWah?1bkn*r^GGo! z3JuA~WERxXB9^^cjQW_h43>p<%o3Y?T#R;O4S(B~6Ha8=I03T-x}yXqkg}1*teAvW zvHr0VOcIcr$>=~?KxazOA)qv-U@|HKx>SP60!n8pI#CtSHznvK$b5J*rcjR=`A$=E z=pXjLIhzQGb2ehq=*+i|MUrV4Qe-fp8^9U)JTYIP&Y9$}P?wj=v>E4R4PTbod0EHv zvMJTE3o>4iDFDyfST+9I#_H^#31OZPZpZVHP$t-D^=3AaO!9qs_fuQoIZy3XPcyX( z^S=QfuPYb;-_f%L0KUjeldO>8WACZ>o@$2c*!wEJuhJHOQVk#fuyBjb$Ns7kzrKjC z=r0D@uASX#Epm$R*NsYc!iFbord`}#qBuBb%a2Zdl?6W%Ily19`WuY!=ge2By|=my zMk3EvuLBZtYKEyjTGK@BjhZ292WzK$Mr2*r@CU$bcpX@R7zqeRWE_$gumdt4;D4HihhcvS2xFS5-fxu5+?c=HrRi(MB;NnYVS) z!J$Z&$lbCri#%+JdDwy$!$#g!jS7lMaWl=KAJ(8s__CT@SsJYlv79KSlqgyJwAI24 z3it|saj~bwtyIZXNYOc;qA*LXvV)Eqy1Q6DTEv+Put01(3EjMKNd>t1+9jQ2pbX2% z!0Ssqgj`#4ilWQv&`$ywVqZ~?Fm7L@eSf>O&8iVw3AAiRLs1@uqeCwPi_jN09Bf%A z?xt3mRHM3>VpQ_)HDpg0X@9wr{1_`&GE%I*0FW$}rTm|5UTNq9E3a&vlwMBBl0tmY zxxP$R^su^J6pG0G2fa49mH*@MJtb+fOy5dmNI?m~xK+^T(7!K3hOq9UU{M7*=AezI zKIzN6Y-1GbDzlmz%OHPem|7hj_p*)u@X0OgJ1hy49C`{UVzC;v_+4=$hu#2*gz>Vb zX)u?!Hsw={?`kT9D*jAUT1FLxkwgh6s1ZabQr##ts`xuiM@VD)id|435Q1AvKN*nI4jvpfGt(=~!KmgreUHIXe!8y)8o9iw z8Sdn3Hr)@4`RAMFz!F{@_z5)dw*m)9r!TmI#;*ovL48CHxqzUo{!L4k604K3#Hhzv z=HQ?jWY>VaT#D22D&RFRXr81`W&AsNP)Jxz!KIf1lGORT{rA8feC_6j z+?#;+%EXx&W){0e$D3d#E@0mRehWn8P5%1kZ01DEc*>Ym1`|fp$DvP&dGV{wc_mG5 z-Jw4NkSbi6ic%~blqr(Lbkt2($aM8HJ3UCXyn0Iq)bbNsrc!aexFtiQ5dLCdvV6wP zbGNmTuw&b1n)zlMfOWS9v&dlNmDNLX&YM)?h4plD;Gi5AD1$ONaBg@RwD7&*eDdG( z;n_*`I;Q8-*GftBj1LWFPQOdUC8M{6(&*GobweEn9Oeh_o0vv} zX$#p-z@5Ug!@%ZfH1oUr>R@XmW%nYhIz%rH_dk%AMuQ~_*|3bm;^iHZS%Zc{k%u36 zUWUbyac>3%>G0kLy2{&o*N_7$_BD_LcJFJX_R_u@!t?e|CVbKU6@)ys z-$(ihBYOznH&R2$#gRg4{OqcKyXQvpfLSQi>5DA>yMW(%EGw~&lEXsfQg!gQW79G} zR)Jzj7NH#d0f0cC3KQHYMV>l#n0|~>-M57T)Ed#&6$&s5w>_23gHQj<(oAbT7T$L} zcPc#x*>2Nr(5IF|H|(^Dg6bV=l_&PeK@W_PL>D3ANr%69yxdJSj7p4Tf+35M{+e*lVK6G|30$+lKt~u5+3JfHzWjvV0Z*$B|jt)42D2biwJBsn@vcv*~Hxq z7#dm7L~GH}dPO5pM4?WlcB)-#b<_^6bq39}Wv14#wJO?nv}#+&KCQ2wyPKG;ZDw-s zJ>Na|-1DFF-E;4L>qGwLhy0GYUIxidNU~0zOwvdj8ykbMP8eg~Sh4UMSJhs^$C4!L zN&15%|D&x^3rF|P2}dKrSa0~s@ZeBvlyQaS_J$K3Ly2Hy29(e6`N{NDez0pOmS|4| zLjzm(hGRXEp?yqKYmDefB+@(*4F&r8GRT}PWCn8t0)fa-XkdB`N%3%^DHdxTnqH%j z(Re5riL6*z!}PR=8Ekh3T%7^kvx=)$W*}o0npVmoWF$JfpDPgT?hXu%B*HOfQ>I;k z?xB&cNSFd3?*QKdN1!j7AYsOt!I4O!ZwAxlU*PiUbQFw0ESwmLMFa6fEE6(w1{q28 z)Ma4V$(u{k>Yl(zJRGA>9S+8Vi6L4dU*R1Kln2iC4r@b8$CfrN$&{RvmIGH>+vQTN zsdIA+aLw)JU-$zJ7y}OUuWJBIXF7LM&*tPpuE#VXPtPwXEM%PPy6#lEdJ!;tC@%>< zZcwACMmLi37n(O`419Kj8i#yC6Upmg1EW76~(jAe?_#)`^AaDK6!`kxO%Z?b|N~Y5>lRJBaKXFj`_2^$V||#%vU&TAS+ch z@_oImX?fO?_(0!qfHsJ;CD~{q))(zn`&Jgs8XAdG8oM*v)w0c2oLrXm0bfY*MR{sr zEEXM7gbybAhN7&_5$NfOjKue_%WZ+4SUAjTJ%LDM?_i)SzArc&=&QY$b=m@h!M-S4 z;h;W3OWDOV3J->cM_DjEq7%cqY=L-JtaX5eT-~G54Wy`!UAKEyATeAJjwga$k-qqz z^nq<34u--Ejo3)EZ77~-4=3U*;3RV$dt%{zOvqAuO|oZYZ|^0mSM~Pxx^8%$w^RWn zeJ%k$7qWi8%jdE@{nqfcYUDFo^#)|7W*~SB8}qq5hMghvy9`&lL+~3$KJ&RP)~q!B zZbIf5h8uX=rgd(PA$lqx{xj0vM_7riEQC8X3hL2TX{8_@eMIPe?jeC=}F^WwI1?BxraMB?m!PMlKV>r3H)GRQI1Yi!r zYR;_tt1!nTuuyo>MDJRSSxwsSV4oCFG|scrL?ZrdSEfSlm;_Pg&hsFt7XqG zMq|dBSCpX}%hV=sEk?JwTb^*vPtFnZa1PE>=#AAlhm_5E!hyNyQ0woj##{xJ3637* z3OZYj9t9N(4f9Y_(5uy$r=Sv{V?OE%`gb+v6J#A0kMU*{&N&q!&N(TP zX20J(LoUlSwN!IX1i+O_x%?V+FVFGVse8LX*ovmO4WHv;iW@k^iDTjgjxWdsbIV{V zb;(?ClHR3a0WFr-l;2M6yX7xX`?zlhwR!%3LrA(S#vpX+mI{DS>g$UfP!bZa>G+y% zC7Z?TI=-$GZGWkoA^Gjfea?{hgHDkQr7Ej_XOeAWZI`3UrMPdHb>d+sKJ2vI>N^=_ z{G8LDp87`_d|Odk9%*wXGLFA~Bf^d@KINv1h;dqanZ2Ew-4>y;Ru?L%-8VTRqbQKBqE5`LAmzWM` zb~NREt;O|gDNFWDmh5OZ4a$&it|4A2pKTuFm<<|KKGst@YSM>3!|NKN_4}<4IdX(a zq+KIVZt+!@X$`yq%Ph8$XjiH?xWPahmJJ9$+AY0bRA5CFXJQeS$v^PXXkqWd;9dn_IUH6FENFwkU5E z5x#)pL4G0FNMC+6SXTIX>3XruW1I&lQWHI$Q}c7CH<;bZB4S(s@G6Z154_@-(qO3? zKYDTjG|2NOU$l9Vp;tb1|3ar%v9|20H;)#B-5?88qt8i6%-A@A7Z&c9*?GoFJ&DYQTADQ; zBX6dbpRP0Q*25I)+$_ZHG2Y@(sXpP*sf%5gE0@H4!)%hzoLcW*r+6evZFFEtrEz+R zf1`>4+GA86y~1HbyKopt)vK9G;oK%Vi@JH4+;O@Fn&siszDqX>L=@nr^Uut6LZDEp z6(npF_D?e9F9djQm}@gb*u&Sqa5XVtawY3L}_rS9#fv#?oS(bEF;sk?jL1?q0t^AW(6 z@<4x_+7J3`2=Wd54ERB({2=lxXic3Pe1}6@Dm8o>^6SJ;0e=cAo6iA02j(`}7rPJI zWlp>izARhgJ79}^D1JL^m1`6Aut|<2z6%}FH!?{&PmgS;anas7*qmzJ>ji>(_g$OQ zPCQwH)#hgT#=a6SNmdQM!|~5V4^z!8rXfw5*OkzMs_PCxt2}evwuPSo-oPmyR#MpA zb^|{H%e6^-3iv5dkUo=Tqw@?G+C9e7%rVgDOtKB$+u`!7<}et(ILPDn>`2|sVhL&*>ce@O17nVkm#8W&BM3-cN( z&|p1H+^3R}vCU93cdA0@Fm{!furJP9dFjnt5V$)wXjA7xtOl}&D7^x8uhw$@GOgqGjupDM2>fHJi{p&cX1K0 z;YS)iqM2Vw{rsjgK#3mx+T#?K)QVfqzzSvRWetx`8#$=Q#h!FRIricnvalPU)doZ# zsXe7(AEniO7#FHlDGmE)caBbP+>24OJ=JnpgZ%yJ8)3gSf1?=1QK}aEW#_FQ={Eu1 zBm=iCD5Al#7BK-hq4Iwdh`(prwpNEe!Er(^IZ|FkgSHkiu5LWioZw=c z4JT4vN1o)cH8pQC7sPBtC=%);rc@+qC=&D(n4(C?mV39+r=PfY7bWdu8gG_cjK z>S!b3Zy#Mkc;T__gbW@F5^sNT>@eZi9B(A#c#dhQQpOA>!Zi=x3UKKs_>3Yuf`(*e>tA=CI@UI@A+CW&MdYutUaAY@vej?1>-2 zm33k@uC`ue>J5?<8r4NcHIK}DKvRU~=B0ve$N!bTo~em~t|6hT^jQ}S*}5~x&${KK zJBw6zZs)#LyF@PLdW?dMH9hU>dUb?6#=2?t6S?UDm;K_n^TD#*E9iUdR0HX7X$)k= zgUgEPBZwMY@i+Y|0s*<{Nktw!#^>u)7YFD$q7JDu5u?^jx86id*i-(846yH{)jp?O zb!Opmlb2d<(_tk&hR>OP)tEs0X{cYJH<TD^R2gZt(TzM&*<5e`m1dXXO{pyZ794m$RQU zub(pRK4q*=9ZErMjuFH^Z4L_tDL6;Nf4ws@1OnL3Aaw$E0#fIOs=$UdgEJ#rx~MC< zRqfK|=)qu@#@3se8!n^-nO@(v)M{JO(o(*pt**MUQHx;WdSQOR#aCBX*K~B$w=b@4 zsA+7`bhXtDWXpoO=IAyHvyS@3W$o=#7hF0>VU~B))wHw}jVRO%wI}W}ZdTEVQBkD# zGIHdIC@OMVbnhji7!WOKyL?}2b$x3`U3=rg#r18~^XeB@&#$jpSl!WhYrSU5KT%0q za&Ln6dbJXv(MZOy3|EBLG#Ss5q{B*+BU4{>OUu&M>W;-VbM*<>=eNz5?Zq-kW5MjlU0tS2TW#$yeJXuO7h|Ngr7kuL%As&8*^TcC7Qv$%0Vn-*|aH#D>?>6ow8n$->M_4Qi%C5~%5 zmO*%p!-r{2W_4>#W1E)h#f&ssv zfS+qkIsSm(@ijRM7pYMoajH?mHCwYd`7Bcl_= z!1EOLOTh~i_Ks}ZH$lAGGx~!~FOL($_%Jb=k9IUCXvc|so-ZtJ3C5X2O+vR5g~1Jx z$aR7D3KLHvuC+v&itvZ0`HYfYSX+}LT?G^;=eS1tb&C(={ct-sowu|3K)X?HcU4fm zJnI??k}P*N>9W*a0NCm-0({h+KXHDVqY2`PBESQ-pOeVpMLB++<1?K{15P;G$#dS! zwsp(VeAdY}dflTW{<;TmvwwIJUS!)^*!Hv#`NJz>a&&yQczrH>c7u!!d z`~Y*ba&eIHgADq4)gwyzK94B(lBp)+)ue(S2*b)f*zMx|aHPx?zXE(-8~|LIJqz%? z?0-?K{9B-tT7P?O4pD1(My{KZTg5ShA2Xa_xj1g{;|8vH)394*d;evgR`CzR(d^dn z|MvgT#@TO;u65^wVV`B$0r8}VKk0G2N_9#cuX`W^EPb6$I~X{Y)#FZ6NLH4-0qA#z zQz%^SG!Q0Fm97OGKK=&4b>r6n+7pHbLd>#Eeh&!`KTje?jTDN97+=FCij9nKl(iH7 znGs@2UAYdm!=OBl(F6<1i`W$pg%_52bey-m@_Jl%sB*1Q;1}r}4=fjPJPy2(od#=3 zR0iaOojWfFCy741k5OU=WN^w=lqvU4;glwiPpMC8PJ=h3b9a>ZR2)5~d?!3>s*k8& zxM^CCnbePKc(2E2;R>JiQ7VNL>*12?{^4!#i=R-r#XZ7>2VL0&kx@R=)ZuoH(7B82 zN|Y|{vSXA{+u6e8N~WgIddQ>_WkjX0p~7A^R0v~USNnw9Eo^Sv*|NAUP>`mVuo4av ztpw-kMv0d!Zt}EdSgA`%E0^c0Yy0ywd1u`yu=;Xc6Al>8hvR_4xdC8i%zcjgx!Y&$ zBC^%JDo*fT_j25uUti~TK~FK*c3*vdwx1h5YdEHZ+=iorrS|4$iY{oSn(2@dY^03kR0c@7nX|M}-GJvs7(J=m-J ztS=LED`<3?An87nK-C@^7@C+y>tf4v7BsumCGr=Cue|<8Hx7#4_#^CqpTrJ~V((^@ ztT;}A>ljL5&Y_r4TPD@8U9q9RW>R1EJ)KF*M3IQ+@jfe&bVYAOSR59$$ZIGTIO%H} zLc`@%Z8>oAy0*OJ5r_$z<82ZX_ynctGG4~>>=E*@w!Sn%cDHQ-oV6ee@YV%$X{0>9 zU=haC7b?u6g)8!u`j80Am2ParSm-dwHIwUB^zDa;`l@@sZ#Wp+|B}A#(X#rRq=LdI zg)jP8X8%k;_dd%T)ipUsvV7JMa;x2cnKuB}n2}*ay8GU!rO7?NyvzHFPv1yEw!%>I zE_&=W?^uz=vqXV~{BVV2TkfT?a>JJ0fD?ZENBT@AJboL-zkEED)MetyV?`(L6kQhY za`MYXkO$?Mt!c2K>$Y;hrCVvCm$08si4)r=nX6@KTG4jxkG?z|A ziq9$cR*@rrbMLmY6vVYcC#D<$NpntVO(K~mb3?tMK%`h4R#7feu>^P3c`B%MrAU*T zA_sa<<20Tk@A}mS@8LxKehQ{`4OFuFYR5HrSmhJz0pEFIMp9K&9MkwTQDyNer?6a1 z=hNl*ofD?aj4s{CZxk~v{t%T0JH?a4XDXUmd={>JlEgz~I)u=I;bT}6shFiBp5V`l ztdweMp(=c2=d}!X=0CN9isiPa&QXaBJv|8H{ZF5xfPDU$859V|?%Ge@d~uLC{tl2m zSibx0ODO@Qvr;D;yj%QX+78=2OnkhZC!gA#p5hm)bi{;}Mz7ej(m?PzvHN-4_v>&& z#z~|>rSqf2kCHfvV0V%f6Q2|RT&6sC%j6x%q>5lW@bCVpC$@4pG? zE&Hb{dG+WVe=qBh*TvUTfOtjC_$#_SBpmpk=ZS`d-}%E3!d0F(@_C*(qVprV*rHpo zu~jIdrZ>^HM0^HqZetF1$^^#t|O+6jWz_8qOK2{P~P zq24mYa<>SW2!8=t`}VUy_jzX}-~;cBE(s{}N17^A?qQc(e2_q$HWaLYlj8;YS1cGG z3C7|)!#zE{YtSClpwj#9CdhpIyGUOZ^2YZk(U|b#?|(}8tUvZ0QKh`+Lyv_kA>zdSv>?(*avQ9-G*MhrSZ9;DFB(Vxeg|`{bU; zs_*obpqYF+6$Y@M`2I*ne~tKSWRH@|P7k32a@*;JG*u>_nLt(Y<}(=}Uw&pRT`jxM z6xuxj{y56mt;9bfE_vFM*6c>qKBnbX{IpA!D@N?JYRPCU;i@B7xeb%68@UA+W z?VXWk`K)J%`lu+^bvBd6$cN810=mu(M%g&xT(XJWH2JH6Y*&U{{#6|&AAGeGD>J@E z3wM`EKT`(8-&(^m|AyjK8BmgPd)CWr=Z5L0^k71lK)@7dRCL+ZJG$&r(PhiG#WY~{E zbWVPIe)wo5|0LemuE5vt==d7W${wvl>_m2TIA{ER#&3$}vP5zzEcj@-faP7Z# z5-cI^!tWrn@M{-#Qjt39Z5=@>ddNznL(Grpn(=vjK2ErWzp6KjMv%Rv^G0ZV^Y=VU z?F#F>>GI8OmoA>i+w7^~#My!hSdwZzv(Ecy=OcSK5p zJBi;($}fw>7_VVrnGcyHenI>f%4XJ*C^q@pP=BIwTHf6X19cl~P``&>_E2_TjH)Jy zwT!P-ad!<9*O+`w_tzf!J)_CpyDW+)aamrFlVTBlkFsZmHV6%nJvDUPOV`lk(6Bg~ zO)a7IahO$vK8&NOt}g=)>^w9&o+f~xGoA*5U`IUN2m&H`r8%m9K1?3-VbBl#vD_yQH&?s4ycs!&^4$c+2_(;#qz^(P#Np5sLV# zqT{7%@{~cvFy+vDX*8Oy4JD@2GzxUrrPE%T77(NODCdZ#D*m9*z0A@Ot`XjTTsj@p zX^`@VA!v9}jG+#S7VrI4j6}f!K{ER~S=(~NOopbDWpQg(RKrN17tJ*4` z$o3j0XqLCmr)GJwHP3y5ChdpM5V_Fq37KUVA}zMI5zWI6jXUD@O1UVw5^D z{NO{G1Vja|5LZX8*!S=(b$I3@if%TaE#^e%wmfpRqHE{vVsV7-o8L4my19=w%T)QvVY9Lsfk1~QQi&6~o7a?mbU1N6>6Ec&2n#B&#qEr;gaAWRT3Cg#-U z1Q)4(RiLnq@mUE!)a9=i+J~Rq$)ZKFUOA@ z+-pyfj~}@TCiUTwQMoS^8Jl!;UbG_8ls&9M?B?E)e6xz=Vo7COnd(r)GfY(h&&Z`q z9;7Rzz4QU(jcrS3(wzI2J&)nh-%qxP8vu6@|wxm74D{{vH#@kZ|5)%C4iO;YC^`K4AP9;~${VJI?rVdGziX;Caxx z01l{HHyu^#9>(`Du@_tSGW&|~v+D|pj>(hv>?}*?Pc!@)fi^=`cF!=y+b+g;sT3Y9 zlO9&pUY^hDjy7nK9Qq^kl_S?bh_Vg3|1V@-<@xWf-{$_9QJxx)S~M)SR_Rz|TK3Jd zeNib2HT<$5Qk9BQWzV94Idzd<#nrCji*UoLgxlh&>M?0NO+Cf1%cZZqkY>x0_P~{O zf^#ki0S<306M_pxnu|%D$mY4A&lZsizFZ9yXDBjOMZ079X#0iqXBnj{U(EPVUzDXy zg>;?lXgXQzSE+s6r7GY*Dd7z8E%=p+w}<*E6Go8$hhg@3IF~Exr5hMUeyWSb0V{hK zuPasYdamQs{AxH)EQs-gPv2;d8!0hx%q{9b{M<*8zCN_CALS*Mi3E5aIwd#^*ay|D z(0Bc)>*l#i#!l7}fiNrLu?8fe7Qb#Ezr*aAHEY()TI)Y+ z&CFA0m5OY259sBv;>)f~Uls>ii(PBYfEeD zipq-1D6A5VmSd>vC&qhE=x<5|nwPYDZ>4yg+tJqV4Nx7Y#MWtdw(|lZt@IW-|d zB$+|A_<&~h^S9{%0eV1S0P%DL1w(L1XeflK;eom?5u&Op_zGF74@jnx04LaqhJ`E& zMHDI)hJ*$GQ1TG}kVn*%$*Zc(p1fU5@Yig>hh1rYi%B!m+ zhq_0?76x_;m8Lr^c8g(~Zp@q|YIbdy zl1(LD)+pFCRkB-bnn|LP!=hO{9|{gl3zY0uL&_7J4l7dpG;O6yx;stvC^jACo%YK0 zNHb2$D31?NJ9pQOt4t4IooHv;sV9+)?-}i^mq!}6nI6azX);X|)EkT@3+mE%UFUyO zL-TAbi6$|PYK%}~z;q_-!AzkF3!*Z^B{CJK1S(Z}_3)_Vo%#Jxu|M<7EinA5AaIUKq%*LnNpGEtSKH$+-y$9vb#AQ%PHohLDM4*i2)5_c52sy zC@=?2cUY*yrW!BW4R^eeXdI2#O`0Luv@=!kk&m$PM?SbTy~B!hU3MQgR{~hv{e2xW zex_P&Cj86|WNJtoQRxSSwGoZB5wtKnMCc*@_pm5va~})?ALMI`i^akGB7Gjq`Rovu zx$)z$+!%iws`+|*JygFE?f|HEM!&#>gEPHjD>r>6nDTbt1yWj5gt&XzR^_px> zvItLWx`S==q1${6t8jr(^dleC4!eGdg4YS^!W~%`U=8=nK8WRs>>jYjtr=y2jhg<= zSl;YE8q0zKi?KXDAl1HxXqrl&0p>$*0rM3#L85C2T}%cs7ojemnDZlYN9IPNu*_WC z+-rEh{712|I=@*-wy-FQYsq7N)DN)+dK7v*NPxhG@HF;2hp=E8tYqsBo-?#xe5}BP zU{|S{i~Ne=Go6{J>HYvcif@9*X=mHu$*es)~k>$K+qpCkk$bMX$Z!G z$y>}8rc+(FuPm`AN6FbFn?@N@K8vK0O12d=s?w+m1ewWDrn3Z^kVGWhIZ=FQNl%F4 zi%X{C_#U)}Zs$Lj*pU)3n;ra_LOa z_=K`f0gRbx5SjzmML|XWmGx1XxuBLE>t=kLsKGo^r8R6l;Av-vOqigowu zvcV9Z;$5K`J=aCdj=P;89=h>2@5CVV58vtIOug@Yol0m2S?`XH&=CeIGppE45fudF z{Z1RTVVjz%B~O3^83UNFifyPeoU;(LKFn96zBbLbUFScvH*i?|9Lw<;5(|fuWMnHdSs@NJVQblDWT}L9Ii=&Uwo|>^K5rL#T6HchVSJnhy?qCeHf*bffZw^q^B}QnP5)9MjsYW6VT!D3=j{9 z46JAvnb55Z2!x46?TCcm9_a-N)|si@#T`7X;q)>^okb3jC?LN2qS__|I;y^cfG7Bi z%-RGUc3=}AIQquGrM!pG?iS?sv1uV7i&+FR5!L!AA=sw;StV(e*h%1thlQ61Ygf zaHXk`0R3E#s%Y#iRz}O%RERep}%W@6?Q?4>lZ6L00UgZGel*ZHW(rZU8y1f*@Fj3%wKsE?m!|U>KNo3ezJlh@B+# zBw?q}vqy>8GG7w_{n~Xq7z!cTH9Q3DD5Ew6M&RhZgzhD5 zACBHf^yHRfA&40`dM{j^9M!MF9!{%^akMaJ87|3!^stJ(nb`24REVFhOn(b zvguavWL)yY3Tc8=&efjun)1V*! z;M!<{jo9lm<$jo3R$Si&S?-)4{Qw7z{OLqgtDVMA7bh&?RtI%>BOyx=5^`?L*Rog! z&0sx+MEAiPF@S`DbRZk-nd17->(+KGf4J2J%gEb(t?$|7HQ*!-3hqSSQvU(!9Y^C>vWDl> zWWKE7Ib3{LBWl7AHU0~J<}T+GSPyD)g*v@>t*7)$TO?CKCP-w5>t7Cfu<%aPju*b89AjHC;XM$>2|+phDRg%98`=fYwX z@y)^n$m8Zk1u&40S@aMd=n`pS2SNPRMLRnMyuFHT0J;J8u#G@B0t!W(zkreNlOTB& zI3pUn2qlLv8Ho~KULri&V`*XN2(KQ)>2Nkeqa%#8JXSyp_zO#O;>LNq#?UcroJQ9} ze`h`026UX@8B52mToxQTjzt*2qVP6n>3>a<{N;9EBjM`PaJT!EUEy=D;`dDiPYuw+}F!E*bSgW9V^4#ZUEi!RwUEgFV~ z5Q1+g=pR|+Jbk$L!0;#P(7&V(@>0Js%PG!ojXnaaiRF`En0r}yqa5lvneO!_&|H}~ z)kZN551jKL<`_?wC3+IWjBV2v0$4@lwEk7(w0aITBl-HRk73Y7RBa*34uC^^EG4CtTO~_A0`KLRc0Z!u?fcM*03Xk$l z+fwnMW5%mUf=J#8{M5ELk-XyXO;`qQ@0Fb(_BsZ`-;+;Qh8Ocx^Z~lyRI>atar%2y zWVZ;;)7tUY-6}5KPi|j__;KvOE5T@feCH5Ibh9@v0e<}4zXFWmzPoF&Y}lQKr0u)^ z2S}5ZH?$mwvF=g-z;nW5yx*R&aFDOrGXl$tdmaipXjhFkyM_tuO*|b@RW%Or2i_6A z&%E;9`izr)j|agf*T8xG_7fqi|UaOM6{$XmF7 zEEMtW``4h1fvsb(zOl78jCOzC8V*SM@!eSk6A@%xFj9}Ey^W?OrI!5!n2ytED#f(+ z6X@8Ft&4>IfX7+U!qb~=p0O;CM!NF z+ylchh}{Kx7jq=GScV7^Xl3p94Cz-{ABzzT$~c z$5ihw`4k{fU{D+=nmV2xo5b01`M(RHil6(p1EFC#+{b^kMnfI=+>`8G)QH0osZ)d; zhCvUnFmH92&&tk#MkY4y_ad=;;giom+|aNp!&c3GyE<^IwrhG`GY0PEONg)UX} zVs=T!FZ)$Sql6e=@Vke51f4`Yokl#F=qiCHlWKg$bB;W&UP1bG{_c^^>d#oa#jhUe z(M$Lyl!l;dBpPVQ_*IN1;i9eLN=WfaxQfuN1bw)Qup*WID$|{^KG{9?Jl&B zZUo?Cs?w+;LfkPkihQ7iH_U$8d{%+J0@eS#&kt$4{q&aSRyvCx>5CT_Dv+-!#DX6BFU6R)KVA23BAC*l@?%abK=O^$;UIO|#w z2f^UqvLz1IlNbf#cm>8+apv}^tHDzDl;L$X%+yjG4;mDX$Gu|r5o<&)e8d%*)Q|?_ zdLe(7IP~Y&;31tv8dlxMaN0DxkLQ_62h>ES%3$n7el!_&coarH*FHOBXo`5g^py}! zs_Tv&uSE}c1?u`Z1)nn-Qs7ieWmh;2EnhldrnzN&Dr5sm3U_^z3O!xN(%_~KKGQ2^ M*`&JK(xK=70dko*&Hw-a diff --git a/lib/emscripten/emtests/test_emulate_function_pointer_casts.wasm b/lib/emscripten/emtests/test_emulate_function_pointer_casts.wasm index 52a1a83b6555639f09fe8d530d701a79c909b313..e115ef77fbbf94dc2145d839e169d7ea379858e4 100644 GIT binary patch delta 3691 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 diff --git a/lib/emscripten/emtests/test_erf.wasm b/lib/emscripten/emtests/test_erf.wasm index 124f3af3be54a25f8b25f92485a2ad5600992adf..fe67b717f0e1677936e64656394def151a5fb17c 100644 GIT binary patch delta 3701 zcmZuz4RBP|6@KTw_jWh?mh59=ve``_=Vk+e1SBC4fmp~(NFanD21In!O$ZCgX7fWf z{DcNJXd<@$@N=PnPSv7RP^;)ut3y>-aO3M?9(xfHm z2MIQ!W~q_RExzV;T|K?4dYfC?uiFyo*%0g6sxY}=bZ(BtYBzVbgxlIuk_qD^-^iTd za5&c0(mrZKTs+cS)6=t}Yt%+c`r<9ku~_Mx62T#3ZMmY#{XJtVbLXT)#+YbSDUBqX zJI4+Pgd-jCmY%lm-biP7W286S8foqh$J@3?6io~OpXVR1&=Zj>NgV~`nf~Nuuj{OC z?(FR9UDDIFwIR~c)zhbd_#vzoK328SssxSc8Zb~4&_HoGoGz!+p{gqR2pUP!fVshK zcs$AkHQlRdq-FxBPHCV{B#U)s0z%9nq8j}W(j?J|wUjX;o?`wPiH6sylhBs`8ZH~7pReE?sPb8vT%zA{{N=eae#Lj1W?m>f!jho_3|qy}pma5sOKbmwCn*V(T*^@!sZj zv9@??GCx*1x|>@f%0%(3T9R0v+0c;V&uVCBa6fZ~RZas)gnS%AK2)LwzL3xIMy>8m zau&*1p;e+{Dh7hr(3OzSYd92C3Ven;IUp2d7{39QmT>gb9xgIIo!TU6N{qC1aS9+; zMq^fUevvtur;T#1N@Coj%=uS|F}`6InVfsZ)Ht6o%KZCPlZ%(M8wwW((N*BH6tD5; zPI%KLukohz!A#yG<$`G{_FO#%;Iof93RD_?ndWuS@H;QpGl!XuZ!kX03>;>bQp-me zj))1FIWTNb&jc6g6;GN>#$wszJw)H1JWTXh-p%0Kk6%NbxQP8w_sBL5P-pk$J82NR zLYYJlg|@ot_(z(hn00nm!Cy?;>gze{oYQp6!_uOB3Qn2E6h0M$;)D8f2#Sp5QQDvk%V>kadR8(N$?#UYK%{@O4t--nvlC7rHuVYO0CD_h1 zdK7kIZ7vv}PgISBwo{ja_8){@FiDI&c()<6q&OtS&PRR$kSB&8y*|rFktGKQ-oB#N zrF=v%(JnpqD1#dD-ec2=cS6|$Nnq4FBv zXW*AN$fi`&BmmZcOPv2vbKtCt(-Y9R)6%)0vc+%dwG@)GE)hMtl^5`IO!pcYph{yc zx#JY+k=JMhH_5~&jaS1|;a^oiUR=AXaAqN|Cf7Ytz8Duv7;CTw3(Z1GN`;=KghNW* z=$2Bkchyl|$R|@aK$Pdv_IVcTjdDbkS{!*&Yt`!YFipI;dJ`0iq8svvF1ukzp+u4D zO09&*tflKRErE)Ts*$?#+W?u;!^Z1I+*3zkH;crdzMGW@r8K;$YcaE!Qwn$uPYQCd z&gFQi;_33v5{Q*idY)jplUP`=iOy2J#%mhPlp3=rDbB*URG%{G~KezGmEmt$wN8;60*a2ikgx>WNm@n+E!=$skdo9h6bkm##To6_bHw#8UvmWoY1{%qo` z68wzeKL|imu1%*YEk4}iCxaJzc0rj~5O2)840t=EcvuPU@Hh;-oJ8RY;1!@CT^3Ko zbGZ*4W3Sbs0!m$8;zBt(BZ;ASC!X(F7&N@b(*Re|(*E8_Fhfl4Z6kVD?@W3|FZB9# zO5k7j6|>Vpaj~z3nDF*3wDR6|0O$8~m`8T@(VGU@r1$8-$^Ekkg8?=U_W?##C#Qck zEEV1T1q8vt{`u*p24)pd+bl}C@0sY^8|bhOepZyp7aOsn|wZx8SYqJc?}?jq(^~W2~KbBrQ5DYEMaw zY!#!a{Z1=!-bt&7a=%Vm-N?fp>Y=Kv>Rl+h@A%x;m#p)B)}*C;J8q}9*(bIPUc6=q za44Buy8(A6-|t<3cY#d$3ckRj8MKU7*Yi68@01`90k6<;NE{!kg+BYALo1xxAayih z-J73Dla=*+h~W^Gaq4osQO7}h+r2L_D7R+n;R-g}+b@X0d1Q>HO0FQ*F5ISnc(@x-kU?WSk`(L=95Nr0DQx%I9h8*_rI1c5>u zQ@QwdX&X^thP2JSeljc)71zI8?Wf52Wq}IJP!t}d5}e&@WpB3JwPS7BFDp_uX3HKa zdnT1E`FY{x`5sM2zi4c1g(c!tW1;gbK(^d}!OA~OoA^x`9V|9g>z-n-kv>k6<~2TM zP$-qXYi7HvWG~>846{y zlSVU3#3yS?z!HHQL)TVw>Kz|yR)J|E{xhrHs*Q&$H*)<7aE z(NBIqBOo)4AS(7BpL&3afoC$s!l!e^iD$lY+)SDwhxqZcc{5QpCj>2zsaXlHVY;bB zsi-a2DnqFcFKTS2hb}`{kdFBL**QUaJyh)!3rr?w#;aLCUkxtfr&)IX^W9Fn%03JB T{-3P`7RwZ+FPDqpE8+hD2xnnd delta 3794 zcmZuz4RBP|6@KTwx4&=6z66pi8#wfv z+~`ZFQcsWeMIsG-(e_|xr;?P686~+Ya|DCINOyZzYKKl-Zzx_Li!JOP(UFq=-uBi= zWJYWnq_vdp$SxP{>Wik%6Sn~uFTvtGY0|lLnOWPkY|&yh zp-A49@=&z{&il%7H4&YD}rwd$eT?dagCe7hc7}GSb z;q_`>yVTIqL9w@|Cm_IdBB~^so)AwmpKAaDcAbbr>}8n*N}V$D(>Fq`oPIMpK7jOe zx@1t9%(Dg8 zw01_7u?`v|q^gXgS!hjrPruTboKe`7`L-p&-nLkm(&S#*PuNBx61xSSYYef?V?(|1 z*0xAz@9L%T*7mNYJ+18_C0&p8MHhGX#+QcTy~}mgETAvcs!=gi9l@*Hlz`i-+Z9v_+`2nC zAQb3&h7$0YN`u^4;33HvUH>&OSHeC(W}Rg3WXf*Rnt8G%Y0t^QRJbw{;EQt%leW&DR1_s^ub78 zE#-n?sMeQS1i)=|*b7t|w!0`d+}0CbZksX8YdHqmhYa-yg5zl0`n5(l8^z)c*W$+~%> z1G1a=84b^9W}<zEOp0)b;TG1&cQM>07MP#W?m0DnGPbi(QfEmL(Le^Z4x%LdG*I_P%Tlb zA<#-kfmSNBu*SqNpG|`i=2ck3^T_;!Fc+`R-{Ej^0}W%mSk@FM&QYsbHRhPgJnl!o zR_y^DZJ5)=3(#(AVP1%Z(w`#C5&N1dAV<946ea^@SVjgK7X(PMX2FlqjSjDV48V{M zWspNS${{pVVK%oroD?w^sU2;eth-V3>SbV;Ae?E=THu$rOIDQgI=WGQ(-;zT8| zc`6~AVi;1=9tTL5D`Wr9Vbu$JD4AYZSd^a49XOW4McyIU?*e4X zg)c(Gxvr4|t{r7kwwwd-$sK9Wo^}kYFip z9LfTpSbu0WG>UVFCfS#OTk2eFn+}B{zrBE*t81ThT@e+AVtT^74(nu)>#-gu8AX&_ ziiC}VC8cf(E=k2u`+g`ARV(v}-oA1r9O5*YAe`PR9ULpPP zO!pM&63^9*Nuv31jfcx@;(i+ym|r}8cxpkhi~-tX+=o8yu%Vqhbo9&9$K&{Vs$I=M zap7<&Ocpsu0<()bB69Fh7f}q(IdZwRkeFgV5esSm#AHGkC?`5q8$og}gKX)~h9j5t zr3FXN-7?qXhfYP$I<59YR10B3j zUZBuA-w}rDLg_&O1JYT=Kpm%XDyb66Bh{;)Emr@@5^0-2HtkD{%>HlJrlu_(>f8-} zYf6|ZqC|Yq)daa#QRE|_AtU+~K&eRU=_Pt!PbrD4o_Bz4c8dFAzl9lAOYa2+WmfIF zgOK6pZveiLYzU_SPk}K@Tw1>eD#Q=&u7exInY)+6Oi|hYFqDh8`m11?uxAy769^A#U8XB>xKFeT?E^Cb->W*YOIN?neGK;MYJwx+0Elnm{#e_v+J9W%l8w ziNyiG?$v(;FiysQ94ay^RaB=b3fECLeR0#*$35sVaz%Nf6LQ5b0qTm9O@rHwn`N^!U!mNmZke*JplZyKoy4pE4j@CGn?(R^ zW}|T5%m|=IA6N$S#f1k72p{jZ%Cr(4vkK^&U7Yg%mTjdzH~*VTy2rFpy2muqeQH}( zP9^_X#gEk*Who!P0g3?Z=J#uOzh+cgpKmLJ>t!gjFw-cZF~d}8)XdE%m0o^?O3*}P z_z1%zj6(hh<3SsKrQ$KwxY4?6`w<{GT@SrPm$zPf=m^Y^rruX^_lS|rS}$LngpFYb zt|kk2;p=J_@1$+VRqQ12p4fr;Qp-{?eC_1u$iW>LH7cyrJ5%+$#R@{k%+?OmE_YfP)g{t-z~nv@%gNzy_;REOcmt35euImq}D8xC5Z?fw~qa_hM#(|})#2t`6(Vpv9^lp;aThGB|?IQ`TTy884zcM>$) z_bef3&hA-Cv}|u3$?x7fmE;HawvgmMds`_xgZmyN`A7TeNK(3g6493Z<+SH}``c;$ z>Hd|3LKlBj#WMbwiZnh(VcMlqV9Ib8MN_|u$q>m*i3xc!q>?Aw4`8Jm8@+l4V+q(q zX+*xhDwEf%XG)Q*eQ5}cs#Lmto=(qWZIewlp>d0YPN)*`mIoc@HK?L26vGGZr-rcf z;LoAiPm!oF-&5pwJ;7D#dkXb5GVBFaCM+}ZxFWxB-{!ZadLF0G4A&%Z<~d!QX>DaE zJ;H3ultW9~`l4!{hG|}XY|5IJbh1E}h*uX{(#e2y(tX=60BXcL%fFN5rZAXkIXTckueWNPyPwa)c{t+$Z^TCKq*seqKfx#*6Qsd{yK3a4 zt|Pb;YOG7a^#Q4lFLnXI4WD;t4cM`Nsg&p*y`HR`@yLBHk+^; zz|g=3NtmIQDqIAroubC+(2S1Qb)0sr7OJ+CjBRIX9XtMETYs=qWh$+sbhPL0M#*&C znLYR3bI(2Z-1D8E_u>0|@_qh5K>;M#W}ZkuVl$&Z&1gB2fRV%1^$Er{>k0Znf=_9A zS~$AX+qq>RHneuAv#amso#EKl$iObf)rJ|}5s9?yh<1f~deWR(GdN%KoS{%CGSJmG zeTG)?@K7)oYaf_Cqd3FyuFgngetm6%X-f61naqW0p8G2A`ua4>yvmvu${@~;=+*lQ zL*f2-SFC4nC>#xK3lD|5!<~bnc+c)I)73?JGxz(${qi8p^5xHD#==TEb&kQ|hy4KZ z2&|J%-gL{drJ!>|2M&yZ4h$R)P1DFU&}roa?gCdvW+pQ=_bjH9NEU#`l(6Oj=GbB- zAizx`nmGai-5ilW;sx?4ZcP83iDowaBPshreTqJFhMRj}h1&RLbe;uIHa$HYi$w>N zyE}(^2BNIc8QQuvvLoKjmK&k1v2d7O;|WC~JNrXh;=9NXJ#`CMlM(9g?1?h3lg0=g zWjQnp_je5rv*3!_yaEDVWW8nHfYaN!d!+pXTm1mHPWS!(M)MR1DK+hlm@hj3iBFZ&(Q zg5`B^Jh^)LR-i?)VVvj5X70AK1K&4M>K?NW97^7S%pTp`COC4v(WW%$6Pi^hv)iw&p)9f=s3e3yfj|-z zZ_fc_t3}SYT(hZt5S;Rr_Bq}>3fmm=2if%p4oC-*#+p@NUe4Ccgud4pA;!*QAs6`N zYd^lPGM95|5~Ni_hG6-XPd(=MIOMCV3MeLY$E5dI$=W^&tw?YWd#gHmFF>@B9bQ;P1Ku zFi#eS<3taIYl-zj_!Z!n^5mgye}T&TYkT+|w1}_1A3Ks3t>LZRH6R>K9*U>aBeul-xWhIVj@yjGG zUySX88X1gtZ2A)LUQRx<6T;zknD`~w1kYE1UjaGtOAz&j4YUOWs;TN$Ksac`&pCP4 zaW(sFs+AejndmX+rZAUp#Y^2c`b>}c6u>nqrpzHfRLJXwdWg!QYO1tnhw=>y^uG*O z@iRW@*xf~o-rYNC=iS`^&VvRlrh~~RZy)3S*QnmBK*=NgM){0D8RdlEoRM|VEWbNa zM({l{azjP6iFswzLo3tqrz#0W2t}MKBq~KInaNv=CG5#7@QRBXX+5pa(0W=Ytu=d= zz#`eVrw|q;$M@91BIVsY%q8bC^x7JYx;?6#JW2UPPUd)&<0K~(j&cz)@QQ|~HLE!J z$=*pI%pV$kmL8hy*f$CDm8#b@d}vyU0=7GaB*$&oO&adP7qvdoLt@Wq*ke`8>it-v zP9-($y?S$W`r>UEwd#|R{nSi{Q?+~8_OBGXaW^ISu-rFxMIQ$om!spwxip#ACJq1| zP%w{!SYpsla=ZnGlV6OtJM}SYMsoF`(p;LXX%pid$EgBSgAyGEjwSaW`UQst$z=~@ zQG}2|X^)U6)FY@@t9azpx^ap;AtQ%7=;^;Yd?x|qKhi+}4IWub^ra)s#Ltjb#J^r{ zAkGhDC&m0Fc^~mdjy4nL?9pKxmYmSY68|wQ@nWmT^s1u1mx76GeLh`>{;tCk6{OuK7r_nkk&`!5 zIkaMQOIv#JEOsB|f1R)Z+T*(6^ofYQa9t0pS>DcAR<+n=1=@LylU zbcRs^{ofa!6ca`M>!?XMs9I3d>`S#c`aWgWY}GofYvt_|MdXhi6II?7KFqM$jf~l) zRJu*7+w$3od4(V7K=I2}lBGV75s+J^4_WeyiHCVEP!_v}VnnSJEf|UkhrHwQYvpf# z@>$15Iva4PVoY-M$*ua9%~qj?uyQ+U^lcNP_i5HFpY68j+t6cLnPixT`f9x~kp7aQ z)@ZrOC4?x+$m~<~J}Mkk?wAc0S2Oc)9?*A+%RHEuY?vH$CPSy*h2-g{8vvHdOFz5k Ef5@>{(EtDd delta 3788 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 delta 38812 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 GsQ(9~YaMU^ diff --git a/lib/emscripten/emtests/test_exceptions_destroy_virtual.wasm b/lib/emscripten/emtests/test_exceptions_destroy_virtual.wasm index f4794ad147d69f14b13f77498bf043171a4d16f3..2f8f4e813928c151d3294b50e56f4a0ce2265937 100644 GIT binary patch delta 38199 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 DmqYn9 diff --git a/lib/emscripten/emtests/test_exceptions_libcxx.wasm b/lib/emscripten/emtests/test_exceptions_libcxx.wasm index c7019ed8f51d1c7b06d59ed8151e071aee7ee1fd..3215a41464aed90bcc016de1519c615b64f0b0ca 100644 GIT binary patch delta 37900 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 B{_6k$ delta 37441 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 E2YBSy8UO$Q diff --git a/lib/emscripten/emtests/test_exceptions_multi.wasm b/lib/emscripten/emtests/test_exceptions_multi.wasm index 2a225775ad5f2c2ba8b5714577f54ae8ba30fc90..d2261445dee9faf8705b6e8ffe010a962d004416 100644 GIT binary patch delta 4561 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 delta 4498 zcmZu!3vg8B6~5=b_U7ItdlN`@$@Bc#Bw#`wkO1MKjysj8%bBJ1Il7zAaD21N|2731@iKvFLRb&CcMZ&1==y-+I+ zKGt@q5z8yH=l8PTrgMaEX%2;(qx9kx*`#2mM_%azIkJ4P4|}O&QPqSVuG|<3vFy} ziAotBn%n7Hsh(Dmjp5F%QnS12j`T=tv{3h&t~M!buH71~A-+&ci?r4|w4rU}%Dc@i z(z+3s-)(N8M_Ql!oqdb6!MD~P6yFJh225E2F&=uJt z1^7X=Jl2}o*2c2i=(#}*;#rZEm9ceR zrF_#e-3cMzvQnj>*OBT4XTFyxBP{Dy88U^`ERt643Ux&}<+j2f*JcFjG91-5nT)an zlVpje-)1_JZQZNSfI42S=fh|o(SyOd49v0m3HP7|NydC=oyHrjR$|Hu<8%2cZ5YNR90W*L~FR(ruh4Kv$VKI)Fz$_lVR zSWt+We2Os%GI^)bN&+gdf&{#41c{<09Y+&AK5GEL7AB;U2{`QRNN4|BQrMHsk}!!r zt1-vsnW*}#iiEGkVRx>cD~_pFI~1-qrr5dsE;Fl)!tER=CbxntB+E#idln!?Y(`#1 z&0A(C*nEyvSe?Z@IFejLb|GkjUn4aQu1_6vP9mb4$f=6Y@+PE%^KzEYdL1B**!i)* z>FlIIwL=Ct1g~=d0l{%<`P-h;3XBu$Z=%^e!1mcD83Dp3a-+SP zjxMV)lr&T<0Vbc7a@h@sifykmKyFVSMoINqf0tp5u=C7K6U zY>{n+j3E=O1+*z+d00UFc?>9mc7a$}mYe64ynbQNq?KQLexgAYt>XhzcFEZmf5A~$C4r16c+$<+nIf*=Nkv830+ zag54K8DWYb^G=a+QH~|=fL>DbrA&HGBx+Kke4L3^hMxd_ z2KH3mQ+_K<b(pZt?@;^NPl1SU&40z$g*9Q78#;Q+ke*Bxa%I1bUpn&CH8lJCA=dz6J95 z@(Cqi#(zA)uYt)Qo?I-yZt*jd!?YP+wVB==ssgAj9IP?+Oi@jp=b%-jenPf{id~by z{$Bu6h2C_E)X4)n&q| zNHn`z$Yum-*=HS}pqy7?DLa?|%s&-UGoTJrGoX^1<=0Njyq0~W;77_#X%XwiUh*OI zv)fg?UA3=`4_sRTlSO#aF^!@lVXC9htR|v#n9`b}B;$QD9+oML_sJ}z;a3U{DE4*n zj2VZ4Aab($*W{=8cIPmR7oy%$uzygdZENr1mTIHo)8X6LmRhv?!g+ z`T+X`PHqD>O`|tw>*`@!yr6!*N9~ibk8hcmmqv?*xonq=yXbbnKAAOY*cX3l-ZL^( z#Wyr0g9~QYBRsayPXOP$u#pb>;lh;^v)PT*%JTh|mP z{FzO65dE>HTB3Z^G=|1eiz|s|&f+kwpIp2)XDYU_`xUHUdlaO34>@J8LT;$Qz2rMy zwj@AeW-q}hCeHC$sj?h{9Ta8?$nOLyd{&wuiO7quz@Cu+-DfG(n5sK8dJ*rlLI%v> zAB?=ib6$mMghhV)lF8uk7nUrbD&kxEJU}jgZCN(miLxDJbWQp!A1DH}SN1V;d z|GRgK5oRB#l(6A==l1t)lHK&PHJ-7i=p`*XmmM+ih~aoe?3WI3(H< ze)j%em4DX^jSka%+Tr$8PWxC0$01YEV{65fdO(z10Q>!5SsXc1D9sFQJ#>% z1D)S7TB)DVMJ4qRw+A)5flg$I5{N)$NTDl!5tZ~`BwB2K*Q5Sm1Iv`D-5lbvDVyD^ zEsJDi(H9N;l}F#Nr^Yy;feNV5ASx=|(xib@4*Pl`$xltd)-Aej5%yWf5}hdjieR5mc3=RA&nlT}^K8GP~MZ$d-7=Y&pa6+9RBp z&k7pu-ys`F6=Cgqwc4iqq_RdY#D6ux$4idyoKbw&wPFW4_xyf1+;P$^ZZW diff --git a/lib/emscripten/emtests/test_exceptions_multiple_inherit.wasm b/lib/emscripten/emtests/test_exceptions_multiple_inherit.wasm index 8ee5a6350edc84e0b648e4c6371bb52ea9a09e21..e608942a2e5b368eb21168f804c19028a47fb351 100644 GIT binary patch delta 5631 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 delta 5697 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 diff --git a/lib/emscripten/emtests/test_exceptions_multiple_inherit_rethrow.wasm b/lib/emscripten/emtests/test_exceptions_multiple_inherit_rethrow.wasm index 5ca16790c556b12fdda28ca4e132533f06f4e34a..6330d0e58ade6c2bd31ac25d7d90e03843134bf6 100644 GIT binary patch delta 32932 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 D*)?HE delta 33156 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 H67l~4jO$gJ diff --git a/lib/emscripten/emtests/test_exceptions_primary.wasm b/lib/emscripten/emtests/test_exceptions_primary.wasm index ba76a05b7f4ebb3590d38faeaefa12c87caa335a..a072880f45468909c303e0f7408c23b3397e2698 100644 GIT binary patch delta 33379 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 diff --git a/lib/emscripten/emtests/test_exceptions_resume.wasm b/lib/emscripten/emtests/test_exceptions_resume.wasm index 7fe8366d1d027c43e316618a5b6447c79a808b73..c0564c6ea120f0aa762c24faa004fd0d016464f0 100644 GIT binary patch delta 6822 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 z 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 diff --git a/lib/emscripten/emtests/test_exceptions_std.wasm b/lib/emscripten/emtests/test_exceptions_std.wasm index 4d1de92dc2b5b4f9f84f449a1826e65331d9c734..2415458b08e50cdc8ac512a6bbb6524835280cf0 100644 GIT binary patch delta 4579 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 delta 4566 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 diff --git a/lib/emscripten/emtests/test_exceptions_virtual_inheritance.wasm b/lib/emscripten/emtests/test_exceptions_virtual_inheritance.wasm index d984fc85999c1fb95d74d4d79fca56d2e7bc759a..6d376d59884282624e1e4e0c473ba60c99eb0e99 100644 GIT binary patch delta 38092 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 UvTm@0gbXrVPXDc!WPFML123aGDgXcg delta 37375 zcmd_T2Y8gl7B{|U-q}sEn~;T&3W0f(5JC$<=}i_PfJm>>tMm>6QW6jl1rc0uP(+FX zf(0I%gt9<*cJ)!oNl)`oECx``>rAF2$Kc+qL)I*}Q$L)<%|t!(mpqXA56v zf4r+n)<>=nU5=;_DTy31g#VMm5lT@GAsqY@<#0qrMLD8~Ls4NN4sr+*6y+udQiYHX zDjw#Dj){$nPbg6$p+w0ND1msV;V=?Qm2yN->5>TvA}Wd~EKH!dAaX~C0SH4>(P2@h zsYry8GbtuHIVC2B%ldzG>Ebb-(3sGaP=_!~5gKOwnK{csPNTekR@iODi)K->@ZiVb zAIU#X|ADaRu*sC{^57?gL;j0l;df1;J01AXlk0|j>8wz!XU`^gw`%CSyJyd4Ju@;g zs$^7g%oQc`W5L0qCJ%{xkG~7`w z1n$tGBl+kr;WkrwaKh|;B|EW76?qgR}&yiyX0&c&a z!^Vy6KcOc|4{;pvhkN3(J^|b@eMS#)eCl%dn>hSVfbKbHkmEC#CqFdEanu!FAUMcz z%oR~EJjij}Rpgq8evT8@#SC(sbVXj1XHY-K=ULas4RU5yTzg7wRV=Ot6$+NTe1y}Chzg&&{ z`@IRN`{@8(aD7OJ@O%B==kx_)PtjL|tmTs)7r7ap%JZ!h&jkI?iM7H%vgm}Y=Z)NK z?7nQ|7@LgE#ug)Byke#7yC(gx@v(8l_{8|s_{=zZO$wLJmeXV|v{`w+IdX2Ee?gw_ zajDs#Xf@-hyyz8jWuAYH1cnVuekwmh)Umv1uHl?KkMMUAEiGAWp7T*>ZnYO&i=2-; znE-KL$*+;;OkTO44S=lPz^^Q{v(BV*eWmv>Kde&>1s|7JQ-Fx|Zz-j(?GtTQ)D$Ceje1^*gn z-qrjG%8&UV&wnuJJDeADJkR%K(03YL9G4cZMJ|A)0ud^FV_w8ok+VN8g~IpB+$Nr#mmYX5imN*MlHaTvE(aR)8Z`!1s(5TFpu6^n(9DTp|qyq|W4jyX24llZmJN zCrf6ESx7ILT5PHFY3DNM_paQ(RftYRu9BPlZKUu16>|=)Cxa7L_?-}D+|AEq< zBfYr)?WC3A>%|W)`!9fIB-KrM#F%IN;F^zr{I}3@pEj1kT@j31Wgz3plAlP zGymZF)(TxfYm?%{Y+#gBU9EB2si&;8(|P%Sw0!@TIs21lp@k`1{3lbM#J~I8Z^|EC z{I?5mQZoE+r*6sEF5VD3#7^<1cuTx3{w3ZK?}}aGC)ZD|i{g86N&Fyw6hDcd#lOWb z;#YAQO-W66zhJy*ykx95HUQz&825hTfN{|H&^W}whuv>UF8-5iH)=^u&v`qo6!}l4 zRSo^o_}TTd>oPK>bqjw%z9>2Pirk89Y4!bYSG?dqSusOwM0&+i;v;s}#eFP~$bY-8 z{W~kaL6M5xihm)$ye9FI`~eA-&{q|o^uL{cA>mQu7uN#(EBLn@;gtZM{!7mEYV|2+ zezgp6do?eu@=vQ)gR_zWeqQqratvYqd$h;@dG&bXGdjwyzxeG* z4RZ55DRO#Y@4^X0avcdtGc3{vFk0vntWJ&pfvDfmHxn%r+T)!B<;`a~Z>J23>yB?Ac`$yG`G8W23mb*+YXE$q|d|q;0 zTV%j;cgUTV`;L6qa^II9Sng%l0eLX!+ax{@`f{;6EHBFMuZ#O#UXfR2wlgK{S++wK1^BlLf}{UO2j_}{2s&e%s+{5$K%8z(KdXT%0^#by7!BCh1@tbdH6*XKqA zT~6MOr0$gSX2T;`zBJqv{gUes>n{*=IkYQhXTzT4FV-Z(ubL$Nt$+J7z2W=hRhRvD zNcz1^Zo3A+{>&oLF9wsh1YOSjuD@uLD%a#JylRz|9rD+Id+FwRPW(yQ%}eE_WQDkY z{oWVcDlZsi!9;!bw^A_x0Mj$&W3r=@J59A3ktDAMC}B)cO$E{AfYxIJ#m zQIz8G6mukp`y82^GbJ1`5gyM;qLK_W5zuznP%T&pFt9{3L?!ySG-*Jw{(m=_P&(e{ zi1cJq7#Cp#ycQmI39r}i&uf~d+$uEEvzMp@XDWeAsz4@%Ooy9pDD76oB0Zfbl=FlY z0%%pUI*DjQU2<{`XCXPRG*i8h!%Kp52sAz}!TY+)Q-vf)$Qz4zl*1%N$Sb_H@Gsk? zWC}nuwb2N@v4nrhT@@LPKh2TWqK*n>IB9mxg&@l{3)E~VCuf}HqM?lAaMXCQAki;^ z=>9s*dy_k7Y4cbC<;3O|Lp!)tc%&!erj#hytWI_n%82xQ6-rN7{PHvy#~;bXcj`4{00eAD#LUtshpXn ziwU7zksgoTE9A?H^t8G;c}uk`Q!xnuq_+t`a9L-hXNi*cINY4f$FV|HJbzRS<;T`)@DgVfh=^nR|k)GShg`EDi9dFOT81(I0 zi-8twCYUeM^Q1xL7*vHqK<)0dmP-4_bUuh$(KW9T73Hi^g=7uyG?GmJlui|ETL?zv z5_0xF)S-e*pd7x|gPE6o?q)OLP3?rz8HtSQB=)Cmo14!Rb6wN><4%_2Ow>ZN8^T=}fnPzaNeS#D+ z<+QoyE-LYpqt~rVQ$#w^yc9;cg`&S%$^|b$|1( zKMUD!P(}7nI8};z_!pl#?2H3aahh(EQ5Aqp301=8)i`cVtcsNld=8-KfS@Jd6=^1g zOQ(wSZ~SU79rBm_I?dJA?$gnO)2X+A#o!c-(02xxt<=Z76KoJZ*leU4F{d|Hja6B1 zAHZ;c=w_G-<5)MSg;;;Wkd@TOzimiq{2m+9kJ|ei4jpCoF{`L_9}PBd2a>n@#Mr@R zRaKSCRa4cha)*Xax!Vo=h|y&s`=JY*CS;a!fbJgdmPk)jE|b2$mb@i=hj?g27K}@Y z^vsoXI}>L9@C53V^Zf906n|DwS?=<(z!=a&MFSNIa?IGLmsgn4 z=(&FS>57zGcYvvsGAUd@lzF>BZ)|erG6)PXlT;a$NHPfw1=fPcGP zBR3|}7<*VSYZKRGLDQLBgjD09!5!NXz8{z@`?ZrV-tkL(C0= zskK3WSQOJj2R*D9Eut3Mh@yLFxb6`}n-MBr9HX&CAiFqyBWQ#k8cStpsD3OK6dz{Z ztL`-ic+>!I2YoV@9za6BI4bX&$}}3L7sBtE>QPgfic{1Sy*rNf&|$qOo~F{_K=B0f zN*boil%j4lQa@0NF3>1FrZnxQVS##zY7-JCn6w5#l|+pNjS1YFLY0U{>qTYgNnleY zl{6~dok~q2PYA14^E0776XpqBx-7+bP6%~OWSYl?I<6a(rS@p$qOz2XGF!`18}Bf4 zn^4Z2<`HtvH zA@mGQ)dxdp9Hea1P|6{D7OQ51JQ_|J?u&8aJY}h=XpZ;HG<5MD>JGChpm{s^m!6qV z!~E%ISK;^2*{6yOGhZh4GMSsm<6DsCpZd)}8tOm&O(%gsgKtM7u<_eXG%V-da}nrD z|Jd^%i(k(9TU?0a3r&KI~e1PDDq>H#umSqSB1{Lqxb-;OjEQSJ!9C$&_!muR1TuU&p#=OtPpFOGDieDn z)jzQejrDJx*qX-q-S^*(Je}^}kXm%hLh~t7Ptj}Ua#G95TnZthmO^qKgzAa1;-^;N zR?w8T0MUL5_r_OK+Q+o95pAVfnQc6(jV~k9Y^_@RTTN}$qKlo>S#>tMc+?VVm^Ima zfm9dHbC0?QZFzyrCFJxGq$j*9kY>gsR03-!{O_?+8agN$Z% zJZYG-4Mw#TdmlECY*s?BT7g!SLMxDRK4U)+X3 zf*pp!|8E!|LHLt#hP^EtF(>26%|sJ(zFyLa)cximLme{Al?G2E(^#skga|(r zB06TddGvK(+6vTpap@4C8vnGL2T;ng_4qxsY%YF#FW>E1C5&Pa_hI0PoY%XQq!!Ua z;Di_g!Qh#}JH?)fuZx{jXzX}9_VW-UJ*(2xP-e3)yW*5Nr%|`5Mhuo<%CXI!Wf~hI z%Q=;+@$Vg2x7zhfw3$TVER(_ulS$#$av_`iEmw3e;^uAXYC)wqdntd5uj6tKtO%iy zrS?i#&-P++n@)PIm+I3Yea1^QLLPEbO=QnW{MQVTxJyzcE?XH@oh&$Mp5(nu_f`GH z4D!FVsxp=aAu7Zy!;@VZ{~xP1a{PwX)7iOwO^pU+SV|_VWSIp?-9r-hKkg)SnaJM^);4ooVq;FN<2*di-9^IzrW%u?YORK zuiPUZA^&HuEaqCqZtcvW54P4syK`Kx#u3Mser;68xdh&;0O2~5R83!Ywj5*rfGA&v zs;n-O`hmQh1Ho^Ex&ZlU1ywotgC%x2#+W~H7G;%_`B;;jneVkLj=xB4RR^jr5KCHie5?Cp8? zXS%!#!O+8F$}A##5Pd>aj1zb!&n~$B%EtQ3zy00zbl4xYs|<5YtzESuXF}e^unM4p zjac@s_>9LaP$mQ&_7b1pW}GszicU3oXrEYUNg(ayxI z1!B;X=7Ul_D7{Gf)_}+S%>ZqpeUJGo?XDW_XC_a?C_a!zpC#s2P;{E=l{lCdsq-Oce z1Er$jNpEhV88exAW|3LPiInySGU@)DB?nrD$eBXT^q)VH6b(=7=H?8cX7G$NQ>FB9vkw6{HWy!j0L(WXS+o-Vol69x!`skW!bY^Kig zoYXARQ;a7S%t!^M0NkM|IL|By^8HUmaZ^T4buycV^L&9Fcg`0*JBEq{;PioWLcWqz zhew+DqK5EOPVFx$ipm9c_t#G)bL^d!iEXhdxgUMm>Hc1WddHtkH-V)zLwrs%7Wl{d zoKRr;PNw@m9W*}caWadjBD@2&lm`-=L*8CMA491&xE$DpU<_TSgn(jzN3Sw+_h$mz z!^H&g8v;5&1$A25TG7%xste9G*_drSsMQsqnvQmz+NxT7dn`O zaPnfjc8oVaCeDtD%a2iZjLMHmvt!coV>0ZRjQp6IgR`v4YUW2_zOtg=<{_{v7zZ~m zZhtTiZeHAxU>w}MxRb#+xOs7Bf^l$@@*<(ev?_+17xxRt`PH)r#RKI3;n}A44y2#8 zX7E=$eJAuABTtveO0xS2edk?5CM&ftMWYApDS9VCY}X2^5W&-qCdlIOU3`w3AQM&% zqgZ?5JGTc3yytd};vE+OcB(LBcRwy@b^twAZw7pci^AFKR|=jwK#n)awv=nI5* ziLP6n#?aGxLv>AHo0;n5&`}bHoK5X?+ziv{48llMC8gyHdHTi50 zr}13V1k^OY;M_2u_vR;SP(>=MBWhBWh`MM&_|U;Th`eQW^O{tZ$_BD)(nCb;wYxSY z#ssY*D9Shr!rD zB&vG`n_aM-aMX4<5K8lwG`p&<45pjvhR$MDO3R842aiZ|fK#=#)CIn{vA(!*+-*=G z=xTMTtyo5Sc3rxyJOl5ejKOAK)z^aRJ8EOsPj&aj4L19${;D5_C>nXHF4ZUoax?BD z)o?YEqYv%TmFiKF1!oMy8LP%#1IMd|Gn}HTsPfuyCf1{}k$~e=;U4oopG6zJz8=-B zf=G}ED|84T0XZ`Pk^n-aEZLU^Do*q|#^ql97wMDlc7>8U@cLMhZuU#dbq z!n2roW-->0b=BQ&qwZC+to1eP%^aW-+L@3$XIR2liH2F;6)Z|2M)yb4Q9gq3SO5J% z+$!4sdta#jlCEqOv^?kN)e#b^3GB8uiLC2qgScFnK%2+7cO6C`ujg(^SRYJC&MlFP zMRx9g`RF_?D4xe-0!CX_rdb5cU&LBk>Kz$W8asz*6>VY{>@Yq0+YCxf$)*Gq!z_nR zW5&)tB&TZrvdiWAn+XC z$H@Qi&uwrTc=YEk;xWpp@$YDY>u>Q(Rd%NTvJJW`jDrh;k^x`i#DJNpLOMMi-kr7I zW=V?z`fxfuQocLrgngpj+S9>vpGH7werN#=!u(JydVBx6hSL0DmrK+0{&JV+!~g1K zGdYcWD@+MA&k0zeW|WFC(*Q4x$zB#cT-N``8U(LJ)vx7lf`I-WJY#dsNPEm~cH+&SOkA!mw# z5)E)BMDD;GA5}EqzS4-|TyPKEMJdkcJs2MU5?Ew=u(;-iU}gKBcDJSyv?q|-n!-Yn zHKQ}w4ejo55BcGoy@x)8v#krX&TgI1m9EgII<6bK`_sVV-AEGLCEY2E;y!hm$E7+h zSumWC>VyQxe<;15>eqYF{b5M`3Y7AG8n~k;%`b|I_K&3TA!(Lc!{cpgz7VQj2=#?q zqtGO^i;prP8=ovm&++lJ9x;Kwp~bq(M0y`i+572sS{&$lKix|RzB!3z!)ZR5I>C8n zGR=UKHiarDFUHVts=0hH^echS;o~UWP{q!qnW=@+`u-_&rQ~AksG*FHM&raYlr_+0 zRaun^eAMEAe=0>70J&lsbw;(9r_rMlks5+rpp>-&(>tD`QWfl+ z?_mLFSq3Ku-`d`{xQuWITH0rb!B)F73<%?EI)FaUR~$_Ma6VF0GC%ERE_Hv%XhtXy9K91n<=$3aC`=au{Y z#&V|ncT`reCG%J30;p~6H}tcssSco@Tum>*d2|iMf)gz2g((!loZ5aZj>z1B57$yHLYXo*mI;{8Q%yd=L7_61 z;z;*sYEer`F@ZnhLPiAxr(|?j8R-) z*+i?;x>##H2~mo*%8QaJbEXUczU~r;e&batp-*q7?tq@Tg?@u`XMmc(nH!+C=n}Bo z?e>}4*#O;cYtOxT60Sf4%IU7JP}_ghiUWnVqMlBFl?Gnhl(m1}l>2~pjo0XMek&%w zPHpT~WZ11Z@;YS%Tanid8*L@0F13v|Vj%3_M#UlaSYncQm9Qn$4oMkI#40xuF%Y?( zwh?X6AG|^Run+*rzjcYG_U4Eepw|<<-42>XYXhI|poRoD@l6Wh;$_~ViMY;yDW(9g zkX-*ZZ4DxstmnQ%4QxzzyF_Cf)67CJz3`5O>9}{v z2TXNf7o7p3%XicG1PjpubKxe8M;mWlC!qAJ&Rc;V(yD@TSLu2+yfw*ZZ* zy4MFZ%*G`d&ZQ4%I8Z2A2nyr&Vi8qF|FD-H3(Lbq&)Y|_b?mt!zqwX*n{umrPf~^4 z!M4LuV3ofEci#dh_fdI)%Yiuko@`%BDopegJxrZ+_CX3kPF#`rtDIMEHD~H+ft6Mf ztlj<^YU)>iBkz}gBk!?W&#Q-jbc-}d{p6OR_OP4(K_so>g`l~P(ES$+DnTzo2^#Pp zrjwN3)7n+_dI+Y%qHA{iI&17jIL0tDbtr5sIUp`ead29L~NY zxTMij|B)aPbp20o$)mdd$I6zV#W6rJjMBM=6?$Rp(l&VT(}>_1tD+ z1Eb$)VN{7o8En>5^|*>VRCT@d7_ERnD;nuZvS-R>$0-TCJoGqqH{50;J*Az94SabV z&s!0@^K+axE`9t9T=!~YpYVj;$n3Z%##=XAT}<9Jyw$=`!!~jdcG%c~X0lF%H3Lp0 zCLlXVh>`VzJ$qT(_lyFZj*E=ghePT?az?O%%7CMnd_j|eIJBL?HA&K!#A}-tUs4S? zGruHXDQoq?Ed`a>!Sc`hA%^)>>lULv^(9Tm8T^LAdu+rN5Hr26)nm}NWtx3dAFIcz zqQ_dJ$25AZFZWnK)sLa~SABKSs}vX0mqUZpARkCQSPkaT5TxC475&#&fABMHq56xO zLmOLv^HA|6QGMN7i2JDTR2yRJQvCs6x54U~{rMGMK>(kWu~ z-tQ@$UeoiPqK$5Oi7G%@fxY^J_T4l+^Ah!RMyo1jygqx0MpTc6&IA{GqH}eaP0ixU zQbES3;y68tv6O1DmOtL9!aP`J#HzT!ydOx=|586}xr}Q-|Ev!%38D|aAQ73xw`%@^ zvgqwx%BEVB{X9}UPf)L*kBT!XSkXJw4eyD>T+!Y-l`!I>E5$2AZrDDmBc`6&s0rO4fCM z>Dy5+(z7fQ7Y122yihnzSC~xGLguIp(6q&^&QT5Y(qs_9ny5BWZN0G?2wOX#q6F6E zwRM+N5Vof_ONnJVJVtCys?Ef$1>)ASi2FQXB2t27X|_T#YtTU$>_ z6Dw?{S|CJ>%_N2GaT=5p1L;NW!}C_mFW9XA4>do4=69z5UpC$D`LSjHqn=-Qi#^|1 zUnnOsAyd%(|0^;@L#8a#6*3@D|G8YT2fzgqURx-zuKoIL&#zTP1A0lQ@Qk z^;NFCoOuWhL@WgCHd5QHW$||67(9Y_gVY;V%nnkB+(DV@LHn%^P~D*Rqx54L6tw!-?MTA)fR@j4-Rp*6NjJp%pPh*(Oh z#sjk|n7b-?`!@4A@OCw3?dqyJvuh1iP4@~j;$o_C2nz~k-MXqShw35i{kGy6tkAIe z{m4mmc}Fy8Wm4Eitz zxTC?f^izFwkp@VvGT8XeocA^Yv=cNDD~lX zruGy~<^Sz=YP9oJ{n#L}?QgUdlQ~w@CnCkV;6~~HYFF7!7&Gc0G+|k!fX2w$<5)VQ z4F$Pv19Mx`F`^fB>uzydcV-4$9J06#Z_v!<;I;+ew(iVrJyZ|oww?$>BAs^Dz{o)yD zZqSSNV=cY+eh~{TL?PEU^yT}-D1K2q*uGa(h_*@3o+R$Z1P`^&(n!LtF?Y{+BRzka z1bP-Gq;7rB2qD$c-ZPHYQ>KbW*y{y1j^;e^FWxw=%@&g(pHipY;>OYU@O2xY{tcCXj*1I~sOFq+DY|kJyL!VoTeZpEj<{7afe(eqW zghQkbk-1h^dKMQ9*YR%P4c+cpu_D3tTf2dEq@EzG$RT|3hJRh4$SUy-#kF#(rdF-k z0hp~ksueHyTdI};?;6pK;zl~vAS-#e8g7pCsF9pJLX8N_curKNa&K4&ZsXm+HhVX4 z7|lQ|gg2J_JFFEwR{U@1qiZn}yrHkG6$$i4Aa0#7=}v2*bPMbI=}!AOyAMmK>y9b| zlb;vm=?)WyGRj!fnwhUFR;o155J`Ah%r^p)m4eQ=j8oO~m?@S&3C~qLxUZ9S!TLmd_ z-jE-OP2rXOqH%c>kCsi|W0G*b!iHbH9JjvTYSe5nOBx(rg zUn)d;{xqXT#utmV@+mwmeC27zI^<2_-$yb3(}s%Xx)20wdE ztQ1*=T9di?0p3Qg@a89YpGVSKOLAIk^6T_b9)-)t4}&j!KW--PZecDW75II-C?RN- zj@t>X@KXW*P7&wi6RI!m%PWD+?}&bc`xVm(M7s`Ppz1rC0Rl#MVSyvsW^@Em}M+~vQwpaaC@+fPTD8F zte1p4wW-#M*^;GhRp0wWP(U@b1=N}X(%?Eo{;7a!jxl#@d=BZZlBQ0Dw;?f`PP4T`e23kawE1!dlTmU&A)6Db5O1D;#_YFliv zE-qa^AWs|>pK-+yHxGLWCz-%=V__rr=y6e*hkf|x*06u@bK!HA#y~#frpa8W(BXdi zYth`<;?{+I@AyxxCVRJX#j?QqI(!Em-6p70w8&-s7RRendq zK1Uc=EGqpj23pZ)?C6}|1x#c;enq^E*l^!+t8n0pD+1RSIAVhxvHq&4!523RG3K%8 zH{)r(|F|>wO1Q8)3;{A$@qy^M82Z*~_9brib&^z17DlIv?JQ{?szRDT+t-d~#-^&C zYC6jNE_ffLhx(3qrtD!(2wWA$4w+R(buiD6(LkNCmddAL#DEvd4zs$CV1L5N@mMUM zC3V&k@ZS)}Kbw$iP#`1>!f|(1awaL=Kliyej3pYK-zZ z1{cMBG&a4V>xUXOyPY9a=RkE>`Ps;xQbjr(>Er7-}@9GJ#TIMh|k9QPs^efoX2zUh34&nzp_t z-yLl6PWr4hMh9~O-gYq#w z(DlQOSel?ah8yi@LSS9EQHmuAmVB^S#TR-lV`A4y5?!*XQCY_pG45t|m>;}WTiDfs zX+?~&oaa`6CF>`e8RaG0PpeZBN$<9{NZ}S?u#}C7QyWsx3!+(r-$*nag5Q*9j{_wjt4cy z>8E3i4Y$;=K&(y9zv!S!xg!0;}d< z3Q@f*Ex!JCtf-{dBpM^JHjXQ0JZI2Oz0)+(DN$cEji=!}nq_;mNmY^v=(=ZQ(&0hpJp`v8}p!5z^k`j5asloaz^;yFN%4z zoQ^1Ogxizp#b{b;%_`3pKAF}lZ|rqP7MM(}S<#wBZ?9(9v*;On)_f3Q%#z!y8TMqm z-;S4usHOmyH?Pi>?9&F9o!x?EkOK99ehe?GAe(C3hmXV-(#bi$&;*M-flchxgm$2QHM zU2lU@3WKhmx=q#78|xXxX=vb`dd3!K)za!N^Dxh+hpqAQ5vh;t`IJ@e^TEN0$6)!G ztsC)RIYR2N-f$-d%VB-sPKd|D`rMsHhxEf_R>m-y&r@P)uB#LVcqxp$H1jJ!Da}BX zy;n0;X+5G5grlWSf?Z1%j(O8%X}z?O(Sk|`zHMYwqR~ z6U?U8eE1dl>K2#}?=pva)KEqM=k2K8Ve)*)cg=<}3d7Ve1~FU>)gv>FxX7U#f;}!q zVT>B1cUBZ}dVQu*3j{iw32SnOE!JUGAo#cbI2)+fSHZ#@{A;|JhsuPpBv+Afi=bG+n$1(i+9)!oMdk%F|?Q}*f<55hE{Bq^`>E}=@ zV?>bzr}9`6BOAm_&}~{9t=tJJ7FH2~L%d$s`j#d}yD#)D&yF?P-qP$?S?_6U4F2mW zva+7m&d3PPlS7!queCF}5+1R{cECK@B~ZVE;T0w<6M$N17fhXDp2S6xE==1zYIV^g zI$;!bVcOwDktvBA&>ZTky6B~yj9CyoDV>dp2A;NJri|Btu0}M)=?}UZ%i#>~X2c}L z1*glGt>M3s*kDrwjF@cWbTdlmEjx`W+SA>rnF!l}!DM)>ylhNw z0ETFsiVyVaZj7Ulwy=;ezHI=uhp^SE{4(vLqkw*rZy5!4_kwW4u!pXC?Vqed!}=H#6DwmrL*Bu7vo5SR z>#8UlLrSo3>M!eq0fRToeTMF4kSs?1I_=Ht3?W`Wbz3TggJMm(t7#9cIfR<^3nuY3xND^zj#KZD1#fku>R(c|jXt572ZZN!2kcK8;llAv1;F~a^k zr1`I+1nu*G-dlLo!NW2*_GX9CAl_4sz}UM%72;7N_+<`GfJXR^zzrN3VssQVFpx3a zAl8H7$^C^8>c9ZHGJxwjKhSO@zKfD>85j>fB85Eo@E*EkSv&ikZQEuSv_F;&`(uGt zV~r<^z(UM7(~YHYWfPahYMTF+Gp@Kroz*@HE3?&NS2mdfF`Gr}9r4 zJiebWAY@?-tATGenZLQ5uusNvc8Q^uSSDMag2ghu{6WaLC-u$;A)ubrM;|oqp(g{? zXB+b<92nMT1a|^Kz5gNONjjy6JZzjEdddR-C4>JG;MG=_`IgJK(yj!FsN`!yeQi~8 z+E9prKtE%sGgi!5Lm~34k!gNosBgIZDJve9-M%$gv|HBSSh$}@S-pLZ(J$hZVZP%E zM>|o~Ze4jUaNZqgJ=cg3v|IO>XM9hm0<9l4vZ(xS$xVM(0=IWz>A?4njTNGS)q7IC zXAyOeRJ--B^BIgzSb(PQ*3}lE>AM4uE-+>i&C$_*<8t{q*7?apP5^tz31BB|V2B2= zxiDYgWHcXfsyVvWLI9hiyDS8-IeOee0Gkuox6pV~Ao!TZntzl&t&P``phLpWv*LTd@Zt?cQp$Qh$V ziQLWR&7OHCVZK>Xoa|=~))Sf=2k}SG8o!0{#Do{pmQ93DUjmu2nE7qJaXbCRd(3%Z z#7io36bQ1v;85SsLw(RjV;~EZ4|5D>P@tR-p^jXj8w%_wIOp!*Irs8r;{!G(hc6av z??fjpG4f5}V&vPchBvY`jOM-IGWS77pttuF7~3%KvBF}*_t~1B)fpeKX+4bXeULL- zFt+yw!|x;f0p!jBq4w(LyA9>uBiIh~K4G5J<8~Y4U8tqLxldo(ZKRe%LId+8%!nK> zP}?y!9u3eZgP>td`h@nqXWScdQkXBfU{d;}_l$0pPY9@7zZ2#qmT8wPnRZdAi)%~05yuR3 zizTyAc$}qk^kaUA2m5JJlaL^Al9?hZUX)%aBg4U>1x?T9WQT&N2NHRPaaO_$S6B zfeN}Dg=`z6*B>>uC5>U(HX5~zMkRHv9vQ<`j8o%Se%*&{^}J))sEpyz{px-Oo~MZ( zqhCJ;z4MrW_c(NTaMzzOjs#`fWl6PpWY#T2wypWf=n_*KQp;uHgtvypNVR-~h*~=K zYvbSLl2q~#6QWCnH-jWAgYHaLKni*Wl{5tB!48$A$|5dV*EnrdrDQ$yw9y*Qw$nF? zH4|IXl7%2q;L$kCwMEy+wdDmDC(HSe?!L3ePnKN6=NR~2$1TaTN8EHD6JZkSzhO(D zzx>fyLpm_$C!?{%`e-z+C5Bl#Y;!d7-*`9T(yzu8d?Q8;#TFtOM${Sd>y{?1Ahx`T z2>Aanp2x8i&isO}(gMxG74xM@VY@!SsXW&r!km|Aq6%q7elZY8Cq0s1%|1` z}jDaQjb|GEI+AY%1?Yl<1u2>LJJYWF77+P3~n)) zlQkb(^GKR>*63mZ>Y~~O)fNmSxC8a7t_-0I7wo3I?69GCuj*!Y(Qj9h(^9Z_4sJ+; zI~zL~TnKly%tq?{8L}GQt1L^GsbI2nwDY=IJn(6{tVnVtnWgoL{;>B^DnnL>xquEC zvT=3vPQH1XLibA7uD)-mR3$zUO5M0OdUJ0SWP+2-1b0@ET?MVw%Wjwbs8c{zl{KNp z#Fnu@y>{z#n`$x&O(^UTcVac!#x`v*!oDV4Sf;bcRNXq{EoQ%o#Mg|hFHZRI0@G8# zQc^*GqP3&eBdg2ABD`6FDULV8Xe9H(lIrp;n1u@TtRwH>4e7E5@};=qnC6NrY6iP% zQP>7Uc@YX5iK=*@zfXQHQj6y*8gbNISf|BXXy~DhWPB!W<^&N`A<79}U_Ac}b*PE+ zP=~*geb&3Dk*vh5!k=l`6(ZW$7tTB1$OyV*W9g^XdIRuI#^ydvMWFr^$TRZ30sGkY z3#am`Jknvza*dA4l(S1CV_nt3=RhXdWv-{{vaqhN>T{;L-Zg=(nX(meuF5JyRZ{Ia zR}}?SZl-ygx{Y&H2B_4gaxki1&{USF*;*M*OxWx9VRO<(wK0oB>C@RBuy2Nl<~IIq z3&H8a;xrAcbP?ztu0!GrzcnK&*2n013Y)POl0cea4wg|_$CHd9=zifkA{4Cw_H`v zx@WK`c)aGdRZ}o`z;hxjLGn$p5T65o(%Ttj;m-trg)#mi0P#)>nHGmU5#ClNTUS6T zEI4p#1X4p<$`p(Ju^7i2UbYCXYqgXu8MAP3ryI1}j>3w+md55xxnMX7u5KxNx?pOK z3wT<|J$(gr^))H zj{dQ?JPmQkGXHm&*s>IlJ#9)~>?33y+s?7AuWW%Fo_=yRoQ3@` zMy*g49o=7cieR-T#6=7H(fY*xR_1s6%M|1~*I)K-9%I|_GQ4-24*LNlh7UjIuq;R$ z-j0Pwx4R}f*_N$K?v=@v?S^3UYoi%&0|M4T4QoY*WxONOW2flz_saNqw(en_9)SqB z4EZ2bua#_=r3XmZsMjrQXVQSY8vHk{fd`6Z9WGeI2LtkIfSw`0hIG4zs{>>@YDga_ z(}Oh5Q$Ypit5E|b8!ehSQ1Wr#!GRF2Zhd}`tfc*ej@tl@Il`X?Yzw7Nh)WTySbZ zOMMr=abUj5n{7C1;kR~FADe+%50fzXAJ{ZZzQg7tCykIDOS?_-&0PgOKhIUO;W>5K zE>prL*~JmE1oDQDl!*v*kr>QfDBTKd`GNWF6GsN>@&99Jo`l}`}YO13*S>#!_d?VK#i$0 z+CnsKbg<#i<~RJ=)j`@Whv(TN*EBraF7{Mzu}xMn%=_fqlv`{A7yGhcG2nYBU=ac} zd&gJ^q>r%>xCyhiO zpap&!FWtn(zIt01T6E|{*_-W0TiSc9<#q?Z1Way&&D37nQ1_Kg0I`nkmW+< z5N0GL_4*ldrmbJix853^{86x$nKA9IKI=Jqi%pJ1VG zG1e*J;2z&=L5I0ZOA}0NJf6|E~9+d-NCvn$&SxbB8 z%iI1cf3Nwu`G@d;2^#9HyFkWAy^g&Gh-n+@t!r;61}>2GZZc|KU0{zIl)7frL_Jn; z)HHfb&bCKQuqw6*oVKlCRfi1wGo6JfTXdWs+A7?^^~*na0Iigi&I9Pvg>nD}Pz4@9 zsa8+f1Bk94K)U}T`2+x5T_oSXtq99>3}rZMh$P)tjCY#$s7k@XN=kuIm1vDBedTe< zMxskrrQ#q}P_DC#jkViSZ;6b>#=-C=@V0_C)|PyJ&JZTP{07;jFe)+%=nG*-Fz~<< z%zIe&@e#{)BZj|1Dt*hhVqGV^l`NRpqXH&&ZO?ACRC{bcumVOhf0@*Xbo%@=`TGHD zT=*;j?^&(g4_>I<2-(SNcUWq~+%@BU#~_}vArH`b!utRv_yEnDLkVbG{;6^S{m^rG zM?skhq#`{p+gb#DY`J_HIp(jBnJDn_3K>CVW1aZEMJ$fwKv`CDaZ4aGd?*{O zV%fnro>YwXJR|v{NzFo$YWR%o$W}{%RAH^eK8OcJV3mZ)^g#L5@-8+#Iqo?*1RaOA zH?|s5_!rA1)>r5(-zUOb@tQ7F{ONM1?``xL-p%2oXZGcZn=%3@z7y+ZyWhbCkmTuR z8T2A6E#n4v#K|br|^9r{_;ei(erX07$Wf93-V=XGxW-hau1y0FUys1iss1Ga9+ug z&%o)nNmlh(=%?9CwPce_LyHUfu%SM(Np=APVhG=1%iwyOWo^T7kiKuTOpiGwF>FB9 z>>ZAlJP}$`Oln};W*HDz`;L1>woQcfI>!*ODB9@@9XlGoUh6k*>}b;!IQ0s)2rhh` zAS*dkhrB9FSN4hoU${4sKkbqnYMCMRvVb;}yh}FlVp4{jM1nOOkuT8hRrv*FNgl*u z5F}n4&|5y?#dAu_XLzA8vwYGU8uU56VL_kEi>cm94e?r{08m1`P=;A?VP5FdET7w3 zgncfD&jSMwaKgP_b|Sn*J+9ggUlDIH4n}&T*ztOcvs2U?%}z0Ij3*xb&Gg}xDCdjH z^v-LM8WU@2Nf&cWp6EaqRwo7_-t&=jt8Cv$50&X|*gyP>XO|(8CTe>*?qDvpx xCAW(W?b)sFy68b%q<-{sIm@agQ05CcFe21JLWUSFr=I(rtPyzsI~gDGe*o>au$ce= diff --git a/lib/emscripten/emtests/test_exceptions_white_list.wasm b/lib/emscripten/emtests/test_exceptions_white_list.wasm index a376143f8101dd85d519e24fabfaf874cdbb4dfc..346bd9d697101a6ec4528abc1ca9991d326b2916 100644 GIT binary patch delta 4452 zcmZt}3vg7`^_}yicUy!Ga)=%-nh@exaYNwrw(rUG}wsq8YMzPp)cLRx)JM+%H_uO;N zz4!d?c@JN&e7ZyVS$(0BNF=1yav}kV)e?O)l2%KE8BD<7t#ij_t3)6cb5kDk1)~{Tly0tWq$E`||O29C5U6*uS zb<@PFYA)54o{=Fbx@k#nqVTAy&Vx!`NYLws9vhQw4!l#eR#&s}5EL`mM$K-5_^wV)|Tco2cPG5h=I%!qT5GvLe z+0YY<_eXmp{R11K($$%?5bf=a_e4maZT+#HxD?bQYu9#d>RTtx&?0Mlqfu#=nTT|C zZSIb=_iZ7~#_DRNh!*K?i^ZjYPJI{gO3gGP-EJ6=RwqY&(SE5-i}bbku9w<9YX(S_ zU0sn_OzQ9sPiVU4;@akz6ivUdwmC*kTAPuY7j#9Eh?sPZ`5g+PS;y~IbNFx6>O?HR zvy&BeQky4$Xe$d+{SaJFZT6hY=ZgL+`c{a+h}JdST4=bm`(j%_qb1$(3vE6P7RTeB z*U!i+N&ylf9}@tj&SGE4XPce&hK*tr%37d?QL-ch!89}}&fmEVp5REZ7rZ<(ft*C}JXC zLY6Ht$;v~y*k?<7J%3vz0)@Y`o zyV!@CX&eY>5Ec>}Nn-VgYgAhjf5`Qa?qwEQ)@Z&=50wR!upGvKEzM^6n6HMtV4#M9 z^{g0Ow%W6k?dp>utisTc`$n>HBoIT=?(+)%{h%Wf*mmSxJ4 zBuGJt%vvP$Xc|A3!7rrel95!Q9DBQ)^ObFRXWdNJP-VKUF~4D;-`1MxxM$rwebp8= zhGk%eX=J60t|ldp6*n@Ch2SB9{Aflcl<+@g6oZeu%#w;yHiPc%?PN{ZBvd>TXJUy} z%G`vtI)$nP)`K2_<;%@qLMi{R86;R}t$}g;dTS#qWi?o7Lnqlo!a7^-?_~8@FZd?l zge2dn%ohQXGa={S-Vq3ge?(=Y#!9fk_dj3331MkVZ-m@!kF>2t7G>JHcP&P6~&_*~t-SCL_4U!0}8mu!@YUn8y2M%D?4A z#DX;1W!ZDd_h=_Z#R{2m#WNu?3y8kA!`4M%5$RjF=e09>4 z{Hg3y1wU09r7PJW4w6z}KijS1Zq=IV6gJdBrqFi|W|O)l^x2A4%iAXV&B^$4nME`_ zr{EFA3OTzcKMZ8^+9}8Ap3Wyz9)=ph_&tOQpRg=9og|}d|6q~Vnp_= zf-w?&;s+QMT#kaBDJEgwc+$FpDQ-=6)M*O%29g|H;0?meyMRs6Xk~7=83vr&!V7eDr;I!KhqH>ZY0x^C?UHd9H!iq|@S|Fq2(zrEgy4>rdZIbj(m~@u>l&g-v=-3#&emKS zKh=ssAI>oipUBqR$ewh9=P4Oc=zplf6!MwdmQR9dykU6@#rTcOUjPX5St|>DM0p`Q zomOBx5%Q0`qan<-^tUxXY1+@Z9sW~JGWmYGJz2#jeOAInf8i2smT>zN_4I4d+Pn`iqPDc8~S z%ko67%i|rs^5Q1uM?boH#W9$!p^NDT=81C!Fd&kiYSr+gzG`UXANWF3n;0T8@RF}f zRyAYDQu$G`nphEzA^IW)8m-lcfk96d#r2NVv&I{M{^!=G7|Us_3# z=YgGlq^n1 zesfwl*~@O$h%dTXvzJatlNn+%3r{(pb%UF@Ki@Q(MDolnw-CH%%PE3g*Dfdc>a|}( zJAY|l5ZdpZz7?R|3I9+Be>;0m#rIS@(ahdg@qLxHcuTd~`PGA4-0kcyD&@>}=gi;- z7Ri3`C+&KvPbkB%g6vT@KI*o;qKcB}sXHl(CtCVXJ{%H79G`ppUttfgzvDH6=kKV4 zJx=YOwLp`7dv_5G?ps1|%f6iizu8w6+9Ml=hBph>`3mUqrjbD59tt*j4%;i^UcO-e z=R|EE2#~Oq2iyuxq6Zh#_^P zDevDUL%!IIN?*Z~hk1f0Ks*7WXl40wSQL&_waTd zJ|Gv0V$$8;OVCQf-2Ps&xk~Q4o@vgsqXxK^i=QtSZ*hVZRA^=eY_H|96Q*HVv;}$N zJT)9j{r6DmYSFKgD8Gq@-{ssgk-VMmEZJbunZ&Q1EnAA{6iXGIYH6a=ESF)tnFsX4 j;Wkd@IgQ6Q=uZ2SXTdr8{1K47+5CwYE^`k4`eyha(+}3t delta 4349 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 QK;{kPp;t$8@@dI`0SB@HTL1t6 diff --git a/lib/emscripten/emtests/test_flexarray_struct.wasm b/lib/emscripten/emtests/test_flexarray_struct.wasm index c1ea8478d5b766f7627a10570d1a4835146de872..dfaf36ac1ae93adcbc756964f852d7e65f3a8780 100644 GIT binary patch delta 3496 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 GyX60!geq_V diff --git a/lib/emscripten/emtests/test_float32_precise.wasm b/lib/emscripten/emtests/test_float32_precise.wasm index 99654449cced139e77ca312aa691f2d7f3d61f89..7e5a512f46f22686ba3103c180fd41997500ea8d 100644 GIT binary patch delta 3547 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 Vxs$y|tAS0=7I18;`1i5e{{!4NM#KOB diff --git a/lib/emscripten/emtests/test_float_builtins.wasm b/lib/emscripten/emtests/test_float_builtins.wasm index ce0eb52d221d7fd71dec83ac9d3162b168fb6ab0..8734671beba5ca6bfbe8a3c53b0e5dfc1cb4072d 100644 GIT binary patch delta 4356 zcmaJ^4RBP~b$;i*_jXr$i}q<%X{D8f&eaNuNPuKX2pqY#9ta`8Mj&KcP{<<00$Tkb z^aGXyEW$uzNE18PwFK^rlg5pICQiZYFq2|u$k=WOOeb#Zc06qwV<)W}r>;G9?2bdm z?ss>gXh^4;(S7%xd(OS*?|$d(lVk z4-8}}^X5=)(ERaud}wd~;B^_S#uF2(#>Up~y)L6EQ{(-8LqoSUH>30A!iiO!oR)u3>FO>8~_vu-z zV7=AGhHE%XA;&gi;gI7q*r*CSxtR}BRe|#@({xhKp^}3*B^Tl!W{=4TW1*#Uz1NMT z6!&dU&oF32(n&xddY&*utvqhtt62v@S?N_V5WX4lbLRpZ-{!V$SuVb2IT z?~@fsiNn^RkXAPUb)nh++KPo%H{fwnnr!H6pi0!8Crh~$N``P}nH!SjxVacBm)-Ny zVdsLIcU}fFDu!e}=eu{yFo$7DL>6$dQ~`fJ6|1O!do?r(RKbmHrkSF{LMvfH33rYT zu4|}o`seqD*#aM#Iy&O_c^uD>hWB2%yDsV$McbeM?bhK{YgL;Y@jlTs7FmPe8KFx7 zeZ(bg>@D}CWnhRXoc>x)m5EO}81musN?6*3mxax*33*vKd|7x#hrA;AiuyECN|)1x z#S{Qvgy%z8waBky{A+m`ZF#bp7Z>dMU8#_on-`-h8)RRsu@KdBm{@mi9TVAR| zzGd-S7IN$FEw@KKRDB@OBmdR%47VpOYJTD3?0;Lf!@n@B)6Q{OemB714S2y8VZdnO zOK_py`lOVe5wJ~--u3S^qc*qw1Y^u=qM7vl-Y&x8hbxX_Y+rdl#y?wm45MtXkIe|j zvH7bc1N6TP147PcSjP6(?Vh383^o>U%W|@SJ-Y_wL!y@3-Nt z9EknhhJ}@x{A?nh=GPV;*}hKOX0>_1hCyk%tjac))dO0*i?xU&=}>_KukZpOI7)u?=Emx9x%6`Z`~kgwDu^MFb~mjh=QsHP9P6-+$CEzzL_9!M>Sy0RRa+Zy0d$x=q_z}dQ|b zkTpP?ypU6neSTKv#D&_tkkd`MI8gECCG-W=wYdrjKe4%HajjelCj^tSo!hm)SMe&Y zachxd2A-Yvo2KS+uBNI>oBy0@)!>#2jHkBjq&oHCmVL5T-o{HjN+LK0H+fbf`wV8}+V3`_jD!<_asthRvpvHTiX-LapJQ-B;FDUyqNwSf`)&63&JZ z`b6y|)2+^mgs#JkyF?;*At#s(7I|-!h5-JyJ}%TZ=bnB6NNkv*GlZ`nc~L$WQM$f^lL0vbLDk9a*_5Q(T%Hz_#gdJtA#}oVRMt zk3}l)a3+$UYTUax7oaZ!pw*N8XNc2Z+=*;$R=-ZHqx$r+UB4!LVtcL;EmalCaf~Y2 z0Me_;zajBqky1ndKrQKk;r9eBPxp*IMPZh&62F>xldloKM(!e&JN6{Cs^`Yq=?~Qh zV_RsMT08!Ax?TO#cq@HT6-_)(cc@n$Lc-7|A`3d6@LL!w^^M#5Wx{YIWSEvYTX0f6`v6w z74VRklD?qN;m^p+T_Zmy{+!^p&(uo~l%dA>ZoVrIfS7arjfI>=*_i#}fy$s4bwbWx z68(V=V*XS))vNlc0gR`o76WO2JQcB#!fzd}6BnZ@nCi!3G_@Z)@1}_S58JdHg6Z^^ zj*0Sr1m5fL7a=T1#GLRS5eUno=^omorl+eAmG4a7p4aSfk*;;MSzX?rE~&pur<+7g z!8>}f(fp;E%0DdioBfrpf@iHcN1nBCZ7h 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 I{(R^E0MCKB+yDRo diff --git a/lib/emscripten/emtests/test_frexp.wasm b/lib/emscripten/emtests/test_frexp.wasm index 402260c57e384b2bd796d3ec397476da3ab1aa49..44632cf1b5c6a69c6ea3c33c2fa4f0ade5cb8afc 100644 GIT binary patch delta 3710 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 R0?P4Raq?u7IP!~Q{{u0VX(<2z delta 3715 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 Uzn-lD2mk;8 diff --git a/lib/emscripten/emtests/test_funcptr.wasm b/lib/emscripten/emtests/test_funcptr.wasm index 6ea033f1fd9d808c470381db26af2c11e91cacad..4b0ad5aaa6b7c2da0f240355abe82d375435020c 100644 GIT binary patch delta 3730 zcmaJ@dvH|c6~E`Z_wH`?uDLfG$YaBj^JNzj6Uc)gV1tsI7Xkr7kf+)u35(fH2zd#H z0vnw`i%5ljl0==>Rzw|q6lRqfM`f_+ltNXk+Hnw-(pp=DCU~4760m1fXT9FGs)}%~lKo%pjo}8z7)bq0`V- z{=X0(v8(84_Ks_$-i~JuF=HcCEA(Azov(nE77B&J-Q68)LhWl>ntCH^IuyS%v}#rR zZ9T0@jUHOn9S$p5W~jY=?dni-&pL`lqX!!-Iw|iWuE8qAQDmLr-yrbo0{7rJ*^9Sn_Aiy zb~d$y6|Xp=mc|eeT`ISxo^zEa2r3@S+k8dIMhD zjM|-DvKL67r&Xe2DF%XR=t{tA8V&`Opx1CG8iZiFVE{`QuzjZCx!6CUm`2TbQ00nB zHm!u|ghAVq1{Dsd2E8`vJ*PsM)GH;u<4GTqipObd@v1hUr}I>6lvtuKf|=q;y@uqM z2|3jUY1I2T&h>E#QRAdj6hDX`?$Ya zWV>NXv$Mb}LvC1p{)7vkaM_+IOtEFmj<|w}rGMwZV>0gI#C89GA#wQnKaku$qa23f zFV0v6G$^n)lYGivLefz+Kyq7ENnnT>hK_dwci~y!DY7T0aERdmo5hD24vTlIz9jAA z)jl%zakWdO!I`?nG?+7UK#O_#6=H0li#t%Ur$@<0C}0X_$gHtkMF*^C96cAt=zzKFh{HOfPp&t+ISEhwie~%aGdmKJo?0>xl_O=B6Fi;pd8D|z=^p5 znmIrBY4oDgH1+{l(jj>baD+ohiTI~^ElvkTEQNlXKEJ^5qGlT9;E*7!nV(Vbm#0e} zHpVGy2(84uxpXHE6%wM!3&K$5JwTe=Ed2_by*|GaT%xLByw}H_m`>p$?_Oho^h138 zg4tl4NmGrOwn^VW6Mw%iZ!OIw z`SsG3P#~5s>!SW2m&ut=mTk=UQdSXh*U_emHH!|#v=}Nnsz&l)#{ou5KOSp1HhX*m z3+}KAWe(cULsYsd_mi&wva0#C`b4&tEm*)B!a{Pxim?&dbLhzh| z5y@~0C>suj!cZ)ND@r^i1dx*lbP8=igjVdQ>9nSPlD}x0S{abOQwG-3g;%Un11E6R zz!Jh!HI4TR)vsABbyEVbvyApRG?M-fN%~7^z90PYhnp!g%fzCUb6`UJH!D8|YPPRB z2QW!&ZS5iXU27>#6-QnH_IZZ*F8UUf$KPoCh`}}SgB=fp*Uw)9d?|4;Uj}>`tgA(D z=Yud!jOwa^ABkmM%VDy3y6Ya8B5JxTV5;cveiE(~#XZBM^ZTBq)W_awP!?a-n*}u0 zeOp(U2w7FuOE&F=5ldiYmBD3@Xheh&B*ShP-~j~ISN2+9#&P2HsWA*F|(k?NRK zKSS!GeC-`jE}mK2c=LI{I~m2yj&X;_Vc>bN-Lv@jfZqcJ@;va#x(&1hgq|S@Ex;Yr z;#o$KbzHt?Hj!w`g)3(o6O!Q0U6<#%-e;J`ZvjS0w12YB4->?F>mnr8+b0qQm))MJ zQ%29)Si}zb#M+H5G&r$wEv+or1mN7N!!-Ia?!RS#`TtCXK;}sX;n&Yb%z8l*MzOHp1#Y zjjTS{UjY^3o&Id7h=1K*4pU`xGjKEoS3$3>QmfhhGRS-B;!uzo-pg<=BNXmsJf!0} z75AxDUOaT?ULeff0|)4!@!t*Xg)(XCZ58joU_=7jnn04_t=LKyevF6JHXb3h=TwYX zW#X4xFjxK+S222d=Z*^---;d9wD`#_RD1gpRNZI$Z{X{3J>BF!@x@QiX`2Bzi_d>H zb~JU0=kP6nTO`bzfmi6X64+V?eevklc}{JBs+4$sN8V`aG|b_f8E%%J0%-fLMgr*6u7xBg57y9p z-(V5V?-^W5Gv^1JDCbuUZKL^5hH7Z0Y&f6fvf;_3^Yh^r>VG-Bl2B;lyHqUagDO%x zNMRb1+*6K26iwqICc`vmOH9ae@q?MC5zLQm)WK<_n7fP3GAg95y#mPoL z-H2}+uZ@*RQkBLn+RIHWdp(tRi!jl-gJ{|+l^wdE7Z*+1lPTNimJ5=ro27 zJJv-mxp<0!DW;Kj@hLe_WNG%@MW&HDV#aM6A2P^~5owD3%O|;OWKH3I!>SUWF0Ud^ zruPBQmYkd|DsCzY*78iuL`S!b0e8}V+-YF8^xKC%NzR&8D(WMu%kyv?>E|U%JROfZl6i<|?no9{;k)@iIr|ypNKzO>*Y|(kzT$<2 zrG(FC3r`c~R7q!CV1g@X?tCQ2JCOqHAXcL)ei{;0TpWBPKfQ#fQREDHLfT!S$5y5I z=8;XoIvEH%_cmDqc`7X#(sK`bd zfcfcn+tu4m(n`pz-fki*jVe?d*W>r^HNdf)3Q-i);u9YyuGm zvJnUtVQTGVAObB2iY3~DUB$78V$m5Y*3zl%sI7|Bww9`G7283q^xR#nnbDoedFP&Y z-uZuSUjK;i{s;eliARso4`NFgd!T%B1>YEhjr@IWv=;7MHzM5G(HgxgTpwQ56o3^d@J9`vV!?$AI7u5+C^f#@zbxILx`UVTK0&&L_lbse1Q17f9b9BrvF z@N<)Zrhu-1A&>EN_eStLOae}IlCN@aY!g&7`k7xooqvI})KDlCjz&AXLLFUgtv!*h zPL}5kEnnWTwtEGeXoQwW!(les7wYI(w<@%>ySH_9C^D&n)fu5xt&vWa>7-`|eaf;3 z3$JQhy`IfWVBO&!R&Rv5mqu5z2KTb{oz+dm7>cm@9(73I5!UGa>JW*rTSkVvds>%v zM7mcr_q4XHY+l{k7G`N?bZuv2S9ecyxTl-l>>|-EE280EHc}qc%41FR8Sv9>2%-wcD%LD9mp*=s{$bW+M1ZgZVu^ z)4`AhJfy zuq~y72|z92v5D=Z1``!uIq{uOnw4ZcPu57OZ#71V6f0ehF>Zx9GHTQid^!O?H!AWI zA})5qS(lP=*7bE|@kU1nfG2*+8PMo)(c^Q_<6}!06VGu2U*h5%H}M=Nzr@QNU*_c9 z8JDQS7hIy&3x+yWtHW$O7q7_x7kyoumq#LHc6ZkXW=?{^__mqLfes%A z2MBiC3kaUGw-RiuD)SF=(=>1=2p3)f;Z~R;;ULGYe6HBTagRJy_3@ZNP8zYmhNvh+ zm#w#pA}qo}MI4MDuXbr9@0r@~kUDGjR(-igd_&+(bO{GC`^I)M9Ev#;9Jw`CXy`yq zIpjcx^-rP)oj&t8 zfTi@NkzO387fJ7)hBl|0qUEN~V19AF2X&u02^@-FdDy?CPWh$>ZH8>6(5yUJH-AhS zb(-B@LU~Mf1xHow0IBM;k>8+Z_x#mhN@rtXFh@9XB*la5LNFA+L24QkfwVnyl`#t6n5qOjtH;h-Ym;3$n3F7vEag}xW~v;ioKb*P z6Zk~FS2r+ARvlac^WOawwNSJ?y`+LLj05FU>_} z6$^nvu@=ywLgZrs@#hN~jEqWx5ZVE1THV7TQ`s}(;m@7h4VX%J{Q1~co_j`z33L!; zl;{gEthFuxWjbX^7``QYmXwjzPIQU_Wp#l(w&V#Sx3=~Zyx2M=SfDKMqhA?IdQBWJ zXpNLnk5CJ|Gfw-I$5Q%WBdNK!-@(+lzvB{zZ^u)*9)`3$@gm@hiD~u{;7efL zC|_KC0A|Q#YieMoJi6v~m?rh;{V-kbicW_~@_h6saFguo9weU3o`r<3?wJae@uNLi zK%`%+UDG&&>bC^PS(P}|?(f&T#V0^TRgPu&Pry&WqW5&V#PK647;qW?4yasA~d;$0cP#~{?m~7ZUuYguJ<`rwYBH&OoLkG*rpPG z-jsjb)JBJ3-#U8pbRR%X;q_^0%~H$2eiqu*5K}Fqkw2PMo2>fZ1Ei^1$)Fte^I^5p z&nbsXHn%{%d}?!mQuyZPX(^Q^W(4S>GA?PQ*fP4TTFDVqxHL7MtkB-mVyS&XmBruG zJ>T8uHUk&q8EvJA5dEZv5hCBU9X*OIu3l{02fUL4#ZE%XE;oc_wG&s_y2vC-`kT(g?eO96S;C_&mzjeg25)rz|deb!7m1D zh+h3*3DLVATu79&54IBjxV<}weqwJ8QLgSSBIw^YnRpiNYa{&GeanbP>>oq;P5ZM5 zU$7sid2p`JOyfKTeUveZ?WyF7OIIY7L{%$bRV8cXaw^^S^*)1M#CP2iazT~6eA^D^ zdpb;4CAxe66sVD}?w?O>pZCM(0P^HpKgy-0%&mMud)jCEk{8tfpYKafFhRRQ=ql9q z1ydfqy>;|yub`WvE}XU@GO0T_Gz#5-_aYJEmAPWXO2ut(-S6+SJmw^XC{}o zgG%pfS73)?K~NW=^V!KpQ0{SSGP&oV_M;_m5fU?1WL{@cd;b;IE=J%8^#yHUJ0=ev z@r*1MskD8)YIb^QXp@uzdFn`C@eOJ**kjkKrV}Y-y1Kp#6HPToxtgP7xyC?-9xctF z$WcvkRoaPv29WLuR!aQHqx-m1r;)l+7&17N5nnuHg5yr&^}A%(V`IxKo^5+AmmTw& zepljZX94-3p?0jBgY+WdD)Gsak5vbBb@g{M8!WOpfpN>BF!Q+#pc|FTJdqLq bLHu2a`ycOe#-mRKfv-rHaH3LPI??$*=G;Z) diff --git a/lib/emscripten/emtests/test_funcptr_namecollide.wasm b/lib/emscripten/emtests/test_funcptr_namecollide.wasm index cf4fe2ed6137957cb72d9a75f700b2f62fb6f4eb..b58125071bec87ea1d612bd89e9288dc6d0b2195 100644 GIT binary patch delta 2177 zcmZuxYi!%q6~E{HU$(Cs-`EXKoY%Rr^C&HDT9-maSNWzRg|$rwZ3<&!t`nTqiR%R0 z1&TUcr1aB<#(IZRgv2K8%aHg0GT&BdL13{CI=bm%!dHl|O>k^#51kd;N^JWv8Cm8+2u@i2SJ}Y4SuTJu(=a%Okr&N7nQ=w3( zpQ+ClE0rC)cC)rD`jza?UF#z8m1sjLOp?>p%Hr$-W7bhmp>(P~TPrU$O4Y&-N{zzF zQgNwJFF##ku9*ULck*V1TFIWYbr`qi$>Pjnt#PEfzgVp z=6#sBXLN+S%wwLz83*7l2hJIA$9DtH9V>Etj|1~(WE0X{5OKs=NW0>!De!LdJoh&K zPO5}n9V89C`twyTehB*+eP6D@C5UxWex+Kix>%qbi;ePPmGuRMxw*>e`bjqC73ONC z5=(l8Q^j(Xbp^CmNRiz}T@Jtt_UMgW znLalD<>3=$wj)uhH;OZra{c7dMsarG=u&aE#Nwvtj5l|7=W+w7Tu&~yi@pT?k#|}! zG6v90#}%aG$mTQgbX>>g_0r>(ODCq>JTl1yLQHrp9ghj0AeiEH|5-?$BKcp`Q!OttnCpqh&U>B12a_1)Hqn zj$0j@AG!UIFt4~7*ld31_6(5r3jm!~-DdE$IE?3=*s~d zOkAtN<&ZVL9J>F9$2FxA)BfZSKjRC;Ddo zA)-Bcndr-UdwPWn;o*;gO8BX58F5yGD;$^k{pupei{`riPu~is8*x}eO^skkyYp%k zM{&doS6cs_2sz|0m^@C`eSdP6z#aRCYo}l!;e$79omLO!NkBr272^$>X>&I?`qzR@^!Zx!sJsP|Z&~1%AdhjpZ+4WQc zdMXBOm>Q5H$YJx*xBCgxn;zKHMB69pOOopdI&z3wCJDx#@;%xr%Mi3~9L6w4d+Ky# z(oQWYcB-&Pd#LK>wGg7rn1@=p|nD z-TLg9KRhr_?SKcbMdQfnje>Qvtq+eTP<2v0gpHegG8&7FDLwqmzT0hjdhoOz7}Y^X z!p0NDs12P_H?4Wzd&8OFA)V6jL#X!&|9kb`rZ+3xw UaKnTV$t~wI&81^5Jo@_o0JUVs3IG5A delta 2186 zcmZuyduW^26~E_xFX_9o_1TVUMe^fZf3mGOU82@;wy?C*O`2@W(}|rXTe2yNDmS(j zDUp<>hHlEh?O!c>TuNL5`)9DNrO>8o|7e#%p%k)su$4U+1jfkTFxVJuV~;;}u5349 z>jygDJ?Eb9cOLh5uAaRK@7;v24Lrf1b(XhUYm%L{TlA2^82_WS*(z6`>MB<&#rl)w z!{rOL`VzB@t^3JxbGFtjR_-_U7tht|&7;-5#cH+I{B*r`Wn=g2yOs~w9jrp3&{%4e zij~SkJ9e^;Eq2c~wPVdB?wQt|qGY*Tt<*}3jOlTZdKspN3}R$vR_#4Fdvw}rF{4L2 zdf~7-r9Xguk8H_ui#ZN+Y|c0Uw>WUyW!&aqd7N{PY_{ugU~Z|W1tAwCEF)~u(#Lo* z`V54wAmQl}m#r_sUPh1DczZvCo*v4rT(4Ja1WeJrKe0r8tW*l~^X#G6hl-jf z{oxNcpPFZredR{8c&;+vI6u=YmKJ9&7E5K;E9#f4)3ru(rrd0>k3|T3_I$m3h4txO zR<5;U^VHOEdMY(FwUeGr^z;AJhHMs~75WlFAK6024}BG1P!}(mRVa?wd1Qel5aPmN zp&u76LzeM{-+3Wqgy>~qOtJmOGZQ0Amk>=522&7N(7_}m*UqaTu=E`(4GH}ZYvkjb zgnA(wJeWd|Q8bHnRb(j6)6iugy6=ZrN0_z;VUw=fnNK7HI?_T{+GwMtyi3Yo=wS@I z4Z@26JqDupBOq?uXLltqCOz~NEXW8(WGn_kU~k4(EH3U=;a0?ad@J(*U$;w61;B6r z*v(k<`dc*a(#r{?lUU^rzR%?<7r4r)De^YQ+xnAy+u9)xo>@20_57?86l?T^lM>)>+fm!E~i@b8@vAiEBg8)KOk9tbP`tDFFiU3 zu=0)kvt)TLf0E=c^UEYlYJ0fCg>dkBpyvG391yLH30F8S^Uum_9IxrO)L#cyI0eK} z1$8-w5oIsPaU91nV_a#!wL$Z{q*@?gju zEn21?7u_IcPB|Em4w}N8xVY{>-ki}MI-=YL&4?p8Vp-S0mpxww7z6|Q`v=2`w3X+1 zOe^*onZlHvr^7}E(~B~LuE}{6M@`rrD}d`=}q3*N-?Lece8O^Z+Ect;O_c ze9_=3K#mZM=%txKBHOi@U9F61s3B>9j4HE&aq4YAbL>dZAvH7$;=smc9OI;;hyH%5 zh2|N1WYi%Ys;YIVGel8=(YT1NS8=Z%MHIckA#I8qSf41m9Xc0G=T`XO@f?h4e)4Y2 zM;;fy0!Wgte(v}kZ`Fba&HC->A#(Y}^iQ26rIge+jtvhdP5S-VZ~AHaOU*EZjmwdk z?U2u(kDZ5Y`qc69Y|mOwpx#Ubp1MiB?!M2`6&JtfFmA#en|;`ykUsiyPy|{1!t9<{ z#t=!S9Ey?BcV@R{wwjpe)@2ftrdO`%OUmT388`2v#@IoqCr;#Gi#~lK+`UyIqJ$XT z3M|M-iPE@^lCo8f;3)ZzNT5Db$7vyG$f#Xk;m~jLdFRA`yt}Zr{>#bnzKralzQ;^5 zF~Xxck$U3Pmp?UXa#q8a%>>DA!Z4Sz6evtSJO~AL$A!f}{Kf{mg8RL-D}XvtPLJU;Dqi$p8QV diff --git a/lib/emscripten/emtests/test_funcptrfunc.wasm b/lib/emscripten/emtests/test_funcptrfunc.wasm index a536d7c2377d8627f7220dc643868ffdf980ac44..2c7a06a755f9cd3fa2ef2394c187ccc5a4716934 100644 GIT binary patch delta 3622 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 delta 3548 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 diff --git a/lib/emscripten/emtests/test_funcs.wasm b/lib/emscripten/emtests/test_funcs.wasm index 653106f3c61f7069cbfc6624cca5f0c701da2245..81f969a1fc366b7811d7ddb1acd42c7b9935e643 100644 GIT binary patch delta 3582 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 delta 3738 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 delta 4570 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 a5NkQn?~Fb2bS0;igD&c+Rn*RaByDypm diff --git a/lib/emscripten/emtests/test_getloadavg.wasm b/lib/emscripten/emtests/test_getloadavg.wasm index ddc4db07eadc88353f90daa549aded38d3fc4e73..cce9f01f53472fae4f04cdeb7869d84bdfaf4147 100644 GIT binary patch delta 3654 zcmZuz3viUx6~5~8XJ^8ai|cC#Vm-0VVP9wd_Rj6!}0X%HlsAW$DHNmxk2=E3d) z4MsLPiH=o^a09W@(GhS2Mn`mQYpYf|YKKBQ;)u3RM@g+zYpr7yOD!Gkxw}y^9d~B$ zSF-Fu1p}Ho@3NEkQp>DDS9VHQc+y z)7IV>jkm_zI<_|N2uC+Z`gSr!9vHpbBaz1Ky&a*ht~4cU66G73GZYF%`Z~5w$j~kp zjxUQwSM^QENXkI0qb(A-y0$vORH-^^GI4I2=DtFkQ=29kS4a~~8ARFMd&ORUDBKh4 zh<5eI!@Z#`;drPs+}0n8b?pi>O&ZFZeBKl85%)k=g?BPB8kXECIR>d`OFfakwoPq2 zwlHZ&Y^5EOq`D-wz zkSoH`Xm6i%e_On(ub26qq0O5k+hd(<_L+hsk93Bbo39fWlK^^0+21$L$UVgR@RWYX`pv0G0GrV=DxC_ZDUS27H?~h zbj3PT;nUjR))8hNkyNV_-^*)in&$I1H8o{^{2OIqDL^9N;Slg3>kfJX9^34;`?twe zAZL|UkIZ5Qf@$b1;4uvcLl*QHnW+gOm}A_pDme*#kaS4l@wAeZC~c&y$3Dxtc{a_b zXcpVG7fP~t1{#<#S7G+4LNu&;KSH_6cpkbjZ-L6}*9*~Y)r5EzxOMa$D06fW%GpN!uoM}2}8nw8dds@-)RfV5c3_PvatdXBl@QgT}TL7n%f6WCK z@qJi0orHz6Xb+8JMW<aB)n8wfSs=%0H7&_hu+=X8P;Xo@%!Z8Jh zmF4_F1s@a*OFo-6rVu*|OB7lD?Z8*OIws8i%#b9{wFp zHPFQ!$n0ynIUtlOOrmHN5L^yaCHf9@ST3%iX617oT|p1(rg2b*dI{4KLaBNZO4Sw< zKUs0i>EISYpD$Lf43zoRdZixyHf!PqSfJIr!9X4TTX_&2^3F4GhBP}9{o=j+(oxGJnVux3i7JE=LjT&%B ze)+R-tsGY5Y(Duhj0d8P}w9 z>>-!9>(RFSaTljJ*0|HwxtH+v+Ik~hcigq_&`yq&pV_971FDqOQVO|zkZH6)Ceg%W zt+Sw5oNEnIP=DE40s+C--#$Ydg)ST?;u(GtjXRE_jI&I060yXNXM*Ug;pvo%wOk^KUss)4j8 zpRQU(X%RDhd&Mf@1cGU}(@qEbT!Bd?Oqc4$n+pnG)}T^8vx)#1he<$>10ntP&0#1L zi*KoNmlFg|9?;2?0kP|rr-@u~>ky4k-a4;7An#7mwTx1iSrrCWaMi#nLQFM{^JVH6 zN+NrA3Z5?&vU75BT|7y3Q3N+U1peep8z|~3MgPVXP?~&UY4?$WpAdp_hgZ=u&3=-__(jQ%Y4(f6E>=bFfGTk| z+EVlt;GGKj%uaBJ+hO2WU}rApUju#(|riZqIyvEs6Y ze#11L0+=eHoQf}4nfc{lUBNv5v5Ft7OIRx(#6fZtJjCzT@NUhTm$YuLfq4>xJj^8s81-3|X3ZXw zP#mZ9A}ACbRq(h%SdA(?q~m23PpH=P#HUsua)NiA7Q>sbcpP%e@nZw_vYTo4j-I^~<%c%y-9Nd%x%qr*9eA2a)S&Mlw&LI9`4wNodgid-4* n<^g>}xQw^*k{gcoJCnN~|1%_CJFys)`*Ot%PtO&N&;00ritSU2 delta 3676 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 RI+Kr{sRg)SUVQree*rz|OYQ&w diff --git a/lib/emscripten/emtests/test_getopt.wasm b/lib/emscripten/emtests/test_getopt.wasm index 674f00335dad9c33e9ef31527edc710750738ca2..025bd912f75ad7b1add44755a97d511616c1e36f 100644 GIT binary patch delta 4951 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 Tog{y7al7oibeo)bsrvr`YWH8Y delta 5129 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 diff --git a/lib/emscripten/emtests/test_getopt_long.wasm b/lib/emscripten/emtests/test_getopt_long.wasm index c30c89b3696ef53a3259f3fe2073399e3c55b9db..3b703125172bd435d134c79c7aa7f2173e051ac4 100644 GIT binary patch delta 5602 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 I-dj`u56}Jw<^TWy diff --git a/lib/emscripten/emtests/test_globaldoubles.wasm b/lib/emscripten/emtests/test_globaldoubles.wasm index 45d14c5c7085125aa969a29ba9df4e1262b29808..0da31aed82f7d12b9498c5ad5fa1f58526c89d24 100644 GIT binary patch delta 3711 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�jC zupTL=%z;c5Ne~QQ0?3eytS>S1%=#_@&GZc=eh;@}7R7`7LeQnWPG&YH18F%|OJf%7 zp-8H3!af9qrcc*WI| z@9G{@&?7FMDlGI!tmj~kyp+5oc_dNe=0z?|CmHqhE~pjZ)1|ge;FL=G@0rQ)aC3yFTXeJ7w; zyJHW{U)do!AMDt_N`@MwQxr#YCEcBAaa43vlMr$n88_l^tlYF&Cn@gflQ=H7@gaj! z>FBA)=Q+!yVV-Z8GsUkTU*Rf}pyIhYT{TyfK2h!~msdwylzWhJp`(r44a}9+r{nZG zDp=|bqW6hPxJ7*P3Gb3}j))vw)Fc$Mh;!spw3rs*(ByJrP{C0q4l>A* z{@9-UxBZ9?3u&Gh*nf!SzpBA(TJQ?O$Q77`#VbHyeEaSY%n|eNsUWZIXy?V!>tfM$ z&v{}O1qX;e6ZdH8egI_a{7m-F3zNI;1=(zK z8%7{6@nQoNMuli;s)vHa^GzQE4X1a04p1pZTDpm*w^kBsdFxxi1{@;2?LC;A7;pQC zK~>`I@HZeckG}@^TC)5v0$v1jz8H)=4mF~MM%2a*!d&rsY*XMm;QfpuWW~A7Wi#+P$m;q6@C%@@ zT?byRTR>YtRYqCU(aUWzd!Nyxf;P7?D_NW()>BmG%Qf7_cL1i!%uPi_f}84dmZDJX z4a*a=JU!fnF0(*f=xKujQPw+Kz8$?eIu%UUedX+uAx_=bObh7mrJZ~G0cuMonvA(j z_E76(XqUC0(ygFsE|=}oZTu1-Q`((InH*q~5Hr9ilYC$c)QR2!A0_g!fkn4h7&uKn zo@J@lB0Csig`7>+I=y#_EHrb8)XfRf%x%0dPaRj|83(uo%wJS8GpbE8Gpdo9vV)8B z7V)bpUR75pn|VL>Qw(8*AJ*`&W-dw$9IS!`GCk8Uo3f)|rlr!TrLuI6%9^so@EF5$ zjM8|F@t}^Mt2nBfwecaesB z@Kv>gw~^RODz*_?W*){uc`Bh|`%TM{3B#=zF>4a7hgHbjmwZ_ES^2B@UffH4W}oPP z@N?|}zz4*AM+&lOGN+yo0uD-?JOF&LPCL&X3BbO@r$^S?wLyl1;K+R@w+K!o)eoWXB{Ut6aCSN zTH6NADh((E-N$QD3xlR22%v7=E>3`bp0xj-!h_9S2tT0)wdt&jZAK1Ow;>V*kB5}UqzjQD`82|tP diff --git a/lib/emscripten/emtests/test_globals.wasm b/lib/emscripten/emtests/test_globals.wasm index a1d0fe01017c4551fe446a982c78ce18b520cd43..e36fa05164c76ff391b23ccc9759fcf023642241 100644 GIT binary patch delta 3531 zcmZuz3viUx75>lt|9^M0|C0ULkWF^;IyW0g%!33H0}>wj^Fj;)21JU;l7z)PHk-$W zMuf>Osaw&JX{wU!Q!k5SUj^kJ6{odA+o8UC?rxAw>(1=C z_nv$1x%YnGx##>JooC0-v;CQw5K}g=SPWtt6#7$-hQl!!9xJPgDar;dMn8zLan-Aa zB3nGIZM_47D+gQKyO(bX4QvYcZdI6^Fe017;ik=z_F!jcQZr?e=8Dc93z!C5HAB(%)^K=MRYgourRyn^mDNd|>#FYBs-()es+urLA72+|L5o=H;eo}v~Iw4;;#f+U$FDJff?Jt9SDqTM`Fc9gLkhczY z_C^$+J-BI8cyqKvS)d0u4TM6IxA-@wR*6pwKJl4?9_&7sgg#$ zP)~c`kkV)+x;=-6X|<@Bih~pZ$VR(-{7tB za}{l<%A?xQW;(crnwiOUlxNo6#$g?5B^`CdM#UuNDu}s}8-8H7aT855Q&cnuiv4OW zt3|)1T+g#GORIH(fjauTc>&rit&2~`=|xQ8Gte(~HdljRJm1_!4l1#d986ytAkC7c z&!Y$JZsP=iDfgAZhLiS1+BfIMcDqhEq|mZ^ZY;|8pyoCz!6xl(s8}N#nmI$J)mjvR z-CQ+&;x{*Dms0>+`%8%-kR*@=h1*L2Q{^D-Teitw)(3WR-?ABAFSlbF;X&uRG*vZX z+8z3Ez!U%AK+pl%qVci4#p#SuS|&#-DhOt_gwbt$mqCW~o=IV#NpP$Yhv+)e>O1G) z6t5b$TRP7mCNnI(iH>{DA>Kc-mFMwPOm!P+pvuKs!XwHXxs4WZl1}VtnF(C{w55Qe z_fIW_W%<0G?(OR04cH(dZp20`H1jE76nbwGDyem%Q)3lJJ?ebX}&!P|;B}l2`sUK)O8P z#bx8M855M4)9Dd_^>f;dE+O}jD5+*{a)~>6PiD^G#FyJ}CHVpCtt>ZX6q2_NiBV5&AvMjQ@7i z#|$dsCp(XU$H!jGw4p() zH2Rp~--uW_!fU9TG(V+8`6X$NN%Ko&E@t=df|=s^{+4xL0p7_7Gb_ezE}Ma0fkpIu z4fr(>kY53>(k-AVAW{vP!~)z#Ena4XtnKPkv?y_=Ogu}sQJUafEFH*qUFSF4#DsC#pZ48H2CATEi|)Y2*AEahq<&cp1o$2 z<-ASFUj~Yo_#0u90%e2|e-CY61$E-%?FB@id&hM}r3QKnsFoEc<4>j)iV%u8nN{TD zrDslP%@KV&yqO;USCzb;&?b33p^?|echqE6^G{U#M6FX+@?jh%Sl|(UkB0YXW_A41 zj!Kv#5%*#`0j{9OQmNIf5efWpdSe7U!vhSDGh*fd<3SxiSMh{u=ET?UJPs5GDX|ym z^6{5r$6=Oq^^S^?IXD%~J8`F3gjw;wpAs-8nL` z@$DEfE8}N&QMDaPB=;dJ=X$;!x6`8^5})4rxwac{xA^;Ax#`rI+05?-yjxPg8+eUQ zGx?)UFcj|`U1rxtsalDb_U5NkXGJsL&2TrRXsTemMaR+jXM0~{Ff0Dd{i#3|;R+&z zguDb5a~Y$IYCDb-65`AQEp+vn`)?!C_U&&W($4N*NwRXRf%MzPN=ScfYz=9?9BZX_ z5PWbi=`TFkK$;3sNOFy+BAfd}JN5q|HWCZn{2>)9`NJww`!KkTun3;$?3Pj3d@>9Ug^Ie)w zHWzQ|086ZEDYTyh$dq2rEI(5;^_whOYO2<|RQFORX;R$AhYSj(@rj#fI~T~>z;g_< zMtpK}9i>Vt>f9$&rBBRTT~e@+XJ7`}2IMigT}K37I9bBNGC>|6R#qDSWql;a@cI>gZAZ z@8{zFqgl=(DjYV-Aevjecyy-kLk%b%nS3;fk5L3MxlH=Na~r0UT&k!o)oKID&mk&lri+eEsFRJD_EeRh9z3Nf s#R8Mbo^ihy=wriS-0h9mJ>6%Iw>|Y|h{vB@1Z=)nSSPAQ@pB9R3yn8C8~^|S delta 3499 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 diff --git a/lib/emscripten/emtests/test_gmtime.wasm b/lib/emscripten/emtests/test_gmtime.wasm index 5c8736f9cad4d316968f5ad84d7fb409f826fbb9..93032ac35ab6c2bbdda5ff3a0b7a3cc52cd92fb3 100644 GIT binary patch delta 3617 zcmZuz3viUx75>lt|9^Lrf64wVCYx+Ra&C4*ViHI&As`WxKM7Hup$P&q=(5CxJT{xK zyMZPRY^;fns8zTKRGdH@|IpZVU$5e zgOSPo@&cj0SZB0*ARdYYwuIt=u266w5bGWeDZ1DV-0PWY5Dm$hl#K%75h%>{1UL0Z z<86`VU?kEXzarYdeMP9RKRP5{fHh(fYig@s2s*Rrz(7$z2gPpJG)>Vo&}rZRmH`== zhM_pMX<3R+7A^oynrbE}woPUNe9R!B8YAG-j1h5~<%+LZCWXgRNY|oF{K&}q>AaNu z<#A^0fMz-I|JMF2xTe$HL(yoYU*a8%clSq>0()Td=I~&wOKH>to1>wS;&BDS;cb0^ zO|k6+M0d?4O0yp53wB48Y&*4KTB_vO1IznDeVqeCN((6o!BAXTtOsJ7qPs60aD{VnK*K9%gktgFrf_$xt0Nxl?Clr`c7~LT#9L~0VoC1OrG?(SrAwD)o_dij zECWdR+#GyvRC@ewpWAZvSOZ&S&o^VG)`*I!7zi#ySA1@lVN+1?yN%3LgW#WGe4@g| z(nA?7J)L%uT1W%AvdnVy@DeQJe(Ii3dc==4Gt0#h0kMuL2xgY}we~b*i9vlnG>M1x z+v-&vORbDnt0Hk~$#i_4@srHJlgv_D`6-5{#EP7JIGOCu0SDRj78cTCv8(8Il3qMX z@;zKnvXOrYt)jko1X>S2Q4G+Ue9~v9Mm+1!Ci#|syQ7uAr&)^Gnp{)zHZ9Mqvv!rw&b zS5HB|+Ehf*@(1m9ZlY=Ci`SR?%DrkMYecW5T*>n>Uu$%NfjWA7i48VOlf)<~V+x;z zUQw{34!ojcMGrZs!5VUKVug=1AFlWXy3y`3jslo+U&&FNvMLU ztZe`sqH@)&oIGyF8H5L&>+|WVkY+t|uMdIC`+)|#+80B(uq@rYbk%ZA@ z>|)@N-gAitngquhb%>06gL!8hocO76yQOmvMbcyG@&TN2h#T(R&Wm{#X1RN(&SYghY;ts|>TXP5A1y0^23w_uBecrh-|5wzR0C2%do{OgW=&Zc~5*crQO%#9-W@R2SXL?xK~^> z+)0D)4{xKHe+~oKZ`NS}EleJ}dW_Bd10{P&lpKoRD4Rl*QAY8r9a#;F#mysr3g06m zmzGr-nB%7sSf1veOe@3?Vw}t>^6}C$C$ts{*N&WAH~+gzUXN;1ydKra>!Ka?`Iquf zRQyD3Qabnuju0$x7r#lvn>6#%q}Wjd^CjXrm`#8y=(bd9HEUD?e}vu`0nczR!y}9$ zvzPIJj^|W7s+ySmdgl=!9y~DmE4qAg?3vs-GO_U%jF@%F;Tx#B4yBU&kTvs4K8(Zk=!eAZW9PJS zz;W@T@xpBC%vr{71iVp(ejIqcPBYJrx57};apOw6Hb&J-tiP=|n>wqO@o|RZl%lDE z@pc`@lDltvl0j{9*&SKHClMheva5W~CM>FTfUzJ`KUv8SDawsTJh z$=~m3A-zXbkiJ>0BhB3+NblghxP|n)_O_7b^}VGe&+e@yo60*osei|v*HILD`JF1( z@O>&$yN_VnFVj>F?k6;j3o$uBI!nfcPI5q{lT_@(A~!B^8E#nub`rtptWT$N)4Lkf zOX6-jG#~24BZt~3MVvqM3_yW+`kt9?GQE)VPN`5SEjP3m!Xoj5_BWb6w6~{+=V4x@ zqHr%I>)g1NJ7{ILP8L^>wVwgVmHvmn z_vfe3x0AstgAweU>TaY*}m4 ziB~Z#UW_GVU(A6XmpMmvWU8RdaDBRriYL~6PU=>Px# delta 3698 zcmZuz3viUx6~5>G|G&H0f64v{$zH}dtgGSI~ z6xkf^+0Hbz#_aA7hwJ;h+X5XONy&t9k{hzrKp+r|MnjRlz~*2_nCWV%lZ4@(wyk4^ zh>M2$mPR5gd&UeY$qsk4Ef@}$&n;ty1ejQ9sHL97RAT0qxhx?vZ;C3Dk`$8kcPBl_ zP7srvf%dMxj;;^`Wy1)lv3woY<}222Dzd!3xkmo_h409NN`Vx&X@bX?km~g^&JDwGDqX_@=4eZcfsdO+G(~hp4EbB0 zkunHAhe^b#IQb6u#CAa)qn~->>--C(rO{qOkw|xs%2=?kqoic2!Y-aauD?F()ScSN@&V6dh)*cM`w%t(Lts-9@ynowVq zEpd^#<}H!Xc9tQZ(#m4XCpR`0i7%K25c9bO_}s`k{cfMz_IBF6+tkQs zuGDLgS(=I9H4Wx-drb#J=69R!#0SA|n(55vv01&+^m|A$!8HG+!E|MG8d>>|VBJ89C%hKZW9bo`>{EXAD(dXB0uY*2sSi&eDiDK^$Lhru9k1x*;di>#ARqQ`cQuH=>o&6*;<-hCv&i)I zTQ)hTxmAKqD^EP(!Y5p|htgs*0r;}ZpP2e@E~9kNk-d-T{Mu6A2scdw?*rk&Pe7!okrLqu$9;U6ILh&;ys!2{(vH>T zkg?-+E{&Me^=paww0@r+bBnJ@v579>KxQxKq!?iuXM!WQ@`Z*D)Ku&abXXptqi#(R z2C7XMUh{+jHL7T}RI{>iH7ip9tF^IHETE6oDXOtn>XO30PjD>}(Q1y+!OgDZR_ zd2+?m=tig4JO^N@fYK=-92XE;n%uLp&6z?OOQB`&t(<1MQTLh^;7~=#Z^~@UQ@cxU zHYNx(RIS7*@qnt60Q>J5Dew4 zXJhW9{~LWR*K1w|$WRk48%Fa|#vI&qWfPFD0%R+V$jR5Ij%qMVxt)z%rM3VIlIfYM z;9rcz1Wj%g$xDyCW@ID7Z28Ee1qIn^G7Gcl_%T&z3Q9r9D+)cjK{~HLx&`Xxl9R=b z)!LKKC0ubmhRi_CRB88`X*aTbWTxe`AEs2Nj+0FA zn*ZQXtODzQY>s=DaxC&pYlb}kSgpse&?IsU+FFjh{@6@^iP|bUA|e~Jh0{QXaGIE- zyidl-ODRFR<&!Hp2+jI>9IUTZHSQP!4Mfe*RlwT|CI zMf|zWcRAb=KhyPnNY4|O052sP!i#_}f>k9q^qhow@{67&Fkja8w!mEZNbdtsDND9h z!))2H?Mb**W<^Fw=UikRjZ>oYpgdk1%?1+P*|%-gJVND6oMDyYJbP$JkBX0gKvjmN z_&(rAV9`8r?{fS%0Y-5+orX#E3oI%=R_d5k|CrR}l>R+XAs_8uU2q+6FQ=T@G2!qy zOuP=ZdzttW@JpaXUYFj1DRk}~UUOFRC^ilhdZy->Uh^q{NvfJV2l4>r$Up~CzP&_U z6x*{5Is*-ZGx=px_7AoZ^XI_9><;{sTa|!ayd~W{8i& zz!0a}d@|Gwx5<@z{8XCgo?F+Jo0#dRn|MYds6-#8>T9SaPAlDTbfZ!x7Af0;K+3)5 z({r@9wOHD2p&;;%MsCjO=FFv3_`p(34u+z?K z5Ib-OHHn?F`QT?&`vLbSV0aJUJ&8tg0Pp~)^HDA4dvuegarSaC3^=T6y&puif&1nD zL-nvT{_3HXPJNi;uq-%Sm_dV8%f&u*W0K}D7pn~%j;}rZ6AqPe>$|BSZf1%yq&7FI zGE_zxqW8rpWk@c5Xf>te@IxD@lJC>FT-F_3L-gp;B_x02=uDEkM%IxeI1(h_UmUrY z35^;eqh?3uy`U*Lb4v)OuD-AGhmy@u&^04; zRY3cyDQoWtPQKs~gkN1aZ9`;{tt{J6PrwTv`P?1bH`a<&O!b-*lh*Y_=*8;g;WZbJ zodrVnS6+iAwR2KIP*GmaQP&WqfYx%Wl(y}l9!d9!#z0O!Jv)>3N*Lk_=ZU8;0_mm3 zTTh?hc{=sYt@N6q7mw}gix9OEG`lY%9P#WQnBZ7Xt9>px{Y*ir#dBy2#fS&|CzZtx_aBDFdHmt^K_;ECKH%Fl-%hZdtB#MnhO zLk&fCdzxE%q63=;np?Xz?hZxU!aaKwCO;UFUEy%Uu1IUJqa(>loyGZaS4-M2uqZ@jr_ejoQe`|9%ytuMFrl?YN>TKrHB+oU&ySg&TGGA;qQvKf9%xFkTC-y0D?15|m zaU8Y?J6qFSwE{GzYrsHJKm)~QQ&p921{y8wz#QO6aXJ-4b)_mANz4IIrKsvA*%mVf z0cH?UjbR9AlIXOwlo=vUGjFU;nf^)sRAqubb)Fe_K&|}n-DrOS+;hqNP&69pkuGl@ z=;(|*Mni#{>*upmvgoe-I)6o)Qa^u47ERg1p#W~7r31U@mgLw(ZA;H zan$m^XqIBu#zTQWo1|-9WsAMYBaJuAO#XxepKw^NrA#54053T56Q4fMf}b(6MZ8}1 zA&iS>SN@LZ!BrJ79{E|liP?ZMR&}KTghMMW)I!eoQxAA}uH4>yXgi-k{Xv0=RUzF!T&23bG zP0C9PM|Lzy+q4>sBD9OEW~PW;KfjCu+&WrJID&+VBq#`<0hlWnY2S0q<=P2d603xZTpZm+==fOL7oi47NH1=En23uMGu&(djRggirfNi}nlTii)InOVRIFSp@J;se$j zS#GL2x^#k0hHOd%uH{@OwOG(cT2#03q6Q14L>VDC1+yY$N(G9Qu5BT>O8jA4nX8yU zwDW*YSOkRYmR}P4`CCSaR&QTc6OblReAXw5U5SCETs5$aFsCElDOUf@VsrK<0REEE zLFbcYGFj!$Q*{(iZ$AZ@@f&WXxGfbd*a(I34Z*(y4J(?z23RPTw)PV}+geVnw_0BX z_DO~~8~P(GijTB?#GpLh)$u5JGWkn@FD0_`Wx$ug%on`tVW9lkkr3uW% zSABV|Yy5`WcoJZqjH#k%HWZ46Xa~`A(S=l;FGamNrNHNVO4xb72<&a8#oc>%)0ZoI z0qlo#SWX+`lQ)gB>^G?;$Uw;;{6^TUKpA0#U+vHqSR+mjLH5ke6stBOosN^|noGLf?{!{_0DldbQZHcRU{jkI33uPSRP|5(M3)iugyK8(ZU z7C6Q4*6?o4TpB;KuL71yk7r;yIb1=HrP8QbBhv9_DaXk13{NmT%Lthhj0bi6TE%m! znH_iCaTX{JezpH;GCtlDI}3}Ysz0fCYFdc|yFGy}!=2bp8g9cE)h^yaV$Z19VU~*Z z2QXLeimTW;b8=+*;GGyTE8>R^P!AqV6!$?Z`&vGPLzMJ`;-Ndg*2VzG#Ob?o(rL1& zksky+D4`z%UZvBQ*Y0Y7!MJyHgIyb?o+dgD=cUtRQzIW^I7TI!`W$c4aWwwO;a@XY z9N+fCIgs+5M?~KdFGca8BTZ!J+edCCh*lhJB8Yx)bTiR+kJb^t;8+Rqn~vQ~oX3wf zlYHv&!^FS;cpY&r9WNwm6O|-WC0c3zu(&;^0=xK+RIK3lsYv5}C01Lx4P&EIaROP$gq>?DR5NE}lERk+MJaq2~cI#qS@^_K@he zU_iTEj)=LL@J9#E%mMRMOQyumVSiW7Bvtg!hdS$rz(3c1|iash{ z@|ED`c`i*yub8-@9W3E&Dzr}l_@w?r8{aCL`(5cQHdX6wYIbvGaZ=pI2Mh|O@NG9P zajudLfoB_Ll{j_d8mf=f$$6%%kD21b8%y$6b1!<)7M0iFb{%cpZeXUo7hPEvO3f@0 z%eI!oO3}VGuyQr02ExHb?=rU WSg$>9{`6glH$Pbo(KHbGP>=miOaGFGuIV#TgQ$FV=m2pu%j4p#az)e*F|wK{d2s-3DG>A9OInbDou z^X@(O-1Gb0bMISk^AqpzLs{tzVp|}_w(wYtMnu^b#vUpyU&x1IFtkOF(GOz$Pg<51 z>fSXi)E#b#w1rlNcJxFB7+1XHwou=?p1zjwS4?>y0XKX=;zz-5(Aw>+fz2c63Z|rcL2|#d8LO!EjG&*W@0WMMHh{kw{Yy(;j*)ZH1n2 zNwEi_tu5j3E#(y~!SmeU%`cx|nKxLILP^Bw@1D>vn?T5CVAU+8(Y1D+y|i)N?W?pH zQ}d+6Jh;+smj8wN)r+cuYlgu=1IB;@{dEn1=}hMi`ZA{rTuE*>n7U_Lax&vw*L8=I z)xE$Rttm0^bCZash;GK@0iKmK1b&A}#3>K*bR2>@Hu*E}hNWuw_1F0qNRe;zw3yEs z+`c{BA8lth8Nuz5P>7{_gW>S59l@>9-7USrjF8!@PWpx^ST>zTp&hNg z18iwxL@8x;MliZH(#7iC+XlLqlAJ2bGS7_(O}~>CiuSc^4R=J_69rwH+uPC_Vku^% zzk5|rv~O*wFUo8esaw|`3GHU7azHDMEzf9Zn34G{CY1^C^_Iso=GtD&Tfv$9F zq|8d_OlYz#rKwyKU^Bt&OF0NujSsbe+h$(#oo=|~QoAm>zPT;lpoan6@pDE%qt6>I zuY*1xBnu;boEvzNi*at^I43{Es~lgIVtO`=#}`cp7s)M|Ig2*S%{d2&ewgzr(HCcJ zAUZwwbEubIs%`y~2N0k>{sZBJ%zE*bj&JF9Y?-*K<5itPdtJBcfGcMax!5M`Jc*zw=Ed3`Ne#|L0Iac)^jLE&#uMllq zR0d=5*rM$~lfN$>B^q9`p6G=oBSaf&O8jHoGz~le!iArKNKzxk!ZD5`yg?l0cvK#* z`8P>FX!}UnPi&V)lb_YyL6fBV5k2M>-;zxeUBZFPuI?lsVK!%iBe$}Jh7Qz}?+$cW zrqEHhW(WgS5Qf)0Za|HyPc4=f1Xu{uQ+){0rAerBhTo)w3jNy0+Q znjxQD;V;V8YIqH1+ibb;p-->zfQbfXcZmQxY`s(DW4`jI0JG&sD=Hvc7B+U0f-)>4 z1!IkV;{2lV1$3j+Yn}zLltZcH5KeIjElnP}t<~wGj3v>w&u^Q(!;QMvECYvVMXjWLi}iymd%^v1 zQ$b3maAF#zkGw@NNL=pOm_7Y#omaBG=4F6%wa{_bcuvx!{u`ET0@gKvEG4n`u{R3F zHJGcc79&@w&c)n`bQLJ%7h)knm0Nl8_2XBJEM%A^&z#83%~Fe*n5m*w(UVgOQeKhg z(G8M$|3o`1m1`d>bgTilveepK4Egfm<^Y|MpEnmmfxOzBo>@S9n6gS~RaV_phC-`A zns@$?Bz}5lF45oJxean<*@m4oKD9w{E^fGcxym^m`el@IX4MkTxE@1hpq2oc*G%~; z$ybUjhy5mHI(Z7m<2C=mp-?$C^7uUWP0FyyF|9&*{_$FmQ0NjqgF^GkT=Da@7+p7d822}Bg&q5i=vAp{B~nopA=k%##t zpO?Ucg=%2Z>7$bD<&dfT`Pa$+Iqx%|lE(42p%I?*vJN-XM3fLJuE7*gUIRkqxs4&X zS zlJ~$6nfZ*9o%0iYd!omlr*`jkHf_4V7nW{mw;aaCGxtQ)i=|0qr+>?oj8hj_2qf|KGSPH2QXb# z^S-_u$dNzl>mZuaf3vzd`ZEnW1M3Ip@XMwg8EmD=dxN`ZCHOtMQVJ#;inT~C-k1?s zta^yo{3AfB!axSqW|&XGz%ZxUxMJ&|PHu_?s5JM)ZoQ+}#Ebx4tVIc@63vOKuc4MW zt#r9Db#$yMrCSh4xz~JQp7yR5OW7k71pcXR*|Yi-GiP-&lQLWdm2&0q45*B^4VS?J zmC6iEr%Wp5~PD!(0Rn{6fRCnssaZwY{f-3Ow}vbCiO3 z`N(OwMXCC;hL27vQB`bDl#OE>wv&d<__Ed|I!Np#4Lhu2>D`C9YFAvt&Ks7yCk?k@ zw>3ZBv`>T7!NmPAXy+^!12{lkVo&ql;zN1qG+5OrM${EblA~O#F>o{HK%5Vxm#Z&A)Jo8-zKC$d3!gHX1Kh@)m=RH>gyfR%r|6GN9^laV#0eitMmH+?% diff --git a/lib/emscripten/emtests/test_i16_emcc_intrinsic.wasm b/lib/emscripten/emtests/test_i16_emcc_intrinsic.wasm index da792700013d3cd1adcd066e1e6de850bd310e95..ddc191ccf09cb4c7e7260b3df866aa9c8c297285 100644 GIT binary patch delta 3692 zcmZuz4RBP|6@KTw_jWh?mh5BWW|M`GbF&MHAt8Z;9}SSaWJ$w-fC+#8E=gD*$>wi2 zzytytodmUL1uhJXI3jARQd_ah*y-3G9RDb(9cD^9b!vsSI96@ZI<{7AL(kn^Os2Xs zd+xpGo_p>+=Q}^|i!1D>SJ;8PJV+>;SRw(5O$z;KM$4fD3>_@5PAJMIEkQp>urW1P zjr8pBw6^ue23iJM+q+iph{U!;dv_{KZWuk=qtV9gJ?-I+jx=Y=B+hl7Jsb{4d)vD* zXJ{3V3@nSqR`q7iNX}rqy)_!0TV0t@RH=H(Waff2&o#lDU!7(d6ReC-7IC)sOx%|r zj&#S{V;y}1k)H6@$Ut~oq_r;`@7NVlGUG{}vwM*GX)7XM&53BNtOWlMB> ze4DaV4{wP@B8t}?jz)KMhuh*i$^4G0d5WcnyIVVYlpH&aQF54a1I;4c?R|qveQHK9 zDGho!-WKapLe9;DJq;u$piSkSUDClViMZHsoqx21xl#n#u_9#N)>C)CQWZ{;>M zP0#Z+H8nXueVx^m03-q)4gn7;ok35)W4Sx6zJ56i9*0Z-{iXYJk#+t#?LbY&ofJDFkmNz(5S~NGVr^U04BN}1-4c;`+K{zPZ;!b)a zlrV*mXXZ4nqAd-y4Q-}_0M^WW!crQcyN%;I)Jc5mzaCZw)?3)g7t>&N@*1q?Gf4gP zPA;BXalmflCYolxXjmC2^{aKP4*izW#HZmjtgey{L9|&~C!dKk<$GqKUmRGu z0Q};Om7S!Z3ad!LqFVyQx$~AY=s~;NI1OOR2gxMENpX%8=asA4?YhhjI`+t_l5P)b zZlelpQeK)qylI6rTC1}t^SZc7*pazu>k}MwB=}Nk>H-NI2kSs7L7ZMNqhx|v+{dB5oB(%NyP{5P?_mQvz3dF|8_Lq7YqsByvR8$bm z0{ITN@ofe^sXdS4NRvLZh8<$h$yRpRAugZv%Hgw)tR+a{{&7ojd4M;N`L0eL!jSazGF*nmW`H70k=T*PB-e>f$rYisPe4Gt zx3-X|ecfgVis-t2n!mG7a>m!~DVFY}g5F4%DyBt7FfDLPCf`#4v)xBeC?lJ9Q)fWh44h0dqIcE>w9XTN*wC>0n8V5y~jxAt=^3^pVzkt z%9CAvc|fd@{{F0L3X0iSYL<)feqSD~tV;ZV;Z*|7lzTVQls3y_K02^0b`MmDH)73& zQ5lzD=Mo6RY!cYRj6is1_gZKW|J@xV42p(sT3>EpZjgFxX*z~v+7rwaH8Sft zwGGNQa>61RhMd|5CC!<6>J>FHbuX6*`MyfmoYp2?b6TToUKpx@h2rl+`LHl)-%|w( zr5AJ2YnIdKu~Zs0Yxt}Z=cgzqEJTKf8J=R~?Zb?Rb^KDr)2cZm*}wM`5R%h}UnI+u z7l%*5T&e2!Dn61?GOWe;0+c?Ye6CcX=IQIZY{b>z#1qkyBSfV&UyzEmRL4|qSwOsL^EyEKEg zan1_94{)DEeiV3(j-z7!Xd?_JhelV~wGrw@;@1xrd1idKr)nAlJJaSS)BO|-8B~r@p-rJe zR~}R8$`ePh(1Xj}hDVm-y@WhH>SyWlaz%q0ia7DXV+-LXQFLN8rFrbc&w={T+>-?! z61`rw##AVik{52B0X5>ITQBN9g2gA!H5WR3GVt;+Pkhvz3qE0M*#`BZx24#A86Zy{ zy1M2MB~!0=nv12TYQ0VECVLVm%Wb^JpjZmOvVNX(sVvdFz%Un!YwPQ&x>1Ye`Lep@ zi(59#4%TuX`p_1Ww{p9VHf}dCUp~W+ehIE-mWf9GljMt1P0=iq6N5fMDBJHz_b5@e@jtb-nH-~x`M-}=gYKq+o&Mgu;FsNn zQjlE3%o{25Y*b`5xA@f)bMoKQfWnf=+(~^XBan>YMzlj$P!s0xsb zD1N%yPjOGhOQEk_CTGS&xj>%?4r4Sox$fCMdvg2Je}d%er)z;N_KI6ySRj`CXvzNo DcY#!x delta 3791 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 YfASrOzx?b9V6_=y{baRR{@l|414TPFuK)l5 delta 3540 zcmZuz3viUx6~5>G|G&H0f64zRA<43N-J8t=1LQ#hgjd-=$wp!zM#3mUaTDT(JeCc~ zZpb7?HX^|nR_s*>_`nBttknT$nObY@-~cm7#woRGJFTNgb+G8Pj-sQb13h;aCDXby zd;W9JJ@?#m&v(wb_qXThx98{{cP4>YJH$vkjm3~dO46l7!54O}3yWDblZrt}3OVWGI}pFIs?$UqNfWwCHGCYt=Wey|Gn^ z5jjptj03B!b>ds_-?V%gP({;JP=FAifPYm1ASzL*4ZpIxVoJqbE!9s3+2$0JN=OYe#30r0Ii0 z;nx00v@IBo5X*t))^-mDhe^5^Q7U6AvznT6-Puh|P0rmX>9W}XF|U(@*U3n4k<;t6 zj9zQ&faJV-i|S*9nzdOGpCEYc`7i(Dv~q3inqGNjR& zXpJR|CQMljO^Hl3QtI=tnMF>E82Y&|oN`FrQw~%%rzxAJ5MHlk^%VRUvWER`}qed`#`l~jr>EEeW>CVe^O1q zNb?Rm{QMKuBBnpS$NP5^ZAWW1*=IXtuyoVIUv#h+9hPe$B^KepPC1GaQ{Uvk^At}k zE-(EQCdK(>Zz6qpc{NPNKUv-dI9Rn}0_oc;Zb4e++llnBufjV?bzNh-fjiiDz*8hA zMQoC?owSMXqiml5>&x6piaWAm3kG=!b69FGFJ+~yL<%S4Mx8@Jdv5>DxLv=0r`qM@ zKN5JIIk=4xYgsQk4znrYluE6m0ec_16JnL1aQYR=*slPA**{V@%E63RM6vT_=d zm8K$Yz2TSk6mBxpoF!74y=6IykNQ}SMOJbT^Qb--=uBfdeY}X-q|e2ySZ-Uwa>UKe z3n525*xZW-s#!G}xZLbTN#Uxa%*pJAegwdj`=tMZ;W9Vl9GErUpVZ&5j%GGVJ zIbdN@ods}9jq^|Z%|4~TT*-SL&xb;>`0;n@-Hb4IFQ3I`%_T$z)pAEI_mJgmiuZ**lIuRF?ih*07;UzpDU4dR+fc_O&G}_A)V2{p$yyMCcm|kj~j~=Sm3=NOv*zW*x?hsxd}1rX)1=R2>HF7Z6wEEOdO>s(wWBKK$*1doUwoC9Uzse>~OkK7L9=f@gX zO(u>Xtc2O(;z94SGU+o17j_$Ba_PBLEyh6^FJ#52U&yiD5R*wp$ErlQ?xK(_9cX*% zKlb}Hs6{^h*4R#(cU*;eIN%kSNM~VMp_~P*l-!L$m?w5@tUx#I%+8CYo5kYwjW46P z|F&_YU);9HS1dj7GOu(N_tn{4j(xfUGY=E%!!qS-8cW>{W4O(C6!$rnZ0^ZEd<=WK z*c>M0lTj%LVDsxzwS;(X0QMD_ zIFF+Xl>HMkM2^^X$R^c~kqEyi)mc*gBC3mrBX>ci$cV0KyaH?o#h6(!Zgbgmb_HZn zUIum2{xG>s@gO)qC;mpZ902)fJ_8@b)Y_ZnwutKmk$huJQ zJc{`f*=4T>P-pnU}O-Q770bi=& z%%yu9VKiQMUyEIxplm`svZpW;nbu~$Q{JnnIYIdvjZMU-_Pk1=IzAy%fnPiS)k92S zm%@~kZxDQsV8$JNWDOqO{^&-;C-~?Z#OF7Uwjp)xZ9w@=d*`71&b{kU^4{JKO#9k> z51{_hMrDo47MYl=)vpB zYb8^PB*Ze4z+95dq>E|zx>dJpI1zuQCE$Q1g5L6g{bLoD$^<^Ne-SJb@9)16o5I`! zzX$M$&mPOei;$Z69PdU$H$ah@_`~@AWPjs$sc=;W-#V*{S8nN;b8~Tdmg=xdY{GXSg=y^IPbuJ#nhGmFl zp%4&1d%8Rey+@>}HGYgF-l`1noiZc-?$eJ^yNXS(k87g;P*(iGLps=gin?Bhc=EY| z3X^&)mua_RhVFGFo-`()b%m)ns6LZmZ&iIb0rIVbdg8)!H6B&IS5t@uCU#`JneWd6 kd_Oq!9a-_`U-}5*i+|B?kKcRP2edX*q#arK^Ou+W7hm);D*ylh diff --git a/lib/emscripten/emtests/test_i64.wasm b/lib/emscripten/emtests/test_i64.wasm index 4efffd068028120311e9e647a02aa3e82f1f1ca5..5a0ced60d5fc338623848a7c5cc104528685cf94 100644 GIT binary patch delta 3550 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 D3t>Sh delta 3608 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 aX^1+W>#;{~J>Un{mMTsks1)zKGWb91&qN{s diff --git a/lib/emscripten/emtests/test_i64_4.wasm b/lib/emscripten/emtests/test_i64_4.wasm index c87b72defd48c4e49826dbf4120200351d776657..4622fb24bb3fa29b6d855daf9efca58b57f683e6 100644 GIT binary patch delta 3647 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 diff --git a/lib/emscripten/emtests/test_i64_7z.wasm b/lib/emscripten/emtests/test_i64_7z.wasm index 6685749b201e22de0b7d8bac496cb9ba1f9600b4..60498708b68171325bc87564ce5c1c47c6738b3f 100644 GIT binary patch delta 3551 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 Gy#BxRBRmoS delta 3521 zcmZt|3vg7`^`86Q+uiKjWM2~UAt7*XHXleJi6j9O(0%zy3>3889=ViB!H7oG7_2M4uQ>ePGUeT|{-m~tm%HAJ_P8k@R$`d0KcHg_x?2==sux;8US zePed^he9>|oy~!^wiqY=GR}8AXCM#=bv1Wf{D!FBU|)4lPkk5D_WUvVIz8%=Vh{E< zH-&Oy>?-nbQTXIJX;2-4maXz&O`+-JxW4FEB@Q zVi}cJ1a>}rKQGmi6HXY6s371O#Kn}aOT?CI}Z*45j$ zBG}ind%!P`={pnr88#CJ8X^u;bKKH4N{WBT!Z@$_w@!G`rM!I6Mf$9$ zn=y5kr9~!;5P&-p@66F?neFyEXsNJ-am8tF;PYIZ<|dxz?P=_^eCR zc)(CZr6R7y(~-R?;G(bhXH6xQ^0BGA306;giJ*mR2zKBXP%T@;5LDm$jsU2RoX>Vb zTD5pn$2WC5TqEAn@hzQ9ysBH(lILu8Rf~6Zn_1P7?K$sQq&ryN(BXezf2pFec9|{2jr=SC_(AVoI1|;TXpeUMmi8JRm=@KbbPd$s*?3&?EBDW$W!CAM-I! zF~=UQbZMk6uI2`^)=)E|x46ZR#N9-fa3Hf6w3FX3oio9aTbV*b2Wsj(4s=+i&{4N0 zQ-;;S46k{}0Kdv)1tqfNvP70pRa{s1fHO{5Xjzlx7j?dZOwG^zm}#>`A_FsYzXwb- zFtbDCphLNwi@C~d9%jmG7teuAxovSfDJaEKQt;7YA90eGoIp1^z2I(0VPZ&THG2+hinhw7&kQ`6YPg_K56 znIZ}1HJ<`VR7CQRnE88sH&xK8rFs4|;lyN$2l<6yD0zd-EQ7)nO^f1fD{s!CvQ5P6?f6>B?oM(sdE77O5)7jXPu`tn5l5{uBnhM3+{TYG94MF zw~NU*c_w2jsCIgvo!)P|YeXhy#v+`q8YKdAQAXmPBV-B4zVNL$5JZdLqd)h@6R;m0{V>RYmd8C6;@2WT}uAA~gT-mhd zFyu*N?KFb9YuCdxxohnv!oP}grrfl3kxBw6rzpZ!1x1DHVPpns(cL4rfannD6mN(Xa2~aH0wDb~OyrG0xTQ|H6eAp!yxBUr9BH8U9 zaF`v5-*_J+Wr*hhpNmd{=K-Gwt4yBiya&olGIL5?3C2@I6-*zaGdjIm8Zvk)N6f-+493F>>--2qr zZvejm3govS$_yK53#bJtj|TdLL*?^xPLXwZ&6&~8m5=skdwdzD*ZeiWB$ecI{aKJD zzv*uy*g7yv-6jKR2KC0nHy83(OnLU^W+JW`8lauWhXAVbE>0S2p&F$2)6lL4fa(#A z&ZAjZs~PGwUk6B1wW6-nVSZVy40Fn1V0a}|$rHmll)}FZUzt#3s{7Py7R0>7?URe= zD?Ne=mwU|vl zs1RNqd7NSrxqb8)m`c?d4aZ4|^zWFIRF3QLl-42Ii2sy^ZNzTbfo>%h(XgG!J9kWi z^2m`L8YFFr-W6NytVLoF2WdcTkx$PJ#QE)kMv|W~c02JO8>=GD7i0MZ zvk#V$%&LRUgglIdT@FH5p|;PN^62Wu$tOL69$C6@+J;D@?ntu@dJ5VnJu>^o z&E?mK1WfRn$uVtu)WsZC-CpyW*v03d()+&$om_J`Ghrqj#6gWlg|9J?;lo9#b!LpB^qjchw&g5xHV^||Ek`==FKJj3=_PCM*1eXi)! z!~)W;p?;n2w-`-N-A@~!-Yg_1&)#2_q1zOMIA()IGna1I2UCIG0WS02)X2ey--bxR XFT0$P!Q+15ttk>7nIr%G$lCt_{2MWD diff --git a/lib/emscripten/emtests/test_i64_cmp2.wasm b/lib/emscripten/emtests/test_i64_cmp2.wasm index 80f8591b68afd9006c8fac4006b8f4174627ca7c..c15965948e9d4762afd027df279704cc13760320 100644 GIT binary patch delta 3637 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 diff --git a/lib/emscripten/emtests/test_i64_i16.wasm b/lib/emscripten/emtests/test_i64_i16.wasm index f2b5179685f15d4101f1b75a67b129067062df1c..7a627eb2fdf3476372621d6d11f7d5716a543f7d 100644 GIT binary patch delta 3634 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 delta 3611 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 Qb}B<`e7;63f8m+`0C_=2j{pDw delta 3531 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 diff --git a/lib/emscripten/emtests/test_i64_precise_needed.wasm b/lib/emscripten/emtests/test_i64_precise_needed.wasm index 74f4fd7604cb823614844c06eb7782f20438b7b8..255aa6efd9c6f17e4416788bb31e5273334ae03b 100644 GIT binary patch delta 3500 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 diff --git a/lib/emscripten/emtests/test_i64_precise_unneeded.wasm b/lib/emscripten/emtests/test_i64_precise_unneeded.wasm index 97db9c75e5aafce09b7f048a95d954f5b3da476e..70d8a469fe6050c3040865215cf50ee10de02294 100644 GIT binary patch delta 3536 zcmZuz4RBP|6@KTw_jWgVOZKrbn`A?hbF&MH`60o?fCM2ge~97F1knL?$(tS9aFiK@Ry)>q?4QO`N2|7Vs;#A>_T1fIG97nj z&%O8DbI-l!JAdy_m)VKSY+p_eB$Rb5k$}WHh5j_7WRK=2&d`z{DBJ8IE^#L?Ux)suGGSRZpABtWELUle`;iQY>SVH6fHnoXye6`*K6! z{&-icXK*MS4Q&Vyg*Jve21D_l`@)JQFY-;@?+^EjT`?OX=h}1@=Fd41CkN!U@a;uC(-Y#ZcYT6pbV@08}ZedPug@OhAAc zL{wu00-7W`EiGk|h+`}}(WFfLB!9dnNuN8%jQgQcZhSjBUk1-~GCv%PMF%A09YZ|> zQ6<+ITE9NBIlfW3Sr4s`g~Q5qo=_yRr9ade-%42YRNtV~>!JRRo~Yt=(iowmN+!+1 z{au5@O0$)mlGBt1JrwVZ^(l?%-NVsF5|oZ_a!)R3*_;`U4|Q}#dg2?CA=5tC(G^yv zi^tWf{+6u8i}SL5ix)3WfAc(>UjmQ_csT^TsPqQC0k7rhwFWoISs-({R*#CQ7ziFi zR{~y-;ZRTsdX4ntfDp_yJ_DAX$lOjk3_4tu)R8=CRhf#oO}kjO$d8PxXav2edW=6u z;etzEdBH{U<`j9;RO}W#0^qf6M^L5V?KF>rh7Ubl&$`HTJkR(=X5d9;DJ}dG!%Lzd zD-SN(^RvK3atrbc=&)E@u$Sn^1s91vU$}_R zN3#+w{9O&-)yUdkYi6T(DzMen$lup2#cZ^TgO^RxZQR)DEb&Sp3^SKM?ZT&Bmb;cI zmcjuqxX3oz`ga~Y#mF{sXu*eYSZu%fHKMmHtcJt($inqNi_434678wKgXqikV?;r@~IAVm@clNX6A4m<(qYn@t6+v(j5)o;k{39{h`yrO*G9Mak4c~ z>R0PoJ^C%>7M_QBTD=<#)Y0F^gXpldUOp3NmN13SLcjQ1Yc2RiaA_|osK#niaA;|O zI4>-H4!!8~7-s=Yd9MsPoDu~{QS-fJT~3{FNTXw4EGsGUqUJHG!6D@xs92-xS~)|e z)ms#YeOxtjg|&P}C55rIuarCl(g`G?c#IbTrpramW-^vSl24;ASOi<-vEvXTuMINIK(upUow9N)C zO4@@Iz02B*D~fm{+3oJ-P1qzMZpLOTHj5}=6v`n9mE@*ly5x$-+fVT#UO=9LUS3G* z3oSO(%MnpZapXyxEcb=`JNFI(a}RUj)SK zYo8_d=v|{k;qJNh0cjG&XLGWol^IyhRRb$iHR;__^?n(rN$2j%vKfgB*#dxM)+RukA|SZbEzJZp4Ri}TNb(5%8r{1osr zFlnDwA2IwpIaaRldYY!h&na>KxfI8g_~#@pPHlPsW{Y5~?XIr@cQC@tN^pnUVc^$b zk$b)Y{00cfuYuR-7SI-uQw>?f0^C6(USWi+V=@&js*Y(BY3VV_lRg(O#fscF`3;Zp z48V0Vrap@0L$Pqhdx*y36;yUl#dH2C-&akldHpc2h~YfxaMhw9-`k$+AKbLJ=pc zicDTgb3$vb7~kg0@$$c_r1h*eMeA9Ov}TOd<<;^}RQyD3P}=zjju0$xls~ND!n$>pe4(hhU$>Kh2<=?{Z!}}=dhsC-FztnaD?i8W1f-IWMZsiXFJ|tbg6L_6Y zI|s&EVA%fM*m9>fM%_x3?J3Hl$;wu~li^M((bU0sn~r04=bjfB%&}+e%>e2M*AO8j zq!HB2WsEZF?Rbfh5Uu;#$n@j;?k1;QrFpqnvA><@6Z@Np|Ka{J;$L^*PU7?*=%74! zuN6(iIVp;XUJx}T^OfkLdB?$S@_x@;6k2_+31MLXK<&E4(>ECSH8=Sepxd$vrJrBT?Gq7=^cRu z3pw=?4sQAwQ_ND?QBvhqF&FY8oJsOU94Lj%GC7e2f%5->RI?Pj?zrk-G?8_bRR8x0 zc;HlCdI|Ln2Ne*_Bd$L+JNE+(C>)v0ndBEK0y5L^qhj};dW;G4$t>~usTty?C%Z@EqSzVjGnI;m7qTdLIuQeQ*V(M&hJnm{KRF?PDfPx($&O0mFX oa%Ko0(6@%m*zL1_{M4Y+e)IHuUlt|9^M0cgg-q$ZJEAbF+Csf=M6&B8iwkFNlEE$)rwuGPRF)`A~TkZ4vyBgwpFZliuUEy$5ib=&)r4IwC>EF z|D1ErJ@?#mzI*OH^#S|i2kdA@ss@qG5YaZXNQ5||+Gb6=r@V40+Y^C3n~ezlAi{p5 zXXwH3j#Iz|fe+lrC{=aAe)UNJr=!r92GTn`1-C9i0P1BWp)Gy82h| z2o80J26k$?n#04Rp-|IkxGT`x8`sR5q4`GV3apRjj!Byu%TXR(YuDNJE$ddd z=@CuI2{Ada%3d%34UIS7PyxQ{K%|aSt?TSAYBts8{T_U*|iJB;RK# z5uY>A-5nYo?$PF%f$pJTP)qd&LZKbo0-eJ{;N=^LWWYO{$8 zZtEHx)9Pa!rBrJ$1H+v|{aT}Y%UHOc>{MBrJl6ygm!|}WM>;w~y~91Rg09US?C1(= zNqlHD+%_;gvNkv}tl2Jdx2|U>xKm4(V|saHMOt(7oQ(A5=4SV$bF5}AK*aAB;CG|e zm+$twZEv4FxLt96-fGmMX6YQk%T3Mi_Hu`YTE3gRV;_Wk&XYC2$JUyZWxj_rvpD}0 zm^+fPm)vslR~~a4b7q%YpvyGld`Ybjnb48vyHWS@KZW5{mkQ%m7frBcOt36H%FPgf zJ9@h#U#HJQ30?<%p79EE!89}R923)w<20in#CeA28HIAzCF<}cmuT{Usf2nZEXV2S zmD%8;*^r$>E+yvNP4slmd7`^>+ljuN`xP|GH>li=KWG&IjnUP4PDpPQ?;7~7VMm(8 zdj`H|&=PMNR-@eJ-|1=;e>QB*YK;EP|A9rmFI09q=ekwOxaAX1yYOk3?ODt;TN8k< zx@gBV^hFjt$!N#2z2*{3$@&|9MReA(3Yd!8%esMtCvTi2T3UMx(F3&;M7dq&pJJSw zcqa%KehDH$aY}_#3@2E#IKl9Q+-U!ctlR2*hCWuG zsKz>xL+N1X}6Ld(jO!4`jUmR`$hG0WCg2p{^4S`TnEF{@wXqr*1(L;)74 zcnUE~{-k9wWXX?O`p7{AR*-}Cm44FfUHLq^(dp%<0W1|zG6jS)P=uB)*R1Mtx+r4_ zH0|fB=5jY0US0tXRfK=8N?YkuyNho&A_z59tr+e-pz0*RzEDgRjSCDlFMkmrNsXj@ z$6`0P4icDNZY@ko7fwu}bWwB&rdq6aW7h0%oxYXjSgM~MUFM#R!#~wltO`Aw;`XR9otX@h4Rr2sp*9@M^km9Y^mJ4DZ52hp?qz_ zV`MSdo=fy-`xeNRpSN!(e(SADbMV$XR=8D5= z!{SpQP?cjDeggO@STs)3#|-~LfKd|8BQ|b+MjIBNDRYdQe@5o=@5B3`Tn>z^$-M%& zpHa^2h;Vou9It@wZWfmTF9Rj=io7^7hmN&XPSyrw52*M-t^5+-o zAL@~$y+T#{Bb{8HHfFdyZIH`1$E%@AdiP~QRdn9I3P@5}OT$!3nuf`?Zk5Vy`_sLP z@IEF2CVs8sY2CU$D)&DHRJmmnKc&4zznFLm7O088)$t@vK_gzCo>)B?Zp9v|#wI+g z_lsUKdr`+;a{R^t%vH0ZI`+jUsUn4AHBytp)}p9&P>1AQv3|bG&R!wLaEy-sE?IEs z>m>&O55xd=5b$8EMH~V=1Pb}pVyVaAG>oM!ViIstRq+6bY7-C0TMjqDuIR&uTb;%v z!%6wc(Y#b*+FHbfy7I_!l8H4YPDYFF`5A+X==(Ae#I?j+-Q6@bB!ZiI9?(;P&}1E3 zLpkX>wvmeT67i*S_VKkudyY4d{+Z(?r2pOV^`u#NqJtoP--#on$EgO=1gDCK-ZfQ8 zHZMukGyOB&P_LpL`?MZl(;t|7Gb`6A$a+XF*FMY;q`x>ZJhcsnINd=!v&wZM`))s zms#^^cMfWDbcS>dkLxL_d0*gX1=u?RUwqewbTkF`wQqj8f_Ytbu=Hbw)nu*gm} zJyGd1Y)V#wW`jk2nyy}%2AVzY;z!b=#*g2J=&>gToY4=Ttp!$?RwMoSO|K=7$6m0SUss{2>w$6GW=$62byWHk+^; zz(8OF2CP3*4Ht!CwLqV9(tRP1?FM zd+xpGo_p@S-*@gg@0AbOz7N<#d3lgf*0Mwb5^ELuQ;&wj2^b!$u1_e+S}j38NU(9$ ztA?XnJ)P_NV}l)oon5^*Z4JjZMEbWWOimclEs;p;mS|U~yF0DPnxeU)bB02pNPk!F z#2OmK!-Flc*z*2~HBvJa@9K<1X4lsy6ji#;nyQ?W*10Ej*Vd<1#-wV(D1$UxqLcgO zhr)gFu2}cLU^p7u7#<953U>~K;@#WBiY7PmPMz-y_lbKU%kP`2jD@9jYMlaOj}`)m z{jgFvSz~9ze9)M#0s}<>4HSn%RaH6}Xf$vFbAc-(GgC2Ccb1}&MK*vcO;wX@*I5Y& zFoT3@3`0PZLZ_jvObYQB^Cg;h-`^(Qm)rS8)D(Ga+Mj1M7H*Y*2T9G7TtB%C_z2c*V!FaJWgsOv{cEV zUbwGoU`T1PQ(YoWY1BjUb+KNhDRcc$w22HQ@y+hZ0S#Mn!tue*b&>A)rc}su40Lvd zm1*LrTAOIiUA(x!=Uu#bapv=9*!*&UM8Lx#;6bIQ)D!U7W{*9vS@r@s%e5dXmSP~7 zhOPuWrr}UfDfJkcsRp4m$9Nso?1Z|@F-%@eT3(y-l3Hum%C)AQ*Tb`@v3j`M7F}AR zd66G=uAy1#LCw_d-xgw)^rnq1F4$8SHpKTJJHJD)9^iwfO%cBn#6Yl+gwfjBh6N< zrlhm<1B-lrR=>_!?va=oRz82)g-^R|_Z&u7;(%vebZMIUM*$pXbT_eO!6$G~+-OA$wAV2N{mCCHxS> zL*g#`Z)Dxu=qG3U8eJ+49&A}fgFm;7YPlZ%Eoh3wjot=7SJ8p0JgNg7mWwFTtURux zJhN^ZkLnPVbTs}y&EmBipK?05g_e~kMwSLD{A!Q|(Qhj^@B%E*f^INSM}IFbMTf2R z@EJIxoGE-J`o*hD=YU^mZ9U|m4(rIlmbL(CzTfr&deCVaCjl(EuZ&Kd5(Q`}qHkH3 zQzslUXxSf@m6ynfGU~t~?H#DtBWss(hD;0E6tcZswekgDKD~w_-ab-641pwpEGXPw z0+=QTIp4BPWcdI%#XHMqdcE9(VsUNNBrs3jO4@4~JYZT|E5Q{S~>4Q648p zDk=!pbP1zr+{eHtz2{LFXc8QI#3g=yq%;4#i&MO6+-d9FM@;%`y_Jr8-X-dfZsWx~ z8?#L#2UNLOOL;_jBhzSyOwx(B+Ghb5u8vZQ-s+CB>Jr{W_jdR2W^9%aw_ppFStS%O zihP0umDFZprqqhv9mjYHFCwO(hZmFkVw(;2a72_=9C^yBdF6Tth^JO=h7wV5OEJlY zTXvR7geg_FO8BfGU6*MIRCH90^p#%&$dxB-x@kNybAl3U20a3>e?hy^CFC9wCDkfQ zFEP{iWY$bhe3^zj%@5db6quBTbP0k^7g^Dha+A44da+?Mc~MQ{vz1MMyJwwGoA5HQMweX?>G$k$uI7pxUCXTgqA{C@?z*Spyut) zuK=pWn_Y2|ZR=}EwR8Qez%F`4+lJr4tYpc?PZ`uEvwEHYPdo(975UGYtVgc@;7QbYK ztYh*i+LRqLCZ45fRHZl371mL_^hk3Lx8CgBb3V%<@Uj~Yo_#0tU0%e2|e;;jM35{a@ zj#8p8wBx$+Dg(WxRQxK^@h8&?MF>Tl%qsHn(laNt=8980ym=n}7nQu8)TVensgc*u zcQh2t;TKfApf)NUd>Drb7C6lB(eNJ4nv-lEu7kM}aWCc);0k(dm0Hank-(pzH%7oS zJizb-BW4aT9@6nE6;G;GVe*-sCxGJMJBgpt<&)D!PQYyG>P;07PdJfeZ%VPta3gLa z4|n2ewU>93*-I*RTUFx1ZY-9ok}CF0?i`)icq2xwx@6@ZsF9oB$qlXmh!y} z_fm?c3dY-Y98ESp@FIiR$*;ec4O9`XAVNsUOHeVFG0Ld6<2WH9Dj#a6tM7W~4kGPs z>Q{-Hu?~`Vk2RD2>{un~FO97x&9eQS^bVfge?RFPL^EkdL>bBBqMmHt5na@`53DB^ zdildD*6~MFr1lYl>7Yzgb$F1_G_G)Rh;+8(gidlurIWmU0E<1i#56pz1ni;!qqF`p zotr+?pg{(1+2eCzo(MgD6Qzh}AO96VzK9+v^pNS5oHwpQm9)&dxd`Tqs+-@?eYCev z=9U%C2mb8o2K?nV2h{Q%be!{@}!r_6@M(Bb|s5`SYfI5 z1*&`5Q#2W-@iBukGTy)Hn#}8EY2by1)gTtEYNSj_HJ#_nOqnn4TUA-Qko(Ywj+i_J zck1ZiP6PAhvHa+lDO0m5#apXtVS&iJHLzeIr&7YfP2XaQRUr#XI=d>?LSBM1$i9RF zy&$Vnc4R)F=f68$D@FIMU;7tLJUV()|MLYX&L1tvET_8Rpai0sBIDSs{Es!DaAfk$ zq&{8|kXeQwmE^Kxk1}!biCpo_vFRfJ$NzNPMwS7G@IF~wP4y?sZ@Vq}zB3IglU%B( zwQ0dX`fG?Pn&qZr6X;|k)<0SAr}s`-O0mIWvS%Fj0)1<^jQ!r^{^JAAlt|9^M0cgg-qNV3_GownLmr(mblR(kF(3U%C> zJ^#Juo_p@O=lkxtchBeS)aUGgFI$87dWdW5Sv*cHlG=Jrd#tKvF54c5?dy#={UFYM ztNZkD-{uM7zDVof#_-Z`Z~x#{jVWFF#&B#^f2=j~y;AOjg7wLv%+|L4!Pv@JYkSYK z&Edh0NdFd1S95sZP$aTwsINWL)s@mrxJmQ9&KU}YBK_?>*XK|#8jb}A2b=pf{jm?S zmKe#9lzMBly)_bO41eGiy>RenWNLD2+5jeJTI48H9WZmKQ3Iu9d6o1x>4# zE!X3k>Zc|9p`~_<{1*i8npX!*H%$X{&@^B`e?te*49#E;`f5%WxYFEi;D%>Hdb-A# zVHgf&Yj{C(v}eR2z&HtA34_PwBg~h!9Rdzc!YTK&Y}^hDwd+5=0~V;}4`1h}kRd-~ zS#iHJ)X@(CVq3#`7;b^S2Ez%Y3Oai*HXrQ${ ztYz@Qp}yt)(b&pxEUMWqa<{5;FuX;}lw0+x_~M+##!0^1#>PhXnbWLp3P3#I77%cw z)?MrlxNUE@J+Mi&0=(I%N6peXf|r|G!0qJ@4Ygu7cPBpx#hhnq0gtUMQkKOY(oEp| zL(tRX`cB7oa_l9KRY}K5ceY+->C$KHUs&%)QyAzicBA1n?GFlYg7tqouGyNG|Dg}g zxKxB^T;$2R$&+R2i7$-^fIHFRDAwt-BhBle&!b*pP9J9`o@Qd4aU5q9pE%3#ETbsj zb%_Ri$0Zhdz*LCoY|RQLejWJSBG+RzZO$of zl}v8=#mg>y*=2iXG1{j9JmaEF(9l2g;TMcHEa%q!8AfGb-g_kfHm@2+6JmY`P-pM$ zyGf?k-$SyaeuU(g^_789#<_`)fN zbyfxMrp`;j5hLyvKapaNF5y7UuIr{4VG7d(LuTa*9UZ8v*d6GwI00!`dBQ}s3De7; zGNE39*6<_r34D$XHg=0T`dHnf78^t%xu4W6$-&$^1Eg7Z=j-T3rn9eQ-aJ5LI^JBGkt>{-Md_mG5KOfguFaqLgVT@lz5EA{mAs8hCbQ+bWxE{9f4fT zHR_3MgeR@7nBos&Bl9oEOyhXpn{+bSq(%V zX2el5QBQKm%QL=D=B0AWVgHpfntqeUUo$Kq$6rrD6bu>f+@1kTLaT&bN_y*mgoCxVXE{GyaKc2nSoKVY2DO9?O$%10~LwOn|wej zPju7rnZ(MeSZ-C|9D8`!h>FWVq^iP7{2K5wSTs((FBtxv2%~y<3pG>bC$*@!qRcU6 zeud2C`_WxcC6~ok6kP*+fKkruxNvwJ9It`xZWP}Eeg~AuYw~1l5*=@cmrqNbxc|l` zdjfv$<*xxuRA^2eDu4pnIMhWlF?6fC4~BA0Is;d?O=ah}EWN*-IuG5ynMPncT@wIHp^-C87_!2n1c>$Q!h|#3v&!!gMw9cRC)S zDQKkd=}ZE`a3gjS9P991y+?GB*;_hxk>eA4ut?2H=-8c_q)_Thf}|$(Su+z~@6jQ1 zTe6^UvkMlBt+qz&%NZJqY+KfZ!;vfzoe1k$rltRRrCJh77G;wKl9{?R9=lK#ynTS$|6 zsFgS!JM=JA9~@msir{D&$==Z#GC4llPHo5G4P?@Dc#@w`rWI9cM)m8tp%q7UTJhP# zc$*s=y*!h#IP4^tDW+dhk)*?(tyBtmnuK7@O%d!$2EA2{ohA(=&Nqi#FjvmM=V9k1 z18NnGFCLx^b<%fa8P$N!BX0xvW!ce!O7d$J3QgTnUeFamf9OAyDrbT&3SlUm?2BAp zzNa>}}by?sk!m>0X|d@@6DMELKkhFTXv>X5k>d z{^;4psUVXHf_guk^Q()5wn}rEHI26CpejdaNY_A~eYPTp_C!=+Ds{>CC<56{NMsy; ziWL}C`FiNtK~EFg6&oaJC8aMmC>)9Rp6B4Wk7fs4^3$IeRa(q%dn~6N_ws-%d7)cC z>*;7LG3qUPhSA1oAQ=|f$Q6U?<~h!|dN4i8O8R?+kT!r#RE5aK7d_L!nS)ptJY#8KPq0 zp%u~Snt{t_6lXZr*&d0^tEq}JO{tzXm06qOd9LuTs!6fTE3C^xX~fyyf91a1P`EGF z8SNe%3ipS;7aj_24Yv=5V%@vLOjj3WPu=ee_sKh9TEIV*84WAxA~dq4thQcWi4iW!eVYJHu?cJg!ys zHDxt7=lQdno15KVKF1f80mOqo0YM+Ko?>6nXM20>!EFi)W~|Zcky*?{@R|k-`n;xt zAuINo?&N|{oM9dVo)&lQB^@q0j7c5IlQvpRUZ;l_)dkQa+~{uLqryZ}csyX5=qmQv z%xk{c4==dX3tmvittrPXizP1T5ddFelcQLp<<>N>gO(#+Vaz+r4Sb%9v)sh9+-6PU z9LIB<-utXeG~hEX(c}R`5sivy#it|Cv97R7zvUL4rS=ahBlb!i@x0PO~earC_9^pV{FX^F&Lm6j+ zBew!VLkDWgAO|`um(WqSa)hB`iH6s_*MNEz$_9#L)s#q9Q6d~&`BSGuSZG-}a%D@f zJfPL{dJNd?8j**2dOhU?8W`vm#pqCPo{2NnwIvvk6D_q6kT16Mkb-KgCIxk?g2d@u z^*H*_=`~LSSn6Jtz28p21*smc zu6%!WekE0eeW;w`2r5)0L8J}+pgfCn>hq*XLxy1GD>r)0?{n}g?KzYzx^j*^>XKvkx93i}1m(Ie zoVFqS6mP$6G|_V>UGmcXJ4K;L$8@im0h&6jCpDt7$ZNKOn|Shp*0~_$pIeJ5$3JT= zg(6wlmgO&^G-6b5$~DT-RG(OC70H&i6D09rTOq;p^;;k)W9zpO{?2;EF|NO*RQZh> zWRr4=RZm86J&w#k%}g2cM}RDK@3gh&R+e0Lv^7)Zk^NifQBPC%Dcdz`M(T(+^?GiV z2#SK&^rXBF_RD!*YCeWi_xhT=f@gJ@qs*+N2u#A144VW>u~#>SVU}EaQ>CYzV&D`( zgIpPuyKZ`n*yT5m68zcC3+jXF?UY_CsFImA+r$c?nOI37)4b*z<=RCaPv4u2&*z-( zIg@IOsg`zzx}hxEbQE$EPi>;KtC0Pn7AQ^pCiFhgamMUU3Z#fVA zLblBAdIjbtKInRnLsjC{?gzn_E1m;Vbt&k%$iD0I?1XZd+GPUY(8QRs}A!M@RLT z_!ub4Ral7^06zwc_KA9rOnjomF(v*9iOW^n_Q72F; z@|hhM4v)jcOJKXN6<+~<1?0#}vM!o0eCW7RGB)+Pw9Dn=H7in4?1~nZUmY;L=A!_a zDwLVXQt6;oFs8WzbYaw`|8#1u4KsE!_=uf46sr|%W2X8)~`%G3H3m8W%5`KvvP^J>Kh8h)TP zur@J*Bjgk~D(=wn4&ACvq>og?0_E>)%p!L)^w}D%x;?7geu_$o+|F^F<0(#Y8RsHo z;1?R6)~tfWu3Jt4WkE3h1X-SVEq)42rRuL59wjC6(7sGxHGUVL)p|uY@t@SNo7hk6 zL$?x3XxKyKcscQp9G*@5rw`vq9RHDak{>>D zfcS=7PMnpplwefWkjz7}lW=o<3&{+Q=M#SScn;ww$Fb0d*LqE#>ayyygnauHwHqq# zw{=)dSt0*(Yym8kv+i3K<$j?rpQ(8ELX1IFdLT1(G8j2T=kFu z22>-{t=aN{4OOs2zPus0WSKxj0UpX7$m#hTgpj`jfmw`NWJkMQ5)#0Fqse9#1$LHq0s{i1v7vw z;XiRN&r+S=H54UiC1K7`R5;|W6Z!J32S0Ocq_aVXocu}Q92yAI0=CDZk1elhx#??Hk#kSh1gMKqlVLVkTw&%!Hqc0SnFq5IH$Ob+OpKiT2PDov SS_gbdmb~tCtz7lt|9xcdlKqpg$+98j+-w3dUU2AL`uD~^vk)tTa>Q|oKA(>f}S_S{XBjP1_s zx#ygF?z!jx&bjB_m)>Ou-(z?Ayc#5$A)z(1M1nY?TC=9zT~@J_4J2To*+|e266`O! zPY-wPo)+$kgrYmbYr{LcqkS4vy7V34cw=`w6!~5$4?tdXYAQ3dy*nD;6c4p@uHPMw zwnn=5Xu4X%yLuy$RlQv;!S?nE&9o_+?{$t~Fc|4>>6~0cQY;*=i$>RVYx>==%8u9fc}OKpc$IM>@;c)CpgnwF5rfHT6((1m|+-p zWovjqv$tdeHHUI%TC*qKYm=_12R-63seXvroKa7sQLWX>YWhMNM zU~6lnH`blYI48YtAI3wdE&g-WsP)!mPS$Na(E_GQ1P${|G&qz9xHFuF%nrx(d~fc9RPO4ReODDg4pq z;rH2~TESmK=$B1Fzs%HSaLpr*G-0A?&XAslKuNA%&8jii(pC#U`i*MJBib;xQxu}z zGCD*N78Ns1%*I@KUBhC?m9n9O9F$`@IWVpckf!+R-=Yg09)1$QRQqQBPu1x1o2y$K zPQoFLmbI=eE^wjY;pJdg_IA{)!R7|RkQvn$m1d{VO}{+3cIJGlZ0mdpWe8Lf$b!o2 zS%3^BWc{CQF0S20#SmFHJ0nLpFpKb@xDae)FF(94ce;DR4_L3|diZ$&ubO!M+VQ-! z$qg=TWl{Do0Qi)}C&%7$jO#E@@p%6%D3De6zh?8HhCb;#mhbebYR$nMS#>NMeDa!O zZLm`Q@z@;uMsTS$FE^D!k^Hu)kb(JWY#9Rt7YKR&mxM12|Bqr!(i z;jp1yI5_&%?lW*k9W@TaMET3@Kxx8)L ze2UtE4pF3{E|O=qJxS``>j#N`aeZZVk%}OI0TnFm%WGE}A`d~PUpx=^JgAJH1w0F8g?w}8aabgO+Eojc@>JJW zSRj4fhoD?O+`SCu%J;h;hsE-qU1MZ3x2K8tp`ImBnmpCx15&*a?MYiiMK~8r%u=}_ zmg6JID#H&MeoEzGs=3RErO8ArhZc;+Zh|s7Bfc^JJHVS6;bA3&-EHUi9aye<@h#xD zKp=f5Z;#L9F0_02yotl}r+7h0z|TGW34rM;A=6P)-=U*EPt(*LVEN*fuUELyZRW|W z-gd~7`+6@|J-au@Ms_yOF3p2(tTHwiayn0s01ij z)nEkOGnzU-<}$f{Fx%%6|J2FrNn?uFlLmR+H@GZ!iTGH@kM$aDlNi7O!Um3tTMfL` zFqb4>9V~}R1#&ie%~BdOEuBWg8a%DV#0ff_79zvL3{Nmh#$hIcHoU0gN!`36x#H#% zK#Bg~mfsO9$p?l`zyjs!O&yO;IvF%#qAitBhC8s0JY0`w^iI)EX3y%_PHEk{AM@3! zq>dezcJ7+ocn5Zwi;~am*CDe%)#v-Iyw#!)`>0#=%a?DxXzT~vFaLboEH5#o4PqE@ zSml2|h-EgKfdi|cKe_tAI)^dLa9AF_tH4Xlh6XXD?lH0)W@4iahm)_|^)!R>G^!IYe2~ckyiuIJL6c6_*mFf!05tvIS3i00=^vpDF zw9!QJ;dMbLES1j92OaMlu#DTq zSB3n8eEUT26Lg6PL#4^Oz~!mUA$Hm=vB|53%BDSwszf@bdwABwY9kd=p*kuaUNu?e zRK!1iFLXbcn?8>Mw^OsDQ>1Gk4?kF%P0>;fFjc6jM9jy*H)fputdUz^?ENubYV9MWUmzh9=3L9-TA+>K#LN^0Qx6_zm@bOw%kdsgu)PJem#kHgNJo*~#BL{thIo Ye% diff --git a/lib/emscripten/emtests/test_i64_varargs.wasm b/lib/emscripten/emtests/test_i64_varargs.wasm index 2b1bf9567cd7e55a64f905982b899a394f2e9503..5a937850a667de193ee87e2e558fc128c584ef1a 100644 GIT binary patch delta 3644 zcmZuz4{(&l72mht_uXCc9l0-u$t4#;-sTb#10exIf(A{#QS940l#F^a z_jdPvZ{OQ}zxQWfxyZlzE8kOukYa0jDg~*vjQ%uZYxPuWBn2aD`EUw`AD!Kh$1*%6 z#LsAjkDe?_aV;F%V#YQ{qaB-Ly`e~iWjGVYalYX>L!nT#zjtF+!lYFqoSYYrFYdp# zM{$M{z1`91jD~uqDa{kc^BS`}_jTUvc@0@!Mq768HK`nu+8n!XuQ(Lml<18|29n`e zXni;t+7Rv@2qhxh!c3RjLCo=u7l?<|my8Spbr4^7Pk%hQB-Y*?i}fex$NRS~3UBI< z4>6Djp-XyrThH8P(7EBzfCFQo19LhxO{4RHP74?C9LUKvP3G1n7o7__w6bs}Hqf}C$(YEZmOFP`A$c4%kx`*w7m1W!I)Jsgk6`jxx8 zlac-y^E*T9)w|PN1-t?RUSxe0-hkKk^w|T0Y8IHdSZ_sU zF%!XK8Z6-Tm=1=l!fWPc284=CdWleICA`4i4dQck6M5~;4w951W6-eU4!#;Y^E z0ue>Pz+!tsBWIX{CYE8b{)-LhEP?~DR?)4N?28V%2x9tRDt<_lxSX>Q;fT%6`6p5`{|5N9}^;pC}PF42Z3 zU82JchFY|%#e6)S&hvqbc3WkWNu{jAM~MC!PZPagtRnic_#Xu2`SM{19$6g#2&UIm zIKdYbAL{s_Zl^lLIUUdGWa78F6_mr3TU|l%v2HUfn7&f^7mIYCYwU4WdlgQmx7P*sbJH~NK@cvy3?fI(6btur9Obu(0~`;?X#2lOIu!JivTZ?^MvHsqFQ>)( z^GEfRSNwpFO>_wdGJ9?xoe`=z6CAl!A~bZMrq1p_hvgDF>Q=EZP+h|Cm`@ncs!(hD zen^RA0TwPMQ(64Tny=+QQ)DT*kWOIYUNq~K*h7ipz zI8sWy0+6r1O#A_3YnKjyQ@*owN}*3UaU!{kPWM^9W~THJV>sYV-?%^If>L?k(+|`X za85mi6lus1tWtFjk9j`_pVD4LVWTS-**jeFr-!@wd6&#TQlN(FBU>r8@-WY1P6SN} z>lqC~f#)%oK`!y++g;P4Tz=VALD4PlsPY9U8JO+v6G03r$IiofSY-ud=#Byi$jx^g zCR((-jOd)@cS41HYWX0|Ju4KaZpHR0F9iyf;tn#xESnC^^%OD#H8Xqgvj7FkZqtv> zQX4W(lrwPr(I>L!8oU76P!&7-98Bi{Bvh%%CDi?+hfUsaz}GVg_Xgk_ zU{%VOHa!guaz!i%jq=IZDyWyA#~y*1a(90-%#x@2pNH9UaNq#RyT&F5xSpm0gdYa{MQOW~pyC(v&`~N%&~Pmc&k|lV2p3m0bnA zo0C86lyJBmCSC>Q`L6-L26EC>8A(nOUUXc~0h=mZ&b55-nA0-2$vw$(_sxFOWBv@_ z1{DUcB}<`N{wWzD+OfHo>SJ=V&!AX*aNAUV!Y^Om)=P`hySC7my>|gP?=xTyZA`CS zHOfnWM^##ZT}UA8;N!sF!3pd?40l1hoW8w+FzDQV)ACvq3oEFd)MR5w6*PjGqK0lo z6^&v_MXohRg`uFHK}quBOznb}${!Ib0sp3vndAC6Gskr@^U?NZXp)mhilHezXJi&M zDK8dcfmKVR*Vbs%?HwmrLL8%#fxA$@pGVqFq$2Dtm`f%zP5R!{_{*rE< zHts$KGnA^|Yk2UQk{x=g|ogxmRhuuSbrYuI<)a_pMn z^%%1n(q*I6DTgwJb;vGVAhzK)O41?OFm|PB3~($HaJvC_XA=2dzZ8S# zn+iFC^59v&>OGX2NEzv%;;Vb)S4XB7U(|uZm8+b}JbMvH#`Ggg+s{0~OX-DT zyOMFDR)!WON6TtavnKd$w?&UPk7?zSB@Ok3dTSv2 zvZ2Ohx#^BnB1lHAJlf!=q@c>iY_PbRnNJl0qwZ_&D@^Y?HsDM@d-Ttc{``d&;0p`n M&Yw5RSbEX_0X$Jp8UO$Q delta 3728 zcmZt}3vg7`^`86Q+uiJ2@?HY@uuGD2vkAcjNPrkXK=P8X{2>F>51%eeSjdljb`vr% zAscAG51moDMFLnTh~LqQuI;oVIymZ#!nDKqX&pNwSZPtKowi`7NR^(u3nlHCnVfge zx#yn$Irr|jf99`T;t%H+Fi5P21Y6G&30e_k>-9upAOQpG8GB?#^&PxF0sV@m82InC zd@b6sbyT#YJrdg-T^ile8QaFVqGfK5_N?mciL~D&%159ek=n|RZ0L;jtn7(2wJqNo zjcsc0>|>fbV|Mhmw}*N=n!+tDY09V(l$$hnI2>;8Y-+o4hOl_FXI?C}tnw4yb4JXWsm}KZ2|*awi&# zb#$r_MtWL0J6OOS-n6N`H{Q(3jqs*eG|FXn8Qsc!5&j5)nC3&aQa#PZr(;CT>LSG4v?A7-Y1f$mH#R|)C&J|$LP7%r! z!DMyJGN0i*kZ>zm<49Ij%EYv&DiZXvaSBGuZdcyjqlG{rf+hwa#^Hris04@?t%A{)n*crn{D|JVU{49ySBf4YID}^iE*Gl_J}bU~kbI)JA3~282LVFKV2K;@LgHf`Kh~W@NSxR4yiO|K z)9sLSO8Yz^@h9D3b|`te^i!K;pQzd3p5RsaGVOqP&V$c+9A6D*4ikWHd&pzj`ey*1 z=H#)QeCKB{Ec52RL-3Qi(_lE6Q@aTW>34P$fj%ON} z9$4~>J42O#?Uyr`2Fn9lEw9CZ!xjiX`t@3>3p6m$CQ8tyY%ax8rFJ|9Y-7=?v zOYtiY2iGrFzUj3NHC3C??121e`M65zN#{a2h=ZEp6@V;-jQ$=qrHx%wLXS3% zugw>398K{cyATY;Z;+bCR3IJiLZ!@sZi=L4nZC4iaNZAC<~e{IVwcy~oh`_?q4t&m z4pq(tfPBS~_p?8^&uTDHtrs0BgrICW@_v0jGR$ukV{z<6##B(9{2nL2*YSo#00Zd= z=c`W1!#w4#a-VEf^<;@+pKf5j96Z_#4f6A&Wv&(ARpPI%o($vVgf%7P-O@E>lgg-{ znB!{|4cMUaGY{usnO#OQ7&Whov!Z$_FGQ8c)*KgQqL56X_Aes)iX7h4DiBd|2^1-= zjcYdo%6HawLz$elu8828bvqWQ^w2F4Qn9z|DPCMpATv-)m7Qf~-HhGEa@*y6Nx8}# zLGfAUB@SiE1^=1Cx<*`z>kjq z+x>t6GiaUsc3_AXyrIJ+LPRAM(ghe%uor+Tc1bu2ljTd{N;1=pZc(btER|n{UnKI; z^@9X4GQGA`SrEjaGM4n3I8o45QAw3Yg>}AM`*2cVzST;-(afA0Zx4IGFZfBzX3kzk$YP|fGNpH+ZPSv2AlQ?`-0)sQ)Km2|M<8O>0`%X1som12xG#OM|XylJ(&sD?K zGJgk-IGsTx0eyP>5m7*W}DK2nG+^6Gxx;-=b z?XGE%r9z&IITUe**^XvcN@pm~s==Rd5jOCeh9@=qj^yT{XMwVwz2}z{f#jJz&%zXS z@Iws`(Gk?sxou7*ljCM=rd0kA-_Y7b3$eYTVG9X<;(jbrr;-}BrVptMccc=m4t3Zy z$&2@Eki9*1p=@^w7Km-Qjb_DmdG`X0bN@?Q@Y=FnpDVzC==x61S$5VH*0sn{EW z?aA2QWo~^p$KCSHeZ@JnXk09Y)U`^SySZ3l;O^wLeZS^Vo&3fAOc1yHzv0AL8d6k} z>Ip*65vsV0kFFrsryp2H`PqM91?A_n11ky69&RA|&fyB8KRu(NiB%bi$akTC~oKNfhhjFGC7g}aE=k%k7@<|rFn!Z(X z6iKC6RT9{<(v@^2iyq+mfI%C{cN@bVm?fv)yVreDhgqtC-#YY5t zpa-gR+9xBc`);olnV4yrqtnv#l!>LP_APU6`o45gVgBDkP#%0dkU5DQaZwvmTWAdA zYmZOPCF?2E+!;L0QmmUx36`P-+8DsAp} ze74(3SZ2_ZdePWG(lyi<>9sba(W=+d2B@bF@k#&F)qdTfAY?EHY#PXPG5<6d==tC= g_va=*eBl#FwmjYGPX6k}THp(Er1MgZtV%BZ4-24M2LJ#7 diff --git a/lib/emscripten/emtests/test_i64_zextneg.wasm b/lib/emscripten/emtests/test_i64_zextneg.wasm index e7072ede9762657839e5648cd50dbe664bef8d33..0b322d33ad165aab29fc97b591e6bc3d6521f71a 100644 GIT binary patch delta 3601 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 HPp~-@D1Pd%wmM2{1*<)G7bP=gXZGB4 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 MtpEzyxf4VG2T=|=IRF3v delta 3612 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 C1vwu8 diff --git a/lib/emscripten/emtests/test_indirectbr.wasm b/lib/emscripten/emtests/test_indirectbr.wasm index 38a98b0d7d861bb20bed756b5c3c94b80529b6f1..ead37257e0d56475cc3422027d184ba906eab75f 100644 GIT binary patch delta 3578 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 delta 3501 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 M#N0~->UjMB2b{wFI{*Lx delta 29229 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 diff --git a/lib/emscripten/emtests/test_intentional_fault.wasm b/lib/emscripten/emtests/test_intentional_fault.wasm index 52100daa127a95765eb546c1ace70f233ca08349..0847ebc061eef7091abd29cc6880ad2282a3f4c4 100644 GIT binary patch delta 1711 zcmZuwU1(fY5I%G6&)(#0vp1WzNp`czoZM`FDy6BZ6=`etCT;9rl0vFNLAIOq#_ndj zNq09&C35=^5hT)-i>5S)LSKp&6t-^)Rz#@jgHQ!QumyjpJ_w~kQSre!o74vEg*#{F zJ2T&zGc)Jvhj9M`Sd4E0pPk^o5B>>8KWXfQ?$ZZ8|4wVxyyDA7W@5TjVf_3;i?1m_ z6lV*C;n`v~oy)NrvSA(a01Ktl>B4k&YSlxKRrV_TOQq52wHSq*DQ7c62b&CSA_G>M9*i-Vz=257(-7{EX?I4E5Y0W&9T9~>@7Xkrc= zUCafeye06tvGzAoCEdji@^Ba5yT-+9FvRHlZw-9}4ULq$S1J{!RlPEm+;ow}Lg~rL z!fg2@lSX>7O|d0-kmwEG^c4)Pa(5GAVh@0oM=Rt3|UuH)Yle-t|svm7>YorNV`T* z3v+E7g1cJ0Gm1PSek{UuOL<+l{_j@ZsuuvF)r&@#M$2bb#H8ix25D?x;Rb%mh2ll-&& zZ%77zbj(5W(hLG5tEXiMnv?RDj<2InW6 zxbF>2gnFZ@B*Ko#D;8d{-0)7$TqXgpTV1uS`*FC;>Bhm_u3up(@OFPia@(E(SgL0C zOad7zPrpv`=-%f^Ufw%Ta%*avv&4lkZ~>%+e}Sx1nu2hN<2*koFL1mN_^EqsOPo%` zqzfh4jh3tDWe@gXw*r@{Z@HF6eDCagj*k0%-@NWevaX)x;6 zh$5nKRRec^ldZc8bV$QGq&_0EI)mjg zq-XHy*gvgzbkKd|?%8Xs_RbNg`{5X}>dm9eJV7JjT9pz>yCz#IC7Kr9y~d`bQGIh< zfO(t<95Yxx*0B{eyCLR=ZNv2=!WJ|%8tO;%l(RZY2JLU4B=nT>34S}aL(qGsLNOO? JE$DrA;a_*!g9HEo delta 1771 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 diff --git a/lib/emscripten/emtests/test_libgen.wasm b/lib/emscripten/emtests/test_libgen.wasm index f444d6f6bffc72e3967bcdc06bac5a1b0e4e6aa6..547f51017507ba0f8d92ca08edb04ae6668cd096 100644 GIT binary patch delta 3758 zcmZuz4RBP|6@KTw_jWgVOZH_W+08=8x!FKsLP$blK>5oH$pTUN2`Ycm%_b})o6QfK zkbnbha1s@5D|i)xjMFNL;2=%Aj-zGDK>ZmCR&B*jJ9UIl8VxzCFuuAc23Pz zqum4ENNZ1`e`SB9t#jExG_f(>GpI1RV03SZ$3t7X+rk|kX~~3fl5b_sa5xDUNY0tGiQnIbDEfSAc)l?=GRUSQIys$Pcb6=O;RFf7N*G1QqGDxze`}%!( z;b>Q1TcV@4KiVDM6zvbUM)jdJcNF@tE1(4dR2NXxE znS>xSh^WSP2x`W5@dWdWF{WSpJChB{wI69&L$x-2@f0(5z(Tq3-RL|Go@{!1G?D1; zk^YYKcl2~CdCu_0jqxpg?aF*TyfG1tDmQq-@%TVjxV3MP9MMrdQ(35oyCNOkiq}bF zoVF@C#6`Q>dbcT!4K_=NDUEu#uQk!Bgfcg5>t0BT67@yy>l2zT&WZN*M_S_@eeHI< ztn7`nMU`yvv|5>5GO?*?k}tQZsVVcF^K4!TKr-m%5cHxFEAj@tmM3QQZkAjyXQ@_) zim4a~9z$1xUXS5WP$}{nnf8EClw&-T0rTYv^JwcH)jq=BNE5kpp7kFV<5e_%Mq>r0 zHfmJ>bz)R6A$nR55p_8vU*(YeR-1p)=0CFeY^Rj3c1oRHHh;$EKezeWE-8<=nus2A zl@!+na9)wuQar}ry5WpVT6V@orkUd`GfgFR*%b%yrrI-$R2qIV!Q-Iei5#w1on<<{ z#`sxg;8|uVA%2eGIYyp%#l`FKw2Oz_pv%cZIa!2fQ~&gXi*|pGQ|L%x7Cub$=Y?m9 zb_UlHeLeVJ2#M20+aYvl{#1ZaYQZ!o_(J@B4d2(SWQbqT@PbBHyrY>RvA%fF72^NU zEX53^-YfpQNoSv$-RdmyN*oL`j~{d4F_-18Ws0S6z%#BQd+Fbk;0U7^i>A7dV85ug zen<3wRyFKTRn>0# zZFiu8M=;TG{u(TMTic_UM(=Z^OT2>1I@t0*W zI-nY>>42u?L6USYe*wMd^cZ6RrZh>ab1yi>ubQWMbGZ|9 z$X#UJTMUpkq&{BR1jd)ys*%)o>f1@M?(wh-^2Ld#9x9#474%JA+dSXxwS(+(%*Hv-FTwXT6;v)*c?@$g?oZW8{D;H*5BZ zTq5f+njw>9;_9jyP$*`sE~3z1xw_aFq)bsPcZ@e+gYF{OeoF9|a_vT9X>rehk2V|`*aa1$bg;SL3gEqr{9z@z!|gEe z3Rsy-_*KBGKu)?M4h~M{UUXbf1&az@#eM`Xb7{36xK|=P~U_O+H ztgRhHw{9(`GI@BbPp7CmxucAYO%k8%XrsxpoddM;`c44nZXIUR#?&M0hgtrgs8~y| za|whYHV*6|Mj#kNcR-_P87d+SMuu+ADmO5LseYg) zvv+ctW|veta!ea{X5}yD_uxI0k=w+^2QJSV0UWVo?tZ}g?W}zO@Bxs?Fo)mb z)(l$48MpHL0PmCFj{u*ej_P^ubI%ibKgp$NB1?5 z{L_79BoFLgO_IL-5enLO_di7P$Y=ve4v!WSeRH&ibkqZF#BVyVfpp$DFnJBd16?US zHA+?0b`@PYs*GOBMsGz)GPBZrnz5qS5|Nm!Q0Yq8ckugI2}ybm>yaUo;K{>(<8ON;<2sn3rdWcffX z&()tGYTDG_pCEKJY8RbcPaQpGfMYEk5Oj!NKVMLesyQKGxlQ_*^cZF)nX008n^qT0 ze`!&#G~Hwi*+DwOb-c!))T9!tSYR@-=y)=9c&yi%dj0rCNaem%2kgCx;>nk4#ZO=E F{y*V^dN2S0 delta 3686 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 qYGxkD0{V#XnD=DGfBbx(JO0{pZ$rHB)N-c4zk7 zd(S=Z+;h+O-E*&em%a8byDKkSgG4hVv}Tq_P>-b6tZ9cTtLL*l3E0zYB>086`wcYWS$Q7j=f`aDMRA$TO?r3~Xyrs4ChMnPP zTcmrJrmJswS8pV;w707@)ZRX-nJ`XsMduEMLXqy)&arQ36br|L(P&e*rXPAOYq^mM zNvZo{tu2wrtm@fXO6R+(tEnDU@vEvaqcqa=c8&U%O(5jsuxg6(=vlMYS<<-nhE;k( zQ{%MMIJDAPC;tP%Z!KB~OgBvfbkH zvNbHwT&)=i2ry1USHj>4c_+(D+XDd?C*hU{SvKy0dTs2-_rem@{i=1p2^sPomX+|k zLv3x5-q<$n8Z*=u4TrUCD-?4eRF6`s)tjN%=4huD^ls_vT0(XTmZiR{0~%hR6^_MQHb>fH+fsn8DeP%!4Qm-Z z+S|3NI~HFPj>j~|L+;jYi-vb;nX*r>Of1W3XqcRr+tAS9y>x~xoCc5xcm)K!sC5*1 z1764KaC&yAUVt|lwW!%TN3gi51-uq_X{Z%>xi{4y6mg!Z1$>USR9P1JNHc-+zk}{g z7<-L9l5jieoADa2eZcX9;Kfk zEVNDu8`IDp)2ESMfzf|TWS|Q(#?&rl?*6)Sx6<+=ucKM~k6rn2)}yw5)C_xevs~0XW(hNUgqe7Ti4n$egwe*uIfm!tg^BqvlDs?-JY@IZ z$y4ZKIeE%Kl21%IM{-x;29m!n{0xHfWg=7X`^yDDFxfcO4Y@(_wt;UOPGYIJVBiIV za`_v>4$AhxE>BRrXE>T2Ouip@*CyXDRd04r^D02N?H5mY@ClFOo6R&w6M$zuMX9Mz z^5IcNdy_XVd>@A8;zci#OuMcMhLek~YXcfQym*jgS?x_EZ>=35>2@jt!;Eti?*!q& zPeG)qo>Jj3!vWSHjxanT*E=7P^@=(_Ion$2(P_{VypaYk1P6?4ulPUNl+DX?7UT<^ z0Mb>cE_B&k7--m&go!F<)8hA2Gcn44F~u(0S+- zIw3;48r@_hSnL!6CqTwTyrp9WW#so&v~FGg;qUonsd9J&UMGaA;0ZhmfJB zO~j&Sn@Tcrg&VUdakK#hlRU_U8}lcAwaoc^i@yqxttLuu9w|s0Tk`7S4l(E=K%TN# zeE;uDMs%2=0x3tPRxHHA(F~R-ikD(3agy0n<)QDLH}g=#JlSzyp(jsG=3=fqbYBkS z$w%+o21{hd{iUwe;8l*r`f@0itJW7$)V=FVXO@U1v=d*4sK zA_!nW1*_S}afYC(UqJ-ZEqV}6LN0ELkxaH#lIl|1%fR|QGP&(_s7wyEf5_n4WIXaPWctPPfX{UgoP==sTpYgy$J-#j0Q>?dZC}c_;*+@-T^64)dLk$F zPW1)++~Q9GOjOui-&+6$GThrv@|E71>Za(;HR)_*-!h%O%4OXxtu%P#mYpSDR^K)W7l^c~Eox;@Z>r}b1_!|J3iUK(VO+On)fqq65_*G&p)XV(-B0{FN zf8MlmjyXkim6xTWOw}<0Uq@Y)F+sPRrcRE%Kt9-?ljjv5=;ZaJG0y8rgS@`dzX0Y+ zzJC(TO&0I3f;lR2Ihajp)-co2sWqJb(^^cNpd;uYGQ6AN2}TLNn~9K#mvua;+w+nK zZ#@A7=lp@6PzsVC4V-{k%GK|5JT~S;VYV#=62q;yjXZ3^=k!j|PG+ZcY$vE*K7fVl ztE7${S6A*DTX-vW*)>Vu?K))cPTd^4oq}be5BsPl?3Us?myH8}2P6(n$)-+uqZkAn zRG1zBvB0F6HA72bckSiR%K_*t4IG79^`Wb_&APn&Z9R0)Mgr&=>X%FV@EVd^4%d_ZvBT3z|N7x| zq$xkrLR`G-$Q`7gJX}wjmf=#8L&Mc%^Xzad^`{=)LMU{KdvvT4hjpa(Fs12;;z|`B zp=|Oim<*H7QJ7F9!#YLs%u$@@#RiLKGM0dSL?(*$8N~{VXDgLD`^pj6^G8YduMB!E z8~aR}NPgB7^1yt#;ify>mkd~-xc>RkIj~SxAG?9d!oaa-VWnTp#@Wt!O+5e-LZ|Ad zQDr0d7U+t+%$_3X7X9YZlpplQpd;Qi^rHx#Qxg5PyX`3{PY>LK^K)iI$62~@=p(z=g_W* zD@+kO^(IE3+i*g1=0o?g0)r}GC%t3T3H8LIB<+;Ui${ek`QF1ETsPC#0gwFT2Za?j z^E*D`sOWqFsBd_q=P0Bkmw-z!yXRD5-`>QV=1xkP(@`rAsuQ0 zKSO7*WM;;6eX%gLq8NBy9*BI-Un0CSk4c()y>C)`Chk6(|q_ zDiD|Mb}5R2r-F*ZG@u^v7+x=#p`^QsiZ&*IB8?Rbtv6c<2vGxtVvIpZHO9mVnu8eH z1eK4(7&MZHpVWR_os{PTk3>9MMh6?vPKLF~`*?uEuVu!DM>;q6_Y7}cGt$}Bw`QobD@HQJYs&n@ zvaIIjTz__RbF=6A&uMKbKqBPh5b`n7TjUG*Y_r!MdPep_nXPJ=5sMfMOhY3fpJ})V zBSk*LlWZ6iWg16->Irop?%~44^OJidSK9OCN*6~IIcYq4M1B|Q=2-b$Z>&mwAJ*Z( z{Sex_a*)<|#v}0@s<-lmP#2fjLFOv**~B#dGzeGS($%YOJja@Lj%5+&6SW_}=XAJ= z6l^BaOcypUnOw`dMm2VY@@v#!*QiaJ_!MPRVrphCTyt*E1UK4!G%Ft$3wQo^Q6A2} zhO(<*1Imj9pFu=iU}F&ZehmkRIExB(Y(!ls3+1}dPIrX=S+$83aju6xv~aJVRBzTx zeG)Lk3h*;-cE)XcYbZewfL(PLC8zG?!fO=oBI;}Jz@(VF^cN^UU0MZ`&YUN^0S5=` zCQxRF*P|Q^kE8q~Tp60AhM}<+fVpy;C`DT?RcCM8CSb~{7WD;n47y8v1@zLaVVvPQ%0>ISD1?_ z@*OnWsvIsp9|vH^3%GDTg#ei1v$@VP5fAk1ZiZrDc4%WEpF>}Yx?z^s zeC&DS5-3`N?$c2%E}ZyrB&g5?>;oLibF4fG>sf?aF^w#WQ*uIKgn>0nPMOAcDEOr# zImjzj;%M)8i)W8_25z`H5?))b)3Si1#^#g4VlVE@iqsd2B{TOuLHiqMq2XFXnustHCkrWmP<{SqKc`eCh_ zT0Z+>jI0t#LHnoBD_xc6Nh}nLrIwhf+fb{NV*pLVn+h1%*KrVLt_W|e^p<1zbRNgR)?_0_)t$VZVkHiS3$8F9*eoySi|2Z`Tf-85jl7pVQ#0 zxX@Yr^>Lc_8?3JKfNTV0Kb;2reu{vc+r1VVg}$fjDSThbk`5%(5^=@^kXb1ijoimF zyI4k?V<|^p&o5MNDT$1ITqegy3hsSYowoN`6`zH-_gn%faQ5u&r0AyeheV#@8%>s- zQ9ExL-_3R-`$ol#Z~t4J05&1K@ig+}M}K|f&g?x8!fd0iAhfsZwthEL|Rd@eE3 z-;p;ojaw=#ktp9iwg{dO<*%$lf{eX#5g;Iz9MAKi=_6`SDNrsgKUkd)wc`Hj>kWQH z#^1{WEKp7e4`MmZ8L@M=+n%P!Mb$4ko5OOFSYpLPe#nIPiV~@(kyn5bw?-zIlY}}dvXm3ISQ+bl}hiL26t(= zVby9aK@^>lq9ZHa_3}fgUb}b^P|YwXXg~;1z`w2m5S{4MgDWw;;LWfsV7hNYW+tIj z*C*JzM@j1r5Kn7X0)mtw&=k-WFyt`J%jk!ohaoT(CC^h|VjnCe_+xih^LLPyg^ow# z@y;$4tmdA!u1*p#BU`t|db_ui`;5recr;4#>_{xOdqiUbC~gHA=Eryti|8S9i~vXiqm;>P2-8+vCwaBwG$@vlDgs;qWAXK{y7G(8$h!aO+9BgKgpk*@;;iS}JR%+o;%2+lD`dm_@ zBujnBnZVd_pk_iJK(!v!H#?;^rOch}EJSS{0WJ}w>cnyN`{80IB+RPH)bCA2c&k*f z33*=;8C7R3MeJPSgyedCUip#$_mo;LvDqIx;gVN*f60q>oN;y>M@zn-#{jHknWt34 zr7pwv;L>OdBX5iv{2~=&l<_f&zKhG0UzShg7Q$HaY%X|F?%bqeJS<-=`U=8Fi!URb zTGEK{@sj^QtsLO}Q2X@{I6!UkmN229R=lC}H*_~qBd+QEnvUW4rS8E#HSYzA$)!DI)s&>0|;LT%?ci)j2ZlkAiVr0hzx}(7C%P$0lHiq zrTnP0-1kuWLpOlR{7bwV5~6x75}&C)pyyfQ|3p(})#WcJ6dLz%O}Xmf9)}5?>&`@B zaOJaMvy%pdR63S?BI}xLsr#0hAsp^F6J>TdSW&2jXowfOWSI!?fFAMz;|4G65T)GX z>g}S8mrbQaOyPwx5}pf%^2u;JDyZa@sK8tiM9#Do&vT2LHX8+Sl-+E!%g0p#cQko> zMXTw>IAq|lwv|&87T0Z72_7Zy;lv$m3Jc1q9&)jyJA{TA!CR#-nGj%bOiHT$eW22T zm3zGc6PG3^$1400K$hCc`J{EmbA-)vurx6p#4T+X(y8B!Rn%2KC96P~JO=}Z7vNx^ z2KmaPg}EP_d9Bc9R{`?W#`BxTiZbq)yl33S3c3#9R}#NC{kl1(!E}Y+K2;2pW${z5 z8GcTynw#i#SZFCRF)9jfK&)8(E=z*1+1s9vV z24hQ{Dy$o-Cpa;u(&0Pm{Ts< z@DiU;Wh4Ry_Deu+7@k&Ip>D=KapC8FVH!AJOvVGs`b0jl8e36!xI8mF8>Y(N4hI)j z2+p|xAGSYngb-XP(J~||#AIHE@{?1Ecep|rHV+1RKZOG2&qGh&G7lN>5aP-2?K?n= zUeaL(5@Hsn|2mATzUzSH2b-fXLvGtV3%xeEDaw@BWpZTmbI5Lp3?lqh!ClZ#UfnC`#UF z`HNbvZW*Sy?ArD!&_Qo9)D|_e1L9@iFM~?yMc@~~nUnlMC!;Ve`O?nM=_R*;f0m*X zZbEo`9>#BjYb_Ta0sjclv)i(*cM`L>$7a*h75hx@Tor{}PLytqYtso4 zj5F8YxXJ!Z?gPwy{QjT zJ|z2&OwL1ObyyrwGa4m_sCdNSL&?!2$91Sl);(DOxU?L7M=jywB{0w8%WalTX#&(M zi#_%ebs?MODV8b|P2I|wpAORdS@?yc4;Z+S{7!wu3-cvg_XYEY4ht}L^3aI~VWIrl ziB(uZStoxA5Rg|-70p7uPO-qLXfqo$737cU!|7%aI8}tMg5X|f^3?ifdch}eug_CU z{)Rp7Vv)%+ZI+Wht*2ZnRcW+YKvTY_TvZdoRgR9P@9-jMMuHBQ=&gKu-S-2F@8k{B z@;^_!tRE@NoQ_BFdq5R~MnHCt%*@A&VKS&Yc!8w8U^sBlt|9^Lrf0O;QA=zXh$+_&3#PG-p;TbUb^OS~{39qWSd9XlUo3I<8 z!GsN(_-Je~ToBZ@jA+%Ow&*&}w6TgKbP(EVM{1pEN3fz;Z7uECcBmG6?rxM!>(1=` z?>+b2bM86cdE5uyXK!C*_vawQlx7x-L9AIx{0HPpp~YY`8;HTc*!;3|MQPSz^n)0? zsCvd;$%!#F6y9lscXV~t?FhF8+uM}{C2bPrOPW0x40iRjbtX9sT17*BwUNlGo{2M( z(jRSW>FT<^ETE`Ta@u6tf+Wp(jW)lwEJ;g9OP-zJN+GTt;cNPGgQ4zdTco|WFBA@L z4fO@Lg<5)p(e~XTMH7RtWRYhwLnI`359IC3)4MC$t3b0g2HJnZ*O-*+x8gZBas$^9& zK(V!&G4L^i2GtkTc`pS85Y8!b&Nx(}U60NT*Vty1AcR(bXjZztMSZLCfWtp=e)AYgc=8 zTT@?4TW3>mOIt{Bi&JXg)^FrCG!#trHZ(M({_PiRSusG&=jPyZqtfAb``nhR!|L5G zXTHo;S|uu`Vj#E-UGceHhD|}m?>15s9|V77(3*u5q4=8s<)LXp$q7r()_jH_?2MXP}N56PtQcwt>dDctM|1 zkq|Zor##5BP{phXE|s{@?sr>?%lKm$PCKNZPCLjBbCMmVsl-!kT>$R*PP<>F&%>!M z8-1QKxt?`~>3E9qGt9s<%u?$3S%zoDyIE7=O#DAt;2^#)^784h$S>GO+%;Qfx@M(wTT)-4d;ee+d{>0Wlr^1trY!e%oeF%qyb;D~k z8Wr>4P`sjI3((^6$`Kl8SsQ2^wuWg;sVemyVuqpPeLw(S0RoU_l7xpC4zuO_FvG** zma4xK_o`|y32U!*sI-XGt*6Cnb;DZB&A-N*20FM66>Dh+-4TkJ!Wl9%pQ~s?Ro>l( zHq*g1)XZsIM`?uaG9K2UQsPtf|6yiem4zLADSgZiUXE2fpTtk=;Nq7J_uFkUJj`jL zZH2GIt5&i~^jgY|d@4@WDxF|Z)Ob6&A8nS_!DrwMd7nb`isLI5fLB~v(Ln;{;XD$s zaixza11q0LH`-msaR5_ZNM;mHiWj7~U$d&suFH_8V?SF}-0eoqWy}Mc!oH8)73 zwMvW9tdpyR9hsZ7KE^>uf-jMiPLRNHuJ0wV@)C3ddJzU1O8F-}h9Eu}N z`pg<~i0?nr!Y(-WAI+jsc#iJkKAD;>BNJ4~t0e^ZrClzg5mJdJUTm5JGsMSDeu{Q; zZPDyPUQO0JJ9rJ&NJrOVEf$%D6kv*kjvOYbl+%(bHm^Mjg~GnBfX1SAo1sYDw{APl zuO=w@>j#UZH$i3{`NXUt8<-YDMMu?0+VKWJmb^#dnzN~e6Ye*!6W_f(yLEb!!EuqI7`ydZB3Ex3qVeRWg_S;O07YJHq867LIE$+WmJ)2F;e3hu z4;D+`lfdW-BRwaQRXkZ_Pf+m|<+nWqdGWVyqlgTMyPF$eX8g_OkAXffw|)k2y%^sd zrLi;=AX0PaSHLc3i_)#Xg}HHk+eZw_;+H!f19u)j33xJ*kf#7ofmtjb?>YhtMO}9d zEEc2PH^V&fLH9nGFLs8@VS#uq{0uA-%{_;S=St5;nm6_?fG z{{rv}ASYcF8>7>>8*SH8!lDXDtzTk6(KjoBn}|iHJC}J4m+=#TDKZS6iRQsfaW>jc z1In46jqAD&GWD^KO zY!cW*j6gVj`&y_Ic>{jJplV?8`hbDie(I+s$rzGZPcT!|$fW1gH7MQ43FR^jIdu=Z z_VaVqi)t)m510A)CzaG3*Cwesu92GG43xtXkv5nMOX5X?^I)O$Vm4-(0s6WvmA;xa zbV7;pW0VsXBEtg=k1_K00mg$mex~Aa)#UN9J;#8MTsrguSswp%=onltMZK-!LlZ)V zv?$+}K#bv5+(r^^!&lW#-cD@eDz+1Duit?M@>E>Kj%%936NdA zTX{F~-ME{Qv|sp!KU+8gIFbmsy8-V`B=S9g_khfVa=yf=8MKXa8u(p+cS+<&fS2ny zBG!%6L4W*vBdhG%Ff}9b$$itaXtJh(k1!mex=Ia-H|jVXpYffaGMFDfzb_s5HCK^~ zq;=G*Wk51&-FTKBfy!a3vk6p4Cj zxMd~YBLf(fpC`-9MGeYj+@>B`2unrPk=2yu`;WW?kSA_>B+o71VH0KRtO~Ov=jEI7 z;RfMqJg0jI7LWL_vB2Sxfk!VX;cChTk0@-~2DM^eQ<41wK#n|=e$(%ZGrnvz=Sob~ z`U7>F^huNymvMaaXlR<~TyyBUor{fIbpPuN6 zW~rPQ^a7!5-(j56kbUTy~Irh<(i-xY6oWp|+zB-b!=7G<7|imc`m ze?B@V_mTz_mQ3bO;!%u1JcbvQc;L~8Sr)xiEJt62Ml&(y^hLN$j6FI{eE!3K*>0w@ zKAX7mc)@H`&2+EjH0k~3GR#y`qN27!tMnxwH`JTVG%}B>0P%?WC(67O_f)(T3rr?w o#=Y4# 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 jh1(j*iof*pzd^k9(OxtD=3^ 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 PvU&XFA>qefd7J$|_xTP9 diff --git a/lib/emscripten/emtests/test_llvmswitch.wasm b/lib/emscripten/emtests/test_llvmswitch.wasm index 9966cf2205e0cd0557f1fcd844e784ffb47ed487..98a9135e99fc0f05cdbfb8d355ab9ea26092e4d6 100644 GIT binary patch delta 3564 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 HOey>qU_svW delta 4548 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 delta 4560 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 w#7r`W{92@JW0Mcfv>V2DFDTSW7+g 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 H8yWg97z3{S diff --git a/lib/emscripten/emtests/test_longjmp_exc.wasm b/lib/emscripten/emtests/test_longjmp_exc.wasm index 6ee493a59899bcc0674e84cbaec4a6a0f574b4d1..f901e34cab754ce9eaf4284174d688650270e2b3 100644 GIT binary patch delta 4123 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 delta 4280 zcmZu!3vg6L7Jawhdoz=HlguL_e<$3|OcKb41R~)p=8+EsG$4r(S#=0u0tq3XNeDtk zCRzj(P?v2m@mHX`t4kInFo+0#vWt`mWv!OF<)=h;Ma559yB1o7TC%riqCwrMn%n(u z-*;~Jz2|oKd$M1BxnKSLB&H}kOD4`>Jt62>u7&6aA@;29Qv`rxX-je)go z!3~Nob#bc#UA1jp^({XscLv9cwJi0}?mQ6ZVXBzIritxrQHC^j)YMvK3u+fGQbUS- zj)^?`Z?x*fJFFr!zY26!(^Lj3V;U$5=saz&B_F&GFanQnheOZQs;iq7@*?f$0X$;!>T ze{FqJtAciFTj*7VQ!lW#p?!n0B+}~)bSX<6{$L^1zM&id{^O`xlJZM#yV`#VjCgpcOTXr`oxBhI|P4C^7K!Eit zTADgn*L2l4tf^_QZwM$JBbdCdbx~WySEq85gXUMeIv7~5WQdbmQRwz;3WR?V{g*G# zAHRJ0@|=44ORle95&0#qa9;eDRgDJ-d7T`*PE?wGPOsB)H(Tu;vgb9bwNg|}-9T^~ zy5e=Z4V!|B&uKU#4T8@w;uWvUQYxjT&qbP8!`N#BPe`JA2o58t5iAQOmd7%ic`7xI zW}bo`o@{A6-5PIlo`z|bQo14DdVItgOfyG%C18`ZuoErJt7u^oEi8pI zRJe-3HB`Bdx;f4QGsRNe#=l$Pv_rml+VR^r!*4iR0G#33PM=CmL#*3IO=kkv6VEao zPceR$8F-e+Q_0UTJR|m{q{G?psT6RK-7AnW|D7|7kUSnVd%I6xC1W(kC8p8!U2YxSrzYR*e|>lUtcr8$RlQ15aikD zu(W2LgE^Qjl>^~Pl@68gW>hU9cRQ>4v|J}oN2f(lmefBZjMAMugerWLKrmLl_6sdOR$?Zogb%B98rmx{X zDmsc*7G_De*_bY>R+d1z=v~=N0L55L0RLU-B~4=B2s+X3HiiI9={Nqj+n)F=&|o(y zPcigbP2>1XCu(k^I9d;Kg}uuc$hB#u7HzF-xJm(jtnr#c+L^81d}0vDNRb7_?F7IW z`H=8`++1vIhj?+zs_fDnZpQ?Q2h9sXm-afjSriGR<*bssnJXSy_sP^Bo$AiJ)EbBRmbvtGvw0I7NkQih1+$saXW2=(t9eVR#0(iW|260tO%xw zPmg(L&ESa0!9|;uVou^5xiqDUF=y~h%p&_t4wOQ(NOlY=b;`tD43g!1Dxdqoey^{JCg>qIml^pPj$R<5NBuC}8^p3Z9){fT zH+N8B%oa~>TmS{(uQz@H)ST=29^iWM-lk5H)uAF%g+i|Z>vf3gyWWPJ(qJy0P6Tgzdt7~HxHETP}?0F;T{_soQu;*EO_K&1%X zJ3uxm+v=#_v27a64i9ci0aBgZ-VswlEX~7QbGEo{M{*H8Sw;9c!>@=QrW~6PJRi<0I?AN19%C{3bA>|T~I1)_bslx0(dv02w5R+bJ+~M00y<^}?oZaKUWP;-d)*Kphz5Cv?dqnHW4i##vq$zA^G3Oa zTF*nXEd407f~r{^rT#ww;-%XpN@Op)iZH#55?Mb`3roe(0Uzb@{ekIAW*e9!kM`W? z<H3q6*D5QtEWU?4)N0Wr4N_H8k{Iq{ILIiA zyBPQD_`Qlls#z7zePj@bA#Xo=l;RY=@3BFcB%$6>@!=7WUaga_jxd4YDqKwnx8q55 z4R0c|6Dl?lSyu1Caq_LOip`^*TSpwP!d9~){L~&5;x|Ulm5r8X9^Zf)Xq(w6p5Obu zwgqsDIPrK!B6TJ%;C+C7k|tY#&(vw;tH�V|dCF)po6qVV~H#FEf!kix%+B@?0m& zKE@a8*cX0r-*XJg!guVCg9w)+5fKj@NG5(ibzm_q^t%JMQO@d~UQ9Xr>(ezPuRL8& z`tpN$q;Ef1N19g;){}kS(00;4J5)}ZABJ*B`VL)7Hn$vVp#BSoR%TS-8opb_V*a3t z)ILZ-=~pQX#n?}=6W1S3A(*=M3?^-~sd zy2`qZgeaO8nc}swOx(uxBMc|L{_4sqZato!KZ_P(qe7;`Lsh86sSeC!OUgv!QIOwO zaTaaAaj1CX#Gc~?5GP(co()V~I-Z%}l>tH^#;Rrw^;MIJ2`82caiRb&h`*f}3rXR3 zPdvgr8ttuX==_!i?C1)TG$S&lE68o(oi7?tdn;%mue|5WDyL658E8wHk947)*MTbC zZ-R7d)6y)L>9#^{!|RA#pv=g18@2f~C~H_Nr2&vPE3y+`z0@?BK0Vw3S1*!OAWTTl*!}xO&&@IMcJeCx`{K~%|yluG69)9=LQeYPoMg5r)ansqG{|9-p Bsa600 diff --git a/lib/emscripten/emtests/test_longjmp_funcptr.wasm b/lib/emscripten/emtests/test_longjmp_funcptr.wasm index b7669987915f9f7723fc933547607052734af054..8c9b1015ccb72d5470be3442c4d91b249404123e 100644 GIT binary patch delta 4203 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 Bvt|GQ delta 4167 zcmZu!32>A}7XDxV|35RCo@D;qAu;52W|CkC5D0fz$PWpJA>l|6j4VS46Uaf1NeBxf z6P2JGTL_IL3$C)eZj~Zu4WL<-#qubG+FdNqEvpb$t##eiJ-ilmWnWK%#AB-Fb@%Jn zU%!4=_rGhOet4gLzwl@fUI}4sB@2hOJw@YJu+3rEywV8M55nw^MwT9I>52`uG}ngK z1S^8;T0%;m|alnY!*^0L)l*U{N$cP> ziD-_x_%QewC!#B2@UZmiX)&9@=io$~Qs^RlC(P35$FH}}gDfSU4iOB6T3Xe?YC9WR zTeMtfpuWC&eaBjDf*Gg}1%ujfZ=kukYh7Sf$A;RrKts_utIK);wQbZEMSEl!ZLup53Jy$X@j$qvwkuc_>}*`urY$f79jii3S``m;20J zjasAM?Q`4SM!T(D^?bb2C_&9KIf9p)n$PX!4h=QGo4cb8f}isQ&F8VT*-FyyAx_~;B2wJSW=V-Gwra5KVtfb1R45-gil-09 z6u;Znye1~wPUW0L>pF{b;`6_>z zCcePLMaJ!7l^(tYKV@_{t~KWfp0TZ z{pK+rKvm?h-wCNz;VO7cVIU8J6;(aoKRTY_&`>sXUBPXqL zj&Q4ZRS+?%r&!p>a4VZ9dKvc0CujYKq#rL$C$JYw zT{;c^H0M?ti?MVJppbiJek$b3*XBZ{nhV#lHKA*+$8U>O)1V3Iyz8~1|d4E zcwwMn

j%F-$K%XhMnd^GtGc;gIYqv`qOm0*Ug%@ygG zZj^X{qlpGK^7TQ_?pHom@?)8aQNF zfQjVoXi@Tj@-vl)tpyYj0|SN>-cJF>%sU5R0YrulJDoXM&kD`QGqvf-aSIsokFijpfmE}rPlc|_0pFNcVY4XieYhjVJ zPvWp|sOlIpi@d85XOS#%OlqbS8v1z(0`m}iZPo{u&qLo2SE979}r zwe8n1PCnS4MfB#^Puj8p)d)7TK(`QH;m&YTX2!5M37u-8onJ2b6YX zWvh}xj~QXqOw_sZkeA0_cgTGOmdC!Iyb?Erli=llWss+i5IQr?Jwd4?GPzYGkDZz6 z8Kojoq*GxN>GJC{BmEPV4bTx1X_zLQCOU+ZW4hXX7!E5V%NbUIEPtX9#>>r5_@+%1 zh$z5ArAf0!34ub1=FniG$i^I!&yL29RiHYY5}SN=7lTx#&s$G??c8p{Wa>wj?AyvR zpEF<-4a69VperyWfUf{W@FSf;m?GWl$B@=eO5+@*b&f1sf0Ec=tnViJv#v=cIZ6W` z`joPoRlu=8=p4sTfazZTcE0`@3&(AN&9u!`bz7brxPk|6%X4(|%71npfZWKA4U|n& zW%0&xxH)p~#=iqK9d~>MP%K;T>>&E?orT0o+VTfr-7fiV_%)ao>F@rK!Su)@_dEg# zx#D@i=RtY%1;7`;Dv>ok4}&eg>?ws=a>lkA_=!BQZ8yx2`S%vXBw2s&QJ5){?&~9& zqxUVNzGM4jm>QX}Jq?JpY)AWKo8n|7=37&7vfbTnbcj!Yg0K+B;J*Mr0gL8o^dZBK zDPYtHZ>Fv_Rl?3xf*7{*E|?|{?p&O84e)M87NU#Q;c;-h2DW>i_y+JBAhTVQo?SO_ zH#)q$U?3ys?aKCyN#|aE93V;gZo{rjxLH21tAXgXU8AUGj{143Nx4zBcO<*SWoU1m zx`Xz1(M*K|D9s%#HP$@3HNbwFqMpi)vW`w_>eej-!TdTvf(ilkuIOe%LZF+GYd+s! z4U1)Yub({A);ndyRIct^FVBx^8LeaFd>wUF#spoPn#vq&j(oW{CCx4Vrk*<|j3KBe z3_`uuTMVVLxNjJgMwavy!6aq46ig;FYnWi`)Eaj8Ijut+rWCXh8SZ0vn2~|^F%dBF zD;-bhR$1itzc>u!&c=gh$OMt>2M@zo1@)$m2L?fu&(=nr#BdF+C4?3DoZciFNbD&c z8^~4v`z2VUt|+@K?q*z-@Bj zq2bBY8C@=V0DF{Aw}B`&Y380ovtd)@!l6p1(ZjGu-t=g8GIbV~i>>O)CCMHp7Ms`; zsd}`Z!Hh`k<8dHvScEL04slUgqL3^>Z;^{+2|4Y^VmkWnBR?eveMJ4KvgBwL(S1it ziT~%LBZ+SwTSlA}$7(4S&mG%I{Q1XAiL>W;9?|~e<4NY@<8{0xAoqPM(E|Trm+R z+OKNr0T32CRX>d?8^L=AU*T51dOH7bykns93A${Aq1(5TiQkFs>Tk6&V>gyJhm;0BdkRd3% zn970Z=ZO-r5+k+0JIFE(s-R8u^ifIe>I@OJqBN~DBpi`p&v0-oSKk^gnSVBGjAf+T z9xK)kd%4dQeOy>TD(Yz5Vw70w8E2Hx1Srdroa{QgWTZpAontimY@zpkw8t!Z&#Mn3 r%FP(gA4&mwzqt7Rlt}%H??B{>v#rj^?DHkS{*f$SK0i^OeW~*QP6)LU diff --git a/lib/emscripten/emtests/test_longjmp_repeat.wasm b/lib/emscripten/emtests/test_longjmp_repeat.wasm index 27419d80e7d091b9d65a33722868c1a5b528510c..2d92be64c3b736ec34d5dee6335114339cdc1a0b 100644 GIT binary patch delta 4091 zcmaJ^4{%h)8Gqlt_wFvYN8ZcD+$9%6c5_F92?-(51O-E0LIP9*7*GjQdnDmP?(&C_ z1ZWhwAPE9?N?=hynYL<2Fk*}I&=DN@Q)P-U&NwR8X{%7H)!Nbi8El6l*l+KsiPdRl z^1a<}zwfuZ-`~B{yVV1`)sbL2#FZ5a#8;^CIF87MIBeKiUQ(tgD>UT9Ax;P4KhAk*>bh-e^yMq&tj<3Aaa@d%}Iudn4ik+;*dX z{BmzZ@)HsY$kV&RovXW7#kzVFb?1p308v1eiv6S}US9{grs|*(qJpA;4vN!B2vG(s-wk>Ly%A;D%}7Fw=ajn`;x?vJkSRzl8jTU+PazIJ7v9&YQ6 zM3jj}xU+LzSGc8bJsKujUZyP4!(GkMZYAKvZzrlM**J=Hwe}1sixVR>v=YC=74D5B z*K=sNuX$Z$Nu*!eYJnc^Yw7J!8dIc4mbUjs)+-BXxIfa@e_f)%y>g(t7Imfjm(a0E zR9Wg7H;XEFe!VFDeOEeSG`Dm{``VY#{^r(>B|Xip5hY7()=J}dvt{`AJ^XKK%Fk1aK8yW z(^5k2pqmr_hF=vJIhpe6`gFI?zm87#4b zW}V4l8KyIUkVXO$=@_Ij25B-g32A%-(v*-zju{B)V>ie{Yt~yi%$I~z6Oc&9Ak{HQ zjcG|p^&60ygnZ61x87~(czu>)y6|-F1QgOSDEAl?WoQL?VfQznsD!F=T169CAmp_a zgQA#0Kj?-tF6oCeu5UZS9(8sCcx``5NX5@A59XQIUf|{W^s_`~rwKoc&N_>xujl6o zJ4bNWS6sY?opSMd59o4ID<^Z=S^Fn`aH00kawj3AIKg%xUBu5K4dg9Hx;F3M&?tI> z8=&#Y&w>Dr_U9od_#65A8hc-};`RK3#x7{M#ao)$C_MS=U5)%BG@IFIKa~GR6R}rU zwm7GFWzJ!)_KA8O)(nHndu*bew-3BvCF_yRvme7={kz2eK-f1vbV=L8VU zUFTA9l0NS)oW$l0YhEwUW*Eu!GA8jFU}g(w@Iy#sHB`YQv8;hXwisxL_!b8+eI_y| zCyW^M!wK-XOg8&cg8`6hYl}|mzFel@L0kq!K!g4%3--u6*}q--ktgou-{DKjT-<@% z&x&zifZ-y+&B6aI#kQ(sKMYU9har0GD~YL7UQ$< zW5)PQR>LPD{KOa+RV^b<563JqgW`NkurQ!jlWNRqWgZ$JTdVc}WjYIV@DOuYT8vL- zljV8xSwQ5qRzN^BwZ;&joRuTM+14O(K5sq3yv%9P!vLl{kgPat+<}-$#IIJiIw^W4 z1=XfTrcf`_3|bBjlo#QMZ$U`jE_vBF$LPeGk|d>?qum`EJe8#yG#yl_ ztR)bOl9AE~ZsduQSP4uO_ryY&RS(1p{Kc4risgy%Ic$zJbRDZ>1!l208OwlT@lNas zqyrtfNcVNDgc5PBV-1dbIwfbM^Zo)a1`hVndfY@Y7vUv{7H5jiRGPfV8vq${-@R?; z-1!M}bB9^FYnQL^#-xCeJS#D$b8G+x{o3GfXB+4NT`EW0vU6V1pjcjN8ru6JjPveA zK=-!vM&KrKrgxg>X0*7I2X!=DP^f*+A^Z8hL8KM^mDNFcQVgj&Ofki*plm8vDVv54 zQVn{cQ2m0$Q#U5Oahc#gCzI_f*?dl7*Amb6KMEmx-dYT`N^yDJ?NDadt^W()XZpYu zfEl9rzCNUn-&cyPH}88L$lrY8@%zuiE%y42pAwj9w`}@3ctiYEV6P@J?KH5{U``X6 zn|}&b;>FE#pjuqryc}*7%Z7HqEb+fosPLPuo8T7Fw5>7s8n6cl z+5`KZ!{ear8d&c6{3~Ez0UGI=IJ<2k_cF&=@LO0yQ?4h1L8m4?^!IIfo;d+(&|d=F zAYGQbJqOCfZQG+r4{R^S0(^eEU&o;PY)26}84!VyR-9}cS%)iMi~u;d=`aHo?Nh6V zNX|Rh2Bfon=!8Ks&e?+mop9@}rErJXu`7f=II`=O)Jn>HA$&*_CeLzZSJt!|8C)Fe z5Z1^eW$K4&JZ&SFS@vfYArEWgAP;K@Su19OCE_9rEPJ0Qhcsz1AGZ8T{CX`F4foz| zzfr|@6CT#t6_p)U%_+9}@F<{*-i=C(Nu_SH${yT@O?DtrD+jEcdHh~> zFXq{Rc=*vPmBYY>6QT4Vum=;lxE0t|kTE`!-|EpQF0+!``4(VXq)&%|&(ztl`1ND; zFkq+dU+C0^uuq8xoTrPBKmX}v$a&)FW{gE`^daPr zjLt#M`OyNTS4VF`nX+eEas0?LD^cdkGZO>oX53QRW-r#tgmG}oy((@w{SeFbviSz} z%4)h1{fvit8LJVd^@keFlo7e%`AVo2N1k7V39P+v92SLm1*@>$PCW49T=fvDU_nKV z|1C-9RG2EGu>>EI*v@iUZn7oi%W6`<3eZx-tP`8s-`4%;N55De&2{11w4P_OOtC5I z1HafCZHL7IVg=5N0GaYUgR6cwCGEf6 zcW~Bx&KTo>*TzzKGv|yai=$%B=Xq>0%I75-p;;jZ6itJPzbV<5#PRMgn`S4{jXN-* zzV%3V$fm$Ha7Cy~Q5q!siLrrZl=AAxg!vV)&B>$nyRP( delta 4299 zcmZu!3v`sl75?x1|G&H0+2sF8$b$_@?qn0d1W0(uLlE;PAq0_E5(GhAldyqoo@@df zXkcR{2m(GBDnYc;*U>6S=%N&?iU;u^IaW@6)N|}nY^AM_W3|%uP^|XOE|qA_Il2GL zojc#$x%ay>vybi3Pw&z157-(+?|`UwhaQcR)U*etjK7`rM4{&ngEUcyvQG@uL+$I5 zL+!2gkyWAjp|+052F*~qlvSbbx{mJp)}cz?MaocHXHBTPR5O(sS7!gy7&4dTG{vW< z);DxSx@)`Z8(S8x3q_h*JJw&B(7v{{wQ6m9W3ah7q45pTTu~(tRsEmYIyLiw%OzYqg+PbbS*wD4UzBAZ7X`;5s47Sxbw`4kj+@LLvwbUA9I?dV=-;iFjcJnubDltpb2&BHDwYh6`Jo~ks^^GBI1dpt3U(^wY@6vAa zkVkc^Bcb)0U#>PvqszoC^f!E7B27x zyp9!iI@hRHfG;r0P_s>rU~y9mcrEVIP%H3qZ~TK$zsy#MC&>Sp(+DyHhbylQ=k*-SNI>dwNRn3}^{bEu8VN}K zTabo=yvsGG%IBE0e@wDDdFPEok-Q4!y$Z#VC!oCFg5nCwc00v6=r5qT7AG@{|FIp; zcvMc#cql2~$w{oo-3s81edsCB>67B4TJy$oQ-wKUkePUzi9yD3kYZmY&N4j9D9)!m zq8wlJh$_YkRO|u|R7R^T(Dd)`( zWi0knz2%@gVf;Zd{6tk}?B)3u0LI>0aMH{`)W|iD#c2tP|9J%LRlAHGth?Zgdd2r- zm!n6x$f22G0SH7O1#XWLI=WC-QFEco9wvyIc7ZTah0nD3eiO9#k3X z1X~(SqssDy8`CH*`mJ7qIf_Z?_3p72i8zTb&LBF=-|AOZSive>B@<=uECt7 zE6ZMWz##^o2gp(ueNVsR9@Js1YX3Tx3*+SPV{e#Qs9}~IIGUG7$6%E@Cyg>XBq^Qb zk)o(2@_mL$HlH3{4U6T{r$@VLz^g!3b&iKp`Cw-O)!eh4qsL9464e}ESX5%A3i@oE zjic=egrTW4Qt*`4OTi|swATDoOrX5_9SDm&@*>Y+-C==<%1WS!Tm5d$N+^<3BWqxS z{ADDMFiW^ibP2b*VrcadIAS)H zpJ5lv`eUUqN$x%tn0c+*f&d?#XPP}$ZA6(CQs-KckA-BPFX%wi>|)j6RQHslI~imu ze?C9bwmlV=R6D{<#`}hp6Cw2G>L0V$ZI#%bfNOPP_9^e zgw)CFdP&~9ZfaSf@*sc#DP45-y|6tLS&Co;3Tw=7&$;36CxKK~h z?JUjp4?$t2mRgc`zpS$cB%BKHGnA8Q?nEx2cQdrA?)zD%$)iuwIY66nztB z#9r(Dh{5%-6LSe>Yp9tpKdE(zi^?1m<`>Camh89_X2>HuYO1~l{2`;5(Jk-t zxj23esuI5f{0bFQ#scUnLuzoNBQFH_(ByQLcLQvauC# zt86-un@)}K^F$wDpGyB$5Hm~~*>|7{Hpb2$Sl~AL81~7DkLRaTW6?aZMP27)*~dhU ziG8u=$B#3Z6$?C>0^(|*uIzS@PBP-Ddiu~ah-g@Iu!dsvi-WgO()2?$l(d@<)slST zP$lXAcBq*2*-tGaP4`pvR10rCwS)8xhbu|**x}J6UpqXRY>a_MYOfwxNj9$zjEqv+ zX-O53ej<;9i6#4Wipg2Z645t^tXk~Tai2~xpvPH|i@ErrPMn@=@l?j5u$d@9{yvwu zj?$G%u|$y(?AZx2UK~cho{Y_=8t^Gw3$60W+hR90)p}sIJkY+w{eb~9R6Ud*nF@2{ z#v=>qj5&Mcd7#U5dn|`8Q)XWyG&O3C6kBraVS@%%eaS55~$nINc# z%sGFe>eN=5J(afVqPWnFqieuDL_DHi8h;qnPo5OI*a}im3#8CY<)oZ{d=#X}Zjwyy zKc1hKtD=ZN;5z*jQIg4X$Ct|MPK?W-;HdDcRKP)8&rFf;zf$#I#l6Pr diff --git a/lib/emscripten/emtests/test_longjmp_stacked.wasm b/lib/emscripten/emtests/test_longjmp_stacked.wasm index 21645b31c1485709c8a55dfd56f12eb7a173364b..ed768c814cdd3cacc3c92d4079690f974379796e 100644 GIT binary patch delta 4410 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 l0%g)?Q-B^X4r6~xT5JDpJBmL&cQ=~Qnwgw; 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 PwFKqy?=F!CzSsU=nu*v% diff --git a/lib/emscripten/emtests/test_longjmp_throw.wasm b/lib/emscripten/emtests/test_longjmp_throw.wasm index 4cb6e05a6d50b78b3bd7c754e290082c8a3ecb6e..4ba7ac0fbfe7faeb40011be24ddec844c1b1f0a4 100644 GIT binary patch delta 5306 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 mXVhoDUzq&cH?LE&{HOii7zY diff --git a/lib/emscripten/emtests/test_longjmp_unwind.wasm b/lib/emscripten/emtests/test_longjmp_unwind.wasm index 219c20777f600d1046340591d8e0709511ab4ebe..a65f578cee1c55d96e63b7a92dfeb1417319a238 100644 GIT binary patch delta 4515 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 Qz(;Z|?5NXt|A#BJW32c_o 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 diff --git a/lib/emscripten/emtests/test_loop.wasm b/lib/emscripten/emtests/test_loop.wasm index b1d7090cfeba317f0a9670c09523e43ba0f51647..976f6c965f7ef715a36ccb6d8465475becb5d332 100644 GIT binary patch delta 3521 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 diff --git a/lib/emscripten/emtests/test_lower_intrinsics.wasm b/lib/emscripten/emtests/test_lower_intrinsics.wasm index d9f919b159fc89b044fc65a4f95e1c554b45b08a..8cd046a46391a2b217552340a37375de9e59c990 100644 GIT binary patch delta 1765 zcmZuxU2GIp6u#%q&rWx?-P>)K(rsza?QEeym6h_7AmUDe%1>#_uL(YEx9e8gZg


^XZdfc$i|q>h!7)U`pL{#cz;yTv-QG z?%h}R03JSHJ&E+j#;cLO**JmpTBjyDML9RcZ6JN(GmtrYr&(f(iV31Q|_}(J_Ggrx_JkhTO6NYJwf>$dFR3>J%Tu^bk(7P z5=jNMBhnBaVd#K7!ejd+6U;7>rqGd@7Qf$wMqSA!EM)DxLe|O>tXINcgW z&TFktilFdXdvP2L6-_|V5dF}kf#s%-(lud+YoqF!RDpGLg^Lxm=E;pcN7E) zxSO`L0RLy6!PD%JIgX5%?@joiL{*(QURgjXz8Q%y5*wdMuVcy(7C+>earFIyPtBe>AcY<;i|2!(g;_?U)ZtltEBKM8y4sgR znYyz*h7JGo_VVf|&IfStMlC~nnk%C#U3L#i#l(b>lc2_RsQWKA*xPqFGc#w z_Uj;~R_xd(qw-R*+(DqILxXh=9qE(xqF&3b6e}}wFYY*4uG5W}9M`$D*I~Gnr3EpC z!LuR13Q(XuykYZfdg)w!?4`Q>oL`}C3_@$vSu*U>tcaD3liKAHi)Zmbwpif2UTpE( z7}V)3)T4s0V4n;Mgqyf5p^c&hXPDTFWCbd#=#y2VN+*@bYEkVN`{Z)>nXAtOdTVNb zS~nLLA7@abb=7{m^6u16{|?xOnBqSeuuR{o`t~jL-Xoh~gIoXT7FbmwD@CO=xG-cH z8jXrF5!G#9g-sK)_zMiGwU!#xa$!CsUqDD!r>;#xwelxw0?V<_yfSKHheTC#;t6E` zJ8>B44?8YvjOtKvgqkyv)^Lmv4c4Fq!{YB$8vml{1&1GZ0VZuW%Nu$T{GT|hcn}&_~o*L0Nz_o z_#O(n#x)bP(=KvPF%{O*Zbjf}A<`N?~mI1vnr)0gnUR;m; zKc;?v_7H+snNd0E)DhC$D-d z63o^=3y6&oJ=wiFPO*4vH1HG%C)kooh$rnG9aSO4xozat`|$A{T9YG_w2G^rE2 zqN~2O`LFDTT~V8nM^nG%vyXWfFgP5W7ZiIHn96`o=7p-}U`3)~(Jol=NWB zeB-AMN7D#$0(8b-jby=2=YZN(*m@qEU3?hc%szGM(Z`yhQhoGTJuFj8rgy5FrmNw7 zH8Z`CaZH$dcKUu=qM_3_l0s@{XwgUti@Q6KE5kzwwR^ot7^^U()2>71*`1wND?+$t0 Y$|wE|?hU_O4fM7G1y47qkDosNKk;++X8-^I delta 3348 zcmZt|YjBj+^`85E-|lAbCi^8}NwOj2+-x35B0-43O2qvLiI5kmWLkNYO$ZxEvLvuc z$Up;2CE=k=#kn0#YwJLjjtDc-`E;hfDjj8{P^Wat*s4FIYFlkrm`7hR zgTOq!xhaTnLBPj?FX z_74xSus7D%mlzw_%BrncUoswNpKq;!T@xQ2VJm$ku4`*DKF;#gK4W2O_3X~hIfVtCot^%tU+0bU08$aZ zgoq#6K)FBScY*`X_8oc`5gld}nQaJ!ps-lP9~2&jtlTgB=>?%&h&&bvIILN7mIsKE zEyN^;uohZG(#}F!YFZW{HW;eJtjk#*#-N;qfU_{qzC*>#NQPu$08Pv%(owU$`3@;i z$lL%3LG0NM!)(nib1+BRX=+iq-(f-V))1WcX_e=Fq|=_E(zXpZVkH3l?om&_k&_ql0>=yLlUc=Z(JcspkNAp8=F(+#%iQ}2o}YVxpekKQ z@b9G`Lz{XJC!p<-J_*p~ZYlH9qJ|?Of>V)kUz_}+=`g#^HOt?&N!Gh{o4oV|v|4}LF9}vGTMX0g+GTw}$l2Sc2sTH* zN$}z5B*BPN8=2-pSa<}a4?hB#rFWWy(;O%HD)}JC2i2JKuQ}74G-8DVNm+?L#~hGV zScR3EIPLCV?lVZ|deG1gdC+4E zX`*QtNei`SR!}@-K~yJcIpt{Kj2tbr4fRUPNpF_4(YA}!p4Q0xVk63%iH;?q< z482Ht2ikkRK8jWrUAx>qugs5TP%H+I=GPwX>u%M)nNcb}HYg1{tmbyisilr_j#X10 zL8pp1s0g10$kj;xSE%Xl*iI$$dPilnKzcEs;z4#HSeoA=HJ#}|I{sB!nFBj0l15Mj zGSb1hTpSda07AsBzW1$*-d}S-+PitHTc9NCnhl>@<4}cN0Vve$$4|UbdC`Cxt!V+t zwg+S>mS$pCsY{-+PtD8ii2C;@{bLBR_X+RHiDvSucC->Glk4TBVAZQk$XKlk5=0r z=QL#_X9gt@6h};0tPOj7V;ImqxAAY_{WFIuO?vUMMgD5(N53o)_B?gU41fa zk+)&hezLl}MthH*q%6cj>9x=!y#mA9pdu`4qL`VsR6jhq5N=SfoQyQoNJNwnpjpD~ zGAU7N)(S#uWEoZvf0+czwJr5VP-jw>zQdtF+f(!Sr{2RB+(LWz;N&DPdC`O$36Zr_ zOjl;k&?`Vy`|9R6)T)MfEm`eFudL8kSE%v$Plj%ZTS?S#C^K|uX;H#c#PB1 zJoF0ieLgp|J#OWNx3v+9{ZL8bOg_XWKlOc$wrn-(Z3_dF<`Tx7gs zq;mI49ohE`l6}UUA^VI;Z_-VNUI19?{_}7TCkNcFBPB-O?)1#t?UbyPyKom3`);-W zzE74M06dTm?LokU>4rE2cnEY-m&#iMrl4b7&?=_@r*u3IfLv zj<2Sg`qS~BLwi`(W4&{k=@%m<4Qd@mZ9%me1Vg8V+jAw2-7n+!WZFj3jFP5~nsY^{ ziM2iaY(TxaHl&vi){fuo=r4t!$j?YK)23GFLLi?qqatH|V^}M>$Am?s)qUV67B9Zn zgj#LFLdxD3-VFEs?)RbFuch36ttg1;3m+YV#sw)t(7s&?XDUx?hJdk zRBJ6YU)G{N-n5#s(9+upFkd~ixhUYr@}PJv^OmXMQ%$f!J$0%Mn$=%Utu+h=YWe8} z@Q&JXdKP56hfhDmOH69%L3&?w3;0Hp1no2|98F4(>pUT#YXg|6h)b|1N_V7O#lD@ diff --git a/lib/emscripten/emtests/test_strtol_bin.wasm b/lib/emscripten/emtests/test_strtol_bin.wasm index a6d4248a0d457a7b425071fbd8781b6b5ad9ed2b..e189c8d677bd65d04334a0eef92a54dc8240d1ff 100644 GIT binary patch delta 4310 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 Odw!at0MqQMP5&;e4% delta 4297 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 diff --git a/lib/emscripten/emtests/test_strtol_dec.wasm b/lib/emscripten/emtests/test_strtol_dec.wasm index 9219a0b6cb97378a7da5e912673fc01dffc1ca9a..071fb413088d8c02fe7c5e62631c5a92984a8bb6 100644 GIT binary patch delta 4409 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 RPnf5sB`FFp&92(?{{ji21<(Kh delta 4359 zcmZu!4Rlo15q@*ud%K&xOZFup$!0^y-0X$`At68vXaMs91SBNMm)c`kpt%}SVi01S23-vXkI4sFAZZVTT$~2CJi^j(4=mKi{`l8n zftvpJ>;65Y$PZXrEa;AG+0xe4(WFf^BU_@4jas@t($=v{b9o<^BGowgr%gjheeY91p@ow&JUqEsyTeZF`1d+?r8aq1c z>f4$-nw&hZ&fQVh(5R*GXjl7+?H!$~8#_C+8$6_LO;faSx0WjR>m{)j87oxP8Y zxzam$i7lKA5DR$)guJM=guNlJ?QgMn>{PQ5uQe)AvviK&=cX3&`ngL(E$ro9=YtUD zJXH(%Y^_R3hJC~t$N5JLrYohzr0s=-R!0{R7U*)4fm;^~hD>ClZ!*(_jyjSKYq2oU z5F)`e(X=&(=|Y#tLlACslbDypJm?Xjgjf%<32?JHvxGXZ$s6Lyw9&4%wVIv|bG#;Km3kKr9 zn7;*xm{ZYDL;`ac}w*{capHsva;kS)uE}` zdIhV%Y+G9*f*3R^e8ADf>{h~z%Qjj>KISWbCSkU$Tvi6zvU^zzDVT+`NWrCLA>t(0 zoIx+T{d@?(QVyk(LwJ=#XzB9Jng+LrB9=tkmeo$?UNroC7PwRrVzn8|g6edM!^Q-m zhO*_>}VkTx96$D7iIr*p1FIUFFiF0(E=(s%T3-MKa>n}f%mUh@DXSDwWtFNN3#)w8t^oTGr;XzJ+k4kCYUCF`q)j3i2UO_^l7AI;P`1MidTPU9MGn9 z-+d+f!(7a3q4ph`rfF1sVLQ-i2f9SQ(olV(hZl)bEEQ!+WBkI293aMGTr8G4CjRmG zdZm2L6H0C)ZWNmwx!*mpRLMm#Dmopx;-^}b+~8BKpjcfF1P8zHPsTviSP;OAO}7MLXBQs64WBC5<2KoR>D5 zYucaZastpPpgJ;5`(M(Is#O`COXG!TR%%eZ1o)EE)z1N*1M50D8ZBo1C<{BbL%AI6 zSP1jvNXG<{|GZ-!%$DVyCDv#zJ_0S`QNXvULhVucwa(>mtsL$whZ)k{wVH%CbghHA z^69PtQc}BXEzOVbnggZrkzD~G)@QqSt|+IzQ;1WoQk-M=_8J}HBOvgX;B+Kle*_k- z6LpE;_?Syy%oyj-0oGmmjQ2MlnOg0Ts{}a%V2wN z5dQ}JH&qEc;T%-vFd4Xk}2!d)Zac z>SYA22m02)GWoZ@Fl9WY|JoZ%Ic9|E!8X-#%DHq2RP@qv`Z2v{G}Rp~+j(+PA7Xxf zW~Tm@9!uFP6te!RlbIpoDl>Pdrex1A6OpoK!tqoraRql8BneY<7W@ehDvE3Sx(LB zD@UG(nxH7dGW%DWdI`paPWPimcOR+ugRY>@tcgNXZ=x^LcO>pcL5~h$sEpa~kCVsN z)@5Bt7KC*}xNTEplCDhKq@ODGg=CqtZufPIL^3A(d0Ild;kcf!o}}vi!%`E6Ojq@G zbt~^xt^8|4O?($K}BF>g1V;Fk0XuVS2HQ3F1iA!6X+VqqBF%A6h{IiQ&r>qQbQoQaq-SG zgUoHvwa_X|nfy#feA+V{TsM*cNLEC4!?U9 zq6NnZl9T(NEe#s#_fwKaK%+a0o{G-~K(l*2d?+AK{b+_<`=g8T#V?FN{FP^SxZ|_W cRsd_tkT0GslP6yadejedx9&3K`IpN61F{wb+5i9m diff --git a/lib/emscripten/emtests/test_strtol_hex.wasm b/lib/emscripten/emtests/test_strtol_hex.wasm index be2d48a0f988742fc01764f3a04e328305f2a814..546f42a9f748007cb55f2ed1d71820a2af1a2aea 100644 GIT binary patch delta 4440 zcmZu!4RBON5`I1Jz1>aTl6`DUvRMe}$u1-W$PWn+4N6`hA+V4{f+8p^Nm$7529f}R zAsZoR@h5l#LZRNtpXX7iz)~veDHeK#px&L{k9Ai{PCY&Uy;HA1EWMuHaHP)LN_u8` zdU|HMzwYVx`c`%4R&|%h0}*8@i$ox@RH1+B(Xb~1J@-#4PSqljNH6p*Rg|T&OG4~| zntK0Bo(NMz;Wb8hbz58I>TqMQxmk&Eh7I9d<=KP5U|UCHYh1#hQCFzDqO-HQV{nb+ ztm|s5Z)+KjddDu|i$jh)RayF=mN zicoj3DOA5Q*wwr~q-bIT@RGEl0-Yf_6O&Ou9we>4p`)|ACOo}99Pa3z+1asnZm7MZ zbDaWWKg<^{R^B|l95kkDz(7$z1I1=jRh5nhng*Z)fMN&c07pV%qGG7dVTz_eQj(&% z093g|HEB(Q837+Nh^R&n_%um$8d}OVA|7XHkr~S1Px5z7iP5LeFk=HumlOYO?Jt3A zIN2i9*%|JT_OI`5?g%UC_Tcj6ZL7PQlnOn#yfYM1u5$(3+SarO8@kq#VVa93Dph*0 zy}miDxb4)o(NZOudZG5lmFtv>S+Op8P?@a3@O9K3ALcTI;Ey&L|ST1O-AfQZk{!RJP$#qajH zEmw=Ra+U1)lB=~cR7}M{a2dMdbGr(Q2%wY;wQAMYvnB`nUjq^BDN8M6lOdHyG76P}Uoy1HMbD)F!;$jJyFvv{A zMDC9>4K!%2lpKb`_-IVyNtk45mE46c3s!OSXZnfknO@BEyDi0KycdRZ4td^l4mz+I zyK?-zrl~~V*4qHw(F(g?rKTm(Wus=j$@P@;OvhIkKhF$2&n%^qUtoAa98Vbm=cBKs zfP>`T$QVV7#pk1T65Wt_o@f;=B6Jo zrv5zw9%FPjk$vMoV6QN5dX?y3ZYqMk(WGh1fd;F~HWR&4wt#4z)lc+oE8n-58HSGA zfoy#lc!KOn7Vc%(&t~y`4EKrL@_&(Z#&j_Mp59&}R-BC{7C>Y|60s_y*z_08!ZlY;=#KbwiT(4Tj z%Ft^mReS`F(8`=(ppM>Ff`ZM`TFCjMCB(*{S48Ga2CsN(P75h0!Xi?TJ=aH^z}!>l zM!U;64q(cCCE{_&zDWCKRyW#pvO@wb+ftnqaiiukioho2ZKzm%O9K+pTA4**(8^Wv z2;C}v$p{A>$tkgzae{OQ2kXpua$J1CkWly>z;HQ}{L|eHOeW|i6Ew*kisf(NqM&98 z*u~D8F{!B(7|CQfy1+NXRU@MH>ODSpbkCzf2aFWoKCvw~g)w?XNVSRzf;m#2%w=q4 zkS6!@5MDHCMXS#tyeI3^2OOM$t#P}h^E7gKnx$9Ly#^d&_sO+9Q^u0ZNCs6d)?yk_ zUfpHPgGAzqXY2BSi;wI41oNc%*%Pw(bUL)Nh0nkl(iat2f!StO>?(94vZ>@!_)4y5 zn12wmgnmmV(b2ao1E1J>%PQ)BALER?bwjo^IA!BX+Eg*C=u%9JprWH{#4q+cfE0O- zZ)+~h9y916b2P;SSkFU?JZe1YD5#pF;!9ld+c0wsC-=FG|2pY|4407ycB$?+wPSM- zba`v?rd8V#)0j9*DwIiuvY5-bFAgCwccBdUcNW&dIFYyL(FzaQvA{|oJJQk*lom>T zX{b>IU@rF1I##Op^{7XEm50S^1=30EWPP00`&pZ6U}LZ?)w+^JT*2 zKFY$}Cz9Gv5c^DfA5kkjrOYP}OtDoVFJu-NIG(Ep<`WFb2p4nJZ&@U%H-@>(jQ08I zBk)XkKcq+NIwgyRHCC6eX*>h#p&AK&*FGzYgrHRB>$WAE79^ z@y<^eOcL#PEo7H6#ksp`W#jFcdflZ=-TE%mAhVqSf`qPHmor66Pi+4Ap3?D`GWj?Q z_!Qhl#Re|qrOqV9Pz+W^!TK`b%OLIi3g9bX`h{;p9&8lzHmrmaadyKDxIs92N6MYX z^iG9h(b!us{8A}fPF{s0ys_D8@UfjsvE@M4`T zVxz1{e=_6yxQ$x8%*d6tYYEDtS0-UFS-Fhyu`m$dZ_0Asl`zO#FHPD}?Qy^U0GLD_`iqTseX|QGM8gQT724LT!LkX>mzSi8&GX6vlrNm__ z;iZoa!DSyKTvlwK53|Mo?S6vGi`%cyDKs$EPsK-WJR)TZCPY#U$_y;?7iBs!)>MHz zQax_|u}WHxYeTdi*GOyij?&yx{+WuOspU!?@4+6j3hd|iYIv_^mhw+kYWWqFY?NYc z5z!q*$y=!|*@*__pxqK=Hr?7TF7LQge~9>xh&A_()elqeF>(05qAAiGx=m0`vo7|8 zuCp?#_f{CZJ%IN}%xnf;s?*Gydn#dFH2r~UyVg%N zfoOd=D}_3>0lt~xW_k#zPT=!&?2jIN_%wsb(K{YVl3{n%B4i192`ZT+xEWPYc!4Y- zwjG#9SAX}wVsiJ?gY(GUI}cXdj-f?>7w;dOL6bR$#?j>bL$}f7@gid=`c5&yx% zGl(;AIP0po<47?H-gu;u*awa*BY(8=Jt`LQ2UMi?0W#QL`6d?OUb3rk)jRu$XG!nS znf9r4rm2r&rWR-n*{s$VAO6=eJ_7XZ@58z(Z{ zBzpBxxuC*$Dfz|CqhOjCHt!F58tt7XKAe}CnI_TeK~D_51ZK*;vh;HCET^WEjK8i4 zW{Dkj+4cbdkJRG4`LCnC^svt%g7QF=DZugv_)%bGc$6Gvri*j8w>xwBG@Qn(46HJ< zg>}a+$Q5tiafIldiyunLHe1SdVkhs8$$cJbm2!)gx6+X|0d4|<*Ppue7bYMkk<^V8v z+z%--Sqy!|`s5>45p6QYVv>B9>5VTF&qM>YZcKFHT^-nNWYx@M3ku-#p;4(g9kS!hXw_7JBR>-o2XBg&mk+Gnho=hrCdAfWu(?#oo zasJBKJ8$chuH|-}K4k0$rb}OY(JS9h%`6blE+~K*;?o7bsg)cNIXLNqLNW6>M;?D> z6|<7QfJT#iR;-jX3uH&;X-dm?$LlyT`?l|=O&iRHWR;)P1~yr!AjqnFU}U@klGtbF z1ge2-le@Y%#&&ty&@^AGb{PLsZ9T!xuQJE^G6(aL=B`k!hWlfL|9c}X(j)n|&m zl(p%pQ7GJ*>=`e3fU0YU@suZOe}1Jsn*Hnmhy$k!Mb+tx(Y0sGfVHIxczLq;@?{jB PS0*JW3NX#C+VuYbr9TNZ delta 4459 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 diff --git a/lib/emscripten/emtests/test_strtol_oct.wasm b/lib/emscripten/emtests/test_strtol_oct.wasm index 52c00a59d6887557c2813e1b0c0b763143dc0e94..4e5d3b97c43dfe7411ef60f76673df979b26bd51 100644 GIT binary patch delta 4409 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 diff --git a/lib/emscripten/emtests/test_strtold.wasm b/lib/emscripten/emtests/test_strtold.wasm index 38a2819f9cbcc969091aea8317a233334cee494e..2d9da6204f45e38d6152580215ae2c7375e4e909 100644 GIT binary patch delta 5376 zcmZu!3s_XwwLa^dGY>c;a~R|?gTUI(AgF*K_yi&ck@$)rh>AuL5S53hps`xQU@k-&I%lpa8?Gta-CpoZi)6na{EH;|rydR4{Ln_UjVQE1`;H8@V^PjHNm``(=@0z! zB_&3wYktI4U9+NPb@}S*+QyPc>ROgGtyn9`f}u69X=*B7(_C9sUoXi#5~BP;+*Vap z)wH6vF*J)tt#zv>wY1DwVIl(rvaYqZx~VBECsR_yUjKxRHZjNjd82YnNV^Y(CWR5Q zra5%nJle@!RkysgwxxdM>bmBtrFE;Tmep0StZJ=aUni;Jq?rEv<#o$zSFWq7sb4Bd zf*ISN*-|G~1=mZk<3a)eKLfLPj$G(}Xga8}MFklo2~?1*R-4^wv)QbQqR>r2RRO{* zVGyo40HgsRM?i#A*QH3sWtUV5qSS!^idd{f)9M=C4_;X#qG)a4RRyuo(2#zZaH|qc zCNla)3x40LXJzeCm?+WTKU&*4a7L1D>RMWwR|s=dudZLwEV*q}OO`aPXfkzCDD5?y?DM7fNN0>5SA85oNhAv{*#e=+e97>6T5c$~oh&%`s)jhP|bE$|IVLDOVmJZ6RP zc!76Cn~ae-2uFq(gY=nvi!D2HI?Kic%nqRmg#NqDH-{D-FxQO2BpemuCW*~nN-`ue z=V(M6E%3uhh=ilp=Q1RxcC#5S*oA{%u#m_j194!d)diSHTk|+%_RtyeqtxlsYN5a-Lj@x@JV2HybCN$^aO<6 zGIq*S*lrnj^L<5M((G-MJha)-Np^(>fyuLJ5I&_-^}E;)=vYHLv!Z0=HP9U)RhF2H zvhHCDT2T>qx1v?IGZj@mj#*F$VR33tTcAK#t&ohC+0SU1BB2x-*ue6r(Hkg?3t1v< zKZr8RfEn9uR;Ht_$MNT8c!znE0=WP^hBTSQW4v1601YkZX=FaM8fpVe#$<7yA?V>> z%oq(Go?6mC8)RcPZLp`rOUUVx6BK?nr*<4b7Z(x<68l{Ub&2mNt+iQ5V_~%Ho6=Ox zg{o7_2CFba#>|-MZXum1te=tBkhOvt)d9jz42tOfQOqTX1D)FQvf}c~?P0_SByAo9+V5>jhCjXCP5|Gu zWf3F={xkacW;jDw^_|5jxOlHq7zMOY+^Jqaga ziawN_ToUd>MiXc_JqCpGE3*&6P`-9f64CBCi(weQH)j>~o97B->)c0ET;$AD4HOHN z>1CudS@ol2K}9p=dJiC4++%6krKv-LF2JmMns9yN4SN0Ps^UChCPhy+mpDynWIdfp z!utPki?8FIS_as}c4Nzj79d!J)Z{-#X)u_K@F`+L16G-~`$Co@O*asZ)6xGW?x2^L zdq4U#EQ_8oTA`2R1FtW1xNx9T+iJQtKQsRc$6HQiHx-0H#3(q^USrR6(VHyt8 zGx*(wTOpfos(J;o1G$SP0}VQ>yJOnvN_sYH!#38gVY`u9%>3x*Sv4N8^XWB6ba~Bu zntZWlGxcZHj-u>E5oyFw{F5}2p2hdn#uMvg?RcVhYO85-+2Ul#;Xhhj3ZwYN#rd=( z1ylMjiK#oz!d~6U_5tpLQ|uYQXMpVoa+>{=A>UUZOK7g-;ZhjGpLzJuq&VVa8e!y4 zbmkwV1{O;XoGPv`jKyh4o>#G=fgpqpkX!c-QtFdx}h^gS5Iw=CG;d*PSPY;nM%|wgkGW|SPpON3T98vH2}Wt)($aF7&P-}}6tejKhC48t zZ*5GY{;9@0;O0F|v%npI>|{;Rb@`pG}a2l-A6 z-?*+zG!g69QWMy?e!2>`0$17>%Gxc!|Cfu|r+}aG{0;L7-m_sQWG1k)3exY4q7P>0 z6k`;IHL}O#A}RQHX97MZQ zjOVL%j&S7CTVi8g3uR+3@7eh>!3&@2AbR7eF$G=`8T43A5|N|lX_&?o4M&hbB+rdu z%74rLh~V46?#gt|S@S!>`~)~lpAUTYuDxW8FLu!*n$HjJo(3ZVf8PBkpyt}%ZvY

?f?|= z>gS7~m>+t69u#mmv<(XRjzhUHkzYRaB23~xKD?Xe3_LQI`pb`uh5W#wBXK~`nHN@- z7EvZ1PRT7F#~K|SYAgE+C}xR{&FNp$ zbl!1v15DuZv9gE11@aQonc-(vhgHLGK_u+&0KWrL3tc6~| zT`v!p`#k*ZmuqQ|^2#H``ROYFwkIqwmKFvYc67=KA5zUK{3J$%xZFR)WwPHVfm!sq zJ@$l;%(vjgxYT?NV|?^6ILv&JM0rOZLiGa)OZ6QExp*V>$^6X|F>x;TN0B&=_fH(h zMdG-9A~*g)c3Z*QN}*IPo)1zB>}4BO+^Fgg1`1DR!x*9Q82Vhvr`BaC)T%~@Q2bGP zfJyN(?v(MUOqSUxvnmUIqu_Bx_XT=hJqqLpb6$Iugbz4hKMGl5tKTS;Sz;IF@mfG}~PphkG)#aQycRjs93VGn{>y|U5=w|u3g3?7fx|%E>U|@J`>p}R7CzkglSKkzwvFW!7E}HuHTIZ4iX=3K0S&1->`)6IT#L_{rd~QXOJytkX z96h=IiWrFHyDFAJIsdLA#nuN9ClzQUz75Vqt`bwIv7}u%5j_8Mk zIkj6dq=-$*D@TTxhysu$X!=8ZTV)|7L;8kbZjlV#{CAbZeWk%t!P+8j!)z9`GMk2O zaXk-uL{?PwJf1c$6K3!Q^SpVbj6OygIOu(o^jyY}nF&QaU$1AtEq?C$Kvnag6!`G^({ch( z@Yz?l5Y>Y;ZgmS4tt#c^MrH|Yy`h119;kk=l^^I!N~bz>fX8s?^abkF^l;i*L3O%X z;59$bsPfSrbbX3!n!`Wu%kfZXQ$much?GT7dom6rs@}EExIpeFD{ar_{$36o`>X)u PycnMKr_llL?LqK2LS+6s delta 5431 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 delta 4263 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 bU=1lE>Fh}H^;y5jI5(n?q5#wEs!jhNIv)0+ delta 4373 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 G)Bg=|Fb-n? delta 4391 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 Jy#CVk{{qKL2>1X1 diff --git a/lib/emscripten/emtests/test_struct_varargs.wasm b/lib/emscripten/emtests/test_struct_varargs.wasm index 82667ab3edc92cf39f3e629d553247890819ddb3..607530d4ea9c57cccdf21e3e0c82fa077d910be0 100644 GIT binary patch delta 3726 zcmZuzdr+L!75~ot9=q^u*e^?9VG%f&T>|nZV1h*rUwB9ihDhFM*#K?`j{xD75|Kp> zv8`#NUJ@9s&zKpLYK^XTroNg^)QQQ|N42dTXOyY0noc{`M?2Bh^xRz{jQag??!D)p zbMCq4ch0%r$+K+oEW14=4Z_Mc77jyro1$z}XrKjg#={sz0DvX#j;7PWPw--iIo~3lFbyyRR!@n z25h5_9M6_YruhVbORAaQWBuojB2s(K(Y`qeO)0(%R4L0y)>?3cCGWwwVlA)kn7Eyl0W^%PQI&xgH6uX=U(7 zocM^-b}eU$t#H6o&OmhQ-)ZnLqq~WhR{jm9#bZ@36CJh7U^?=sy&Y(=qjA9rpuw;yK`Pawb_g&2TSU&1V?Sh?i?VCFy5tePry>vsH3l&^3Co&qBgHLR1>>>kY zSVjh3YV;H5Y~z#YL5JHs4q(Z1WeI&di=SWD?$9X?aio@eO>WqOn%gXkWxaulJ+W;K zXUMcFo9e2YtAq&MDt5^*2OSBNXc4+V!ok6QEsubUEf`W3J_E2=?j(NqbQ2S~8xtv^ z2@b^$baCh?@R~N6r8i_?M)?$v86TJ%E zh+-uih*3uG!BJn~?v8$M%a&W&+ z5%-JpEsqoX@!$l}W!qL%`Q?=;U2Cc46|2O=0r5}8wJBk52eE*U<(puf>E9T!*%t_)W~rMMxS3YC$A;WAhuqnnIL6kG*8 zwo0RBPsku2qk5tsGn`_0j1dY`j0bi6O2y-kbrE*fdORxMSZ}+9cqlxc%0QB$^bh;rjshNth>rSL(EL^42;Sjl})~(@_3@52O)8oaPble*e2Y$m~dF1Ll6M)Z0gd!m?LGQTCM@G*&o}oyH zG0{X~NM$%p!89*GGDAFDLPCzrsN_iD3}$+8 zwcGT_o<2^wM6Ny;YeVmAP$_ftM-Qxk%f;~r8X@C}2cHMX5WhW~?jgww-R+DD1yZnO zLk6rAH*R=S_tMc`v1wywrdQ@z3Z_JJj8cv|miz~B^DLL9lg!k{9Z)C!w=u^t3y>nM zjIDn=ckzWsZ7SbV?O)`(&4dM84dBeztWLHAQ;Od8%xR zsp9Re`GIQgMK2ly(hcs=(clgfQ>9-%^vUk1StTN`xdd!+ZL|NfYL18;T=W;FSjC(p zk2O-os^(dkP4ZdM_tz?s6IuFH={Ln5Kk;<)e|;Wj+fTYrqA^hjEKAw3ZW^$N`` znvWEvexw0qBaLeqcI$G|d(x!%_*kCa^GfyQ0{be}K6UmYH Xe%bGcsK;g@vOdxPFedJQ^6>uwEofUN delta 3864 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 Z^7W?&oXL-#`a2{WjxGgQEJvT;_CFfVZ)yMl delta 3717 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 delta 1794 zcmZuxU1(fY5I%GN_U4{V_a-q-vfFItWH;NmqD@WOJ~VA}lQuU0frKh5Y&Pqr&1SP3 z?`~QHEw@N~vS9HF28vQCh-e>#^+gm~5g|4YB7N|o*n&Ukqxc{wBF@=OY{1@!nKR#+ z`Och~IrqVb@XkkYwRMz%HwPY@Q#_AWB-tEebDBpVc*=KbtC}sGug@0pY4>b)BD-94 z*O(%)J!iA!*jA!cwA0crU!C_(QM3^Drnjt*>s-9UL| zUAIt_wMds2iv<=Aq!t$PtEF>H=&1!an`O;WWIo zy7W|O-d$n|>!r2A5c$dS?+^ZG^evLz-IOhr)ARYo(z$BqW>(UfENkHIYGJxqD$iug zB^EP@ZuXp;y}%m%klN!tzBifN*V>XyCavo?puHQwi&+9<7P4I2idjx5=d8ReS1~@R z4Ir~sju7HHi&-IVFl2FyTUCV+=e&`{f({#&p79_d^_)Kiy5uy7%&u})nH-y#oE|0= zWI{y{8X9rSVIlrQ0X9t;v1$H4q;gNq16Y;QdR!&7Y=#U{m-Yz#;FhA}SBltDIBqGF zgSeyM9fdOa(iDUEg(-%Epi5&&8qeTX<(nojDf-(;lqmh*_Ps&!a{C>UW6|eHz90Py z68?J~7a?&YiU5g9hX_DRLfqHzzUFwt;(>+_G&KIuPaWot)C%Ujp=99pP|LW*ri1?q5=7^vddx;=979(VG>=U#w z5aJ&L*fOC;N(gr)gtqE;j%NZURjiJ}u8enc3$+mM1w%IB*7)A>u)JOEvYw!+p>9>j zJ_xc;0-Vdu)X|zj103R?0W`>+rbiqmCRS*e-keB`w1@yUQMo9)y6xbHG!6|(!w&y? zvu!w6=#V|TkYI@aqQHKcBuqYS31Oin+PU4~ADbKuMr9pESf|kn`>#(v(cURqumufQ zv|_6W=xB%l$FO`EZP@1Dojd~Q^Ql;*Qy`*%AUzyrM}YuOb><;V;N<3);&nf~e7 zjsvz5c7k@m@j^UiRts&*Ux13*s5W5J^Ppb{ZGap%^7G%C?c?;YsBX*wTleqIUilYq Ch=zOs diff --git a/lib/emscripten/emtests/test_transtrcase.wasm b/lib/emscripten/emtests/test_transtrcase.wasm index fc14fb98b32adaac56edce5d041ebe5d510fd7a0..fc54b2a415b07ae9d666c976cdc88ec509eb4bbd 100644 GIT binary patch delta 2133 zcmZuxTWpj?6rMBxWq12;*}uEA-R|}>(=Bb0OS|?G6_EXb7NN9=EiDkqcDrotWxLyM zx5b*uR)bHPD9%GM#6Y4Znly+hFA69xB(+V%L}FADFc7>v_@EEo;)7>)TWAP>@}D_# z=A3WlobSxMeFbh@hPS*NGNhMgGLY#d_@hR8)eL^pKV91h2m(czqjfwS>gx+RtBNG``n%hY%@5|0NP>xm+f^H65$tO>F_`-G8!Hqd?`j$u@(3e#j71s zF}afUAs`P@9O+A@()$xTBZ)*Zy*rgW-X0rCrltsp!_XzZf*sq|*Mdql6(|q_Di8pQ zfA&*!)drx*1w{v<_n8?8Py>ZxOhZ65rp12h6*E*@{tK|o)`bf6ur8dvN{yFcC&BOj zX!{t}6kvw2R4S2_RgI(vlL=B{3-|ZOC&mZJ1})s5ip9uUEj$t#Oc1vX$2d9?4{EWI z=;#!w%W6mhsn^2eeW_s*%sV!PDaPaB^~l=e&Xw69ex$(@8&602;)CM@o#{w)xN|fT zjgbPeOR3K^7B)5ci;J3?n)1HC2(`5UnSh%^z|F`|l{?_JTtn9AnA8HE4mHGxNel)q zLn8sV%g_lURc<3MJ20s77&8ExL{Kr5Wf8J*7L#$RWe#z`K^@}MBAhUxt4}po`4~01 zkAb;aYADnyw?$mWodhh{CE9`=;mlQVrb*@})i{8A{;pP~;9z&SbR4`ct`#m)ja{RB zks53f_i5!zlr4#lwSHKfA6g4`^oy64W3YI=>`j#Z@%8m zs~acHEhp7NH-AJm#q~W!TYOw$I#c9Pb*7tkt}@m1a*fF|YcAuA1|dnu4rHT#6&v*? z5p3^AHl3TyG`-^My@AJkN{EJ-&mzxoKl7_0Cm2j)zF}U)bjklZwyu^EUd?=>tgRV* zqN{BP0UB5X0$ghgpyk)Li_FbzF5?1#DfgBA_)t@cEBm504eQ{*u$uPTN;gwoMg!>5 zUuVRc>22ebQ8i>?lMZvmED>YvrFGcj*11At2qX#Uf$eq)pg>MMkJ#pN`zYANrjBZN z5w|f9)&tLVodUyvdAfful&v6H$h%`1)nzOxun}EEYiBty5$n966*Iz$#nW9C6~(eO zz051mCeMn%l2#Y5bgCNqOm_`How(OkWBU=nD^ZR;cT>-RQ>tfs8lh6$=xK3oxSy;U z5H~wmEzey+4YU6uBQG3SzCE%C7K|aoiVI(-`xxu87#km8REwdGYP<-iI!c>2=gc;| z_NB5$7BGs}v{s@px?A>#RgtzTCa_1aKW1}0iC3R}GEYRIEAVaLp4GGGLh`|d&*fQ2LrDX z68H**Vp-*PyZ`flLcxzZFU7Wa=nWDr2kMd5$pd$sZbtFJf?U|SLp7cgYn7U65 g1#;J165+({u>;XZoIl!VfP8oz$h1ktZ%04)A3Z11K>z>% delta 2202 zcmZt`ZERat^`84a{qAf0(yWbR=i}VkX`^;q6PzVNZ5O|G&9<~@y(DW3Y;)b~qYBq}I)LP%_42n|Xj#1AHcgxIET6G$Ks`+>xV5a-$n zjl}McbI&>Ve1F_`-hi*Y2`?q47(}NbVyAf&5k`=mHX}MjFvfplB#ct!nJuMCxmbI; zG+jDZtzBeX^E#d`HRh^~VtIq9^3WHxp0*axRBMgdMsa@m_%o&2Lb-Z@8CpkFR?Fqd z)yjNfak0(WvWc_7a|(q*xjMhRu0vG4)HqzL9jmVEXwJp@e6d^}869S3E5bJK!8UWO z&GhdIJ}}y5iMyA~a#+?@B(2HpUv*$Y_NOM8J(7+Ut3V9;-ETnBgz)`bYMqhwK zjE>m2om&ueQgo$Sty0w$DK-|X6_#`g3k&7d`dPNeDlF7WCAQ5foGUI?SeHY0nFQHA zgq6wW%Wfi+kM}0J$H&LLzrGH;hXA6qCn4=2 zTgrH8FN`mRE9W(q7RSsSvcM1sabdBv7Z)}|mhptwx)3r#Y-MRbWRqGl;}d6#5SIZg zZPX-d*fQEO6(X5ZKQyMt?n@#M?oT2Fdo@PD%y=P-i#rv#%ri z-h03$?UCMoGO6-?FA{ve?>512_kWh4J@8M+D!^wU`^`%TkZnfNf$pq)*Ti?tFq)L_ znfRVbE`DtWS@rcD7u>A;$P8JKZT6-=2*CUP=ox3o)1?zZQr>X!h8y~0oP|sR-f}ao zr@yD*HBJeu=lA^)uB!U}Ul2TSAPZNU=MO9Z5x;%#O9Y>qI7#pa6ITfC%k52HM;Y~do)}wQfMnLYT zD_D~I@SyA`^Sw(_{pZn_oR|zS2zu1ZQ|a9)Bgb=?3fUtviAgi(gFp*Y%QAy@XfDY? z9Mtjb#FV--H3liwb7YAOWHCzyoL*t!V=)7y_Gb$0D!BS}L;-D=Ih54ukh!f$M&jTfgKZE~q2`O{3Vzvr&pfO>ld zonLW4dTj1KHU)|M+pi8;k<=v?0&-fYwED|zANlm>J{=9}RP;6k$fz(zFhq_58d*y^ z7Lgf^&=_qz#xYJbI_OPObT$cg%9uqoRKn;yjT+TWU@R_T>*?PuL`Y-)Jq{^dh~D+p z73*I}NV}^hPY%N_b>ZY4-$Nc3?*k-so=-jYJ7>*+do}*m@jYYO_7qbC_~8gN(ZVco7B_oJe(La0fMHk?Ff90PRxu# zpK8n;-poMFaPB}`x^!w+*P!gA+WFd{FDMxv>`>QFU7FY_J@mqXRlQxZgS_akQwkJ1 z5FTU%cEp9jKzwL|86giZzr|XgFj9AeEzQq;<{Ixa!?)Nnb&_m^ZlgvpXu(9IChca| z69VR*AnmlP_l1P$W2XhCe`g8}gh$S!K}%LMa{*6=e&B>rT%_IB#0NkVW1u-jk0ei@ cIz52idy-QtPmT&x|I#rUw!l)~eezrX1;`}UHvj+t diff --git a/lib/emscripten/emtests/test_trickystring.wasm b/lib/emscripten/emtests/test_trickystring.wasm index def39a82483549dbeb2ebe57bca6a391f817d861..99c45e80029daaf7ecc5e696e9d284673d627486 100644 GIT binary patch delta 3660 zcmZ`*4RBP|6~5=b_jWgVOZH_$vdNN=bF)hl10jKgfF_u{5JE7LNCK#cU6QbvY&L(J z0EWMf8XOf{ey*LMjMl$eM`;aR+G$7a;Gi=IV{6qqow1{cwkpnaY@wa;XSC<;qGVdT zGkfm6=bm%!J?A_3ocG0f{=#{FFgF+CY%`C?A-pJue&9f#eA%B$myZPw%TgE&8{ zCZyW3h_4TDVvu1F<onfY{gK}o>4}=Hgy)et~o5_rYm2^^%u|r1- zfXTzKPC9vGcU>*hxxsYC82}C7aA=wan#OcmI2m^_S6X^Hn3{VQ=p>QBn5INE56O00 zaR_jeh-U7FfUbx^OPgIG@)7P^(8MnP6n|n#lK$!>H}}8_wej8PdLzte-WdZy6t4L2?S}mF_DGS~h2eN5{IlqkW^j$t3A?40rW}S*CnktBkMm z=B#RIY01y^wX~$a{W7mD1&9Z{0s>xSk)Su=wLKAgctp(tS#5d)GK-lA9@Ag}ug7#S zWI?Z)o*WQ@S!OY4%78|iR?Dv`^*FC6n@e!2zPNxo3zjFWgAKrY9@`(3Hq5a)Pf(ysP88x*cy8@9FrSPDi|{TTQYeu*20P{z_h1O^IIwKCsC4 z;p%Q@saJ*4wEW_j3y-;McMWIcIpAqmFuC>bIq)q5aSNDNZNi zJR4%77+tm=5hYlH#fmwVC~tIWWUprB20HGCD<}21SA0+4O>_wdGP^E97l%^L1V?Vo z5gIyBQw}-MVY!4(Smp@>m1l;>JZeCLg0hj2telZ3l`2shZH$OI8mx$@#YQog%;!gh zJb2wfr$bn1S$VRgHBjc)8h8WxZPp^@;2gcd4JI1s?-xOIC}-y3JawO9^vki<8t}_! zTO(wk3aiLK{`CRkG+ciIz3B9q(*TybkjiaUEQ$+V<5H$( z#`V3%?tnM(mj^;FD3Emz?=Q>doH_s*(vTro1uC2#^F9tfWj&XYMpv=0A9cyDN4xSS z(gfwaE}XU@e1yBtHk$PYdm>G~^XLwNA_Fr#W>)H{>Pd@2q2@6=AYC~%(XkMUdP{IgQt$k_JtbbsC91K_Dtwkr?s7ej%s|adx%@gn zwz}bkwzJn2ClL@1t5{{8{Q}u0CzM4MCCw^Ksd!R;a;rozg^4?b57?LHc&L^c%G~p9 za|%xBP_Cj`L0FxG87XiMC` z-6`)@(%Wa&0uvVq&BO`W!k@ZJY#PX$t;w7S6Y?}VUQ z;Z-!X%4Oz=k4#)OatBn%XGb~;zXrUMQ-tieaJU^Nehqf|YVi%=H$Y+gTIR>{g%=%H zo{~*vGVSuS@|X)!n5~Evxv%k?9`iYX*$TvwSOJvE1F=4$pU29n$d-)y3`*hp+voFh zei^;JhZe8jzMXbfjRQFEHDDPjCbDjtXa#|;oKi*Xf zOXVMT<-yX#r@N{kQ$;KXvnjp|y|zYytJvf7RO16&gbe&r!)eW$n^?c+8GyxymZ6~y~M)EcytH`xs1iOrL3PJNPEllh?OQa@Lj$Em$jW4Eg18wWZlvF9DU zl`y;OUD%KgpNF-QB2MdNK|P<$XmpN8a}8|45$W&OtBh2p|2iX z?J>QoitnY2p!>c^MT$zohdR`%-2MH-OW|tic%+>k|At3?2km}QgEjVBOm)z>&?w%F z%#+4{m$S1PEKqs75V@+wg;=O6U@;b}N<{6Pg2=5}`Q{C889oY}Paa!aSm;xmxtL3D zkg4uXB~5)Sctnv~H%R8f+FodsogF34a{#&Of^W3HQ=0i*ldeAtNMW`Fs(ZI!TLt3n$)*No~oL8a?ytQ!Fu6CA39>{8p3IyLpV*$Q}^MG?*;`65AIaa42F#H3hJ&A21g zAf>(m}zhQXu&;j6gD` zA6eqkV@G)bP#1EI#fVx-nmZPw;ObQ6`-PD>_M{1pjbtF;kT3qUu$(&7EWhox=zGy) zTIqC>hWhn-Lm>6tL_N=PlaB-u$w>35YLm(;)j?*1#pQKRRU~eHdf1s5f9f10UVW|s P_@->RcDhE|$FKeme}YFK delta 3577 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 L$7-bZ%-sJ0#=JVg diff --git a/lib/emscripten/emtests/test_uname.wasm b/lib/emscripten/emtests/test_uname.wasm index 097a46649bd7dfe2764b8b65ffb47e42d0aa385a..c28801d39b0d2a728dd42d614a9a1fc5c92cd9b6 100644 GIT binary patch delta 3736 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 Y^`|?X@wsP$z#q(z=g(Bgvu7Xq4@071iU0rr diff --git a/lib/emscripten/emtests/test_unary_literal.wasm b/lib/emscripten/emtests/test_unary_literal.wasm index 14042277d5aaceae6ff8f8298d258282644cecf1..aa7695bfed0bea23bdd31c652213db76ed96635e 100644 GIT binary patch delta 3622 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 SpQ#4E$R`h-Um$y*UHU(YY$?wG diff --git a/lib/emscripten/emtests/test_utf.wasm b/lib/emscripten/emtests/test_utf.wasm index 92e6da9ab401b29a58a4c831ee28326091897d14..6e0f90770d29526d7eae2220284fc434e9866138 100644 GIT binary patch delta 3605 zcmZuz4NzRw6@KTw_jZ?k8}_jXyDS0DW%-kzfPws&#Dqr(MU#>QVv-tlLtsgOWq}2f zk`NaoXrpNZxrx|hYBg=uX0%4PQ>}l46VpkP*4i2CIMeAg*56vkI%?ynQG4z#3S+x7 zd+xpGoqNtb=R4=z`{Y~fvp3m<&j&GOJB!62wq2n=&1g9igOSOKnwX+&*JAX87<)(c zs-ehkPwS4}=wQoWYg_mF-JxhlxOb1jJbNF-XiZ@W;7(F6Z;hSpDod$ zNHD2?^2d1q;!)Tn3Rqq1@@1egT>}P+0vaebo2sgGXwYb32j&1riqokWs%xI2kwhwh zDn(T{$?h;?5MTxo)fj<*CW%fNw{hCFUF@rm4gS^)P@Z{+g{orNQQO+i1u%xt?*J>3Ej$^UT2W%u*Wo z1%?;Ix{Pc%AK#S$4wCE2$)(NWVD4d}S$XG)zL9qW(N*{v)Qe?&1nPhG1P7>(Kbdc* zK}-iSh`tioD)O-LE_V; zYsjn$;!%(?(^-d^`>^q}2soCYwZU74HTN-**CciZebMJt826*iUR zdr)&5)nJqI(!*oW-vxgoD`|3AecEajBevj z241P%N6Dhe;8>#$;kdsw>!O2G7HiyY>D)_rdo8_zj(gD|4&1+oBTvOtw~-F2+^i)u za_N!VXa*wb_-gXo)y3f@N}49cr>1uoU)~=EupiW6DQ%2DwRMc;yh2xkOq5K*Z?*Q&smv)_OGWBPrq9Fwsgl;y+8nK?HPX6bWO?=y{+^2O zsdY*VAHfj{3moTnXn2QaE{Pu*sfHyo;+dF10awstsWfWVs0{omsxb;Y!=nsOF+%1j z<3SxiSMjuJ=Eg7YKLwNr55|5&&c}nJr{F57>Qxnw&nS^#?@FM{a3}5}4L9Q%wVQX6 z*wZR@niXQ%0nC%T;wpB{T8_*Z-iZ;jCO&+C?%?4>b04;H8u?z_OGQ5{estUC+Bo32 z_~BS?22B>M<+lUgE}zFem-(_;-V9Jh}**|jmc)5P}<R65yA5bd9AA^PXZdg5muDIxzc_Li@ehi6;=Cw|iCz*lBvW>@jpm1sw&&JhH$SFgHNRU$8t_L3oQ7tg{h`8M)XANCDez9GxmFne!$WxDy$ zmq<6tK5Aa_mEh+2E=@g$;V*5n^pVU9R;jblWU$@S&3RATXRk)4RIh+)? z@iv2EDcrPqp>w6Y5O|JZt`K)_uA}})H#yIe{V_|ty1A@i75AbSZBcm)Zr9Pq?FMGa zbJ3AyqtwiDQM{!Jt`S?e1Xir#bb)Yi(Ys7B%j7kZ?5T>misxe?$>(#Rx-rY;M0Nox z`dgDXqW&f&~Qlm=x)@x8KIGOFdl5PtdwGGWJwwzp$^|l6-giKaS;=zhQuNlLS zO8msh6D$L$JRO5kqGp2n2BX|2E}xt)cK+g%<{M~lz$R}ZlA|XuVM_IV9jXY8{ixCl zCQ9d3%~ZeTGBqpaHcTg(S5aH1)drI9CA#xW7r96Xk&Jl!ff_$`1nOgo1tya-W7-Gw e8gUp;`r;QK>a#!o;A;@yczP8;I6nEP delta 3611 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 delta 4559 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 diff --git a/lib/emscripten/emtests/test_varargs_multi.wasm b/lib/emscripten/emtests/test_varargs_multi.wasm index 99e2b5b86701369124fe2db36e6274f2143a409c..d81b0a176160b1a2c30b48257da2474b8a6cfcc2 100644 GIT binary patch delta 3772 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 delta 3657 zcmZuz4Rlo15x#TZd%K%`OZFup$&%l>*@T1;NFaeAzj=@!AVN~YQABjJgbn#43A+g? z7}%f*sQ7;c0vwBotric8U2E&H^>Arwhal)tX|v{3h! z38C(;V0dF_MQBq`cq`+Im$)(1x4Ne<*!3k--U8Xp@vY?G`kruKQ(v&9vtdgp+}hPM zz%+Hn?C$UCs_pM?3ADG5aVA{G`I6@h1Oi<>EuG_MXcYY7n8o5gvaOT1YXV=VI$Yg{OSIQ`vY`sGRx@)2mvQ5s!MtL-KAs~Z}%C{yc% z_&Tt{UL*etHBE~a0@n=sanOJ<;6Q&}17JGSxr0XLbb%|u?FLi#Oh`;*oa?&oP_nug zn4={r3Vv=9(G=0msJw&w5(dHVFo`(j-8?lq2-R%-XKsfjYWmga`~xH=2D-YoYznN83!(^Ai+1ud7Qgd%;x^+9Vwy}%b10Yv?7 z0e&~Kj(oS@ZF@WH-py*}H&^Oa$Slo7@R|nmyS=7^A@3C2}lFauI zXM$-Cb3mn3khZe8(zq(Sj8w^VeI+cGt@?L~p3^h(7H6QyC(WzDsm{3Q3|@8yElp+` zlNO~Q7X})rSt+O?%;t<34s^sBE~Vgq0Le;25@|R&c9$`;C+P|@V*GycL`=$e+stde z)eSGWlhYri#xpxvx$J0dL!nH&fh)32eUop@8n zH+4H&E6(Y7PNz8jR=4WpEBOPiI`NKfGpjDvRPYyzbXU$^?{v9UGE6H=9$AnwA-?!e zCOpjPHuBj8@4=`%w(yrk`xceMXzbxdtw0N}JwkM^eKpa)+rvb|i%b2Z+%yfm4TK9n z0g<3)iiM*bhxszGpW}Y{{NjIQjdB(30vp0&GP-QNLlj~mPFBp(*l(7&G}8A*?NwxM zX5FyfI+nw)1=U0sWsBMKI|LvUaV9u&D_dwPgQUr(R9dFcQMWQF&y-L!yyhVTs#Ka5 ze-lVD>&hQG6NH79l__7m(qEjZRq-m!wAoUTff;(02TX!XW~azUhw`}q3zXT(m?aGG6yPEBtbBI8X!q6QohB^PaAp(G*cQU zS4|R5Ordy?UkHYhH^@w5Jdn0~nKEX>W{RZdH9ce6!G0yvYn}y2C2@Jrb!V~@#?4-G zz$O@-2k?4&=+v?t8`XAw!>h^?SLwK85vkOjnmumn4rAYP=%P zqZ=fXa<~m@?4HHJgOC+F6{Nx_lUrKqAvgAmmcIcFkA^M+%#g=6 zMu_ILl@Y6)D&?%+ zYPdpf>s<@w^3~ouVU`SSo(I$9k+&asD1vWU0GtSu@Zt94dRCaEhbDYnH@|Qx0#* zD=x?|z2;*86IJFWB2(a|`Yd5gm}uI*KHJwXJm|4<<=HLmkSpg7OjB>iK)OK%Gc-7r zpEc$2!4_I1ZQnvWH*W{1o;==UtVODa+CPI1Rr_PQ8NGv5s(pIR*T&z$G|J=3W5Qg#?7+Zv7fSeA}aSyPrc-plbAr!?NnMZmy|8lKRsd9hD#ItB!h?~go5af)5H z>ln;Xs(z>8!Eq%+dPKCvp}=t?wvmSG@j0ziw3FD=8nzQ!=G=_A>Qqd_j!Txi#|>}9 zZmTjjaI*%<+u{$)HamN%*os@J&uo*o-EvXi1-MJ@xiu%1Ce!Q12;hjq$u1D{4BC0- z)>_yWGxn@>>LVOSFSY_Zy?2db$;xH?=bZ;WW!5oi>4D3rM zfDi0jMHfB2?>fp^(f(DGvm5p|5&iZ4YT{2Eol5+w(KW<5Fd8KJi=%spzxzNnab7%7 zNc6&i3X+*}u!ZKgAKZ{riJfAvhUH?PhBWS@pzPNu4CT0=Vkf&k>>(@R`WXaLY z#OZVq2URjvkj6lM=je2JTMiwa2oqwXM-TCAo!Vk2J-w>*Tzz4pR-F3!!onfp!HIIi z4?cFR13l_@$>2k|r54YyJ(kmsdQHD8{*hw=+0am5u2)&A%=9YSP@l3&P9A@#B12bS xrwPmkiyAq-)wibseNni~k+fLnV}FL&XAku_WA%?$0iTm9Uw(YHeC|gJ{trotM+g7_ diff --git a/lib/emscripten/emtests/test_vprintf.wasm b/lib/emscripten/emtests/test_vprintf.wasm index 0c2d4d462559107a28c3bcb12b31d07168cf3e5b..34391ea23aaa83d4d67fe26fc41fdafe7c3f473f 100644 GIT binary patch delta 3489 zcmZuz3viUx75>lt|9^Lre_?+%W;a<9a&C4ZF%J?*OvFUVA2u<{(DJNo#e~P9HOZk5-GVXy4Wj^xWNOGLAd5 z=iYnnx#!$_zVrBxzR!O59y^qk1#x8)i^n0pNufW@XgM5*;lrhsaYfmr#pwreHmQ2l zaNl-!TYGo^zUaLuHC(OtYqh(ulLIZ`xjV zDBK(Ch;|Qb4floa4sQ*0h1&)~vF@E=MU#d+GxvMLz2X6w<@3&DM#EA%c}{`D$8!P1 z5oi^5R^MJ*0~*tH4Hzg2XrS0^s;bh}K%<2nm;)SX>FJ80I%g>wNz4XNrKsv6*>*Dy zer6C+jbZR>lIXOwlxZSPGH*#xnfgio_zg+=!Wm}lhGlZ&tI_^4xWs2HBkr?@Iy)oV zVqMBDdZ;rR4l9|iP$aUwH`E^6LC^25SgcrjsJE@VPsy;;7$Ju#*U>E8+c7Yt)F)>I zld?j*1z#A9lC&#j)O zrkpHqQ&Us=o99?fAwb;k=HPdu(i3p|-IlAz8W@x_f5s}U4i!@|5L||?_}wnUrl1mV z8|ldbA&_C*1iDmUqm!6akUVCgsfg8Dc7B}?Z2>yC0c=uC{|2!KwOnwEr?i{}Zqx&A zOK}f-U } z1jPgnL-6~h93Yrjm~RJfkiVnhJDL@5*uFLX;E8m5mw?ZBrUma~c}mcjwgI|9kAf6axb7`<35sr?9!iu{{jCHj|}E8u7X zZ|MYD>|Z)cbXMIuqT#v`qL=H+{70E#=y(9Q13w3zCTEg`M;VT=+xRht$3(65Hm4dBS{l~U;&j7^7I*V+@UejoZbQYY?V&qDAyYU*X3pg*+EA5ux1r5+a1Avx zo9ieap}UOZI@C$j>It;+8K9NR7^qsXdFrMw2eG_BzC#@iunJA>JL& zl*50S)~z0nyt!Nb`%Wl5?$fcLC)-Qi*INBZ_I!rI{8- zMMu?0UHo-`OljA?dNO@MstVZ51)_har#&wv;YwYWnFXBcip%)Q!*9)Xk;{|yh5T== zNd}{pew%!c1%qTubs1+hD3xz5Be!3I8Buo$s0O{UJ`6>o`mQo(F*)AO{W|&2FQRun zN9@3cy+ohbP+jMj51`0uphQ;85(7)PYG4`RL>4Xb%TgQR0p6$HDF6=K#+o6YdqjSHPSv_HX$fREmN~5UNBZvL4FCFCqtFu~^qz0~JE_ zJ_9!htM3@e{J!r_npgDS2&IWge-;pHbYL*8l7gTZi_B7SZNQsFE2|tYGyH@=Gv(g( zG^NdjgI+q&IJghW#QDMIysLosGV+HN=QgL!z^foVe+}>&kdv;8CD9!2M%#1_SXANC zrt-mMlq7Kzo1*#7n|y}LcoyI~83qqWbD>Z?9qlISiIq})492`V#o~s0irE>Tc;KE6 zTKx5%?XSMj3{jdIlxQ^NZCF)cBk|TqfY3RWdW7%`h{e zk(nRus)1_p$*yduPB?}upjvv-gPCS2jc!Y&QM2}*QDXcw<%EUEaE#$;M&2G{Jf!0n zDo&{8yhL>OX&@wX<3FaCC*F>qhDB1hqLO4zi4L0U zW1C5)XDr7@!7zo&F)FM{RLJBpl}wJ0VV)ara~W<~diN0Wbg7@E%F72D)X2E~_(U}< z5&n~_Da~Uie-7n7UWHZGTZ-(4ajrU-_@%-SPs>#68bW98Yh=w*vlYl{O*xfi`?i%O&1uA`0H4a}Ce z@S#s)u9+p`#M*MWS-iH^U%QkeA_saLmBnIC?Il$x6>}-i$N40mpX`lhiJTbZ04f6e zQmsmquKQnZE@*T!u3NABroJNR?Oj(F+uf7{keWj68R6M3bmnzMYC)1*%@mtm$;2CJy8(CYlD?-Oc2rjxEp ziB2-Y_GG1xLYwN7Vu8uz%$W3mLOs+t>q%5THDFJ)KKU*ro_KaCu;EOxXrfBwJh$ur Dzx^@F delta 3625 zcmZuz4RBON5}uy--tK1Kl6^@CS+e=*$>s+MunEKf0-6WO3JHG#r3m6C#0?}_cFAS~ zM~rOb2+YGqywCT2z<2u!8Kl}F#oBo)MI2Gq&e)@M4L9(i6b!ZNDf&T*|4H*{ zk=T}Tkyx}Nu_3Y~vMHX}#<-H@ZipmT#giS;?}YLJC~eP7<#())Cz30Z9i6?)wnP$L z(fC%TsWoP7AQ}w~#5%*>-C4=FYb4*voZ)ad8t?4AvW7yi8eitz2axxt3yT zoRb-cm)NW2H_)=;#(BUs!!S5#z!-3#zpeo=o$1^`U*>dyE642yQ}>L^&1IbHy6#ZA zx)+$EGcN@JZW7TH(an^6nEP^uAmA{GIOT3$m>Pm+cI9W@0}B-U{nzS0WN&6TIPQbjzmj`u?pQo5S5Rrn3b`cvDArjE#5F zH%d!cA#ssSotw9@<_t#>W-Z2waR2&5FAKTv+7??tiVCKiJy!=bTv!n4Pj;-2cK2`0 z0K9T@M`wiPnTdhe@_2u8WhB|p=DWz;s*Q=rR+cXZwYt=zqSn^ZiN4m>R`(~z`MgO0 zseoHRz>Tb@(j9Qy-X42%pW*`MQoRY8rI`p`(_jI&*K{ysm2T6W`5;u9WoP&OT83^O(}mTXj(W;=w2OmNf?8aYEQbktF^>|%6O(gt^cL#;Lbf2~}m zmqLNuq?c3|pi$|znb&+j1}9xg|D=l+Sl4W3Sz7v#9tCixOB|INee4{sgFd%-g;77o z4Lrfc7&mc@llS5j$5WinaLgs<;~Op!@_?ZR3)J9d97{ht9$d8g`I0g+DUX*vLUdKx zDWc`&Ylse({|7>H0EZy->=y_SN`EPwP!tkpbUdTmsgQV2$MRoQ}1A#ZuB^=1? zxjp1KOyUY|Zj})54%F0v9O$r21-w-(3{)pGyyoKuG$|2&dr_)8z%AsZLOD0vgQTLiNvMH)gINaW*&Zaln zR1m#Fv;6XfB_%uqmm|0{E21xhMbT z9MfQm;)|asgMgg<#5)Uo$k5j#CgQ{?jH#g7zNGCNu-zfyM}IcLK2<42Sfq}t0485m zK6yojM>o(Xmp{1?n&qoc);LyxTbX}z^)#rK->j~r)0N&{Gqr~5iP@eW(TvRspB8Mv z8moqEFe+XZXC-wLE+mzGw?89lL>ajPJ))faE4O*FM688L5(!m zmJ_XAd(T4ZJ_yQPioLaf;>Gn8G6S_t+Ih{q?_#&7)^gZS5LUU@NIYKi9ETcpg!4b0 z?w+h%5~Zd!Nmd`6@2OCUD2fdVLa|I9tc6y<+RVy?A?&<<45UAkQ>4Wz@O&rR6RkN z?r4Lu^yQ9Efj*yhUIeI<=OX~-!F~> z9?$fM6M!ecx?aA$=^!-9M64NR$yZ`)V7knYKLQQ%nfM%-BG1HMf|>H6&7-7K)wi1X z?R~Q#n0}?t2P8V3=v&@MsZxuRtsu^_hlllk@g-1x)nO1n2mBH&ny1luj{l?#Q6s#L z*sS_d)-Nt7bvN zs^;~RO4sR4s=Ip4cLDNM zu1p{dhxs+RGRz6XSZWot$YZHWg7D+i?A)M<6Vx3%IqPL`cw%s_vLh&Qxz{{0UHec= zIwt zU?D}EVZN0Sqh>KE-@Nalz6)@dJb8avAu-e1#0cPsLV6d7IR?#Kygvkk>G=;Vb?PG= zN93N}6@|nsZxcJ!y-J!RT&yr~Bt5qKRSpg55t$3(>iMr6VvM>JrKEa;(0hb3?#P}M zbadxq>jM%zo@N@fT!aVu+{mZB+OgZpdpbPfX$4luV7t*-o$0PaO~8LtDF1z^QJy(`_x}KhbwAAj diff --git a/lib/emscripten/emtests/test_vsnprintf.wasm b/lib/emscripten/emtests/test_vsnprintf.wasm index dca3d57e4c8c1f68bb663061619bcd2cd9e15869..22e33b19ac79205c106925490f353d1fd87381d3 100644 GIT binary patch delta 3846 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 I{QUm^0U|Yht^fc4 delta 3989 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 diff --git a/lib/emscripten/emtests/test_write_stdout_fileno.wasm b/lib/emscripten/emtests/test_write_stdout_fileno.wasm index a12aab93f199fc9587cc740df3258972cda52841..18aafd632fb30806afe680e2bc19efb14c6a4266 100644 GIT binary patch delta 1755 zcmZuxU2GIp6u#%q%HaZ_TbKamCHPWMro^nZD_4 zGM-AYie$+m$%4!ukH<5)r}kkWMafd`?uJ6TBPQ&UAZ8-Kwq#>d^nRJ@RS*=4FX1melY z#R_>>-c)oLNY@$@qq%%>cXnGMo6Qw>1Ia0VV7^ha1YvFvQH&!HRwdDhb=U*q9p-`(?wnsKW#`|$!i`s88>4l9_g{v( zr4*c-&u4Qo#ff4nmu0p;J~oz_E{wCV79Y#IE^E-@lZjN8)%$7BkRn?~CwDSAHN#d_ zPE--LT8kG(^Ajvu`}_<=m&wG}Pzl=t3tWm8TT|~Aiiy!osxZF4m`G0SpGqWMW_kTe zM``Wy_V(r#jqUC2wb$NLU+!22I$3XMZY4->Z_7!dKeWsfz1Vt)sDI@hh){H!|6jFwx%w@ku@?oof6B@aGqA8?A;JHF``nDdG~*NAS}+y!&x{N^zr=G!gDh{m@bB>KtL zqeOdR>%(*0Ff@D<`j@&9MpWoTDqmT-ZKL%-!ur z)siJ1kz)gO;iE$Jq{&BU<4kbmW|L6Rhl=#whd#4LsHmDDp`i>y3mRuNh{>w;QqejV zRlY-3zSqID=%LL_i%r-oS_!^6Exdnsp7Q&IiKZFyPVWk@wUro;q3y6|L=!ftu>csT zp*UCl|~x5Gkb+qegFv64FMZj`NY1n-0M8h;QhX@ z**kRLZ{Hy~{66pC@XB?ln02-jFlkJJhG~$m3aSHYEL`m&jqaDwi)u{jco&Ad4f>N( N^vnU1dp`}I{ttAOj>P}~ delta 1818 zcmZuxO>7%Q6rMM`Yp-{lc$1Jev72P3>-@MSYN~`5M1Q>fZ_+ew69S?L$1$7c$FVY>-+FH;(yqWjS zd*7RRKl|xTxOWpSH+clSG4RM3^*r36Bx8h(sUCjd(chG2#mQf&aq_v0d)66r&K2AR zLM2vv)+vn?N|{_WxH&Uka7#n^gPDB3P&(=s=BrQZE2qPyOm=4Ig5yr)3iBROBpJ)k z<#I>n^4av%)H+gAg*?E5>2x|*$j)r|pjLEBhh6t%VZ%ov3&m_Em)qIbL)6OEtFc|{ z7<+_0-M0>fA3;xTKvh;7ejzlP%dg+S?*!p5LaJ2;(T7Lug99T&DFxqydZ?nO2kjU9 zZ{hH6-Ud|BGztn30u%^tXaIl&P*sDtX6rn#C_|x0p-Q3oDcTsi2v&fh2ujT_(6IL^ z93=R$2WxNz%sRZ82sN>Jb5CBYYq)b zBkr7Y+1UlsS=nJaNtc!`j=M7?VZ5?{byUcp&gD~uVrkeZ6-kGVbR(0lGfx_POX=~R+}z#W(%jVD-EFKbLt7VsXBh%4gOlmF zVHtL0+MYcxcNROTCOI(`#v#HqVi^$@Ae_VvW>gjqamMP26}HI{X&DbAQo~phRLQ9z znOWhiFxjSLI-m&jwJ(JdgzP4`HCqMPzzGMlJ<651VUq~En}-!$a;)h8CnY zEw13=>yZF1*J_2iE_E+ zHp=s@FQWXq^&TYrFWW9c;@Tk&kSHG(LD-xScT|2ywY?)^P33DUKJ+`)O!(QY^Lj%3 ztlGp(l<#i+(M0YqddGuZhRhZ-W8#L+Z|HV-7bP|kz*qEm<>;>%T&MUpKlSXdu;f3p z=PQ)T-dbMuo=Z%d`l)szFi~?Eu!Sr>gKhrsBVU{JmgE znA|j@{+WJjTTDsPB#+tTn27SInhXQu8jsD0I1k7>xAS%xwu8s~>;1bR=CAcnBSA0k zMS|3Tg-B`OBX00ugna;D%DD9ymsiE*828wTY*5E+h0yK86J1*ku0~id1f;!u;ia(w z`8G9aV=vAK#fQ_>qrOQ5c?0GH z@AVA@jt=GD2m4`PXoKkyr;UA5w~m7SR-+lP-@%BrRY*;Q{X(G=IsEU3UJG-XKM~ci zoudBBsiYp2E#AzV{pHjoa6fXY8~b?gsr%70P?;V%&i|P}e|l)=cH?2?jP=SX1lUh1 zjxDG5rCX#j_Z+a~wdK>NuhJIPzJSjHqz6Urm}g4fwaf1CWh`cK+GXK8AA?VIg9Jsrk#JZ~qHuKbAWH diff --git a/lib/emscripten/emtests/test_zero_multiplication.wasm b/lib/emscripten/emtests/test_zero_multiplication.wasm index bf8da640ab0549ca977047e93e5562c827999b7e..664643eeeff091eda6ff94292558cb8e0514dfce 100644 GIT binary patch delta 3624 zcmZuz3viUx75>lt|9^M0f8hVwm`$=V@&A))}eOjx7YWW7V0CtyBkXwdd{zld0XA zJ@?*o&pr2^^PR_k>_hgK57_?fY=|pcSUe8#Eeic#kX3sw%wmWfN+ELbL-dMVKgy|j?z za|0e*F^%^laLy&oIp?CcSV?14yo z;m^D9d6%6o4OTedIaeUL^+hf`$H+GE?$W=(5%H_4-w?gOx*U!qUaRf^S_EoFh@Pt1 zM3mXXMDMld`;Rcg&~YDd7hVCLCTEg`M;H#X75pf}qvB8YKS}zxwLVhzQLRg*#b*s0 zX|cRjR)F&%0o9JPc-*%UO&EJZ9> z`4gvuTWDF?;?hcgu}`gGHR!XI8+k6~YBlL#ppL#C9zch!b@N#`tB5IlHu}W8RSUr< zLaVw-K{=L_f_GQ>iSyN}m(hbx(>M)a$$MouFy}y`%ODz~u6ut^DL+)gJ z|8@g2xQQ7QngoYp2fDeqxcYW*it079yQTKO{5cz{8cyf2&LMU!5%hg>4}cuUT>i&J20+-d7Piy+Uk^+vL5 z+$9bl-^KI!bewJ)8KBC;T2doQ(@moZ+{6=0n&$x*UCjXs^B*-A&Mn||^yu_%UXS$> ziw11KLaQKY3Ry%xm0UNvC0D%Pd;$u@$ohPuC)c-wU${4Hqxs+l$$4zU9fi{2RB9XP zQpKtvqnH*)MMu?08TK|nrhLaUYsTWUClIn`QBHvU3+R?lmG?3pt9sOi#Fg3w;uomAsqA+^}BjkKty@rDL-rNn$fZXBir&bSH`I+0sLFh`uf zb$)s=LFMFrS)KgCyzM1ozkb^g(b~<6YW&h93fBh8dBrL*u#~F?&L?E)ii^eSzgT?w z-Xx4y7+v(ek||!<{3zrk*56KHTq^V}E1@v4Zp)`YLsje70CU9+?J=S+w3iXBoZ-VsES-`Vk1w$;`b&uft+Gn0V{vVV3tU^#U0vUczsPO$n4CMsd=(XFb%4V|xMw-cak9wB6s2S)Z!Hph(3|byAFHJGv^GWSX^ph58LWhb;=#cjSeQ6DSPqM% zcfHgvOKJ4jDvg>wB%OSU@`;?x@DRgOj8Hhlcu>c$RXnX)c?omxDIm;$9{(8`nurda zf(265A60yGLWu;nGl?X_t=LH#ZpSy&9^OS_ud3K(m5Q70!hCrupO*ZbKXIs?Q0U=@RV?R^s7T`@M-VeaD{1jWKrKs!9;I;Emem;)SyxZ>3vTug2m#@6Kkj(SWo^EAV>WEsXPyf zUafCqDwIme$hw)ZL_D6RkGUiJj1FKk8iA{ zvPk`$=g6{{BR<_&5~!vRzbte_fJt z>)HId)NH2t>~xF1?M%aRlS&n}Ra%Wd^(92@%Sxwblh;W`oPD;!N6AekNwL9Va%SxJ m0)1z=jQhNa&!6jeCNh3}2@>t6mjPRvDgJSKp?L45n*RbwdP&Xz delta 3630 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 n_veCQ4|Ck@x-z7z% diff --git a/lib/emscripten/emtests/test_zerodiv.wasm b/lib/emscripten/emtests/test_zerodiv.wasm index 7af5932ca3ea4f1b0209375842623f5c7ecda230..42f047cdab07852a4ea705219778cd09157ca76b 100644 GIT binary patch delta 3665 zcmZuz3viUx75>lt|9^Mce_{V@*iEuA$+_8ugg_pc@R0DxPac{HCXk@`WD~*yNj96X z2{4NZ8#QspM@QjCz(;*xt;&c+*RkWMEmmnQjMH|Cj;#(*t3#`{!&EIrDE8dl&}7t| z*?Z4D|GDShbH4MqKmL@R`h-1@T?h%Koh1^GXjkY@lw1xg?Jz8tLkSq#y{IaoDD7H; zevn|tRi7G;ZufL-=!*@u4R&<)v}_N@Hbwe&C`^7ZqT3>ohHcT#P*+!)Gkpr@GS40g zg(7{OJrjFqH4q-GkHwn%CiX~9e4w)<5}99B(W9tR_4KLCg=wB^lDD8L%`zrg6GGF7 zvn@J#UQQ_7JJ1>H>K_b8Lz}~cp)KK#{?I_z&ak411n|XKQw3sS`6VTzfV@Xm%J!CM zZAUcPH+XfdZ^yOa-o98|0r4oT6&Y-0=dz`sG2LcYfq|lc28zR>sw!O&G+Imp<^-qV zaw*f*8E!=*2@^n-qG|>xwhd+i0?eR6HHILd$w8;3rA!XuH;fY^*4Zk_JNxnxW(-5E zLcjmd_BX+uLAHluv1p(4cgJ8?UsTDphc<1BY#Z33tk6T7V&SmjbB7|4?Y*H513SnO zU6ofVEA>!sM^{vtX{R|tTNN)+;oi>vxKf*<2ry+$5GocQ{5NR=JJEpXx_F5?S8kX739cXYnDx8Tv z&45gCn^tPG{AdI{;stH?>@?{%6k|El5^R`sX{5`XqRTWD@r{;W=t1T-UIV5lyi&|Y zVii-wDoAXJzWr(s=JJ`=M|n8Y^q`%4ty6jECDOrt*2j71BhnW1Sc=>DI12ALqz~S4 zeE-PgIXwd4Np7?URhsU0x@|N)WOChmjOlok@ng)uW6V+-_;H5E#qYeia4h+`7aSz_ zkGy=^EL;Wm)A(q?F&a1HO*H-rzkz!31|Nd@rysY@|7w!%*B5NC7keZ!hMCKsci{65%e9axmcjwwaRgJJ z{+$cYGO|rHEc+Ym6XnZ)OXKrqh`F@7`MdQkUk@V79KPg*R>riRY-f%rFe%>&uc|H6GyeU>U`Kqtr zD%wz$SGA$dbZ`wd)6aF3ch=p;BRbSbI9C1uvQIWWXSZ<^P17&dtO}I))f!fVeoMKA z=VGo_;{pS9^!M-}+AOV`&%#;7OyRT9FCJU95d7l3Ro$eZ5-UkT!?gk8bYJ^2QiQmT z!vLl{SLVQXf>u)JA{5<2j_eS&Tt!H=9k)vN`t(X9OUZebyz2{sK$L?mdav6Ev&7Epwi5ltb&}({ez-_FoN90b9jcfs$tWrqsOYE~X~TXG;Fb57x%zlw z_5?y^5#nZ=yon*!2_TsNVnOH&C#Yjt-@jk8f|v0y7{ zQQgK{8k9jC^J#xXooV@Df-A&$ocz0y**$ z@G9K``UI4DhOB7;Zlf8`GxDr$G6gNlO?nVW94VCNr7#!01BI??zu`811~5~`)FT6V zFh{&P&_!clu#~Fsn!zlc0=+9fmmTqoz41<3d=uYJU$*W9u-~o2V%nHocH=0^d!KrN zJitfzjj$(Rx@Tt-lF0)L$aR(O2T}c(YCr^$}9K0E$=7QwKJE+mdQ*}LV!EkIQ&u)YkDhc|u%#pp{H-*?lVkbZB=g zl$d8D7iSHV(BhH%fA{yi4RV4Gmcqh@G2R9N3 zJ^VoxEBRg(Y2Hg-+9xYgCGI0<8kZs2PdrOPLKoSu(nStEhy@;ObQ>O7(|5^WMdgij z8Tv$nY8j*dd2A6Z5fzWOP&F8N{1*VZV#Skr9umD=-j1sp5@&bZvwJ}EI( z>kDdaGp2B+xs5Xnilp!#uD{Z`LKb_TXPC>x^mQw#DpEV=IkGC|h@02V4c721%tBjC zUW40pv~jzEIr3h9^vm+7nWf_3x(Zk>K3o@ATEh{MgNvSFiaC#S zUdIT?Ov8^#GXJSZn0WJPuSh&~h4}30bGDmEGGG&Dep*mUy=J=Ka+&nBa~r0URH~@0 z(rNyVTspkSSt%K-zxC!SV7h5~yawo?X~2N~h7O<^n!$YZ)l&T6=YasE8flhoYm6C& z;Zw3kI%uAj^f&|=C!i}}C}7ItEHkASf*wx5t0?&_3&i(8twulo#n<~9q^FbNt+7}n zs+`r_-4=~#1>W$cO&vX5TeL}LcvGykRm--*9UVJ5!yCGGHg5~JRZi3D%y4IOTSUwB z(zk=QYFUJ}cD8KWrPaF_d0T5R!(AI9$omz$*)GOk*fXtHTl2$D^@iDARhD!2>MZL5BYYQR!`nY4a3ms=MxP9Fcnd&h(^4SIGG7P+Wkaf5vi0f7Try- zx%fQ6$+(K(e*6zK$~#0aG=Be@0BC$7=!NV?@rHqK7*4!FTr%*IK_~p)up4DjXs54H zylps|-IzEUddnu&{WCUrC-_w$xm_S0^WkGYCoq#~jwS$K@P*u^f9J!G7+qNMoBj$z z^6E{$CiqNMB@89rui6Ae+*UnE@KW`+2+nc_2tMtU2ZtEvCVmGfq@RFDQJ7-k5W@ks zKpbXxSfzqf3D*LF$WJygu?+3T^9LJc0Ysuy`eSR1l6Y&RSTY zZkN1lTu{0CF9a_sqn^-yU02O zQyuoNwfSSeRQgiB#V-P6s)g6rTqsPre!y2pIh0730dkbY)nkA3UeIB(!p9#if{<)D z`jVN08s^C2W5vZessyqz+o+~wqj=KUDpM>`5-?1XS$k{?)XQHU8}C^Lex>B)+or;J zX|4*9wPmZuPnkf4qB((fQHOQP>-AWV|CwFsd0|21>q(>sp~)-o37ztoBkXELB#Q z%Jb_^5xY0sNASPlS=FV=f*=N!v6@}Nak8KmUQX$wTl`X){vnH}?RA^|CydTHlbj>T zc7KM(hwNTI0tE@HnF^sop4rd@#fd=6dqAI$H+~9mgS@(_i{O^c6~r3e{2O3>KDnjs z4=^oJ)&4Gn>4}M*KY)w^aTf5b+Xv18o&$TPycBs5X32Q84sMiZqpP4&7H_*7X2{34 z&4nrQy=^~%*>ZUM5Xnr7tt9-e*legsoQ>rGvHsMxed#R9(n(lmSKw@?ug~Zb9{?p) z1(xGK0Y3nn)`@zT;om7?6onHBO^Tneo{~Um9=G`80Ap1&KkF%kVwtz2jo`qJ zDQZ6K$Tq1a&fh+XUF7nk+gpfO-MfQUe%DKbW1QPJgvY*Fo?4p~s#d+j;x7Yas2s?m z*z~bcInc)_Hn;b!fChQ7FGQjFul74*$;bh|fuGUk5|0c%3URgZRUJoY3mVDzY;gm^a5HY9aIC}U^{t|f z#7^tjMpA2V?N-r_ZP?x}Ixq)2wu(-7N2f!h&JAEf$M&Q?6~KraKcz21tD8kwRi3W; zeiY@!{Z}(~yOUtIQ#fDj!d=uTcFUI!d^&3%;667M_XF;Co5=yd1E6YTu9y=rI4$GU zCNT&&sN%g3#9R~iN#DT+*qvB%aIx1IWH=}vI#iNL$kHY;poS$$4l=RK#KFX?hknjr zM&f(-rh)j%gV)_~fm#BbzUVbsW~oIrQ=gbFl#5(WyNwuy_Vzao9__LiYZGIxTgKOvO^^ zL;4WxdC4rjnof^yW3QmP&EjK{+6>p+aq10X@tfW9aNn5!_Y~#S;YkERJy0&@smVmw zroGIbN>`<)r7B8Y19{}c)GWG_@|yCn``AVxxzxm)CyuZ}gIeiUde_j~$MJQ?2-+^p z>5d6cV&sP$JZoro&?kTVaB;cK@|=L}b>bEe`rH?T4RoH4#w|v*P03FeqXpM2l9L}j zJU!1)uiO;P0h>BM4fhjSpgDa$K9ZGq>ZgB(M8hLdZ{og_)xhRwN^xqYOnqY6{{U%= BVsHQe diff --git a/lib/emscripten/src/lib.rs b/lib/emscripten/src/lib.rs index df0a0da6c..3ed5c36dd 100644 --- a/lib/emscripten/src/lib.rs +++ b/lib/emscripten/src/lib.rs @@ -1,6 +1,7 @@ #[macro_use] extern crate wasmer_runtime_core; +use lazy_static::lazy_static; use std::cell::UnsafeCell; use std::{f64, ffi::c_void}; use wasmer_runtime_core::{ @@ -11,11 +12,12 @@ use wasmer_runtime_core::{ import::ImportObject, imports, memory::Memory, + module::ImportName, table::Table, - types::{ElementType, MemoryDescriptor, TableDescriptor, Value}, + types::{ElementType, FuncSig, MemoryDescriptor, TableDescriptor, Type, Value}, units::Pages, vm::Ctx, - Func, Instance, Module, + Func, Instance, IsExport, Module, }; #[macro_use] @@ -56,6 +58,11 @@ const DYNAMICTOP_PTR_DIFF: u32 = 1088; // TODO: make this variable const STATIC_BUMP: u32 = 215_536; +lazy_static! { + static ref OLD_ABORT_ON_CANNOT_GROW_MEMORY_SIG: FuncSig = + { FuncSig::new(vec![], vec![Type::I32]) }; +} + // The address globals begin at. Very low in memory, for code size and optimization opportunities. // Above 0 is static memory, starting with globals. // Then the stack. @@ -187,6 +194,7 @@ pub struct EmscriptenGlobalsData { memory_base: u32, table_base: u32, temp_double_ptr: u32, + use_old_abort_on_cannot_grow_memory: bool, // Global namespace infinity: f64, @@ -205,6 +213,27 @@ pub struct EmscriptenGlobals { impl EmscriptenGlobals { pub fn new(module: &Module /*, static_bump: u32 */) -> Self { + let mut use_old_abort_on_cannot_grow_memory = false; + for ( + index, + ImportName { + namespace_index, + name_index, + }, + ) in &module.0.info.imported_functions + { + let namespace = module.0.info.namespace_table.get(*namespace_index); + let name = module.0.info.name_table.get(*name_index); + if name == "abortOnCannotGrowMemory" && namespace == "env" { + let sig_index = module.0.info.func_assoc[index.convert_up(&module.0)]; + let expected_sig = &module.0.info.signatures[sig_index]; + if **expected_sig == *OLD_ABORT_ON_CANNOT_GROW_MEMORY_SIG { + use_old_abort_on_cannot_grow_memory = true; + } + break; + } + } + let (table_min, table_max) = get_emscripten_table_size(&module); let (memory_min, memory_max) = get_emscripten_memory_size(&module); @@ -247,6 +276,7 @@ impl EmscriptenGlobals { memory_base, table_base, temp_double_ptr, + use_old_abort_on_cannot_grow_memory, infinity: std::f64::INFINITY, nan: std::f64::NAN, @@ -266,6 +296,12 @@ impl EmscriptenGlobals { } pub fn generate_emscripten_env(globals: &mut EmscriptenGlobals) -> ImportObject { + let abort_on_cannot_grow_memory_export = if globals.data.use_old_abort_on_cannot_grow_memory { + func!(crate::memory::abort_on_cannot_grow_memory_old).to_export() + } else { + func!(crate::memory::abort_on_cannot_grow_memory).to_export() + }; + imports! { "env" => { "memory" => Export::Memory(globals.memory.clone()), @@ -409,8 +445,10 @@ pub fn generate_emscripten_env(globals: &mut EmscriptenGlobals) -> ImportObject "_sigsuspend" => func!(crate::signal::_sigsuspend), // Memory - "abortOnCannotGrowMemory" => func!(crate::memory::abort_on_cannot_grow_memory), + "abortOnCannotGrowMemory" => abort_on_cannot_grow_memory_export, "_emscripten_memcpy_big" => func!(crate::memory::_emscripten_memcpy_big), + "_emscripten_get_heap_size" => func!(crate::memory::_emscripten_get_heap_size), + "_emscripten_resize_heap" => func!(crate::memory::_emscripten_resize_heap), "enlargeMemory" => func!(crate::memory::enlarge_memory), "getTotalMemory" => func!(crate::memory::get_total_memory), "___map_file" => func!(crate::memory::___map_file), diff --git a/lib/emscripten/src/memory.rs b/lib/emscripten/src/memory.rs index c4540dff0..dcd98c317 100644 --- a/lib/emscripten/src/memory.rs +++ b/lib/emscripten/src/memory.rs @@ -16,6 +16,20 @@ pub fn _emscripten_memcpy_big(ctx: &mut Ctx, dest: u32, src: u32, len: u32) -> u dest } +/// emscripten: _emscripten_get_heap_size +pub fn _emscripten_get_heap_size(ctx: &mut Ctx) -> u32 { + debug!("emscripten::_emscripten_get_heap_size",); + // TODO: Fix implementation + 16_777_216 +} + +/// emscripten: _emscripten_resize_heap +pub fn _emscripten_resize_heap(ctx: &mut Ctx, requested_size: u32) -> u32 { + debug!("emscripten::_emscripten_resize_heap {}", requested_size); + // TODO: Fix implementation + 0 +} + /// emscripten: getTotalMemory pub fn get_total_memory(_ctx: &mut Ctx) -> u32 { debug!("emscripten::get_total_memory"); @@ -33,7 +47,14 @@ pub fn enlarge_memory(_ctx: &mut Ctx) -> u32 { } /// emscripten: abortOnCannotGrowMemory -pub fn abort_on_cannot_grow_memory(ctx: &mut Ctx) -> u32 { +pub fn abort_on_cannot_grow_memory(ctx: &mut Ctx, requested_size: u32) -> u32 { + debug!("emscripten::abort_on_cannot_grow_memory {}", requested_size); + abort_with_message(ctx, "Cannot enlarge memory arrays!"); + 0 +} + +/// emscripten: abortOnCannotGrowMemory +pub fn abort_on_cannot_grow_memory_old(ctx: &mut Ctx) -> u32 { debug!("emscripten::abort_on_cannot_grow_memory"); abort_with_message(ctx, "Cannot enlarge memory arrays!"); 0 diff --git a/lib/runtime-core/src/lib.rs b/lib/runtime-core/src/lib.rs index 18c3ae76c..d130b8899 100644 --- a/lib/runtime-core/src/lib.rs +++ b/lib/runtime-core/src/lib.rs @@ -35,6 +35,8 @@ use self::error::CompileResult; #[doc(inline)] pub use self::error::Result; #[doc(inline)] +pub use self::import::IsExport; +#[doc(inline)] pub use self::instance::Instance; #[doc(inline)] pub use self::module::Module; From 7bb947aba755a393c39c29e085d4a46539946a17 Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Sun, 17 Feb 2019 14:12:05 -0600 Subject: [PATCH 065/262] Add func signature lookup functions --- lib/runtime-c-api/src/lib.rs | 125 +++++++++++++++++++++++++ lib/runtime-c-api/tests/test-exports.c | 20 ++++ lib/runtime-c-api/wasmer.h | 34 +++++++ lib/runtime-c-api/wasmer.hh | 26 +++++ 4 files changed, 205 insertions(+) diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index 733e10fb8..6b6e5567f 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -674,6 +674,120 @@ pub unsafe extern "C" fn wasmer_func_new( Box::into_raw(export) as *mut wasmer_func_t } +/// Sets the result parameter to the arity of the params of the wasmer_func_t +/// +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +#[no_mangle] +#[allow(clippy::cast_ptr_alignment)] +pub unsafe extern "C" fn wasmer_func_params_arity( + func: *mut wasmer_func_t, + result: *mut uint32_t, +) -> wasmer_result_t { + let mut export = unsafe { Box::from_raw(func as *mut Export) }; + let result = if let Export::Function { ref signature, .. } = *export { + unsafe { *result = signature.params().len() as uint32_t }; + wasmer_result_t::WASMER_OK + } else { + update_last_error(CApiError { + msg: "func ptr error in wasmer_func_params_arity".to_string(), + }); + wasmer_result_t::WASMER_ERROR + }; + Box::into_raw(export); + result +} + +/// Sets the params buffer to the parameter types of the given wasmer_func_t +/// +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +#[no_mangle] +#[allow(clippy::cast_ptr_alignment)] +pub unsafe extern "C" fn wasmer_func_params( + func: *mut wasmer_func_t, + params: *mut wasmer_value_tag, + params_len: c_int, +) -> wasmer_result_t { + let mut export = unsafe { Box::from_raw(func as *mut Export) }; + let result = if let Export::Function { ref signature, .. } = *export { + let params: &mut [wasmer_value_tag] = + slice::from_raw_parts_mut(params, params_len as usize); + for (i, item) in signature.params().iter().enumerate() { + params[i] = item.into(); + } + wasmer_result_t::WASMER_OK + } else { + update_last_error(CApiError { + msg: "func ptr error in wasmer_func_params".to_string(), + }); + wasmer_result_t::WASMER_ERROR + }; + Box::into_raw(export); + result +} + +/// Sets the returns buffer to the parameter types of the given wasmer_func_t +/// +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +#[no_mangle] +#[allow(clippy::cast_ptr_alignment)] +pub unsafe extern "C" fn wasmer_func_returns( + func: *mut wasmer_func_t, + returns: *mut wasmer_value_tag, + returns_len: c_int, +) -> wasmer_result_t { + let mut export = unsafe { Box::from_raw(func as *mut Export) }; + let result = if let Export::Function { ref signature, .. } = *export { + let returns: &mut [wasmer_value_tag] = + slice::from_raw_parts_mut(returns, returns_len as usize); + for (i, item) in signature.returns().iter().enumerate() { + returns[i] = item.into(); + } + wasmer_result_t::WASMER_OK + } else { + update_last_error(CApiError { + msg: "func ptr error in wasmer_func_returns".to_string(), + }); + wasmer_result_t::WASMER_ERROR + }; + Box::into_raw(export); + result +} + +/// Sets the result parameter to the arity of the returns of the wasmer_func_t +/// +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +#[no_mangle] +#[allow(clippy::cast_ptr_alignment)] +pub unsafe extern "C" fn wasmer_func_returns_arity( + func: *mut wasmer_func_t, + result: *mut uint32_t, +) -> wasmer_result_t { + let mut export = unsafe { Box::from_raw(func as *mut Export) }; + let result = if let Export::Function { ref signature, .. } = *export { + unsafe { *result = signature.returns().len() as uint32_t }; + wasmer_result_t::WASMER_OK + } else { + update_last_error(CApiError { + msg: "func ptr error in wasmer_func_results_arity".to_string(), + }); + wasmer_result_t::WASMER_ERROR + }; + Box::into_raw(export); + result +} + /// Frees memory for the given Func #[allow(clippy::cast_ptr_alignment)] #[no_mangle] @@ -955,6 +1069,17 @@ impl From<(std::string::String, wasmer_runtime_core::export::Export)> for NamedE } } +impl From<&wasmer_runtime::wasm::Type> for wasmer_value_tag { + fn from(ty: &Type) -> Self { + match *ty { + Type::I32 => wasmer_value_tag::WASM_I32, + Type::I64 => wasmer_value_tag::WASM_I64, + Type::F32 => wasmer_value_tag::WASM_F32, + Type::F64 => wasmer_value_tag::WASM_F64, + } + } +} + // Error reporting thread_local! { diff --git a/lib/runtime-c-api/tests/test-exports.c b/lib/runtime-c-api/tests/test-exports.c index c0c6a4a7b..2ac339e6a 100644 --- a/lib/runtime-c-api/tests/test-exports.c +++ b/lib/runtime-c-api/tests/test-exports.c @@ -43,6 +43,26 @@ int main() assert(name_bytes.bytes[idx] == expected[idx]); } + uint32_t params_arity; + wasmer_func_params_arity(func, ¶ms_arity); + assert(params_arity == 2); + + wasmer_value_tag *params_sig = malloc(sizeof(wasmer_value_tag) * params_arity); + wasmer_func_params(func, params_sig , params_arity); + assert(params_sig[0] == WASM_I32); + assert(params_sig[1] == WASM_I32); + free(params_sig); + + uint32_t returns_arity; + wasmer_func_returns_arity(func, &returns_arity); + assert(returns_arity == 1); + + wasmer_value_tag *returns_sig = malloc(sizeof(wasmer_value_tag) * returns_arity); + wasmer_func_returns(func, returns_sig , returns_arity); + assert(returns_sig[0] == WASM_I32); + free(returns_sig); + + // wasmer_value_t param_one; // param_one.tag = WASM_I32; // param_one.value.I32 = 7; diff --git a/lib/runtime-c-api/wasmer.h b/lib/runtime-c-api/wasmer.h index 3434d1a10..6af262a0a 100644 --- a/lib/runtime-c-api/wasmer.h +++ b/lib/runtime-c-api/wasmer.h @@ -168,6 +168,40 @@ const wasmer_func_t *wasmer_func_new(void (*func)(void *data), const wasmer_value_tag *returns, int returns_len); +/** + * Sets the params buffer to the parameter types of the given wasmer_func_t + * Returns `wasmer_result_t::WASMER_OK` upon success. + * Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` + * and `wasmer_last_error_message` to get an error message. + */ +wasmer_result_t wasmer_func_params(wasmer_func_t *func, wasmer_value_tag *params, int params_len); + +/** + * Sets the result parameter to the arity of the params of the wasmer_func_t + * Returns `wasmer_result_t::WASMER_OK` upon success. + * Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` + * and `wasmer_last_error_message` to get an error message. + */ +wasmer_result_t wasmer_func_params_arity(wasmer_func_t *func, uint32_t *result); + +/** + * Sets the returns buffer to the parameter types of the given wasmer_func_t + * Returns `wasmer_result_t::WASMER_OK` upon success. + * Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` + * and `wasmer_last_error_message` to get an error message. + */ +wasmer_result_t wasmer_func_returns(wasmer_func_t *func, + wasmer_value_tag *returns, + int returns_len); + +/** + * Sets the result parameter to the arity of the returns of the wasmer_func_t + * Returns `wasmer_result_t::WASMER_OK` upon success. + * Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` + * and `wasmer_last_error_message` to get an error message. + */ +wasmer_result_t wasmer_func_returns_arity(wasmer_func_t *func, uint32_t *result); + /** * Frees memory for the given Global */ diff --git a/lib/runtime-c-api/wasmer.hh b/lib/runtime-c-api/wasmer.hh index 3b6ca9551..e00c17531 100644 --- a/lib/runtime-c-api/wasmer.hh +++ b/lib/runtime-c-api/wasmer.hh @@ -147,6 +147,32 @@ const wasmer_func_t *wasmer_func_new(void (*func)(void *data), const wasmer_value_tag *returns, int returns_len); +/// Sets the params buffer to the parameter types of the given wasmer_func_t +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +wasmer_result_t wasmer_func_params(wasmer_func_t *func, wasmer_value_tag *params, int params_len); + +/// Sets the result parameter to the arity of the params of the wasmer_func_t +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +wasmer_result_t wasmer_func_params_arity(wasmer_func_t *func, uint32_t *result); + +/// Sets the returns buffer to the parameter types of the given wasmer_func_t +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +wasmer_result_t wasmer_func_returns(wasmer_func_t *func, + wasmer_value_tag *returns, + int returns_len); + +/// Sets the result parameter to the arity of the returns of the wasmer_func_t +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +wasmer_result_t wasmer_func_returns_arity(wasmer_func_t *func, uint32_t *result); + /// Frees memory for the given Global void wasmer_global_destroy(wasmer_global_t *global); From 36767e0bd66ae9d11017948e40b93d7fd816b458 Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Sun, 17 Feb 2019 14:39:26 -0600 Subject: [PATCH 066/262] Move ctx pointer to first parameter to fix test --- lib/runtime-c-api/tests/test-import-function.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/runtime-c-api/tests/test-import-function.c b/lib/runtime-c-api/tests/test-import-function.c index 54390b863..a93a33340 100644 --- a/lib/runtime-c-api/tests/test-import-function.c +++ b/lib/runtime-c-api/tests/test-import-function.c @@ -9,7 +9,7 @@ static memory_len = 0; static ptr_len = 0; static char actual_str[14] = {}; -void print_str(int32_t ptr, int32_t len, wasmer_instance_context_t *ctx) +void print_str(wasmer_instance_context_t *ctx, int32_t ptr, int32_t len) { wasmer_memory_t *memory = wasmer_instance_context_memory(ctx, 0); uint32_t mem_len = wasmer_memory_length(memory); From a77d1be983c9aeb0fac42e8a79f50d75b07e0cb0 Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Sun, 17 Feb 2019 14:48:30 -0600 Subject: [PATCH 067/262] Remove unused API functions --- lib/runtime-c-api/src/lib.rs | 63 ------------------- .../tests/test-import-function.c | 7 --- lib/runtime-c-api/wasmer.h | 28 --------- lib/runtime-c-api/wasmer.hh | 22 ------- 4 files changed, 120 deletions(-) diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index 6b6e5567f..16070ccbe 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -157,13 +157,6 @@ pub unsafe extern "C" fn wasmer_validate( wasmer_runtime_core::validate(bytes) } -/// Creates a new ImportObject and returns a pointer to it. -/// The caller owns the object and should call `wasmer_import_object_destroy` to free it. -#[no_mangle] -pub extern "C" fn wasmer_import_object_new() -> *mut wasmer_import_object_t { - Box::into_raw(Box::new(ImportObject::new())) as *mut wasmer_import_object_t -} - /// Creates a new Memory for the given descriptor and initializes the given /// pointer to pointer to a pointer to the new memory. /// @@ -364,15 +357,6 @@ pub extern "C" fn wasmer_global_destroy(global: *mut wasmer_global_t) { } } -/// Frees memory for the given ImportObject -#[allow(clippy::cast_ptr_alignment)] -#[no_mangle] -pub extern "C" fn wasmer_import_object_destroy(import_object: *mut wasmer_import_object_t) { - if !import_object.is_null() { - drop(unsafe { Box::from_raw(import_object as *mut ImportObject) }); - } -} - /// Frees memory for the given Memory #[allow(clippy::cast_ptr_alignment)] #[no_mangle] @@ -901,53 +885,6 @@ pub unsafe extern "C" fn wasmer_func_call( // let named_export = &*(export as *mut NamedExport); //} -/// Registers a `func` with provided `name` and `namespace` into the ImportObject. -/// -/// Returns `wasmer_result_t::WASMER_OK` upon success. -/// -/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` -/// and `wasmer_last_error_message` to get an error message. -#[allow(clippy::cast_ptr_alignment)] -#[no_mangle] -pub unsafe extern "C" fn wasmer_imports_set_import_func( - import_object: *mut wasmer_import_object_t, - namespace: *const c_char, - name: *const c_char, - func: extern "C" fn(data: *mut c_void), - params: *const wasmer_value_tag, - params_len: c_int, - returns: *const wasmer_value_tag, - returns_len: c_int, -) { - let mut import_object = unsafe { Box::from_raw(import_object as *mut ImportObject) }; - let namespace_c = unsafe { CStr::from_ptr(namespace) }; - let namespace_r = namespace_c.to_str().unwrap(); - let name_c = unsafe { CStr::from_ptr(name) }; - let name_r = name_c.to_str().unwrap(); - - let params: &[wasmer_value_tag] = slice::from_raw_parts(params, params_len as usize); - let params: Vec = params.iter().cloned().map(|x| x.into()).collect(); - let returns: &[wasmer_value_tag] = slice::from_raw_parts(returns, returns_len as usize); - let returns: Vec = returns.iter().cloned().map(|x| x.into()).collect(); - - let export = Export::Function { - func: unsafe { FuncPointer::new(func as _) }, - ctx: Context::Internal, - signature: Arc::new(FuncSig::new(params, returns)), - }; - - // TODO handle existing namespace - // let maybe_namespace = import_object.get_namespace(namespace_r); - // if let Some(n) = maybe_namespace { - // n.insert(name_r, export); - // } else { - let mut namespace = Namespace::new(); - namespace.insert(name_r, export); - import_object.register(namespace_r, namespace); - Box::into_raw(import_object); - // }; -} - /// Gets the memory within the context at the index `memory_idx`. /// The index is always 0 until multiple memories are supported. #[allow(clippy::cast_ptr_alignment)] diff --git a/lib/runtime-c-api/tests/test-import-function.c b/lib/runtime-c-api/tests/test-import-function.c index a93a33340..4e52f113e 100644 --- a/lib/runtime-c-api/tests/test-import-function.c +++ b/lib/runtime-c-api/tests/test-import-function.c @@ -27,7 +27,6 @@ void print_str(wasmer_instance_context_t *ctx, int32_t ptr, int32_t len) int main() { -// wasmer_import_object_t *import_object = wasmer_import_object_new(); wasmer_value_tag params_sig[] = {WASM_I32, WASM_I32}; wasmer_value_tag returns_sig[] = {}; @@ -50,10 +49,6 @@ int main() import.value.func = func; wasmer_import_t imports[] = {import}; - -// wasmer_imports_set_import_func(import_object, "env", "print_str", print_str, params_sig, 2, returns_sig, 0); - - // Read the wasm file bytes FILE *file = fopen("wasm_sample_app.wasm", "r"); fseek(file, 0, SEEK_END); @@ -92,7 +87,5 @@ int main() // wasmer_func_destroy(func); // printf("Destroy instance\n"); // wasmer_instance_destroy(instance); -// printf("Destroy import object\n"); -// wasmer_import_object_destroy(import_object); return 0; } \ No newline at end of file diff --git a/lib/runtime-c-api/wasmer.h b/lib/runtime-c-api/wasmer.h index 6af262a0a..d37a9dbd1 100644 --- a/lib/runtime-c-api/wasmer.h +++ b/lib/runtime-c-api/wasmer.h @@ -27,8 +27,6 @@ enum wasmer_value_tag { }; typedef uint32_t wasmer_value_tag; -typedef struct wasmer_import_object_t wasmer_import_object_t; - typedef struct wasmer_instance_context_t wasmer_instance_context_t; typedef struct wasmer_instance_t wasmer_instance_t; @@ -228,32 +226,6 @@ wasmer_global_t *wasmer_global_new(wasmer_value_t value, bool mutable_); */ void wasmer_global_set(wasmer_global_t *global, wasmer_value_t value); -/** - * Frees memory for the given ImportObject - */ -void wasmer_import_object_destroy(wasmer_import_object_t *import_object); - -/** - * Creates a new ImportObject and returns a pointer to it. - * The caller owns the object and should call `wasmer_import_object_destroy` to free it. - */ -wasmer_import_object_t *wasmer_import_object_new(void); - -/** - * Registers a `func` with provided `name` and `namespace` into the ImportObject. - * Returns `wasmer_result_t::WASMER_OK` upon success. - * Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` - * and `wasmer_last_error_message` to get an error message. - */ -void wasmer_imports_set_import_func(wasmer_import_object_t *import_object, - const char *namespace_, - const char *name, - void (*func)(void *data), - const wasmer_value_tag *params, - int params_len, - const wasmer_value_tag *returns, - int returns_len); - /** * Calls an instances exported function by `name` with the provided parameters. * Results are set using the provided `results` pointer. diff --git a/lib/runtime-c-api/wasmer.hh b/lib/runtime-c-api/wasmer.hh index e00c17531..a8931496d 100644 --- a/lib/runtime-c-api/wasmer.hh +++ b/lib/runtime-c-api/wasmer.hh @@ -24,8 +24,6 @@ enum class wasmer_value_tag : uint32_t { WASM_F64, }; -struct wasmer_import_object_t; - struct wasmer_instance_context_t; struct wasmer_instance_t; @@ -189,26 +187,6 @@ wasmer_global_t *wasmer_global_new(wasmer_value_t value, bool mutable_); /// Sets the value stored by the given Global void wasmer_global_set(wasmer_global_t *global, wasmer_value_t value); -/// Frees memory for the given ImportObject -void wasmer_import_object_destroy(wasmer_import_object_t *import_object); - -/// Creates a new ImportObject and returns a pointer to it. -/// The caller owns the object and should call `wasmer_import_object_destroy` to free it. -wasmer_import_object_t *wasmer_import_object_new(); - -/// Registers a `func` with provided `name` and `namespace` into the ImportObject. -/// Returns `wasmer_result_t::WASMER_OK` upon success. -/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` -/// and `wasmer_last_error_message` to get an error message. -void wasmer_imports_set_import_func(wasmer_import_object_t *import_object, - const char *namespace_, - const char *name, - void (*func)(void *data), - const wasmer_value_tag *params, - int params_len, - const wasmer_value_tag *returns, - int returns_len); - /// Calls an instances exported function by `name` with the provided parameters. /// Results are set using the provided `results` pointer. /// Returns `wasmer_result_t::WASMER_OK` upon success. From ee81560e06d1476901f6c0799c9690081a4e4768 Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Sun, 17 Feb 2019 16:51:59 -0600 Subject: [PATCH 068/262] Cleanup tests --- lib/runtime-c-api/tests/test-exports.c | 2 -- lib/runtime-c-api/tests/test-instantiate.c | 1 - lib/runtime-c-api/tests/test-module.c | 2 -- 3 files changed, 5 deletions(-) diff --git a/lib/runtime-c-api/tests/test-exports.c b/lib/runtime-c-api/tests/test-exports.c index 2ac339e6a..3f458ebab 100644 --- a/lib/runtime-c-api/tests/test-exports.c +++ b/lib/runtime-c-api/tests/test-exports.c @@ -5,8 +5,6 @@ int main() { -// wasmer_import_object_t *import_object = wasmer_import_object_new(); - // Read the wasm file bytes FILE *file = fopen("sum.wasm", "r"); fseek(file, 0, SEEK_END); diff --git a/lib/runtime-c-api/tests/test-instantiate.c b/lib/runtime-c-api/tests/test-instantiate.c index f276b8dee..2a675de12 100644 --- a/lib/runtime-c-api/tests/test-instantiate.c +++ b/lib/runtime-c-api/tests/test-instantiate.c @@ -5,7 +5,6 @@ int main() { - // Read the wasm file bytes FILE *file = fopen("sum.wasm", "r"); fseek(file, 0, SEEK_END); diff --git a/lib/runtime-c-api/tests/test-module.c b/lib/runtime-c-api/tests/test-module.c index 5948fd26b..bacd37c3a 100644 --- a/lib/runtime-c-api/tests/test-module.c +++ b/lib/runtime-c-api/tests/test-module.c @@ -19,8 +19,6 @@ int main() printf("Compile result: %d\n", compile_result); assert(compile_result == WASMER_OK); - // TODO add module exports - printf("Destroy module\n"); wasmer_module_destroy(module); return 0; From 123d55cb4a230dc31b4a8584ac17a53e50091689 Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Sun, 17 Feb 2019 17:10:15 -0600 Subject: [PATCH 069/262] Remove commented out code, cleanup build warnings --- lib/runtime-c-api/src/lib.rs | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index 16070ccbe..38414c8d7 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -6,18 +6,14 @@ use std::cell::RefCell; use std::collections::HashMap; use std::error::Error; use std::ffi::CStr; -use std::ffi::CString; use std::fmt; use std::slice; -use std::str; use std::sync::Arc; -use std::{ffi::c_void, mem, ptr}; +use std::{ffi::c_void, ptr}; use wasmer_runtime::{Ctx, Global, ImportObject, Instance, Memory, Module, Table, Value}; use wasmer_runtime_core::export::{Context, Export, FuncPointer}; -use wasmer_runtime_core::import::{LikeNamespace, Namespace}; -use wasmer_runtime_core::types::{ - ElementType, FuncSig, GlobalDescriptor, MemoryDescriptor, TableDescriptor, Type, -}; +use wasmer_runtime_core::import::Namespace; +use wasmer_runtime_core::types::{ElementType, FuncSig, MemoryDescriptor, TableDescriptor, Type}; use wasmer_runtime_core::units::{Bytes, Pages}; #[allow(non_camel_case_types)] @@ -841,7 +837,7 @@ pub unsafe extern "C" fn wasmer_func_call( update_last_error(CApiError { msg: "wasmer_func_call not yet implemented".to_string(), }); - return wasmer_result_t::WASMER_ERROR; + wasmer_result_t::WASMER_ERROR // let result = instance.call(func_name_r, ¶ms[..]); // Box::into_raw(export_func); // match result { @@ -876,15 +872,6 @@ pub unsafe extern "C" fn wasmer_func_call( // } } -///// Gets wasmer_export func -//#[no_mangle] -//pub unsafe extern "C" fn wasmer_export_name(export: *mut wasmer_export_t) { -// if exports.is_null() { -// return ptr::null_mut(); -// } -// let named_export = &*(export as *mut NamedExport); -//} - /// Gets the memory within the context at the index `memory_idx`. /// The index is always 0 until multiple memories are supported. #[allow(clippy::cast_ptr_alignment)] From e381bbd07bb8f2a12b1f2ef10b1fe26cfe174bec Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Mon, 18 Feb 2019 11:56:20 -0800 Subject: [PATCH 070/262] Use ModuleInfo instead of ModuleInner when possible --- lib/clif-backend/src/func_env.rs | 12 +- lib/clif-backend/src/lib.rs | 4 +- lib/clif-backend/src/module.rs | 130 +++++---------- lib/clif-backend/src/module_env.rs | 8 +- lib/clif-backend/src/signal/mod.rs | 2 +- lib/runtime-core/src/backend.rs | 4 + lib/runtime-core/src/backing.rs | 10 +- lib/runtime-core/src/instance.rs | 18 +-- lib/runtime-core/src/module.rs | 20 ++- lib/runtime-core/src/types.rs | 14 +- lib/runtime-core/src/vm.rs | 5 +- lib/runtime/Cargo.toml | 6 +- lib/runtime/src/cache.rs | 243 +++++++++++++++-------------- lib/runtime/src/lib.rs | 52 +++--- 14 files changed, 252 insertions(+), 276 deletions(-) diff --git a/lib/clif-backend/src/func_env.rs b/lib/clif-backend/src/func_env.rs index 8670e0000..e222f2e07 100644 --- a/lib/clif-backend/src/func_env.rs +++ b/lib/clif-backend/src/func_env.rs @@ -75,7 +75,7 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> { let vmctx = func.create_global_value(ir::GlobalValueData::VMContext); let ptr_type = self.pointer_type(); - let local_global_addr = match global_index.local_or_import(self.env.module) { + let local_global_addr = match global_index.local_or_import(&self.env.module.info) { LocalOrImport::Local(local_global_index) => { let globals_base_addr = func.create_global_value(ir::GlobalValueData::Load { base: vmctx, @@ -145,7 +145,7 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> { let vmctx = func.create_global_value(ir::GlobalValueData::VMContext); let ptr_type = self.pointer_type(); - let (local_memory_ptr_ptr, description) = match mem_index.local_or_import(self.env.module) { + let (local_memory_ptr_ptr, description) = match mem_index.local_or_import(&self.env.module.info) { LocalOrImport::Local(local_mem_index) => { let memories_base_addr = func.create_global_value(ir::GlobalValueData::Load { base: vmctx, @@ -253,7 +253,7 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> { let vmctx = func.create_global_value(ir::GlobalValueData::VMContext); let ptr_type = self.pointer_type(); - let (table_struct_ptr_ptr, description) = match table_index.local_or_import(self.env.module) + let (table_struct_ptr_ptr, description) = match table_index.local_or_import(&self.env.module.info) { LocalOrImport::Local(local_table_index) => { let tables_base = func.create_global_value(ir::GlobalValueData::Load { @@ -476,7 +476,7 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> { ) -> cranelift_wasm::WasmResult { let callee_index: FuncIndex = Converter(clif_callee_index).into(); - match callee_index.local_or_import(self.env.module) { + match callee_index.local_or_import(&self.env.module.info) { LocalOrImport::Local(_) => { // this is an internal function let vmctx = pos @@ -568,7 +568,7 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> { let mem_index: MemoryIndex = Converter(clif_mem_index).into(); - let (namespace, mem_index, description) = match mem_index.local_or_import(self.env.module) { + let (namespace, mem_index, description) = match mem_index.local_or_import(&self.env.module.info) { LocalOrImport::Local(local_mem_index) => ( call_names::LOCAL_NAMESPACE, local_mem_index.index(), @@ -631,7 +631,7 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> { let mem_index: MemoryIndex = Converter(clif_mem_index).into(); - let (namespace, mem_index, description) = match mem_index.local_or_import(self.env.module) { + let (namespace, mem_index, description) = match mem_index.local_or_import(&self.env.module.info) { LocalOrImport::Local(local_mem_index) => ( call_names::LOCAL_NAMESPACE, local_mem_index.index(), diff --git a/lib/clif-backend/src/lib.rs b/lib/clif-backend/src/lib.rs index 07bae97c6..cbe455b93 100644 --- a/lib/clif-backend/src/lib.rs +++ b/lib/clif-backend/src/lib.rs @@ -48,7 +48,7 @@ impl Compiler for CraneliftCompiler { let isa = get_isa(); - let mut module = module::Module::empty(); + let mut module = module::Module::new(wasm); let module_env = module_env::ModuleEnv::new(&mut module, &*isa); let func_bodies = module_env.translate(wasm)?; @@ -72,7 +72,7 @@ impl Compiler for CraneliftCompiler { let isa = get_isa(); - let mut module = module::Module::empty(); + let mut module = module::Module::new(wasm); let module_env = module_env::ModuleEnv::new(&mut module, &*isa); let func_bodies = module_env.translate(wasm)?; diff --git a/lib/clif-backend/src/module.rs b/lib/clif-backend/src/module.rs index c48072ac8..e2ee8efe8 100644 --- a/lib/clif-backend/src/module.rs +++ b/lib/clif-backend/src/module.rs @@ -6,115 +6,83 @@ use cranelift_codegen::{ir, isa}; use cranelift_entity::EntityRef; use cranelift_wasm; use hashbrown::HashMap; -use std::{ - ops::{Deref, DerefMut}, - ptr::NonNull, -}; + #[cfg(feature = "cache")] use wasmer_runtime_core::{ backend::sys::Memory, cache::{Cache, Error as CacheError}, }; + use wasmer_runtime_core::{ - backend::{Backend, FuncResolver, ProtectedCaller, Token, UserTrapper}, - error::{CompileResult, RuntimeResult}, - module::{ModuleInfo, ModuleInner, StringTable}, + backend::Backend, + error::CompileResult, + module::{ModuleInfo, ModuleInner, StringTable, WasmHash}, structures::{Map, TypedIndex}, types::{ FuncIndex, FuncSig, GlobalIndex, LocalFuncIndex, MemoryIndex, SigIndex, TableIndex, Type, - Value, }, - vm::{self, ImportBacking}, }; -struct Placeholder; - -impl FuncResolver for Placeholder { - fn get( - &self, - _module: &ModuleInner, - _local_func_index: LocalFuncIndex, - ) -> Option> { - None - } -} - -impl ProtectedCaller for Placeholder { - fn call( - &self, - _module: &ModuleInner, - _func_index: FuncIndex, - _params: &[Value], - _import_backing: &ImportBacking, - _vmctx: *mut vm::Ctx, - _: Token, - ) -> RuntimeResult> { - Ok(vec![]) - } - - fn get_early_trapper(&self) -> Box { - unimplemented!() - } -} - /// This contains all of the items in a `ModuleInner` except the `func_resolver`. pub struct Module { - pub module: ModuleInner, + pub info: ModuleInfo, } impl Module { - pub fn empty() -> Self { + pub fn new(wasm: &[u8]) -> Self { Self { - module: ModuleInner { - // this is a placeholder - func_resolver: Box::new(Placeholder), - protected_caller: Box::new(Placeholder), + info: ModuleInfo { + memories: Map::new(), + globals: Map::new(), + tables: Map::new(), - info: ModuleInfo { - memories: Map::new(), - globals: Map::new(), - tables: Map::new(), + imported_functions: Map::new(), + imported_memories: Map::new(), + imported_tables: Map::new(), + imported_globals: Map::new(), - imported_functions: Map::new(), - imported_memories: Map::new(), - imported_tables: Map::new(), - imported_globals: Map::new(), + exports: HashMap::new(), - exports: HashMap::new(), + data_initializers: Vec::new(), + elem_initializers: Vec::new(), - data_initializers: Vec::new(), - elem_initializers: Vec::new(), + start_func: None, - start_func: None, + func_assoc: Map::new(), + signatures: Map::new(), + backend: Backend::Cranelift, - func_assoc: Map::new(), - signatures: Map::new(), - backend: Backend::Cranelift, + namespace_table: StringTable::new(), + name_table: StringTable::new(), - namespace_table: StringTable::new(), - name_table: StringTable::new(), - }, + wasm_hash: WasmHash::generate(wasm), }, } } pub fn compile( - mut self, + self, isa: &isa::TargetIsa, functions: Map, ) -> CompileResult { let (func_resolver_builder, handler_data) = - FuncResolverBuilder::new(isa, functions, &self.module.info)?; + FuncResolverBuilder::new(isa, functions, &self.info)?; + - self.module.func_resolver = - Box::new(func_resolver_builder.finalize(&self.module.info.signatures)?); + let func_resolver = + Box::new(func_resolver_builder.finalize(&self.info.signatures)?); - let trampolines = Trampolines::new(isa, &self.module.info); + let trampolines = Trampolines::new(isa, &self.info); - self.module.protected_caller = - Box::new(Caller::new(&self.module.info, handler_data, trampolines)); + let protected_caller = + Box::new(Caller::new(&self.info, handler_data, trampolines)); - Ok(self.module) + Ok(ModuleInner { + func_resolver, + protected_caller, + + info: self.info, + }) } #[cfg(feature = "cache")] @@ -124,16 +92,16 @@ impl Module { functions: Map, ) -> CompileResult<(ModuleInfo, BackendCache, Memory)> { let (func_resolver_builder, handler_data) = - FuncResolverBuilder::new(isa, functions, &self.module.info)?; + FuncResolverBuilder::new(isa, functions, &self.info)?; - let trampolines = Trampolines::new(isa, &self.module.info); + let trampolines = Trampolines::new(isa, &self.info); let trampoline_cache = trampolines.to_trampoline_cache(); let (backend_cache, compiled_code) = func_resolver_builder.to_backend_cache(trampoline_cache, handler_data); - Ok((self.module.info, backend_cache, compiled_code)) + Ok((self.info, backend_cache, compiled_code)) } #[cfg(feature = "cache")] @@ -159,20 +127,6 @@ impl Module { } } -impl Deref for Module { - type Target = ModuleInner; - - fn deref(&self) -> &ModuleInner { - &self.module - } -} - -impl DerefMut for Module { - fn deref_mut(&mut self) -> &mut ModuleInner { - &mut self.module - } -} - pub struct Converter(pub T); macro_rules! convert_clif_to_runtime_index { diff --git a/lib/clif-backend/src/module_env.rs b/lib/clif-backend/src/module_env.rs index 65bd5f839..b80e8826d 100644 --- a/lib/clif-backend/src/module_env.rs +++ b/lib/clif-backend/src/module_env.rs @@ -139,7 +139,7 @@ impl<'module, 'isa, 'data> ModuleEnvironment<'data> for ModuleEnv<'module, 'isa> // assert!(!desc.mutable); let global_index: GlobalIndex = Converter(global_index).into(); let imported_global_index = global_index - .local_or_import(self.module) + .local_or_import(&self.module.info) .import() .expect("invalid global initializer when declaring an imported global"); Initializer::GetGlobal(imported_global_index) @@ -249,7 +249,7 @@ impl<'module, 'isa, 'data> ModuleEnvironment<'data> for ModuleEnv<'module, 'isa> let base = match base { Some(global_index) => { let global_index: GlobalIndex = Converter(global_index).into(); - Initializer::GetGlobal(match global_index.local_or_import(self.module) { + Initializer::GetGlobal(match global_index.local_or_import(&self.module.info) { LocalOrImport::Import(imported_global_index) => imported_global_index, LocalOrImport::Local(_) => { panic!("invalid global initializer when declaring an imported global") @@ -319,7 +319,7 @@ impl<'module, 'isa, 'data> ModuleEnvironment<'data> for ModuleEnv<'module, 'isa> let base = match base { Some(global_index) => { let global_index: GlobalIndex = Converter(global_index).into(); - Initializer::GetGlobal(match global_index.local_or_import(self.module) { + Initializer::GetGlobal(match global_index.local_or_import(&self.module.info) { LocalOrImport::Import(imported_global_index) => imported_global_index, LocalOrImport::Local(_) => { panic!("invalid global initializer when declaring an imported global") @@ -389,7 +389,7 @@ impl<'module, 'isa, 'data> ModuleEnvironment<'data> for ModuleEnv<'module, 'isa> let name = ir::ExternalName::user(0, func_index.index() as u32); let sig = func_env.generate_signature( - self.get_func_type(Converter(func_index.convert_up(self.module)).into()), + self.get_func_type(Converter(func_index.convert_up(&self.module.info)).into()), ); let mut func = ir::Function::with_name_signature(name, sig); diff --git a/lib/clif-backend/src/signal/mod.rs b/lib/clif-backend/src/signal/mod.rs index 31dbb44dd..1468d99eb 100644 --- a/lib/clif-backend/src/signal/mod.rs +++ b/lib/clif-backend/src/signal/mod.rs @@ -160,7 +160,7 @@ fn get_func_from_index( .get(func_index) .expect("broken invariant, incorrect func index"); - let (func_ptr, ctx) = match func_index.local_or_import(module) { + let (func_ptr, ctx) = match func_index.local_or_import(&module.info) { LocalOrImport::Local(local_func_index) => ( module .func_resolver diff --git a/lib/runtime-core/src/backend.rs b/lib/runtime-core/src/backend.rs index 9b5ec049e..328e3c826 100644 --- a/lib/runtime-core/src/backend.rs +++ b/lib/runtime-core/src/backend.rs @@ -99,3 +99,7 @@ pub trait FuncResolver: Send + Sync { local_func_index: LocalFuncIndex, ) -> Option>; } + +pub trait CacheGen: Send + Sync { + fn generate_cache(&self, module: &ModuleInner) -> Result<(Box, Box<[u8]>, Memory), CacheError>; +} \ No newline at end of file diff --git a/lib/runtime-core/src/backing.rs b/lib/runtime-core/src/backing.rs index d81e33065..ef2556895 100644 --- a/lib/runtime-core/src/backing.rs +++ b/lib/runtime-core/src/backing.rs @@ -91,7 +91,7 @@ impl LocalBacking { } } as usize; - match init.memory_index.local_or_import(module) { + match init.memory_index.local_or_import(&module.info) { LocalOrImport::Local(local_memory_index) => { let memory_desc = module.info.memories[local_memory_index]; let data_top = init_base + init.data.len(); @@ -159,7 +159,7 @@ impl LocalBacking { } } as usize; - match init.table_index.local_or_import(module) { + match init.table_index.local_or_import(&module.info) { LocalOrImport::Local(local_table_index) => { let table = &tables[local_table_index]; @@ -177,7 +177,7 @@ impl LocalBacking { SigRegistry.lookup_sig_index(Arc::clone(&signature)).index() as u32, ); - let (func, ctx) = match func_index.local_or_import(module) { + let (func, ctx) = match func_index.local_or_import(&module.info) { LocalOrImport::Local(local_func_index) => ( module .func_resolver @@ -215,7 +215,7 @@ impl LocalBacking { SigRegistry.lookup_sig_index(Arc::clone(&signature)).index() as u32, ); - let (func, ctx) = match func_index.local_or_import(module) { + let (func, ctx) = match func_index.local_or_import(&module.info) { LocalOrImport::Local(local_func_index) => ( module .func_resolver @@ -364,7 +364,7 @@ fn import_functions( }, ) in &module.info.imported_functions { - let sig_index = module.info.func_assoc[index.convert_up(module)]; + let sig_index = module.info.func_assoc[index.convert_up(&module.info)]; let expected_sig = &module.info.signatures[sig_index]; let namespace = module.info.namespace_table.get(*namespace_index); diff --git a/lib/runtime-core/src/instance.rs b/lib/runtime-core/src/instance.rs index a8f36325a..a634b21e5 100644 --- a/lib/runtime-core/src/instance.rs +++ b/lib/runtime-core/src/instance.rs @@ -121,14 +121,14 @@ impl Instance { })?; } - let ctx = match func_index.local_or_import(&*self.module) { + let ctx = match func_index.local_or_import(&self.module.info) { LocalOrImport::Local(_) => self.inner.vmctx, LocalOrImport::Import(imported_func_index) => { self.inner.import_backing.vm_functions[imported_func_index].vmctx } }; - let func_ptr = match func_index.local_or_import(&self.module) { + let func_ptr = match func_index.local_or_import(&self.module.info) { LocalOrImport::Local(local_func_index) => self .module .func_resolver @@ -288,7 +288,7 @@ impl Instance { })? } - let vmctx = match func_index.local_or_import(&self.module) { + let vmctx = match func_index.local_or_import(&self.module.info) { LocalOrImport::Local(_) => self.inner.vmctx, LocalOrImport::Import(imported_func_index) => { self.inner.import_backing.vm_functions[imported_func_index].vmctx @@ -355,7 +355,7 @@ impl InstanceInner { .get(func_index) .expect("broken invariant, incorrect func index"); - let (func_ptr, ctx) = match func_index.local_or_import(module) { + let (func_ptr, ctx) = match func_index.local_or_import(&module.info) { LocalOrImport::Local(local_func_index) => ( module .func_resolver @@ -384,7 +384,7 @@ impl InstanceInner { } fn get_memory_from_index(&self, module: &ModuleInner, mem_index: MemoryIndex) -> Memory { - match mem_index.local_or_import(module) { + match mem_index.local_or_import(&module.info) { LocalOrImport::Local(local_mem_index) => self.backing.memories[local_mem_index].clone(), LocalOrImport::Import(imported_mem_index) => { self.import_backing.memories[imported_mem_index].clone() @@ -393,7 +393,7 @@ impl InstanceInner { } fn get_global_from_index(&self, module: &ModuleInner, global_index: GlobalIndex) -> Global { - match global_index.local_or_import(module) { + match global_index.local_or_import(&module.info) { LocalOrImport::Local(local_global_index) => { self.backing.globals[local_global_index].clone() } @@ -404,7 +404,7 @@ impl InstanceInner { } fn get_table_from_index(&self, module: &ModuleInner, table_index: TableIndex) -> Table { - match table_index.local_or_import(module) { + match table_index.local_or_import(&module.info) { LocalOrImport::Local(local_table_index) => { self.backing.tables[local_table_index].clone() } @@ -462,7 +462,7 @@ impl<'a> DynFunc<'a> { })? } - let vmctx = match self.func_index.local_or_import(self.module) { + let vmctx = match self.func_index.local_or_import(&self.module.info) { LocalOrImport::Local(_) => self.instance_inner.vmctx, LocalOrImport::Import(imported_func_index) => { self.instance_inner.import_backing.vm_functions[imported_func_index].vmctx @@ -488,7 +488,7 @@ impl<'a> DynFunc<'a> { } pub fn raw(&self) -> *const vm::Func { - match self.func_index.local_or_import(self.module) { + match self.func_index.local_or_import(&self.module.info) { LocalOrImport::Local(local_func_index) => self .module .func_resolver diff --git a/lib/runtime-core/src/module.rs b/lib/runtime-core/src/module.rs index 0fdb24018..aca3fc221 100644 --- a/lib/runtime-core/src/module.rs +++ b/lib/runtime-core/src/module.rs @@ -51,6 +51,18 @@ pub struct ModuleInfo { pub namespace_table: StringTable, pub name_table: StringTable, + + pub wasm_hash: WasmHash, +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "cache", derive(Serialize, Deserialize))] +pub struct WasmHash([u8; 32]); + +impl WasmHash { + pub fn generate(wasm: &[u8]) -> Self { + WasmHash(super::cache::hash_data(wasm)) + } } /// A compiled WebAssembly module. @@ -60,7 +72,9 @@ pub struct ModuleInfo { /// /// [`compile`]: fn.compile.html /// [`compile_with`]: fn.compile_with.html -pub struct Module(#[doc(hidden)] pub Arc); +pub struct Module { + inner: Arc, +} impl Module { pub(crate) fn new(inner: Arc) -> Self { @@ -68,7 +82,7 @@ impl Module { EARLY_TRAPPER .with(|ucell| *ucell.get() = Some(inner.protected_caller.get_early_trapper())); } - Module(inner) + Module { inner } } /// Instantiate a WebAssembly module with the provided [`ImportObject`]. @@ -94,7 +108,7 @@ impl Module { /// # } /// ``` pub fn instantiate(&self, import_object: &ImportObject) -> Result { - Instance::new(Arc::clone(&self.0), import_object) + Instance::new(Arc::clone(&self.inner), import_object) } } diff --git a/lib/runtime-core/src/types.rs b/lib/runtime-core/src/types.rs index fd57bf12c..271b336ba 100644 --- a/lib/runtime-core/src/types.rs +++ b/lib/runtime-core/src/types.rs @@ -1,4 +1,4 @@ -use crate::{memory::MemoryType, module::ModuleInner, structures::TypedIndex, units::Pages}; +use crate::{memory::MemoryType, module::ModuleInfo, structures::TypedIndex, units::Pages}; use std::{borrow::Cow, mem}; /// Represents a WebAssembly type. @@ -364,23 +364,23 @@ define_map_index![ macro_rules! define_local_or_import { ($ty:ident, $local_ty:ident, $imported_ty:ident, $imports:ident) => { impl $ty { - pub fn local_or_import(self, module: &ModuleInner) -> LocalOrImport<$ty> { - if self.index() < module.info.$imports.len() { + pub fn local_or_import(self, info: &ModuleInfo) -> LocalOrImport<$ty> { + if self.index() < info.$imports.len() { LocalOrImport::Import(::Import::new(self.index())) } else { - LocalOrImport::Local(::Local::new(self.index() - module.info.$imports.len())) + LocalOrImport::Local(::Local::new(self.index() - info.$imports.len())) } } } impl $local_ty { - pub fn convert_up(self, module: &ModuleInner) -> $ty { - $ty ((self.index() + module.info.$imports.len()) as u32) + pub fn convert_up(self, info: &ModuleInfo) -> $ty { + $ty ((self.index() + info.$imports.len()) as u32) } } impl $imported_ty { - pub fn convert_up(self, _module: &ModuleInner) -> $ty { + pub fn convert_up(self, _info: &ModuleInfo) -> $ty { $ty (self.index() as u32) } } diff --git a/lib/runtime-core/src/vm.rs b/lib/runtime-core/src/vm.rs index faee819be..abea76db8 100644 --- a/lib/runtime-core/src/vm.rs +++ b/lib/runtime-core/src/vm.rs @@ -116,7 +116,7 @@ impl Ctx { pub fn memory(&self, mem_index: u32) -> &Memory { let module = unsafe { &*self.module }; let mem_index = MemoryIndex::new(mem_index as usize); - match mem_index.local_or_import(module) { + match mem_index.local_or_import(&module.info) { LocalOrImport::Local(local_mem_index) => unsafe { let local_backing = &*self.local_backing; &local_backing.memories[local_mem_index] @@ -497,6 +497,7 @@ mod vm_ctx_tests { use crate::backend::{Backend, FuncResolver, ProtectedCaller, Token, UserTrapper}; use crate::error::RuntimeResult; use crate::types::{FuncIndex, LocalFuncIndex, Value}; + use crate::module::WasmHash; use hashbrown::HashMap; use std::ptr::NonNull; struct Placeholder; @@ -553,6 +554,8 @@ mod vm_ctx_tests { namespace_table: StringTable::new(), name_table: StringTable::new(), + + wasm_hash: WasmHash::generate(&[]), }, } } diff --git a/lib/runtime/Cargo.toml b/lib/runtime/Cargo.toml index 2a2478193..fe6cc80d2 100644 --- a/lib/runtime/Cargo.toml +++ b/lib/runtime/Cargo.toml @@ -10,11 +10,9 @@ readme = "README.md" [dependencies] wasmer-runtime-core = { path = "../runtime-core", version = "0.1.2" } -wasmer-clif-backend = { path = "../clif-backend", version = "0.1.2", optional = true } +wasmer-clif-backend = { path = "../clif-backend", version = "0.1.2" } lazy_static = "1.2.0" [features] -default = ["default-compiler", "cache"] -default-compiler = ["wasmer-clif-backend/cache", "wasmer-runtime-core/cache"] -cache = ["default-compiler"] +default = ["wasmer-clif-backend/cache", "wasmer-runtime-core/cache"] debug = ["wasmer-clif-backend/debug", "wasmer-runtime-core/debug"] diff --git a/lib/runtime/src/cache.rs b/lib/runtime/src/cache.rs index ceb6d171e..b0db19fe8 100644 --- a/lib/runtime/src/cache.rs +++ b/lib/runtime/src/cache.rs @@ -1,128 +1,139 @@ use crate::Module; use std::path::Path; use wasmer_runtime_core::cache::{hash_data, Cache as CoreCache}; +use wasmer_runtime_core::module::{WasmHash}; pub use wasmer_runtime_core::cache::Error; -/// On-disk storage of compiled WebAssembly. -/// -/// A `Cache` can be used to quickly reload already -/// compiled WebAssembly from a previous execution -/// during which the wasm was explicitly compiled -/// as a `Cache`. -/// -/// # Usage: -/// -/// ``` -/// use wasmer_runtime::{compile_cache, Cache}; -/// -/// # use wasmer_runtime::error::{CompileResult, CacheError}; -/// # fn make_cache(wasm: &[u8]) -> CompileResult<()> { -/// // Make a cache. -/// let cache = compile_cache(wasm)?; -/// -/// # Ok(()) -/// # } -/// # fn usage_cache(cache: Cache) -> Result<(), CacheError> { -/// // Store the cache in a file. -/// cache.store("some_cache_file")?; -/// -/// // Load the cache. -/// let cache = Cache::load("some_cache_file")?; -/// let module = unsafe { cache.into_module()? }; -/// # Ok(()) -/// # } -/// ``` -/// -/// # Performance Characteristics: -/// -/// Loading caches from files has been optimized for latency. -/// There is still more work to do that will reduce -/// loading time, especially for very large modules, -/// but it will require signifigant internal work. -/// -/// # Drawbacks: -/// -/// Due to internal shortcomings, you cannot convert -/// a module into a `Cache`. This means that compiling -/// into a `Cache` and then converting into a module -/// has more overhead than directly compiling -/// into a [`Module`]. -/// -/// [`Module`]: struct.Module.html -pub struct Cache(pub(crate) CoreCache); +// /// On-disk storage of compiled WebAssembly. +// /// +// /// A `Cache` can be used to quickly reload already +// /// compiled WebAssembly from a previous execution +// /// during which the wasm was explicitly compiled +// /// as a `Cache`. +// /// +// /// # Usage: +// /// +// /// ``` +// /// use wasmer_runtime::{compile_cache, Cache}; +// /// +// /// # use wasmer_runtime::error::{CompileResult, CacheError}; +// /// # fn make_cache(wasm: &[u8]) -> CompileResult<()> { +// /// // Make a cache. +// /// let cache = compile_cache(wasm)?; +// /// +// /// # Ok(()) +// /// # } +// /// # fn usage_cache(cache: Cache) -> Result<(), CacheError> { +// /// // Store the cache in a file. +// /// cache.store("some_cache_file")?; +// /// +// /// // Load the cache. +// /// let cache = Cache::load("some_cache_file")?; +// /// let module = unsafe { cache.into_module()? }; +// /// # Ok(()) +// /// # } +// /// ``` +// /// +// /// # Performance Characteristics: +// /// +// /// Loading caches from files has been optimized for latency. +// /// There is still more work to do that will reduce +// /// loading time, especially for very large modules, +// /// but it will require signifigant internal work. +// /// +// /// # Drawbacks: +// /// +// /// Due to internal shortcomings, you cannot convert +// /// a module into a `Cache`. This means that compiling +// /// into a `Cache` and then converting into a module +// /// has more overhead than directly compiling +// /// into a [`Module`]. +// /// +// /// [`Module`]: struct.Module.html +// pub struct Cache(pub(crate) CoreCache); -impl Cache { - /// Load a `Cache` from the file specified by `path`. - /// - /// # Usage: - /// - /// ``` - /// use wasmer_runtime::Cache; - /// # use wasmer_runtime::error::CacheError; - /// - /// # fn load_cache() -> Result<(), CacheError> { - /// let cache = Cache::load("some_file.cache")?; - /// # Ok(()) - /// # } - /// ``` - pub fn load>(path: P) -> Result { - CoreCache::open(path).map(|core_cache| Cache(core_cache)) - } +// impl Cache { +// /// Load a `Cache` from the file specified by `path`. +// /// +// /// # Usage: +// /// +// /// ``` +// /// use wasmer_runtime::Cache; +// /// # use wasmer_runtime::error::CacheError; +// /// +// /// # fn load_cache() -> Result<(), CacheError> { +// /// let cache = Cache::load("some_file.cache")?; +// /// # Ok(()) +// /// # } +// /// ``` +// pub fn load>(path: P) -> Result { +// CoreCache::open(path).map(|core_cache| Cache(core_cache)) +// } - /// Convert a `Cache` into a [`Module`]. - /// - /// [`Module`]: struct.Module.html - /// - /// # Usage: - /// - /// ``` - /// use wasmer_runtime::Cache; - /// - /// # use wasmer_runtime::error::CacheError; - /// # fn cache2module(cache: Cache) -> Result<(), CacheError> { - /// let module = unsafe { cache.into_module()? }; - /// # Ok(()) - /// # } - /// ``` - /// - /// # Notes: - /// - /// This method is unsafe because the runtime cannot confirm - /// that this cache was not tampered with or corrupted. - pub unsafe fn into_module(self) -> Result { - let default_compiler = super::default_compiler(); +// /// Convert a `Cache` into a [`Module`]. +// /// +// /// [`Module`]: struct.Module.html +// /// +// /// # Usage: +// /// +// /// ``` +// /// use wasmer_runtime::Cache; +// /// +// /// # use wasmer_runtime::error::CacheError; +// /// # fn cache2module(cache: Cache) -> Result<(), CacheError> { +// /// let module = unsafe { cache.into_module()? }; +// /// # Ok(()) +// /// # } +// /// ``` +// /// +// /// # Notes: +// /// +// /// This method is unsafe because the runtime cannot confirm +// /// that this cache was not tampered with or corrupted. +// pub unsafe fn into_module(self) -> Result { +// let default_compiler = super::default_compiler(); - wasmer_runtime_core::load_cache_with(self.0, default_compiler) - } +// wasmer_runtime_core::load_cache_with(self.0, default_compiler) +// } - /// Compare the Sha256 hash of the wasm this cache was build - /// from with some other WebAssembly. - /// - /// The main use-case for this is invalidating old caches. - pub fn compare_wasm(&self, wasm: &[u8]) -> bool { - let param_wasm_hash = hash_data(wasm); - self.0.wasm_hash() as &[u8] == ¶m_wasm_hash as &[u8] - } +// /// Compare the Sha256 hash of the wasm this cache was build +// /// from with some other WebAssembly. +// /// +// /// The main use-case for this is invalidating old caches. +// pub fn compare_wasm(&self, wasm: &[u8]) -> bool { +// let param_wasm_hash = hash_data(wasm); +// self.0.wasm_hash() as &[u8] == ¶m_wasm_hash as &[u8] +// } - /// Store this cache in a file. - /// - /// # Notes: - /// - /// If a file exists at the specified path, it will be overwritten. - /// - /// # Usage: - /// - /// ``` - /// use wasmer_runtime::Cache; - /// - /// # use wasmer_runtime::error::CacheError; - /// # fn store_cache(cache: Cache) -> Result<(), CacheError> { - /// cache.store("some_file.cache")?; - /// # Ok(()) - /// # } - /// ``` - pub fn store>(&self, path: P) -> Result<(), Error> { - self.0.store(path) - } +// /// Store this cache in a file. +// /// +// /// # Notes: +// /// +// /// If a file exists at the specified path, it will be overwritten. +// /// +// /// # Usage: +// /// +// /// ``` +// /// use wasmer_runtime::Cache; +// /// +// /// # use wasmer_runtime::error::CacheError; +// /// # fn store_cache(cache: Cache) -> Result<(), CacheError> { +// /// cache.store("some_file.cache")?; +// /// # Ok(()) +// /// # } +// /// ``` +// pub fn store>(&self, path: P) -> Result<(), Error> { +// self.0.store(path) +// } +// } + +pub trait Cache { + type Key; + type LoadError; + type StoreError; + + unsafe fn load(&self, key: Self::Key) -> Result; + fn store(&mut self, module: Module) -> Result; } + diff --git a/lib/runtime/src/lib.rs b/lib/runtime/src/lib.rs index f100a5bad..48a4c27f5 100644 --- a/lib/runtime/src/lib.rs +++ b/lib/runtime/src/lib.rs @@ -99,7 +99,6 @@ pub mod wasm { } pub mod error { - #[cfg(feature = "cache")] pub use super::cache::Error as CacheError; pub use wasmer_runtime_core::error::*; } @@ -109,13 +108,10 @@ pub mod units { pub use wasmer_runtime_core::units::{Bytes, Pages}; } -#[cfg(feature = "cache")] mod cache; -#[cfg(feature = "default-compiler")] use wasmer_runtime_core::backend::Compiler; -#[cfg(feature = "cache")] pub use self::cache::Cache; /// Compile WebAssembly binary code into a [`Module`]. @@ -131,7 +127,6 @@ pub use self::cache::Cache; /// binary code of the wasm module you want to compile. /// # Errors: /// If the operation fails, the function returns `Err(error::CompileError::...)`. -#[cfg(feature = "default-compiler")] pub fn compile(wasm: &[u8]) -> error::CompileResult { wasmer_runtime_core::compile_with(&wasm[..], default_compiler()) } @@ -154,38 +149,35 @@ pub fn compile(wasm: &[u8]) -> error::CompileResult { /// `error::CompileError`, `error::LinkError`, or /// `error::RuntimeError` (all combined into an `error::Error`), /// depending on the cause of the failure. -#[cfg(feature = "default-compiler")] pub fn instantiate(wasm: &[u8], import_object: &ImportObject) -> error::Result { let module = compile(wasm)?; module.instantiate(import_object) } -/// Compile wasm into a [`Cache`] that can be stored to a file or -/// converted into [`Module`]. -/// -/// [`Cache`]: struct.Cache.html -/// [`Module`]: struct.Module.html -/// -/// # Usage: -/// -/// ``` -/// # use wasmer_runtime::error::CompileResult; -/// use wasmer_runtime::compile_cache; -/// -/// # fn make_cache(wasm: &[u8]) -> CompileResult<()> { -/// let cache = compile_cache(wasm)?; -/// # Ok(()) -/// # } -/// ``` -#[cfg(feature = "cache")] -pub fn compile_cache(wasm: &[u8]) -> error::CompileResult { - let default_compiler = default_compiler(); +// /// Compile wasm into a [`Cache`] that can be stored to a file or +// /// converted into [`Module`]. +// /// +// /// [`Cache`]: struct.Cache.html +// /// [`Module`]: struct.Module.html +// /// +// /// # Usage: +// /// +// /// ``` +// /// # use wasmer_runtime::error::CompileResult; +// /// use wasmer_runtime::compile_cache; +// /// +// /// # fn make_cache(wasm: &[u8]) -> CompileResult<()> { +// /// let cache = compile_cache(wasm)?; +// /// # Ok(()) +// /// # } +// /// ``` +// pub fn compile_cache(wasm: &[u8]) -> error::CompileResult { +// let default_compiler = default_compiler(); - wasmer_runtime_core::compile_to_cache_with(wasm, default_compiler) - .map(|core_cache| Cache(core_cache)) -} +// wasmer_runtime_core::compile_to_cache_with(wasm, default_compiler) +// .map(|core_cache| Cache(core_cache)) +// } -#[cfg(feature = "default-compiler")] fn default_compiler() -> &'static dyn Compiler { use lazy_static::lazy_static; use wasmer_clif_backend::CraneliftCompiler; From 380d7669435b5b653507d74726bddec1f3b443d9 Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Mon, 18 Feb 2019 23:30:08 -0600 Subject: [PATCH 071/262] Convert from Box into/from raw to pointer ref-deref to fix free issue --- lib/runtime-c-api/src/lib.rs | 50 +++++++------------ .../tests/test-import-function.c | 4 +- 2 files changed, 20 insertions(+), 34 deletions(-) diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index 38414c8d7..bcd4fd344 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -196,9 +196,8 @@ pub extern "C" fn wasmer_memory_grow( memory: *mut wasmer_memory_t, delta: uint32_t, ) -> wasmer_result_t { - let memory = unsafe { Box::from_raw(memory as *mut Memory) }; + let memory = unsafe { &*(memory as *mut Memory) }; let maybe_delta = memory.grow(Pages(delta)); - Box::into_raw(memory); if let Some(_delta) = maybe_delta { wasmer_result_t::WASMER_OK } else { @@ -213,9 +212,8 @@ pub extern "C" fn wasmer_memory_grow( #[allow(clippy::cast_ptr_alignment)] #[no_mangle] pub extern "C" fn wasmer_memory_length(memory: *mut wasmer_memory_t) -> uint32_t { - let memory = unsafe { Box::from_raw(memory as *mut Memory) }; + let memory = unsafe { &*(memory as *mut Memory) }; let Pages(len) = memory.size(); - Box::into_raw(memory); len } @@ -262,9 +260,8 @@ pub extern "C" fn wasmer_table_grow( table: *mut wasmer_table_t, delta: uint32_t, ) -> wasmer_result_t { - let table = unsafe { Box::from_raw(table as *mut Table) }; + let table = unsafe { &*(table as *mut Table) }; let maybe_delta = table.grow(delta); - Box::into_raw(table); if let Some(_delta) = maybe_delta { wasmer_result_t::WASMER_OK } else { @@ -279,9 +276,8 @@ pub extern "C" fn wasmer_table_grow( #[allow(clippy::cast_ptr_alignment)] #[no_mangle] pub extern "C" fn wasmer_table_length(table: *mut wasmer_table_t) -> uint32_t { - let table = unsafe { Box::from_raw(table as *mut Table) }; + let table = unsafe { &*(table as *mut Table) }; let len = table.size(); - Box::into_raw(table); len } @@ -313,9 +309,8 @@ pub unsafe extern "C" fn wasmer_global_new( #[allow(clippy::cast_ptr_alignment)] #[no_mangle] pub extern "C" fn wasmer_global_get(global: *mut wasmer_global_t) -> wasmer_value_t { - let global = unsafe { Box::from_raw(global as *mut Global) }; + let global = unsafe { &*(global as *mut Global) }; let value: wasmer_value_t = global.get().into(); - Box::into_raw(global); value } @@ -323,9 +318,8 @@ pub extern "C" fn wasmer_global_get(global: *mut wasmer_global_t) -> wasmer_valu #[allow(clippy::cast_ptr_alignment)] #[no_mangle] pub extern "C" fn wasmer_global_set(global: *mut wasmer_global_t, value: wasmer_value_t) { - let global = unsafe { Box::from_raw(global as *mut Global) }; + let global = unsafe { &*(global as *mut Global) }; global.set(value.into()); - Box::into_raw(global); } /// Returns a descriptor (type, mutability) of the given Global @@ -334,13 +328,12 @@ pub extern "C" fn wasmer_global_set(global: *mut wasmer_global_t, value: wasmer_ pub extern "C" fn wasmer_global_get_descriptor( global: *mut wasmer_global_t, ) -> wasmer_global_descriptor_t { - let global = unsafe { Box::from_raw(global as *mut Global) }; + let global = unsafe { &*(global as *mut Global) }; let descriptor = global.descriptor(); let desc = wasmer_global_descriptor_t { mutable: descriptor.mutable, kind: descriptor.ty.into(), }; - Box::into_raw(global); desc } @@ -458,7 +451,7 @@ pub unsafe extern "C" fn wasmer_instantiate( wasmer_import_export_kind::WASM_GLOBAL => import.value.global as *mut Export, wasmer_import_export_kind::WASM_TABLE => import.value.table as *mut Export, }; - namespace.insert(import_name, unsafe { *Box::from_raw(export) }); + namespace.insert(import_name, unsafe { *Box::from_raw(export) }); // TODO Review } for (module_name, namespace) in namespaces.into_iter() { import_object.register(module_name, namespace); @@ -524,11 +517,10 @@ pub unsafe extern "C" fn wasmer_instance_call( let func_name_c = unsafe { CStr::from_ptr(name) }; let func_name_r = func_name_c.to_str().unwrap(); - let instance = unsafe { Box::from_raw(instance as *mut Instance) }; let results: &mut [wasmer_value_t] = slice::from_raw_parts_mut(results, results_len as usize); - let result = instance.call(func_name_r, ¶ms[..]); - Box::into_raw(instance); + let result = (&*(instance as *mut Instance)).call(func_name_r, ¶ms[..]); + match result { Ok(results_vec) => { if results_vec.len() > 0 { @@ -570,11 +562,10 @@ pub unsafe extern "C" fn wasmer_instance_exports( instance: *mut wasmer_instance_t, exports: *mut *mut wasmer_exports_t, ) { - let mut instance = unsafe { Box::from_raw(instance as *mut Instance) }; + let mut instance = unsafe { &mut *(instance as *mut Instance) }; let named_exports: Box = Box::new(NamedExports(instance.exports().map(|e| e.into()).collect())); unsafe { *exports = Box::into_raw(named_exports) as *mut wasmer_exports_t }; - Box::into_raw(instance); } pub struct NamedExports(Vec); @@ -608,9 +599,8 @@ pub unsafe extern "C" fn wasmer_exports_get( if exports.is_null() { return ptr::null_mut(); } - let mut named_exports = unsafe { Box::from_raw(exports as *mut NamedExports) }; + let mut named_exports = unsafe { &mut *(exports as *mut NamedExports) }; let ptr = &mut (*named_exports).0[idx as usize] as *mut NamedExport as *mut wasmer_export_t; - Box::into_raw(named_exports); ptr } @@ -666,7 +656,7 @@ pub unsafe extern "C" fn wasmer_func_params_arity( func: *mut wasmer_func_t, result: *mut uint32_t, ) -> wasmer_result_t { - let mut export = unsafe { Box::from_raw(func as *mut Export) }; + let mut export = unsafe { &mut *(func as *mut Export) }; let result = if let Export::Function { ref signature, .. } = *export { unsafe { *result = signature.params().len() as uint32_t }; wasmer_result_t::WASMER_OK @@ -676,7 +666,6 @@ pub unsafe extern "C" fn wasmer_func_params_arity( }); wasmer_result_t::WASMER_ERROR }; - Box::into_raw(export); result } @@ -693,7 +682,7 @@ pub unsafe extern "C" fn wasmer_func_params( params: *mut wasmer_value_tag, params_len: c_int, ) -> wasmer_result_t { - let mut export = unsafe { Box::from_raw(func as *mut Export) }; + let mut export = unsafe { &mut *(func as *mut Export) }; let result = if let Export::Function { ref signature, .. } = *export { let params: &mut [wasmer_value_tag] = slice::from_raw_parts_mut(params, params_len as usize); @@ -707,7 +696,6 @@ pub unsafe extern "C" fn wasmer_func_params( }); wasmer_result_t::WASMER_ERROR }; - Box::into_raw(export); result } @@ -724,7 +712,7 @@ pub unsafe extern "C" fn wasmer_func_returns( returns: *mut wasmer_value_tag, returns_len: c_int, ) -> wasmer_result_t { - let mut export = unsafe { Box::from_raw(func as *mut Export) }; + let mut export = unsafe { &mut *(func as *mut Export) }; let result = if let Export::Function { ref signature, .. } = *export { let returns: &mut [wasmer_value_tag] = slice::from_raw_parts_mut(returns, returns_len as usize); @@ -738,7 +726,6 @@ pub unsafe extern "C" fn wasmer_func_returns( }); wasmer_result_t::WASMER_ERROR }; - Box::into_raw(export); result } @@ -754,7 +741,7 @@ pub unsafe extern "C" fn wasmer_func_returns_arity( func: *mut wasmer_func_t, result: *mut uint32_t, ) -> wasmer_result_t { - let mut export = unsafe { Box::from_raw(func as *mut Export) }; + let mut export = unsafe { &*(func as *mut Export) }; let result = if let Export::Function { ref signature, .. } = *export { unsafe { *result = signature.returns().len() as uint32_t }; wasmer_result_t::WASMER_OK @@ -764,7 +751,6 @@ pub unsafe extern "C" fn wasmer_func_returns_arity( }); wasmer_result_t::WASMER_ERROR }; - Box::into_raw(export); result } @@ -830,7 +816,7 @@ pub unsafe extern "C" fn wasmer_func_call( let params: &[wasmer_value_t] = slice::from_raw_parts(params, params_len as usize); let params: Vec = params.iter().cloned().map(|x| x.into()).collect(); - let export_func = unsafe { Box::from_raw(func as *mut Export) }; + let export_func = unsafe { &*(func as *mut Export) }; let results: &mut [wasmer_value_t] = slice::from_raw_parts_mut(results, results_len as usize); // TODO implement func.call @@ -880,7 +866,7 @@ pub extern "C" fn wasmer_instance_context_memory( ctx: *mut wasmer_instance_context_t, memory_idx: uint32_t, ) -> *const wasmer_memory_t { - let mut ctx = unsafe { Box::from_raw(ctx as *mut Ctx) }; + let mut ctx = unsafe { &mut *(ctx as *mut Ctx) }; let memory = ctx.memory(0); memory as *const Memory as *const wasmer_memory_t } diff --git a/lib/runtime-c-api/tests/test-import-function.c b/lib/runtime-c-api/tests/test-import-function.c index 4e52f113e..bd09938d5 100644 --- a/lib/runtime-c-api/tests/test-import-function.c +++ b/lib/runtime-c-api/tests/test-import-function.c @@ -85,7 +85,7 @@ int main() printf("Destroying func\n"); // wasmer_func_destroy(func); - // printf("Destroy instance\n"); - // wasmer_instance_destroy(instance); + printf("Destroy instance\n"); + wasmer_instance_destroy(instance); return 0; } \ No newline at end of file From d2f30231911484254355b23c715cc5d988c54fed Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Tue, 19 Feb 2019 00:05:08 -0600 Subject: [PATCH 072/262] Allow specifying optional max value in limits --- lib/runtime-c-api/src/lib.rs | 22 +++++++++++++++++++--- lib/runtime-c-api/tests/test-memory.c | 5 ++++- lib/runtime-c-api/tests/test-tables.c | 16 ++++++++++------ lib/runtime-c-api/wasmer.h | 7 ++++++- lib/runtime-c-api/wasmer.hh | 7 ++++++- 5 files changed, 45 insertions(+), 12 deletions(-) diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index bcd4fd344..d4286a9ca 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -87,7 +87,13 @@ pub struct wasmer_global_t(); #[repr(C)] pub struct wasmer_limits_t { pub min: uint32_t, - pub max: uint32_t, + pub max: wasmer_limit_option_t, +} + +#[repr(C)] +pub struct wasmer_limit_option_t { + pub has_some: bool, + pub some: uint32_t, } #[repr(C)] @@ -167,9 +173,14 @@ pub unsafe extern "C" fn wasmer_memory_new( mut memory: *mut *mut wasmer_memory_t, limits: wasmer_limits_t, ) -> wasmer_result_t { + let max = if limits.max.has_some { + Some(Pages(limits.max.some)) + } else { + None + }; let desc = MemoryDescriptor { minimum: Pages(limits.min), - maximum: Some(Pages(limits.max)), + maximum: max, shared: false, }; let result = Memory::new(desc); @@ -231,10 +242,15 @@ pub unsafe extern "C" fn wasmer_table_new( mut table: *mut *mut wasmer_table_t, limits: wasmer_limits_t, ) -> wasmer_result_t { + let max = if limits.max.has_some { + Some(limits.max.some) + } else { + None + }; let desc = TableDescriptor { element: ElementType::Anyfunc, minimum: limits.min, - maximum: Some(limits.max), + maximum: max, }; let result = Table::new(desc); let new_table = match result { diff --git a/lib/runtime-c-api/tests/test-memory.c b/lib/runtime-c-api/tests/test-memory.c index d472c2b08..63913c73b 100644 --- a/lib/runtime-c-api/tests/test-memory.c +++ b/lib/runtime-c-api/tests/test-memory.c @@ -8,7 +8,10 @@ int main() wasmer_memory_t *memory = NULL; wasmer_limits_t descriptor; descriptor.min = 10; - descriptor.max = 15; + wasmer_limit_option_t max; + max.has_some = true; + max.some = 15; + descriptor.max = max; wasmer_result_t memory_result = wasmer_memory_new(&memory, descriptor); printf("Memory result: %d\n", memory_result); assert(memory_result == WASMER_OK); diff --git a/lib/runtime-c-api/tests/test-tables.c b/lib/runtime-c-api/tests/test-tables.c index 3f8c29805..66ebf832d 100644 --- a/lib/runtime-c-api/tests/test-tables.c +++ b/lib/runtime-c-api/tests/test-tables.c @@ -8,7 +8,11 @@ int main() wasmer_table_t *table = NULL; wasmer_limits_t descriptor; descriptor.min = 10; - descriptor.max = 15; + wasmer_limit_option_t max; +// max.has_some = false; + max.has_some = true; + max.some = 15; + descriptor.max = max; wasmer_result_t table_result = wasmer_table_new(&table, descriptor); printf("Table result: %d\n", table_result); assert(table_result == WASMER_OK); @@ -17,11 +21,11 @@ int main() printf("Table length: %d\n", len); assert(len == 15); - // wasmer_result_t grow_result1 = wasmer_table_grow(&table, 5); - // assert(grow_result1 == WASMER_OK); - // uint32_t len_grow1 = wasmer_table_length(table); - // printf("Table length: %d\n", len_grow1); - // assert(len_grow1 == 15); +// wasmer_result_t grow_result1 = wasmer_table_grow(table, 5); +// assert(grow_result1 == WASMER_OK); +// uint32_t len_grow1 = wasmer_table_length(table); +// printf("Table length: %d\n", len_grow1); +// assert(len_grow1 == 15); // // Try to grow beyond max // wasmer_result_t grow_result2 = wasmer_table_grow(&table, 1); diff --git a/lib/runtime-c-api/wasmer.h b/lib/runtime-c-api/wasmer.h index d37a9dbd1..8d328836f 100644 --- a/lib/runtime-c-api/wasmer.h +++ b/lib/runtime-c-api/wasmer.h @@ -93,9 +93,14 @@ typedef struct { wasmer_import_export_value value; } wasmer_import_t; +typedef struct { + bool has_some; + uint32_t some; +} wasmer_limit_option_t; + typedef struct { uint32_t min; - uint32_t max; + wasmer_limit_option_t max; } wasmer_limits_t; /** diff --git a/lib/runtime-c-api/wasmer.hh b/lib/runtime-c-api/wasmer.hh index a8931496d..ab2808bf3 100644 --- a/lib/runtime-c-api/wasmer.hh +++ b/lib/runtime-c-api/wasmer.hh @@ -90,9 +90,14 @@ struct wasmer_import_t { wasmer_import_export_value value; }; +struct wasmer_limit_option_t { + bool has_some; + uint32_t some; +}; + struct wasmer_limits_t { uint32_t min; - uint32_t max; + wasmer_limit_option_t max; }; extern "C" { From 3c7dc200fa615bd21ec11f17cc2e36988e7a859e Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Tue, 19 Feb 2019 09:58:01 -0800 Subject: [PATCH 073/262] close to working --- lib/clif-backend/src/cache.rs | 32 +++- lib/clif-backend/src/lib.rs | 48 +++--- lib/clif-backend/src/module.rs | 63 ++++---- lib/clif-backend/src/resolver.rs | 246 ++++++++++++++--------------- lib/clif-backend/src/signal/mod.rs | 9 +- lib/clif-backend/src/trampoline.rs | 4 +- lib/runtime-core/src/backend.rs | 9 +- lib/runtime-core/src/lib.rs | 20 +-- lib/runtime-core/src/module.rs | 4 +- lib/runtime-core/src/vm.rs | 10 +- 10 files changed, 239 insertions(+), 206 deletions(-) diff --git a/lib/clif-backend/src/cache.rs b/lib/clif-backend/src/cache.rs index aef6adf4c..cf1b9c919 100644 --- a/lib/clif-backend/src/cache.rs +++ b/lib/clif-backend/src/cache.rs @@ -2,15 +2,41 @@ use crate::relocation::{ExternalRelocation, TrapSink}; use hashbrown::HashMap; use wasmer_runtime_core::{ - backend::sys::Memory, + backend::{ + sys::Memory, + CacheGen, + }, cache::{Cache, Error}, - module::ModuleInfo, + module::{ModuleInfo, ModuleInner}, structures::Map, types::{LocalFuncIndex, SigIndex}, }; +use std::{ + sync::Arc, + cell::UnsafeCell, +}; use serde_bench::{deserialize, serialize}; +pub struct CacheGenerator { + backend_cache: BackendCache, + memory: Arc, +} + +impl CacheGenerator { + pub fn new(backend_cache: BackendCache, memory: Arc) -> Self { + Self { backend_cache, memory } + } +} + +impl CacheGen for CacheGenerator { + fn generate_cache(&self, module: &ModuleInner) -> Result<(Box, Box<[u8]>, Arc), Error> { + let info = Box::new(module.info.clone()); + + Err(Error::Unknown("".to_string())) + } +} + #[derive(Serialize, Deserialize)] pub struct TrampolineCache { #[serde(with = "serde_bytes")] @@ -22,7 +48,7 @@ pub struct TrampolineCache { pub struct BackendCache { pub external_relocs: Map>, pub offsets: Map, - pub trap_sink: TrapSink, + pub trap_sink: Arc, pub trampolines: TrampolineCache, } diff --git a/lib/clif-backend/src/lib.rs b/lib/clif-backend/src/lib.rs index cbe455b93..621d5b59e 100644 --- a/lib/clif-backend/src/lib.rs +++ b/lib/clif-backend/src/lib.rs @@ -62,36 +62,36 @@ impl Compiler for CraneliftCompiler { module::Module::from_cache(cache) } - #[cfg(feature = "cache")] - fn compile_to_backend_cache_data( - &self, - wasm: &[u8], - _: Token, - ) -> CompileResult<(Box, Vec, Memory)> { - validate(wasm)?; + // #[cfg(feature = "cache")] + // fn compile_to_backend_cache_data( + // &self, + // wasm: &[u8], + // _: Token, + // ) -> CompileResult<(Box, Vec, Memory)> { + // validate(wasm)?; - let isa = get_isa(); + // let isa = get_isa(); - let mut module = module::Module::new(wasm); - let module_env = module_env::ModuleEnv::new(&mut module, &*isa); + // let mut module = module::Module::new(wasm); + // let module_env = module_env::ModuleEnv::new(&mut module, &*isa); - let func_bodies = module_env.translate(wasm)?; + // let func_bodies = module_env.translate(wasm)?; - let (info, backend_cache, compiled_code) = module - .compile_to_backend_cache(&*isa, func_bodies) - .map_err(|e| CompileError::InternalError { - msg: format!("{:?}", e), - })?; + // let (info, backend_cache, compiled_code) = module + // .compile_to_backend_cache(&*isa, func_bodies) + // .map_err(|e| CompileError::InternalError { + // msg: format!("{:?}", e), + // })?; - let buffer = - backend_cache - .into_backend_data() - .map_err(|e| CompileError::InternalError { - msg: format!("{:?}", e), - })?; + // let buffer = + // backend_cache + // .into_backend_data() + // .map_err(|e| CompileError::InternalError { + // msg: format!("{:?}", e), + // })?; - Ok((Box::new(info), buffer, compiled_code)) - } + // Ok((Box::new(info), buffer, compiled_code)) + // } } fn get_isa() -> Box { diff --git a/lib/clif-backend/src/module.rs b/lib/clif-backend/src/module.rs index e2ee8efe8..23f07eac9 100644 --- a/lib/clif-backend/src/module.rs +++ b/lib/clif-backend/src/module.rs @@ -1,11 +1,12 @@ #[cfg(feature = "cache")] -use crate::cache::BackendCache; +use crate::cache::{BackendCache, CacheGenerator}; use crate::{resolver::FuncResolverBuilder, signal::Caller, trampoline::Trampolines}; use cranelift_codegen::{ir, isa}; use cranelift_entity::EntityRef; use cranelift_wasm; use hashbrown::HashMap; +use std::sync::Arc; #[cfg(feature = "cache")] use wasmer_runtime_core::{ @@ -67,42 +68,44 @@ impl Module { ) -> CompileResult { let (func_resolver_builder, handler_data) = FuncResolverBuilder::new(isa, functions, &self.info)?; - - let func_resolver = - Box::new(func_resolver_builder.finalize(&self.info.signatures)?); + let trampolines = Arc::new(Trampolines::new(isa, &self.info)); - let trampolines = Trampolines::new(isa, &self.info); + let (func_resolver, backend_cache) = + func_resolver_builder.finalize(&self.info.signatures, Arc::clone(&trampolines), handler_data.clone())?; let protected_caller = - Box::new(Caller::new(&self.info, handler_data, trampolines)); + Caller::new(&self.info, handler_data, trampolines); + + let cache_gen = Box::new(CacheGenerator::new(backend_cache, Arc::clone(&func_resolver.memory))); Ok(ModuleInner { - func_resolver, - protected_caller, + func_resolver: Box::new(func_resolver), + protected_caller: Box::new(protected_caller), + cache_gen, info: self.info, }) } - #[cfg(feature = "cache")] - pub fn compile_to_backend_cache( - self, - isa: &isa::TargetIsa, - functions: Map, - ) -> CompileResult<(ModuleInfo, BackendCache, Memory)> { - let (func_resolver_builder, handler_data) = - FuncResolverBuilder::new(isa, functions, &self.info)?; + // #[cfg(feature = "cache")] + // pub fn compile_to_backend_cache( + // self, + // isa: &isa::TargetIsa, + // functions: Map, + // ) -> CompileResult<(ModuleInfo, BackendCache, Memory)> { + // let (func_resolver_builder, handler_data) = + // FuncResolverBuilder::new(isa, functions, &self.info)?; - let trampolines = Trampolines::new(isa, &self.info); + // let trampolines = Trampolines::new(isa, &self.info); - let trampoline_cache = trampolines.to_trampoline_cache(); + // let trampoline_cache = trampolines.to_trampoline_cache(); - let (backend_cache, compiled_code) = - func_resolver_builder.to_backend_cache(trampoline_cache, handler_data); + // let (backend_cache, compiled_code) = + // func_resolver_builder.to_backend_cache(trampoline_cache, handler_data); - Ok((self.info, backend_cache, compiled_code)) - } + // Ok((self.info, backend_cache, compiled_code)) + // } #[cfg(feature = "cache")] pub fn from_cache(cache: Cache) -> Result { @@ -111,17 +114,19 @@ impl Module { let (func_resolver_builder, trampolines, handler_data) = FuncResolverBuilder::new_from_backend_cache(backend_cache, compiled_code, &info)?; - let func_resolver = Box::new( + let (func_resolver, backend_cache) = func_resolver_builder - .finalize(&info.signatures) - .map_err(|e| CacheError::Unknown(format!("{:?}", e)))?, - ); + .finalize(&info.signatures, Arc::clone(&trampolines), handler_data.clone()) + .map_err(|e| CacheError::Unknown(format!("{:?}", e)))?; - let protected_caller = Box::new(Caller::new(&info, handler_data, trampolines)); + let protected_caller = Caller::new(&info, handler_data, trampolines); + let cache_gen = Box::new(CacheGenerator::new(backend_cache, Arc::clone(&func_resolver.memory))); Ok(ModuleInner { - func_resolver, - protected_caller, + func_resolver: Box::new(func_resolver), + protected_caller: Box::new(protected_caller), + cache_gen, + info, }) } diff --git a/lib/clif-backend/src/resolver.rs b/lib/clif-backend/src/resolver.rs index 48ea5c7e5..1eccb2715 100644 --- a/lib/clif-backend/src/resolver.rs +++ b/lib/clif-backend/src/resolver.rs @@ -17,6 +17,7 @@ use cranelift_codegen::{ir, isa, Context}; use std::{ mem, ptr::{write_unaligned, NonNull}, + cell::UnsafeCell, sync::Arc, }; #[cfg(feature = "cache")] @@ -56,7 +57,7 @@ impl FuncResolverBuilder { backend_cache: BackendCache, mut code: Memory, info: &ModuleInfo, - ) -> Result<(Self, Trampolines, HandlerData), CacheError> { + ) -> Result<(Self, Arc, HandlerData), CacheError> { unsafe { code.protect(.., Protect::ReadWrite) .map_err(|e| CacheError::Unknown(e.to_string()))?; @@ -69,35 +70,17 @@ impl FuncResolverBuilder { Self { resolver: FuncResolver { map: backend_cache.offsets, - memory: code, + memory: Arc::new(UnsafeCell::new(code)), }, local_relocs: Map::new(), external_relocs: backend_cache.external_relocs, import_len: info.imported_functions.len(), }, - Trampolines::from_trampoline_cache(backend_cache.trampolines), + Arc::new(Trampolines::from_trampoline_cache(backend_cache.trampolines)), handler_data, )) } - #[cfg(feature = "cache")] - pub fn to_backend_cache( - mut self, - trampolines: TrampolineCache, - handler_data: HandlerData, - ) -> (BackendCache, Memory) { - self.relocate_locals(); - ( - BackendCache { - external_relocs: self.external_relocs, - offsets: self.resolver.map, - trap_sink: handler_data.trap_data, - trampolines, - }, - self.resolver.memory, - ) - } - pub fn new( isa: &isa::TargetIsa, function_bodies: Map, @@ -169,10 +152,10 @@ impl FuncResolverBuilder { previous_end = new_end; } - let handler_data = HandlerData::new(trap_sink, memory.as_ptr() as _, memory.size()); + let handler_data = HandlerData::new(Arc::new(trap_sink), memory.as_ptr() as _, memory.size()); let mut func_resolver_builder = Self { - resolver: FuncResolver { map, memory }, + resolver: FuncResolver { map, memory: Arc::new(UnsafeCell::new(memory)) }, local_relocs, external_relocs, import_len: info.imported_functions.len(), @@ -207,128 +190,143 @@ impl FuncResolverBuilder { } pub fn finalize( - mut self, + self, signatures: &SliceMap>, - ) -> CompileResult { - for (index, relocs) in self.external_relocs.iter() { - for ref reloc in relocs.iter() { - let target_func_address: isize = match reloc.target { - RelocationType::LibCall(libcall) => match libcall { - LibCall::CeilF32 => libcalls::ceilf32 as isize, - LibCall::FloorF32 => libcalls::floorf32 as isize, - LibCall::TruncF32 => libcalls::truncf32 as isize, - LibCall::NearestF32 => libcalls::nearbyintf32 as isize, - LibCall::CeilF64 => libcalls::ceilf64 as isize, - LibCall::FloorF64 => libcalls::floorf64 as isize, - LibCall::TruncF64 => libcalls::truncf64 as isize, - LibCall::NearestF64 => libcalls::nearbyintf64 as isize, - #[cfg(all(target_pointer_width = "64", target_os = "windows"))] - LibCall::Probestack => __chkstk as isize, - #[cfg(not(target_os = "windows"))] - LibCall::Probestack => __rust_probestack as isize, - }, - RelocationType::Intrinsic(ref name) => match name.as_str() { - "i32print" => i32_print as isize, - "i64print" => i64_print as isize, - "f32print" => f32_print as isize, - "f64print" => f64_print as isize, - "strtdbug" => start_debug as isize, - "enddbug" => end_debug as isize, - _ => Err(CompileError::InternalError { - msg: format!("unexpected intrinsic: {}", name), - })?, - }, - RelocationType::VmCall(vmcall) => match vmcall { - VmCall::Local(kind) => match kind { - VmCallKind::StaticMemoryGrow => vmcalls::local_static_memory_grow as _, - VmCallKind::StaticMemorySize => vmcalls::local_static_memory_size as _, + trampolines: Arc, + handler_data: HandlerData, + ) -> CompileResult<(FuncResolver, BackendCache)> { + { + let mut memory = unsafe { (*self.resolver.memory.get()) }; - VmCallKind::SharedStaticMemoryGrow => unimplemented!(), - VmCallKind::SharedStaticMemorySize => unimplemented!(), - - VmCallKind::DynamicMemoryGrow => { - vmcalls::local_dynamic_memory_grow as _ - } - VmCallKind::DynamicMemorySize => { - vmcalls::local_dynamic_memory_size as _ - } + for (index, relocs) in self.external_relocs.iter() { + for ref reloc in relocs.iter() { + let target_func_address: isize = match reloc.target { + RelocationType::LibCall(libcall) => match libcall { + LibCall::CeilF32 => libcalls::ceilf32 as isize, + LibCall::FloorF32 => libcalls::floorf32 as isize, + LibCall::TruncF32 => libcalls::truncf32 as isize, + LibCall::NearestF32 => libcalls::nearbyintf32 as isize, + LibCall::CeilF64 => libcalls::ceilf64 as isize, + LibCall::FloorF64 => libcalls::floorf64 as isize, + LibCall::TruncF64 => libcalls::truncf64 as isize, + LibCall::NearestF64 => libcalls::nearbyintf64 as isize, + #[cfg(all(target_pointer_width = "64", target_os = "windows"))] + LibCall::Probestack => __chkstk as isize, + #[cfg(not(target_os = "windows"))] + LibCall::Probestack => __rust_probestack as isize, }, - VmCall::Import(kind) => match kind { - VmCallKind::StaticMemoryGrow => { - vmcalls::imported_static_memory_grow as _ - } - VmCallKind::StaticMemorySize => { - vmcalls::imported_static_memory_size as _ - } - - VmCallKind::SharedStaticMemoryGrow => unimplemented!(), - VmCallKind::SharedStaticMemorySize => unimplemented!(), - - VmCallKind::DynamicMemoryGrow => { - vmcalls::imported_dynamic_memory_grow as _ - } - VmCallKind::DynamicMemorySize => { - vmcalls::imported_dynamic_memory_size as _ - } + RelocationType::Intrinsic(ref name) => match name.as_str() { + "i32print" => i32_print as isize, + "i64print" => i64_print as isize, + "f32print" => f32_print as isize, + "f64print" => f64_print as isize, + "strtdbug" => start_debug as isize, + "enddbug" => end_debug as isize, + _ => Err(CompileError::InternalError { + msg: format!("unexpected intrinsic: {}", name), + })?, + }, + RelocationType::VmCall(vmcall) => match vmcall { + VmCall::Local(kind) => match kind { + VmCallKind::StaticMemoryGrow => vmcalls::local_static_memory_grow as _, + VmCallKind::StaticMemorySize => vmcalls::local_static_memory_size as _, + + VmCallKind::SharedStaticMemoryGrow => unimplemented!(), + VmCallKind::SharedStaticMemorySize => unimplemented!(), + + VmCallKind::DynamicMemoryGrow => { + vmcalls::local_dynamic_memory_grow as _ + } + VmCallKind::DynamicMemorySize => { + vmcalls::local_dynamic_memory_size as _ + } + }, + VmCall::Import(kind) => match kind { + VmCallKind::StaticMemoryGrow => { + vmcalls::imported_static_memory_grow as _ + } + VmCallKind::StaticMemorySize => { + vmcalls::imported_static_memory_size as _ + } + + VmCallKind::SharedStaticMemoryGrow => unimplemented!(), + VmCallKind::SharedStaticMemorySize => unimplemented!(), + + VmCallKind::DynamicMemoryGrow => { + vmcalls::imported_dynamic_memory_grow as _ + } + VmCallKind::DynamicMemorySize => { + vmcalls::imported_dynamic_memory_size as _ + } + }, + }, + RelocationType::Signature(sig_index) => { + let sig_index = + SigRegistry.lookup_sig_index(Arc::clone(&signatures[sig_index])); + sig_index.index() as _ + } + }; + + // We need the address of the current function + // because some of these calls are relative. + let func_addr = self.resolver.lookup(index).unwrap().as_ptr(); + + // Determine relocation type and apply relocation. + match reloc.reloc { + Reloc::Abs8 => { + let ptr_to_write = (target_func_address as u64) + .checked_add(reloc.addend as u64) + .unwrap(); + let empty_space_offset = self.resolver.map[index] + reloc.offset as usize; + let ptr_slice = unsafe { + &mut memory.as_slice_mut() + [empty_space_offset..empty_space_offset + 8] + }; + LittleEndian::write_u64(ptr_slice, ptr_to_write); + } + Reloc::X86PCRel4 | Reloc::X86CallPCRel4 => unsafe { + let reloc_address = (func_addr as usize) + reloc.offset as usize; + let reloc_delta = target_func_address + .wrapping_sub(reloc_address as isize) + .wrapping_add(reloc.addend as isize); + + write_unaligned(reloc_address as *mut u32, reloc_delta as u32); }, - }, - RelocationType::Signature(sig_index) => { - let sig_index = - SigRegistry.lookup_sig_index(Arc::clone(&signatures[sig_index])); - sig_index.index() as _ } - }; - - // We need the address of the current function - // because some of these calls are relative. - let func_addr = self.resolver.lookup(index).unwrap().as_ptr(); - - // Determine relocation type and apply relocation. - match reloc.reloc { - Reloc::Abs8 => { - let ptr_to_write = (target_func_address as u64) - .checked_add(reloc.addend as u64) - .unwrap(); - let empty_space_offset = self.resolver.map[index] + reloc.offset as usize; - let ptr_slice = unsafe { - &mut self.resolver.memory.as_slice_mut() - [empty_space_offset..empty_space_offset + 8] - }; - LittleEndian::write_u64(ptr_slice, ptr_to_write); - } - Reloc::X86PCRel4 | Reloc::X86CallPCRel4 => unsafe { - let reloc_address = (func_addr as usize) + reloc.offset as usize; - let reloc_delta = target_func_address - .wrapping_sub(reloc_address as isize) - .wrapping_add(reloc.addend as isize); - - write_unaligned(reloc_address as *mut u32, reloc_delta as u32); - }, } } + + unsafe { + memory + .protect(.., Protect::ReadExec) + .map_err(|e| CompileError::InternalError { msg: e.to_string() })?; + } } - unsafe { - self.resolver - .memory - .protect(.., Protect::ReadExec) - .map_err(|e| CompileError::InternalError { msg: e.to_string() })?; - } + let backend_cache = BackendCache { + external_relocs: self.external_relocs.clone(), + offsets: self.resolver.map.clone(), + trap_sink: handler_data.trap_data, + trampolines: trampolines.to_trampoline_cache(), + }; - Ok(self.resolver) + Ok((self.resolver, backend_cache)) } } +unsafe impl Sync for FuncResolver {} +unsafe impl Send for FuncResolver {} + /// Resolves a function index to a function address. pub struct FuncResolver { map: Map, - memory: Memory, + pub(crate) memory: Arc>, } impl FuncResolver { fn lookup(&self, local_func_index: LocalFuncIndex) -> Option> { let offset = *self.map.get(local_func_index)?; - let ptr = unsafe { self.memory.as_ptr().add(offset) }; + let ptr = unsafe { (*self.memory.get()).as_ptr().add(offset) }; NonNull::new(ptr).map(|nonnull| nonnull.cast()) } diff --git a/lib/clif-backend/src/signal/mod.rs b/lib/clif-backend/src/signal/mod.rs index 1468d99eb..bedcff87a 100644 --- a/lib/clif-backend/src/signal/mod.rs +++ b/lib/clif-backend/src/signal/mod.rs @@ -40,11 +40,11 @@ impl UserTrapper for Trapper { pub struct Caller { func_export_set: HashSet, handler_data: HandlerData, - trampolines: Trampolines, + trampolines: Arc, } impl Caller { - pub fn new(module: &ModuleInfo, handler_data: HandlerData, trampolines: Trampolines) -> Self { + pub fn new(module: &ModuleInfo, handler_data: HandlerData, trampolines: Arc) -> Self { let mut func_export_set = HashSet::new(); for export_index in module.exports.values() { if let ExportIndex::Func(func_index) = export_index { @@ -187,15 +187,16 @@ fn get_func_from_index( unsafe impl Send for HandlerData {} unsafe impl Sync for HandlerData {} +#[derive(Clone)] pub struct HandlerData { - pub trap_data: TrapSink, + pub trap_data: Arc, exec_buffer_ptr: *const c_void, exec_buffer_size: usize, } impl HandlerData { pub fn new( - trap_data: TrapSink, + trap_data: Arc, exec_buffer_ptr: *const c_void, exec_buffer_size: usize, ) -> Self { diff --git a/lib/clif-backend/src/trampoline.rs b/lib/clif-backend/src/trampoline.rs index 76fb521d6..492314c14 100644 --- a/lib/clif-backend/src/trampoline.rs +++ b/lib/clif-backend/src/trampoline.rs @@ -58,7 +58,7 @@ impl Trampolines { } #[cfg(feature = "cache")] - pub fn to_trampoline_cache(self) -> TrampolineCache { + pub fn to_trampoline_cache(&self) -> TrampolineCache { let mut code = vec![0; self.memory.size()]; unsafe { @@ -67,7 +67,7 @@ impl Trampolines { TrampolineCache { code, - offsets: self.offsets, + offsets: self.offsets.clone(), } } diff --git a/lib/runtime-core/src/backend.rs b/lib/runtime-core/src/backend.rs index 328e3c826..769281ff2 100644 --- a/lib/runtime-core/src/backend.rs +++ b/lib/runtime-core/src/backend.rs @@ -45,13 +45,6 @@ pub trait Compiler { #[cfg(feature = "cache")] unsafe fn from_cache(&self, cache: Cache, _: Token) -> Result; - - #[cfg(feature = "cache")] - fn compile_to_backend_cache_data( - &self, - wasm: &[u8], - _: Token, - ) -> CompileResult<(Box, Vec, Memory)>; } /// The functionality exposed by this trait is expected to be used @@ -101,5 +94,5 @@ pub trait FuncResolver: Send + Sync { } pub trait CacheGen: Send + Sync { - fn generate_cache(&self, module: &ModuleInner) -> Result<(Box, Box<[u8]>, Memory), CacheError>; + fn generate_cache(&self, module: &ModuleInner) -> Result<(Box, Box<[u8]>, Arc), CacheError>; } \ No newline at end of file diff --git a/lib/runtime-core/src/lib.rs b/lib/runtime-core/src/lib.rs index d130b8899..6edc85e9b 100644 --- a/lib/runtime-core/src/lib.rs +++ b/lib/runtime-core/src/lib.rs @@ -90,17 +90,17 @@ pub fn validate(wasm: &[u8]) -> bool { } } -#[cfg(feature = "cache")] -pub fn compile_to_cache_with( - wasm: &[u8], - compiler: &dyn backend::Compiler, -) -> CompileResult { - let token = backend::Token::generate(); - let (info, backend_metadata, compiled_code) = - compiler.compile_to_backend_cache_data(wasm, token)?; +// #[cfg(feature = "cache")] +// pub fn compile_to_cache_with( +// wasm: &[u8], +// compiler: &dyn backend::Compiler, +// ) -> CompileResult { +// let token = backend::Token::generate(); +// let (info, backend_metadata, compiled_code) = +// compiler.compile_to_backend_cache_data(wasm, token)?; - Ok(Cache::new(wasm, info, backend_metadata, compiled_code)) -} +// Ok(Cache::new(wasm, info, backend_metadata, compiled_code)) +// } #[cfg(feature = "cache")] pub unsafe fn load_cache_with( diff --git a/lib/runtime-core/src/module.rs b/lib/runtime-core/src/module.rs index aca3fc221..2a398d53e 100644 --- a/lib/runtime-core/src/module.rs +++ b/lib/runtime-core/src/module.rs @@ -1,5 +1,5 @@ use crate::{ - backend::{Backend, FuncResolver, ProtectedCaller}, + backend::{Backend, FuncResolver, ProtectedCaller, CacheGen}, error::Result, import::ImportObject, structures::{Map, TypedIndex}, @@ -21,10 +21,12 @@ use std::sync::Arc; pub struct ModuleInner { pub func_resolver: Box, pub protected_caller: Box, + pub cache_gen: Box, pub info: ModuleInfo, } +#[derive(Clone)] #[cfg_attr(feature = "cache", derive(Serialize, Deserialize))] pub struct ModuleInfo { // This are strictly local and the typsystem ensures that. diff --git a/lib/runtime-core/src/vm.rs b/lib/runtime-core/src/vm.rs index abea76db8..79d18255a 100644 --- a/lib/runtime-core/src/vm.rs +++ b/lib/runtime-core/src/vm.rs @@ -494,7 +494,8 @@ mod vm_ctx_tests { fn generate_module() -> ModuleInner { use super::Func; - use crate::backend::{Backend, FuncResolver, ProtectedCaller, Token, UserTrapper}; + use crate::backend::{Backend, FuncResolver, ProtectedCaller, Token, UserTrapper, CacheGen, sys::Memory}; + use crate::cache::Error as CacheError; use crate::error::RuntimeResult; use crate::types::{FuncIndex, LocalFuncIndex, Value}; use crate::module::WasmHash; @@ -526,10 +527,17 @@ mod vm_ctx_tests { unimplemented!() } } + impl CacheGen for Placeholder { + fn generate_cache(&self, module: &ModuleInner) -> Result<(Box, Box<[u8]>, Memory), CacheError> { + unimplemented!() + } + } + ModuleInner { func_resolver: Box::new(Placeholder), protected_caller: Box::new(Placeholder), + cache_gen: Box::new(Placeholder), info: ModuleInfo { memories: Map::new(), globals: Map::new(), From 82eea00a023779bc353d69ef47c17e87d6cc308c Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Tue, 19 Feb 2019 15:36:22 -0800 Subject: [PATCH 074/262] Saved --- lib/clif-backend/Cargo.toml | 8 - lib/clif-backend/src/cache.rs | 19 +- lib/clif-backend/src/lib.rs | 12 +- lib/clif-backend/src/module.rs | 37 +--- lib/clif-backend/src/relocation.rs | 18 +- lib/clif-backend/src/resolver.rs | 245 ++++++++++----------- lib/clif-backend/src/trampoline.rs | 6 +- lib/runtime-core/Cargo.toml | 12 +- lib/runtime-core/src/backend.rs | 11 +- lib/runtime-core/src/cache.rs | 29 +-- lib/runtime-core/src/lib.rs | 10 +- lib/runtime-core/src/module.rs | 42 ++-- lib/runtime-core/src/structures/map.rs | 2 +- lib/runtime-core/src/sys/mod.rs | 10 +- lib/runtime-core/src/sys/unix/memory.rs | 12 +- lib/runtime-core/src/sys/windows/memory.rs | 12 +- lib/runtime-core/src/types.rs | 22 +- lib/runtime-core/src/units.rs | 4 +- lib/runtime/Cargo.toml | 11 +- lib/spectests/Cargo.toml | 2 +- 20 files changed, 267 insertions(+), 257 deletions(-) diff --git a/lib/clif-backend/Cargo.toml b/lib/clif-backend/Cargo.toml index becb71a04..701f821fc 100644 --- a/lib/clif-backend/Cargo.toml +++ b/lib/clif-backend/Cargo.toml @@ -23,24 +23,16 @@ libc = "0.2.48" # Dependencies for caching. [dependencies.serde] version = "1.0" -optional = true [dependencies.serde_derive] version = "1.0" -optional = true [dependencies.serde_bytes] version = "0.10" -optional = true -# [dependencies.bincode] -# version = "1.0.1" -# optional = true [dependencies.serde-bench] version = "0.0.7" -optional = true [target.'cfg(windows)'.dependencies] winapi = { version = "0.3", features = ["errhandlingapi", "minwindef", "minwinbase", "winnt"] } wasmer-win-exception-handler = { path = "../win-exception-handler", version = "0.0.1" } [features] -cache = ["serde", "serde_derive", "serde_bytes", "serde-bench", "wasmer-runtime-core/cache"] debug = ["wasmer-runtime-core/debug"] diff --git a/lib/clif-backend/src/cache.rs b/lib/clif-backend/src/cache.rs index cf1b9c919..7e805271b 100644 --- a/lib/clif-backend/src/cache.rs +++ b/lib/clif-backend/src/cache.rs @@ -32,8 +32,7 @@ impl CacheGenerator { impl CacheGen for CacheGenerator { fn generate_cache(&self, module: &ModuleInner) -> Result<(Box, Box<[u8]>, Arc), Error> { let info = Box::new(module.info.clone()); - - Err(Error::Unknown("".to_string())) + Ok((info, self.backend_cache.into_backend_data()?.into_boxed_slice(), Arc::clone(&self.memory))) } } @@ -54,18 +53,26 @@ pub struct BackendCache { impl BackendCache { pub fn from_cache(cache: Cache) -> Result<(ModuleInfo, Memory, Self), Error> { - let (info, backend_data, compiled_code) = cache.consume(); + let (info, backend_data, compiled_code_arc) = cache.consume(); - let backend_cache = deserialize(backend_data.as_slice()) + // If this is the only references to this arc, move the memory out. + // else, clone the memory to a new location. This could take a long time, + // depending on the throughput of your memcpy implementation. + let compiled_code = match Arc::try_unwrap(compiled_code_arc) { + Ok(code) => code, + Err(arc) => (*arc).clone(), + }; + + let backend_cache = deserialize(&backend_data) .map_err(|e| Error::DeserializeError(e.to_string()))?; Ok((info, compiled_code, backend_cache)) } - pub fn into_backend_data(self) -> Result, Error> { + pub fn into_backend_data(&self) -> Result, Error> { let mut buffer = Vec::new(); - serialize(&mut buffer, &self).map_err(|e| Error::SerializeError(e.to_string()))?; + serialize(&mut buffer, self).map_err(|e| Error::SerializeError(e.to_string()))?; Ok(buffer) } diff --git a/lib/clif-backend/src/lib.rs b/lib/clif-backend/src/lib.rs index 621d5b59e..42d56552b 100644 --- a/lib/clif-backend/src/lib.rs +++ b/lib/clif-backend/src/lib.rs @@ -1,4 +1,4 @@ -#[cfg(feature = "cache")] + mod cache; mod func_env; mod libcalls; @@ -14,7 +14,7 @@ use cranelift_codegen::{ settings::{self, Configurable}, }; use target_lexicon::Triple; -#[cfg(feature = "cache")] + use wasmer_runtime_core::{ backend::sys::Memory, cache::{Cache, Error as CacheError}, @@ -25,10 +25,10 @@ use wasmer_runtime_core::{ error::{CompileError, CompileResult}, module::ModuleInner, }; -#[cfg(feature = "cache")] + #[macro_use] extern crate serde_derive; -#[cfg(feature = "cache")] + extern crate serde; use wasmparser::{self, WasmDecoder}; @@ -57,12 +57,12 @@ impl Compiler for CraneliftCompiler { } /// Create a wasmer Module from an already-compiled cache. - #[cfg(feature = "cache")] + unsafe fn from_cache(&self, cache: Cache, _: Token) -> Result { module::Module::from_cache(cache) } - // #[cfg(feature = "cache")] + // // fn compile_to_backend_cache_data( // &self, // wasm: &[u8], diff --git a/lib/clif-backend/src/module.rs b/lib/clif-backend/src/module.rs index 23f07eac9..29eea5f2c 100644 --- a/lib/clif-backend/src/module.rs +++ b/lib/clif-backend/src/module.rs @@ -1,4 +1,4 @@ -#[cfg(feature = "cache")] + use crate::cache::{BackendCache, CacheGenerator}; use crate::{resolver::FuncResolverBuilder, signal::Caller, trampoline::Trampolines}; @@ -8,7 +8,7 @@ use cranelift_wasm; use hashbrown::HashMap; use std::sync::Arc; -#[cfg(feature = "cache")] + use wasmer_runtime_core::{ backend::sys::Memory, cache::{Cache, Error as CacheError}, @@ -17,13 +17,15 @@ use wasmer_runtime_core::{ use wasmer_runtime_core::{ backend::Backend, error::CompileResult, - module::{ModuleInfo, ModuleInner, StringTable, WasmHash}, + module::{ModuleInfo, ModuleInner, StringTable}, structures::{Map, TypedIndex}, types::{ FuncIndex, FuncSig, GlobalIndex, LocalFuncIndex, MemoryIndex, SigIndex, TableIndex, Type, }, }; +use wasmer_runtime_core::module::WasmHash; + /// This contains all of the items in a `ModuleInner` except the `func_resolver`. pub struct Module { pub info: ModuleInfo, @@ -56,6 +58,7 @@ impl Module { namespace_table: StringTable::new(), name_table: StringTable::new(), + wasm_hash: WasmHash::generate(wasm), }, } @@ -77,37 +80,19 @@ impl Module { let protected_caller = Caller::new(&self.info, handler_data, trampolines); + let cache_gen = Box::new(CacheGenerator::new(backend_cache, Arc::clone(&func_resolver.memory))); Ok(ModuleInner { func_resolver: Box::new(func_resolver), protected_caller: Box::new(protected_caller), - cache_gen, + cache_gen, info: self.info, }) } - // #[cfg(feature = "cache")] - // pub fn compile_to_backend_cache( - // self, - // isa: &isa::TargetIsa, - // functions: Map, - // ) -> CompileResult<(ModuleInfo, BackendCache, Memory)> { - // let (func_resolver_builder, handler_data) = - // FuncResolverBuilder::new(isa, functions, &self.info)?; - - // let trampolines = Trampolines::new(isa, &self.info); - - // let trampoline_cache = trampolines.to_trampoline_cache(); - - // let (backend_cache, compiled_code) = - // func_resolver_builder.to_backend_cache(trampoline_cache, handler_data); - - // Ok((self.info, backend_cache, compiled_code)) - // } - - #[cfg(feature = "cache")] + pub fn from_cache(cache: Cache) -> Result { let (info, compiled_code, backend_cache) = BackendCache::from_cache(cache)?; @@ -120,12 +105,14 @@ impl Module { .map_err(|e| CacheError::Unknown(format!("{:?}", e)))?; let protected_caller = Caller::new(&info, handler_data, trampolines); + + let cache_gen = Box::new(CacheGenerator::new(backend_cache, Arc::clone(&func_resolver.memory))); Ok(ModuleInner { func_resolver: Box::new(func_resolver), protected_caller: Box::new(protected_caller), - cache_gen, + cache_gen, info, }) diff --git a/lib/clif-backend/src/relocation.rs b/lib/clif-backend/src/relocation.rs index 840255e61..03adbc4bb 100644 --- a/lib/clif-backend/src/relocation.rs +++ b/lib/clif-backend/src/relocation.rs @@ -22,7 +22,7 @@ pub mod call_names { pub const DYNAMIC_MEM_SIZE: u32 = 5; } -#[cfg_attr(feature = "cache", derive(Serialize, Deserialize))] +#[derive(Serialize, Deserialize)] #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum Reloc { Abs8, @@ -30,7 +30,7 @@ pub enum Reloc { X86CallPCRel4, } -#[cfg_attr(feature = "cache", derive(Serialize, Deserialize))] +#[derive(Serialize, Deserialize)] #[derive(Debug, Copy, Clone)] pub enum LibCall { Probestack, @@ -44,7 +44,7 @@ pub enum LibCall { NearestF64, } -#[cfg_attr(feature = "cache", derive(Serialize, Deserialize))] +#[derive(Serialize, Deserialize)] #[derive(Debug, Clone)] pub struct ExternalRelocation { /// The relocation code. @@ -66,7 +66,7 @@ pub struct LocalRelocation { pub target: FuncIndex, } -#[cfg_attr(feature = "cache", derive(Serialize, Deserialize))] +#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Copy)] pub enum VmCallKind { StaticMemoryGrow, @@ -79,7 +79,7 @@ pub enum VmCallKind { DynamicMemorySize, } -#[cfg_attr(feature = "cache", derive(Serialize, Deserialize))] +#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Copy)] pub enum VmCall { Local(VmCallKind), @@ -87,7 +87,7 @@ pub enum VmCall { } /// Specify the type of relocation -#[cfg_attr(feature = "cache", derive(Serialize, Deserialize))] +#[derive(Serialize, Deserialize)] #[derive(Debug, Clone)] pub enum RelocationType { Intrinsic(String), @@ -218,7 +218,7 @@ impl binemit::RelocSink for RelocSink { } } -#[cfg_attr(feature = "cache", derive(Serialize, Deserialize))] +#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Copy)] pub enum TrapCode { StackOverflow, @@ -244,7 +244,7 @@ impl RelocSink { } } -#[cfg_attr(feature = "cache", derive(Serialize, Deserialize))] +#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Copy)] pub struct TrapData { pub trapcode: TrapCode, @@ -253,7 +253,7 @@ pub struct TrapData { /// Simple implementation of a TrapSink /// that saves the info for later. -#[cfg_attr(feature = "cache", derive(Serialize, Deserialize))] +#[derive(Serialize, Deserialize)] pub struct TrapSink { trap_datas: Vec<(usize, TrapData)>, } diff --git a/lib/clif-backend/src/resolver.rs b/lib/clif-backend/src/resolver.rs index 1eccb2715..06b678a5b 100644 --- a/lib/clif-backend/src/resolver.rs +++ b/lib/clif-backend/src/resolver.rs @@ -1,4 +1,4 @@ -#[cfg(feature = "cache")] + use crate::{ cache::{BackendCache, TrampolineCache}, trampoline::Trampolines, @@ -20,7 +20,7 @@ use std::{ cell::UnsafeCell, sync::Arc, }; -#[cfg(feature = "cache")] + use wasmer_runtime_core::cache::Error as CacheError; use wasmer_runtime_core::{ self, @@ -43,16 +43,24 @@ extern "C" { pub fn __chkstk(); } +fn lookup_func(map: &SliceMap, memory: &Memory, local_func_index: LocalFuncIndex) -> Option> { + let offset = *map.get(local_func_index)?; + let ptr = unsafe { memory.as_ptr().add(offset) }; + + NonNull::new(ptr).map(|nonnull| nonnull.cast()) +} + #[allow(dead_code)] pub struct FuncResolverBuilder { - resolver: FuncResolver, + map: Map, + memory: Memory, local_relocs: Map>, external_relocs: Map>, import_len: usize, } impl FuncResolverBuilder { - #[cfg(feature = "cache")] + pub fn new_from_backend_cache( backend_cache: BackendCache, mut code: Memory, @@ -68,10 +76,8 @@ impl FuncResolverBuilder { Ok(( Self { - resolver: FuncResolver { - map: backend_cache.offsets, - memory: Arc::new(UnsafeCell::new(code)), - }, + map: backend_cache.offsets, + memory: code, local_relocs: Map::new(), external_relocs: backend_cache.external_relocs, import_len: info.imported_functions.len(), @@ -155,7 +161,8 @@ impl FuncResolverBuilder { let handler_data = HandlerData::new(Arc::new(trap_sink), memory.as_ptr() as _, memory.size()); let mut func_resolver_builder = Self { - resolver: FuncResolver { map, memory: Arc::new(UnsafeCell::new(memory)) }, + map, + memory, local_relocs, external_relocs, import_len: info.imported_functions.len(), @@ -171,11 +178,11 @@ impl FuncResolverBuilder { for ref reloc in relocs.iter() { let local_func_index = LocalFuncIndex::new(reloc.target.index() - self.import_len); let target_func_address = - self.resolver.lookup(local_func_index).unwrap().as_ptr() as usize; + lookup_func(&self.map, &self.memory, local_func_index).unwrap().as_ptr() as usize; // We need the address of the current function // because these calls are relative. - let func_addr = self.resolver.lookup(index).unwrap().as_ptr() as usize; + let func_addr = lookup_func(&self.map, &self.memory, index).unwrap().as_ptr() as usize; unsafe { let reloc_address = func_addr + reloc.offset as usize; @@ -190,127 +197,126 @@ impl FuncResolverBuilder { } pub fn finalize( - self, + mut self, signatures: &SliceMap>, trampolines: Arc, handler_data: HandlerData, ) -> CompileResult<(FuncResolver, BackendCache)> { - { - let mut memory = unsafe { (*self.resolver.memory.get()) }; + for (index, relocs) in self.external_relocs.iter() { + for ref reloc in relocs.iter() { + let target_func_address: isize = match reloc.target { + RelocationType::LibCall(libcall) => match libcall { + LibCall::CeilF32 => libcalls::ceilf32 as isize, + LibCall::FloorF32 => libcalls::floorf32 as isize, + LibCall::TruncF32 => libcalls::truncf32 as isize, + LibCall::NearestF32 => libcalls::nearbyintf32 as isize, + LibCall::CeilF64 => libcalls::ceilf64 as isize, + LibCall::FloorF64 => libcalls::floorf64 as isize, + LibCall::TruncF64 => libcalls::truncf64 as isize, + LibCall::NearestF64 => libcalls::nearbyintf64 as isize, + #[cfg(all(target_pointer_width = "64", target_os = "windows"))] + LibCall::Probestack => __chkstk as isize, + #[cfg(not(target_os = "windows"))] + LibCall::Probestack => __rust_probestack as isize, + }, + RelocationType::Intrinsic(ref name) => match name.as_str() { + "i32print" => i32_print as isize, + "i64print" => i64_print as isize, + "f32print" => f32_print as isize, + "f64print" => f64_print as isize, + "strtdbug" => start_debug as isize, + "enddbug" => end_debug as isize, + _ => Err(CompileError::InternalError { + msg: format!("unexpected intrinsic: {}", name), + })?, + }, + RelocationType::VmCall(vmcall) => match vmcall { + VmCall::Local(kind) => match kind { + VmCallKind::StaticMemoryGrow => vmcalls::local_static_memory_grow as _, + VmCallKind::StaticMemorySize => vmcalls::local_static_memory_size as _, - for (index, relocs) in self.external_relocs.iter() { - for ref reloc in relocs.iter() { - let target_func_address: isize = match reloc.target { - RelocationType::LibCall(libcall) => match libcall { - LibCall::CeilF32 => libcalls::ceilf32 as isize, - LibCall::FloorF32 => libcalls::floorf32 as isize, - LibCall::TruncF32 => libcalls::truncf32 as isize, - LibCall::NearestF32 => libcalls::nearbyintf32 as isize, - LibCall::CeilF64 => libcalls::ceilf64 as isize, - LibCall::FloorF64 => libcalls::floorf64 as isize, - LibCall::TruncF64 => libcalls::truncf64 as isize, - LibCall::NearestF64 => libcalls::nearbyintf64 as isize, - #[cfg(all(target_pointer_width = "64", target_os = "windows"))] - LibCall::Probestack => __chkstk as isize, - #[cfg(not(target_os = "windows"))] - LibCall::Probestack => __rust_probestack as isize, + VmCallKind::SharedStaticMemoryGrow => unimplemented!(), + VmCallKind::SharedStaticMemorySize => unimplemented!(), + + VmCallKind::DynamicMemoryGrow => { + vmcalls::local_dynamic_memory_grow as _ + } + VmCallKind::DynamicMemorySize => { + vmcalls::local_dynamic_memory_size as _ + } }, - RelocationType::Intrinsic(ref name) => match name.as_str() { - "i32print" => i32_print as isize, - "i64print" => i64_print as isize, - "f32print" => f32_print as isize, - "f64print" => f64_print as isize, - "strtdbug" => start_debug as isize, - "enddbug" => end_debug as isize, - _ => Err(CompileError::InternalError { - msg: format!("unexpected intrinsic: {}", name), - })?, - }, - RelocationType::VmCall(vmcall) => match vmcall { - VmCall::Local(kind) => match kind { - VmCallKind::StaticMemoryGrow => vmcalls::local_static_memory_grow as _, - VmCallKind::StaticMemorySize => vmcalls::local_static_memory_size as _, - - VmCallKind::SharedStaticMemoryGrow => unimplemented!(), - VmCallKind::SharedStaticMemorySize => unimplemented!(), - - VmCallKind::DynamicMemoryGrow => { - vmcalls::local_dynamic_memory_grow as _ - } - VmCallKind::DynamicMemorySize => { - vmcalls::local_dynamic_memory_size as _ - } - }, - VmCall::Import(kind) => match kind { - VmCallKind::StaticMemoryGrow => { - vmcalls::imported_static_memory_grow as _ - } - VmCallKind::StaticMemorySize => { - vmcalls::imported_static_memory_size as _ - } - - VmCallKind::SharedStaticMemoryGrow => unimplemented!(), - VmCallKind::SharedStaticMemorySize => unimplemented!(), - - VmCallKind::DynamicMemoryGrow => { - vmcalls::imported_dynamic_memory_grow as _ - } - VmCallKind::DynamicMemorySize => { - vmcalls::imported_dynamic_memory_size as _ - } - }, - }, - RelocationType::Signature(sig_index) => { - let sig_index = - SigRegistry.lookup_sig_index(Arc::clone(&signatures[sig_index])); - sig_index.index() as _ - } - }; - - // We need the address of the current function - // because some of these calls are relative. - let func_addr = self.resolver.lookup(index).unwrap().as_ptr(); - - // Determine relocation type and apply relocation. - match reloc.reloc { - Reloc::Abs8 => { - let ptr_to_write = (target_func_address as u64) - .checked_add(reloc.addend as u64) - .unwrap(); - let empty_space_offset = self.resolver.map[index] + reloc.offset as usize; - let ptr_slice = unsafe { - &mut memory.as_slice_mut() - [empty_space_offset..empty_space_offset + 8] - }; - LittleEndian::write_u64(ptr_slice, ptr_to_write); - } - Reloc::X86PCRel4 | Reloc::X86CallPCRel4 => unsafe { - let reloc_address = (func_addr as usize) + reloc.offset as usize; - let reloc_delta = target_func_address - .wrapping_sub(reloc_address as isize) - .wrapping_add(reloc.addend as isize); - - write_unaligned(reloc_address as *mut u32, reloc_delta as u32); + VmCall::Import(kind) => match kind { + VmCallKind::StaticMemoryGrow => { + vmcalls::imported_static_memory_grow as _ + } + VmCallKind::StaticMemorySize => { + vmcalls::imported_static_memory_size as _ + } + + VmCallKind::SharedStaticMemoryGrow => unimplemented!(), + VmCallKind::SharedStaticMemorySize => unimplemented!(), + + VmCallKind::DynamicMemoryGrow => { + vmcalls::imported_dynamic_memory_grow as _ + } + VmCallKind::DynamicMemorySize => { + vmcalls::imported_dynamic_memory_size as _ + } }, + }, + RelocationType::Signature(sig_index) => { + let sig_index = + SigRegistry.lookup_sig_index(Arc::clone(&signatures[sig_index])); + sig_index.index() as _ } + }; + + // We need the address of the current function + // because some of these calls are relative. + let func_addr = lookup_func(&self.map, &self.memory, index).unwrap().as_ptr() as usize; + + // Determine relocation type and apply relocation. + match reloc.reloc { + Reloc::Abs8 => { + let ptr_to_write = (target_func_address as u64) + .checked_add(reloc.addend as u64) + .unwrap(); + let empty_space_offset = self.map[index] + reloc.offset as usize; + let ptr_slice = unsafe { + &mut self.memory.as_slice_mut() + [empty_space_offset..empty_space_offset + 8] + }; + LittleEndian::write_u64(ptr_slice, ptr_to_write); + } + Reloc::X86PCRel4 | Reloc::X86CallPCRel4 => unsafe { + let reloc_address = (func_addr as usize) + reloc.offset as usize; + let reloc_delta = target_func_address + .wrapping_sub(reloc_address as isize) + .wrapping_add(reloc.addend as isize); + + write_unaligned(reloc_address as *mut u32, reloc_delta as u32); + }, } } + } - unsafe { - memory - .protect(.., Protect::ReadExec) - .map_err(|e| CompileError::InternalError { msg: e.to_string() })?; - } + unsafe { + self.memory + .protect(.., Protect::ReadExec) + .map_err(|e| CompileError::InternalError { msg: e.to_string() })?; } let backend_cache = BackendCache { external_relocs: self.external_relocs.clone(), - offsets: self.resolver.map.clone(), + offsets: self.map.clone(), trap_sink: handler_data.trap_data, trampolines: trampolines.to_trampoline_cache(), }; - Ok((self.resolver, backend_cache)) + Ok((FuncResolver { + map: self.map, + memory: Arc::new(self.memory), + }, backend_cache)) } } @@ -320,16 +326,7 @@ unsafe impl Send for FuncResolver {} /// Resolves a function index to a function address. pub struct FuncResolver { map: Map, - pub(crate) memory: Arc>, -} - -impl FuncResolver { - fn lookup(&self, local_func_index: LocalFuncIndex) -> Option> { - let offset = *self.map.get(local_func_index)?; - let ptr = unsafe { (*self.memory.get()).as_ptr().add(offset) }; - - NonNull::new(ptr).map(|nonnull| nonnull.cast()) - } + pub(crate) memory: Arc, } // Implements FuncResolver trait. @@ -339,7 +336,7 @@ impl backend::FuncResolver for FuncResolver { _module: &wasmer_runtime_core::module::ModuleInner, index: LocalFuncIndex, ) -> Option> { - self.lookup(index) + lookup_func(&self.map, &self.memory, index) } } diff --git a/lib/clif-backend/src/trampoline.rs b/lib/clif-backend/src/trampoline.rs index 492314c14..7a90c085e 100644 --- a/lib/clif-backend/src/trampoline.rs +++ b/lib/clif-backend/src/trampoline.rs @@ -1,4 +1,4 @@ -#[cfg(feature = "cache")] + use crate::cache::TrampolineCache; use cranelift_codegen::{ binemit::{NullTrapSink, Reloc, RelocSink}, @@ -33,7 +33,7 @@ pub struct Trampolines { } impl Trampolines { - #[cfg(feature = "cache")] + pub fn from_trampoline_cache(cache: TrampolineCache) -> Self { // pub struct TrampolineCache { // #[serde(with = "serde_bytes")] @@ -57,7 +57,7 @@ impl Trampolines { } } - #[cfg(feature = "cache")] + pub fn to_trampoline_cache(&self) -> TrampolineCache { let mut code = vec![0; self.memory.size()]; diff --git a/lib/runtime-core/Cargo.toml b/lib/runtime-core/Cargo.toml index 9a748eb62..4781751af 100644 --- a/lib/runtime-core/Cargo.toml +++ b/lib/runtime-core/Cargo.toml @@ -8,7 +8,6 @@ repository = "https://github.com/wasmerio/wasmer" edition = "2018" [dependencies] -hashbrown = "0.1" nix = "0.12.0" page_size = "0.4.1" wasmparser = "0.23.0" @@ -21,22 +20,20 @@ libc = "0.2.48" # Dependencies for caching. [dependencies.serde] version = "1.0" -optional = true +features = ["rc"] [dependencies.serde_derive] version = "1.0" -optional = true [dependencies.serde_bytes] version = "0.10" -optional = true [dependencies.serde-bench] version = "0.0.7" -optional = true [dependencies.memmap] version = "0.7.0" -optional = true [dependencies.sha2] version = "0.8.0" -optional = true +[dependencies.hashbrown] +version = "0.1" +features = ["serde"] [target.'cfg(windows)'.dependencies] winapi = { version = "0.3", features = ["memoryapi"] } @@ -47,5 +44,4 @@ field-offset = "0.1.1" [features] debug = [] -cache = ["serde/rc", "serde_derive", "serde_bytes", "hashbrown/serde", "serde-bench", "memmap", "sha2"] diff --git a/lib/runtime-core/src/backend.rs b/lib/runtime-core/src/backend.rs index 769281ff2..a4afe2ee5 100644 --- a/lib/runtime-core/src/backend.rs +++ b/lib/runtime-core/src/backend.rs @@ -2,11 +2,11 @@ use crate::{ backing::ImportBacking, error::CompileResult, error::RuntimeResult, - module::ModuleInner, + module::{ModuleInner}, types::{FuncIndex, LocalFuncIndex, Value}, vm, }; -#[cfg(feature = "cache")] + use crate::{ cache::{Cache, Error as CacheError}, module::ModuleInfo, @@ -14,12 +14,14 @@ use crate::{ }; use std::ptr::NonNull; +use std::sync::Arc; + pub mod sys { pub use crate::sys::*; } pub use crate::sig_registry::SigRegistry; -#[cfg_attr(feature = "cache", derive(Serialize, Deserialize))] +#[derive(Serialize, Deserialize)] #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum Backend { Cranelift, @@ -43,7 +45,7 @@ pub trait Compiler { /// be called from inside the runtime. fn compile(&self, wasm: &[u8], _: Token) -> CompileResult; - #[cfg(feature = "cache")] + unsafe fn from_cache(&self, cache: Cache, _: Token) -> Result; } @@ -93,6 +95,7 @@ pub trait FuncResolver: Send + Sync { ) -> Option>; } + pub trait CacheGen: Send + Sync { fn generate_cache(&self, module: &ModuleInner) -> Result<(Box, Box<[u8]>, Arc), CacheError>; } \ No newline at end of file diff --git a/lib/runtime-core/src/cache.rs b/lib/runtime-core/src/cache.rs index e166599e8..b60301e94 100644 --- a/lib/runtime-core/src/cache.rs +++ b/lib/runtime-core/src/cache.rs @@ -6,6 +6,7 @@ use std::{ fs::File, io::{self, Seek, SeekFrom, Write}, mem, + sync::Arc, path::Path, slice, }; @@ -67,31 +68,26 @@ impl CacheHeader { struct CacheInner { info: Box, #[serde(with = "serde_bytes")] - backend_metadata: Vec, - compiled_code: Memory, + backend_metadata: Box<[u8]>, + compiled_code: Arc, } pub struct Cache { inner: CacheInner, - wasm_hash: Box<[u8; 32]>, } impl Cache { - pub(crate) fn new( - wasm: &[u8], + pub(crate) fn from_parts( info: Box, - backend_metadata: Vec, - compiled_code: Memory, + backend_metadata: Box<[u8]>, + compiled_code: Arc, ) -> Self { - let wasm_hash = hash_data(wasm); - Self { inner: CacheInner { info, backend_metadata, compiled_code, }, - wasm_hash: Box::new(wasm_hash), } } @@ -110,7 +106,6 @@ impl Cache { Ok(Cache { inner, - wasm_hash: Box::new(header.wasm_hash), }) } @@ -118,12 +113,8 @@ impl Cache { &self.inner.info } - pub fn wasm_hash(&self) -> &[u8; 32] { - &self.wasm_hash - } - #[doc(hidden)] - pub fn consume(self) -> (ModuleInfo, Vec, Memory) { + pub fn consume(self) -> (ModuleInfo, Box<[u8]>, Arc) { ( *self.inner.info, self.inner.backend_metadata, @@ -152,11 +143,7 @@ impl Cache { file.seek(SeekFrom::Start(0)) .map_err(|e| Error::Unknown(e.to_string()))?; - let wasm_hash = { - let mut array = [0u8; 32]; - array.copy_from_slice(&*self.wasm_hash); - array - }; + let wasm_hash = self.inner.info.wasm_hash.into_array(); let cache_header = CacheHeader { magic: [ diff --git a/lib/runtime-core/src/lib.rs b/lib/runtime-core/src/lib.rs index 6edc85e9b..18cf2a703 100644 --- a/lib/runtime-core/src/lib.rs +++ b/lib/runtime-core/src/lib.rs @@ -2,7 +2,7 @@ #[macro_use] extern crate field_offset; -#[cfg(feature = "cache")] + #[macro_use] extern crate serde_derive; @@ -11,7 +11,7 @@ mod macros; #[doc(hidden)] pub mod backend; mod backing; -#[cfg(feature = "cache")] + pub mod cache; pub mod error; pub mod export; @@ -44,7 +44,7 @@ pub use self::module::Module; pub use self::typed_func::Func; use std::sync::Arc; -#[cfg(feature = "cache")] + use self::cache::{Cache, Error as CacheError}; pub mod prelude { @@ -90,7 +90,7 @@ pub fn validate(wasm: &[u8]) -> bool { } } -// #[cfg(feature = "cache")] +// // pub fn compile_to_cache_with( // wasm: &[u8], // compiler: &dyn backend::Compiler, @@ -102,7 +102,7 @@ pub fn validate(wasm: &[u8]) -> bool { // Ok(Cache::new(wasm, info, backend_metadata, compiled_code)) // } -#[cfg(feature = "cache")] + pub unsafe fn load_cache_with( cache: Cache, compiler: &dyn backend::Compiler, diff --git a/lib/runtime-core/src/module.rs b/lib/runtime-core/src/module.rs index 2a398d53e..0526c0ad4 100644 --- a/lib/runtime-core/src/module.rs +++ b/lib/runtime-core/src/module.rs @@ -1,6 +1,6 @@ use crate::{ - backend::{Backend, FuncResolver, ProtectedCaller, CacheGen}, - error::Result, + backend::{Backend, FuncResolver, ProtectedCaller}, + error, import::ImportObject, structures::{Map, TypedIndex}, typed_func::EARLY_TRAPPER, @@ -10,8 +10,11 @@ use crate::{ LocalGlobalIndex, LocalMemoryIndex, LocalTableIndex, MemoryDescriptor, MemoryIndex, SigIndex, TableDescriptor, TableIndex, }, + cache::{Cache, Error as CacheError}, Instance, }; + +use crate::backend::CacheGen; use hashbrown::HashMap; use indexmap::IndexMap; use std::sync::Arc; @@ -21,13 +24,15 @@ use std::sync::Arc; pub struct ModuleInner { pub func_resolver: Box, pub protected_caller: Box, + + pub cache_gen: Box, pub info: ModuleInfo, } #[derive(Clone)] -#[cfg_attr(feature = "cache", derive(Serialize, Deserialize))] +#[derive(Serialize, Deserialize)] pub struct ModuleInfo { // This are strictly local and the typsystem ensures that. pub memories: Map, @@ -57,13 +62,19 @@ pub struct ModuleInfo { pub wasm_hash: WasmHash, } + #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -#[cfg_attr(feature = "cache", derive(Serialize, Deserialize))] +#[derive(Serialize, Deserialize)] pub struct WasmHash([u8; 32]); + impl WasmHash { pub fn generate(wasm: &[u8]) -> Self { - WasmHash(super::cache::hash_data(wasm)) + WasmHash(crate::cache::hash_data(wasm)) + } + + pub(crate) fn into_array(self) -> [u8; 32] { + self.0 } } @@ -109,22 +120,27 @@ impl Module { /// # Ok(()) /// # } /// ``` - pub fn instantiate(&self, import_object: &ImportObject) -> Result { + pub fn instantiate(&self, import_object: &ImportObject) -> error::Result { Instance::new(Arc::clone(&self.inner), import_object) } + + pub fn cache(&self) -> Result { + let (info, backend_cache, code) = self.inner.cache_gen.generate_cache(&self.inner)?; + + } } impl ModuleInner {} #[doc(hidden)] -#[cfg_attr(feature = "cache", derive(Serialize, Deserialize))] +#[derive(Serialize, Deserialize)] #[derive(Debug, Clone)] pub struct ImportName { pub namespace_index: NamespaceIndex, pub name_index: NameIndex, } -#[cfg_attr(feature = "cache", derive(Serialize, Deserialize))] +#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum ExportIndex { Func(FuncIndex), @@ -134,7 +150,7 @@ pub enum ExportIndex { } /// A data initializer for linear memory. -#[cfg_attr(feature = "cache", derive(Serialize, Deserialize))] +#[derive(Serialize, Deserialize)] #[derive(Debug, Clone)] pub struct DataInitializer { /// The index of the memory to initialize. @@ -147,7 +163,7 @@ pub struct DataInitializer { } /// A WebAssembly table initializer. -#[cfg_attr(feature = "cache", derive(Serialize, Deserialize))] +#[derive(Serialize, Deserialize)] #[derive(Debug, Clone)] pub struct TableInitializer { /// The index of a table to initialize. @@ -209,7 +225,7 @@ impl StringTableBuilder { } } -#[cfg_attr(feature = "cache", derive(Serialize, Deserialize))] +#[derive(Serialize, Deserialize)] #[derive(Debug, Clone)] pub struct StringTable { table: Map, @@ -233,7 +249,7 @@ impl StringTable { } } -#[cfg_attr(feature = "cache", derive(Serialize, Deserialize))] +#[derive(Serialize, Deserialize)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct NamespaceIndex(u32); @@ -249,7 +265,7 @@ impl TypedIndex for NamespaceIndex { } } -#[cfg_attr(feature = "cache", derive(Serialize, Deserialize))] +#[derive(Serialize, Deserialize)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct NameIndex(u32); diff --git a/lib/runtime-core/src/structures/map.rs b/lib/runtime-core/src/structures/map.rs index f67000b6d..df95fe652 100644 --- a/lib/runtime-core/src/structures/map.rs +++ b/lib/runtime-core/src/structures/map.rs @@ -8,7 +8,7 @@ use std::{ }; /// Dense item map -#[cfg_attr(feature = "cache", derive(Serialize, Deserialize))] +#[derive(Serialize, Deserialize)] #[derive(Debug, Clone)] pub struct Map where diff --git a/lib/runtime-core/src/sys/mod.rs b/lib/runtime-core/src/sys/mod.rs index 4079a506d..2fdc1ef0f 100644 --- a/lib/runtime-core/src/sys/mod.rs +++ b/lib/runtime-core/src/sys/mod.rs @@ -10,18 +10,18 @@ pub use self::unix::*; #[cfg(windows)] pub use self::windows::*; -#[cfg(feature = "cache")] + use serde::{ de::{self, SeqAccess, Visitor}, ser::SerializeStruct, Deserialize, Deserializer, Serialize, Serializer, }; -#[cfg(feature = "cache")] + use serde_bytes::Bytes; -#[cfg(feature = "cache")] + use std::fmt; -#[cfg(feature = "cache")] + impl Serialize for Memory { fn serialize(&self, serializer: S) -> Result where @@ -36,7 +36,7 @@ impl Serialize for Memory { } } -#[cfg(feature = "cache")] + impl<'de> Deserialize<'de> for Memory { fn deserialize(deserializer: D) -> Result where diff --git a/lib/runtime-core/src/sys/unix/memory.rs b/lib/runtime-core/src/sys/unix/memory.rs index d1579d958..7154f34f9 100644 --- a/lib/runtime-core/src/sys/unix/memory.rs +++ b/lib/runtime-core/src/sys/unix/memory.rs @@ -205,7 +205,17 @@ impl Drop for Memory { } } -#[cfg_attr(feature = "cache", derive(Serialize, Deserialize))] +impl Clone for Memory { + fn clone(&self) -> Self { + let mut new = Memory::with_size_protect(self.size, self.protection).unwrap(); + unsafe { + new.as_slice_mut().copy_from_slice(self.as_slice()); + } + new + } +} + +#[derive(Serialize, Deserialize)] #[derive(Debug, Copy, Clone, PartialEq, Eq)] #[allow(dead_code)] pub enum Protect { diff --git a/lib/runtime-core/src/sys/windows/memory.rs b/lib/runtime-core/src/sys/windows/memory.rs index c8fd197eb..578070a3e 100644 --- a/lib/runtime-core/src/sys/windows/memory.rs +++ b/lib/runtime-core/src/sys/windows/memory.rs @@ -156,7 +156,17 @@ impl Drop for Memory { } } -#[cfg_attr(feature = "cache", derive(Serialize, Deserialize))] +impl Clone for Memory { + fn clone(&self) -> Self { + let mut new = Memory::with_size_protect(self.size, self.protection).unwrap(); + unsafe { + new.as_slice_mut().copy_from_slice(self.as_slice()); + } + new + } +} + +#[derive(Serialize, Deserialize)] #[derive(Debug, Copy, Clone, PartialEq, Eq)] #[allow(dead_code)] pub enum Protect { diff --git a/lib/runtime-core/src/types.rs b/lib/runtime-core/src/types.rs index 271b336ba..f19e73a6e 100644 --- a/lib/runtime-core/src/types.rs +++ b/lib/runtime-core/src/types.rs @@ -2,7 +2,7 @@ use crate::{memory::MemoryType, module::ModuleInfo, structures::TypedIndex, unit use std::{borrow::Cow, mem}; /// Represents a WebAssembly type. -#[cfg_attr(feature = "cache", derive(Serialize, Deserialize))] +#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum Type { /// The `i32` type. @@ -25,7 +25,7 @@ impl std::fmt::Display for Type { /// /// As the number of types in WebAssembly expand, /// this structure will expand as well. -#[cfg_attr(feature = "cache", derive(Serialize, Deserialize))] +#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq)] pub enum Value { /// The `i32` type. @@ -171,14 +171,14 @@ impl ValueType for f64 { } } -#[cfg_attr(feature = "cache", derive(Serialize, Deserialize))] +#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum ElementType { /// Any wasm function. Anyfunc, } -#[cfg_attr(feature = "cache", derive(Serialize, Deserialize))] +#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Copy)] pub struct TableDescriptor { /// Type of data stored in this table. @@ -203,7 +203,7 @@ impl TableDescriptor { /// A const value initializer. /// Over time, this will be able to represent more and more /// complex expressions. -#[cfg_attr(feature = "cache", derive(Serialize, Deserialize))] +#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq)] pub enum Initializer { /// Corresponds to a `const.*` instruction. @@ -212,7 +212,7 @@ pub enum Initializer { GetGlobal(ImportedGlobalIndex), } -#[cfg_attr(feature = "cache", derive(Serialize, Deserialize))] +#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct GlobalDescriptor { pub mutable: bool, @@ -220,7 +220,7 @@ pub struct GlobalDescriptor { } /// A wasm global. -#[cfg_attr(feature = "cache", derive(Serialize, Deserialize))] +#[derive(Serialize, Deserialize)] #[derive(Debug, Clone)] pub struct GlobalInit { pub desc: GlobalDescriptor, @@ -228,7 +228,7 @@ pub struct GlobalInit { } /// A wasm memory. -#[cfg_attr(feature = "cache", derive(Serialize, Deserialize))] +#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct MemoryDescriptor { /// The minimum number of allowed pages. @@ -261,7 +261,7 @@ impl MemoryDescriptor { /// The signature of a function that is either implemented /// in a wasm module or exposed to wasm by the host. -#[cfg_attr(feature = "cache", derive(Serialize, Deserialize))] +#[derive(Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct FuncSig { params: Cow<'static, [Type]>, @@ -324,7 +324,7 @@ pub trait LocalImport { #[rustfmt::skip] macro_rules! define_map_index { ($ty:ident) => { - #[cfg_attr(feature = "cache", derive(Serialize, Deserialize))] + #[derive(Serialize, Deserialize)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct $ty (u32); impl TypedIndex for $ty { @@ -400,7 +400,7 @@ define_local_or_import![ (GlobalIndex | (LocalGlobalIndex, ImportedGlobalIndex): imported_globals), ]; -#[cfg_attr(feature = "cache", derive(Serialize, Deserialize))] +#[derive(Serialize, Deserialize)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct SigIndex(u32); impl TypedIndex for SigIndex { diff --git a/lib/runtime-core/src/units.rs b/lib/runtime-core/src/units.rs index 8fa54474b..6a1582e9e 100644 --- a/lib/runtime-core/src/units.rs +++ b/lib/runtime-core/src/units.rs @@ -7,7 +7,7 @@ const WASM_PAGE_SIZE: usize = 65_536; const WASM_MAX_PAGES: usize = 65_536; /// Units of WebAssembly pages (as specified to be 65,536 bytes). -#[cfg_attr(feature = "cache", derive(Serialize, Deserialize))] +#[derive(Serialize, Deserialize)] #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] pub struct Pages(pub u32); @@ -33,7 +33,7 @@ impl fmt::Debug for Pages { } /// Units of WebAssembly memory in terms of 8-bit bytes. -#[cfg_attr(feature = "cache", derive(Serialize, Deserialize))] +#[derive(Serialize, Deserialize)] #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] pub struct Bytes(pub usize); diff --git a/lib/runtime/Cargo.toml b/lib/runtime/Cargo.toml index fe6cc80d2..29af96844 100644 --- a/lib/runtime/Cargo.toml +++ b/lib/runtime/Cargo.toml @@ -9,10 +9,15 @@ edition = "2018" readme = "README.md" [dependencies] -wasmer-runtime-core = { path = "../runtime-core", version = "0.1.2" } -wasmer-clif-backend = { path = "../clif-backend", version = "0.1.2" } lazy_static = "1.2.0" +[dependencies.wasmer-runtime-core] +path = "../runtime-core" +version = "0.1.2" + +[dependencies.wasmer-clif-backend] +path = "../clif-backend" +version = "0.1.2" + [features] -default = ["wasmer-clif-backend/cache", "wasmer-runtime-core/cache"] debug = ["wasmer-clif-backend/debug", "wasmer-runtime-core/debug"] diff --git a/lib/spectests/Cargo.toml b/lib/spectests/Cargo.toml index c02e8269d..f69782b40 100644 --- a/lib/spectests/Cargo.toml +++ b/lib/spectests/Cargo.toml @@ -19,5 +19,5 @@ wasmer-clif-backend = { path = "../clif-backend", version = "0.1.2" } wabt = "0.7.2" [features] -default = ["fast-tests", "wasmer-runtime-core/cache", "wasmer-clif-backend/cache"] +default = ["fast-tests"] fast-tests = [] \ No newline at end of file From 64519b15813c9e37393cd4549a815a8957230507 Mon Sep 17 00:00:00 2001 From: Jordan Danford Date: Tue, 19 Feb 2019 17:01:44 -0700 Subject: [PATCH 075/262] Fix formatting and grammar in documentation --- ARCHITECTURE.md | 33 +++-- ATTRIBUTIONS.md | 22 ++-- LICENSE | 4 +- README.md | 64 +++++----- integration_tests/lua/README.md | 4 +- integration_tests/nginx/README.md | 6 +- lib/README.md | 18 +-- lib/spectests/spectests/README.md | 199 +++++++++++++++--------------- 8 files changed, 177 insertions(+), 173 deletions(-) diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index b2f30f753..e3d87738d 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -2,19 +2,19 @@ Wasmer uses the following components: -- [Cranelift](https://github.com/cranestation/cranelift): for compiling WASM function binaries into Machine IR -- [wabt](https://github.com/pepyakin/wabt-rs): for transforming `.wast` files to `.wasm` and also to run WebAssembly spectests -- [wasmparser](https://github.com/yurydelendik/wasmparser.rs): for parsing the `.wasm` files and translating them into WebAssembly Modules +- [Cranelift](https://github.com/cranestation/cranelift): for compiling Wasm binaries to machine code +- [wabt](https://github.com/pepyakin/wabt-rs): for transforming `.wast` files to `.wasm` and running WebAssembly spec tests +- [wasmparser](https://github.com/yurydelendik/wasmparser.rs): for parsing the `.wasm` files and translating them into WebAssembly modules -## How Wasmer works? +## How Wasmer works -The first time you run `wasmer run myfile.wasm`, wasmer will: +The first time you run `wasmer run myfile.wasm`, Wasmer will: -- Check if is a `.wast` file. If so, transform it to `.wasm` -- Check that the provided binary is a valid WebAssembly one. That means, that its binary format starts with `\0asm`. -- If it looks like a WebAssembly file, try to parse it with `wasmparser` and generate a `Module` from it -- Once a `Module` is generated, an `Instance` is created with the proper `import_object` (that means, if is detected as an emscripten file, it will add the emscripten expected imports) -- Try to call the WebAssembly start function, or if unexistent try to search for the one that is exported as `main`. +- Check if is a `.wast` file, and if so, transform it to `.wasm` +- Check that the provided binary is a valid WebAssembly one, i.e. its binary format starts with `\0asm`. +- Parse it with `wasmparser` and generate a `Module` from it +- Generate an `Instance` with the proper `import_object` (that means, if is detected to be an Emscripten file, it will add the Emscripten expected imports) +- Try to call the WebAssembly `start` function, or if it does not exist, try to search for the function that is exported as `main` Find a more detailed explanation of the process below: @@ -22,7 +22,7 @@ Find a more detailed explanation of the process below: As the WebAssembly file is being parsed, it will read the sections in the WebAssembly file (memory, table, function, global and element definitions) using the `Module` (or `ModuleEnvironment`) as the structure to hold this information. -However, the real IR initialization happens while a function body is being parsed/created. That means, when the parser reads the section `(func ...)`. +However, the real IR initialization happens while a function body is being parsed/created, i.e. when the parser reads the section `(func ...)`. While the function body is being parsed the corresponding `FuncEnvironment` methods will be called. So for example, if the function is using a table, the `make_table` method within that `FuncEnvironment` will be called. @@ -41,15 +41,14 @@ Once we have the compiled values, we will push them to memory and mark them as e #### Relocations -Sometimes the functions that we generated will need to call other functions. -However the generated code have no idea how to link this functions together. +Sometimes the functions that we generate will need to call other functions, but the generated code has no idea how to link these functions together. -For example, if a function `A` is calling function `B` (that means is having a `(call b)` on it's body) while compiling `A` we will have no idea where the function `B` lives on memory (as `B` is not yet compiled nor pushed into memory). +For example, if a function `A` is calling function `B` (that means is having a `(call b)` on its body) while compiling `A` we will have no idea where the function `B` lives on memory (as `B` is not yet compiled nor pushed into memory). For that reason, we will start collecting all the calls that function `A` will need to do under the hood, and save it's offsets. We do that, so we can patch the function calls after compilation, to point to the correct memory address. -Note: Sometimes this functions rather than living in the same WebAssembly module, they will be provided as import values. +Note: sometimes this functions rather than living in the same WebAssembly module, they will be provided as import values. #### Traps @@ -66,5 +65,5 @@ Once that's finished, we will have a `Instance` function that will be ready to e ## Emscripten -The Wasmer Emscripten integration tries to wrap (and emulate) all the different syscalls that Emscripten needs. -We provide this integration by filling the `import_object` with the emscripten functions, while instantiating the WebAssembly Instance. +Wasmer's Emscripten integration tries to wrap (and emulate) all the different syscalls that Emscripten needs. +We provide this integration by filling the `import_object` with the Emscripten functions, while instantiating the WebAssembly Instance. diff --git a/ATTRIBUTIONS.md b/ATTRIBUTIONS.md index eff1434ab..54e0eed02 100644 --- a/ATTRIBUTIONS.md +++ b/ATTRIBUTIONS.md @@ -2,7 +2,7 @@ Wasmer is a community effort. In order to build the best WebAssembly runtime it's our duty to see how other runtimes are approaching the same space -and get inspired from them on the things that they got right, so wasmer and its community can benefit from a solid +and get inspired from them on the things that they got right, so Wasmer and its community can benefit from a solid foundation. These are the different project that we used as inspiration: @@ -10,9 +10,9 @@ These are the different project that we used as inspiration: - [Nebulet](https://github.com/nebulet/nebulet): as the base for creating a great Rust WebAssembly runtime - [WAVM](https://github.com/wavm/wavm): for their great integration and testing framework - [greenwasm](https://github.com/Kimundi/greenwasm): for their [spectests framework](https://github.com/Kimundi/greenwasm/tree/master/greenwasm-spectest) -- [wasmtime](/wasmtime): on their [mmap implementation](https://github.com/CraneStation/wasmtime/blob/3f24098edc81cd9bf0f877fb7fba018cad0f039e/lib/runtime/src/mmap.rs). -- [stackoverflow](https://stackoverflow.com/a/45795699/1072990): to create an efficient HashMap with pair keys. -- [Emscripten](https://github.com/kripken/emscripten): for emtests test sources to ensure compatibility. +- [wasmtime](https://github.com/CraneStation/wasmtime): for their [mmap implementation](https://github.com/CraneStation/wasmtime/blob/3f24098edc81cd9bf0f877fb7fba018cad0f039e/lib/runtime/src/mmap.rs) +- [stackoverflow](https://stackoverflow.com/a/45795699/1072990): to create an efficient HashMap with pair keys +- [Emscripten](https://github.com/kripken/emscripten): for emtests test sources to ensure compatibility We would love to hear from you if you think we can take inspiration from other projects that we haven't covered here. 😊 @@ -21,10 +21,10 @@ We would love to hear from you if you think we can take inspiration from other p ### Nebulet -``` +```text MIT License -Copyright (c) 2018 +Copyright (c) 2018 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -47,7 +47,7 @@ SOFTWARE. ### WAVM -``` +```text Copyright (c) 2018, Andrew Scheidecker All rights reserved. @@ -69,7 +69,7 @@ The contents of [Test/spec](Test/spec) is covered by the license in [Test/spec/L ### Greenwasm -``` +```text Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -275,7 +275,7 @@ limitations under the License. ### Wasmtime -``` +```text Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -497,7 +497,7 @@ Software. ``` ### Emscripten -``` +```text Emscripten is available under 2 licenses, the MIT license and the University of Illinois/NCSA Open Source License. @@ -557,7 +557,7 @@ the following conditions: Neither the names of Mozilla, nor the names of its contributors may be used to endorse or promote products derived from this Software without specific prior - written permission. + written permission. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF diff --git a/LICENSE b/LICENSE index 689596400..7e40523b0 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,4 @@ -The MIT License (MIT) - -Copyright (c) 2018-Present Syrus Akbary +Copyright (c) 2019 Syrus Akbary Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index df4ac0186..bdb921afd 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,24 @@ -

Wasmer logo

+

+ + Wasmer logo + +

- Build Status - License + + Build Status + + + License + - Join the Wasmer Community + Join the Wasmer Community

## Introduction -[Wasmer](https://wasmer.io/) is a Standalone JIT WebAssembly runtime, aiming to be fully compatible with Emscripten, Rust and Go. +[Wasmer](https://wasmer.io/) is a standalone JIT WebAssembly runtime, aiming to be fully compatible with Emscripten, Rust and Go. Install Wasmer with: @@ -18,20 +26,20 @@ Install Wasmer with: curl https://get.wasmer.io -sSfL | sh ``` -_**NEW ✨**: Now you can also embed Wasmer in your Rust application, check our [example repo](https://github.com/wasmerio/wasmer-rust-example) to see how to do it!_ +_**NEW ✨**: You can now embed Wasmer in your Rust application, check our [example repo](https://github.com/wasmerio/wasmer-rust-example) to see how!_ ### Usage -`wasmer` can execute both the standard binary format (`.wasm`) and the text +Wasmer can execute both the standard binary format (`.wasm`) and the text format defined by the WebAssembly reference interpreter (`.wat`). -Once installed, you will be able to run any WebAssembly files (_including Nginx, and Lua!_): +Once installed, you will be able to run any WebAssembly files (_including nginx and Lua!_): ```sh # Run Lua wasmer run examples/lua.wasm -# Run Nginx +# Run nginx wasmer run examples/nginx/nginx.wasm -- -p examples/nginx -c nginx.conf ``` @@ -39,13 +47,13 @@ wasmer run examples/nginx/nginx.wasm -- -p examples/nginx -c nginx.conf Wasmer is structured into different directories: -- [`src`](./src): code related to the wasmer excutable binary itself +- [`src`](./src): code related to the Wasmer executable itself - [`lib`](./lib): modularized libraries that Wasmer uses under the hood -- [`examples`](./examples): some useful examples to getting started with wasmer +- [`examples`](./examples): some useful examples to getting started with Wasmer ## Dependencies -Building wasmer requires [rustup](https://rustup.rs/). +Building Wasmer requires [rustup](https://rustup.rs/). To build on Windows, download and run [`rustup-init.exe`](https://win.rustup.rs/) then follow the onscreen instructions. @@ -66,13 +74,13 @@ Please select your operating system: #### macOS -If you have [homebrew](https://brew.sh/) installed: +If you have [Homebrew](https://brew.sh/) installed: ```sh brew install cmake ``` -Or, in case you have [ports](https://www.macports.org/install.php): +Or, in case you have [MacPorts](https://www.macports.org/install.php): ```sh sudo port install cmake @@ -86,16 +94,16 @@ sudo apt install cmake #### Windows (MSVC) -Windows support is _highly experimental_. Only simple wasm programs may be run, and no syscalls are allowed. This means -nginx and lua do not work on Windows. See [this issue for ongoing Emscripten syscall polyfills for Windows](https://github.com/wasmerio/wasmer/pull/176). +Windows support is _highly experimental_. Only simple Wasm programs may be run, and no syscalls are allowed. This means +nginx and Lua do not work on Windows. See [this issue](https://github.com/wasmerio/wasmer/issues/176) regarding Emscripten syscall polyfills for Windows. -1. Install Python for Windows (https://www.python.org/downloads/release/python-2714/). The Windows x86-64 MSI installer is fine. - You should change the installation to install the "Add python.exe to Path" feature. +1. Install [Python for Windows](https://www.python.org/downloads/release/python-2714/). The Windows x86-64 MSI installer is fine. + Make sure to enable "Add python.exe to Path" during installation. -2. Install Git for Windows (https://git-scm.com/download/win). DO allow it to add git.exe to the PATH (default +2. Install [Git for Windows](https://git-scm.com/download/win). Allow it to add `git.exe` to your PATH (default settings for the installer are fine). -3. Install CMake (https://cmake.org/download/). Ensure CMake is in the PATH. +3. Install [CMake](https://cmake.org/download/). Ensure CMake is in your PATH. ## Building @@ -113,7 +121,7 @@ cargo install --path . ## Testing -Thanks to [spectests](https://github.com/wasmerio/wasmer/tree/master/lib/runtime-core/spectests) we can assure 100% compatibility with the WebAssembly spec test suite. +Thanks to [spec tests](https://github.com/wasmerio/wasmer/tree/master/lib/spectests/spectests) we can ensure 100% compatibility with the WebAssembly spec test suite. Tests can be run with: @@ -121,7 +129,7 @@ Tests can be run with: make test ``` -If you need to re-generate the Rust tests from the spectests +If you need to regenerate the Rust tests from the spec tests you can run: ```sh @@ -138,20 +146,20 @@ make integration-tests Wasmer is an open project guided by strong principles, aiming to be modular, flexible and fast. It is open to the community to help set its direction. -Below are some of the goals (written with order) of this project: +Below are some of the goals of this project (in order of priority): -- [x] It should be 100% compatible with the [WebAssembly Spectest](https://github.com/wasmerio/wasmer/tree/master/spectests) +- [x] It should be 100% compatible with the [WebAssembly spec tests](https://github.com/wasmerio/wasmer/tree/master/lib/spectests/spectests) - [x] It should be fast _(partially achieved)_ - [ ] Support Emscripten calls _(in the works)_ - [ ] Support Rust ABI calls -- [ ] Support GO ABI calls +- [ ] Support Go ABI calls ## Architecture -If you would like to know how Wasmer works under the hood, please visit our [ARCHITECTURE](https://github.com/wasmerio/wasmer/blob/master/ARCHITECTURE.md) document. +If you would like to know how Wasmer works under the hood, please see [ARCHITECTURE.md](./ARCHITECTURE.md). ## License -MIT/Apache-2.0 +Wasmer is primarily distributed under the terms of the [MIT license](http://opensource.org/licenses/MIT) ([LICENSE](./LICENSE)). -[Attributions](./ATTRIBUTIONS.md). +[ATTRIBUTIONS](./ATTRIBUTIONS.md) diff --git a/integration_tests/lua/README.md b/integration_tests/lua/README.md index ce2b03f6f..208e3438d 100644 --- a/integration_tests/lua/README.md +++ b/integration_tests/lua/README.md @@ -1,8 +1,8 @@ # `lua` integration test -This starts wasmer with the lua wasm file. The test asserts on -the output of wasmer. Run test with: +This starts Wasmer with the Lua Wasm file. The test makes assertions on +the output of Wasmer. Run test with: ``` > ./integration_tests/lua/test.sh diff --git a/integration_tests/nginx/README.md b/integration_tests/nginx/README.md index 9df8af773..3e9e46d8b 100644 --- a/integration_tests/nginx/README.md +++ b/integration_tests/nginx/README.md @@ -1,11 +1,11 @@ # `nginx` integration test -This starts wasmer with the nginx wasm file and serves an html -file with some simple text to assert on. The test script does +This starts Wasmer with the nginx Wasm file and serves an HTML +file with some simple text to assert on. The test script does the assertion. -Run test with: +Run test with: ``` > ./integration_tests/nginx/test.sh diff --git a/lib/README.md b/lib/README.md index 44b316865..79ae446d3 100644 --- a/lib/README.md +++ b/lib/README.md @@ -2,34 +2,34 @@ Wasmer is modularized into different libraries, separated into three main sections: -- [Runtime](#Runtime) -- [Integrations](#Integrations) -- [Backends](#Backends) +- [Runtime](#runtime) +- [Integrations](#integrations) +- [Backends](#backends) ## Runtime The core of Wasmer is the runtime, which provides the necessary -abstractions to create a good user-experience when embedding. +abstractions to create a good user experience when embedding. The runtime is divided into two main libraries: - [runtime-core](./runtime-core/): The main implementation of the runtime. -- [runtime](./runtime/): Easy-to-use api on top of runtime-core. +- [runtime](./runtime/): Easy-to-use API on top of `runtime-core`. ## Integrations -The intergration run on-top of the Wasmer runtime and allow us to run WebAssembly files compiled for different environments. +The integration builds on the Wasmer runtime and allow us to run WebAssembly files compiled for different environments. Wasmer intends to support different integrations: -- [emscripten](./emscripten): run emscripten-generated WebAssembly files, such as [Lua](../examples/lua.wasm) or [Nginx](../examples/nginx/nginx.wasm). +- [emscripten](./emscripten): run Emscripten-generated WebAssembly files, such as [Lua](../examples/lua.wasm) or [nginx](../examples/nginx/nginx.wasm). - Go ABI: _we will work on this soon! Want to give us a hand? ✋_ -- Blazor: _researching period, see [tracking issue](https://github.com/wasmerio/wasmer/issues/97)_ +- Blazor: _research period, see [tracking issue](https://github.com/wasmerio/wasmer/issues/97)_ ## Backends The Wasmer [runtime](./runtime) is designed to support multiple compiler backends, allowing the user -to tune the codegen properties (compile speed, performance, etc) to fit your usecase best. +to tune the codegen properties (compile speed, performance, etc) to best fit their use case. Currently, we support a Cranelift compiler backend: diff --git a/lib/spectests/spectests/README.md b/lib/spectests/spectests/README.md index b9c26d864..669246528 100644 --- a/lib/spectests/spectests/README.md +++ b/lib/spectests/spectests/README.md @@ -1,136 +1,135 @@ This directory contains tests for the core WebAssembly semantics, as described in [Semantics.md](https://github.com/WebAssembly/design/blob/master/Semantics.md) and specified by the [spec interpreter](https://github.com/WebAssembly/spec/blob/master/interpreter/spec). -This files should be a direct copy of the original [WebAssembly spec tests](https://github.com/WebAssembly/spec/tree/master/test/core). +These files should be a direct copy of the original [WebAssembly spec tests](/test/core). Tests are written in the [S-Expression script format](https://github.com/WebAssembly/spec/blob/master/interpreter/README.md#s-expression-syntax) defined by the interpreter. ## Autogenerated Rust test cases -This files will serve as base for autogenerating Rust testcases +These files will serve as a base for autogenerating Rust testcases when `WASM_GENERATE_SPECTESTS=1 cargo build` is executed -([src/build_spectests.rs](https://github.com/wasmerio/wasmer/blob/master/src/build_spectests.rs)). +([src/build_spectests.rs](/src/build_spectests.rs)). -The result autogenerated spectests live in the [src/spectests](https://github.com/wasmerio/wasmer/tree/master/src/spectests) -directory. +The resulting autogenerated spec tests live in the [src/spectests](/src/spectests). ## Testcases Currently supported command assertions: -- [x] Module _mostly implemented_ (it should support named modules `(module $Xx)`). -- [x] AssertReturn _mostly implemented_ (it should support calls to named modules `(invoke $Xx "call")`). -- [x] AssertReturnCanonicalNan _fully implemented_ -- [x] AssertReturnArithmeticNan _fully implemented_ -- [x] AssertTrap _fully implemented_ -- [x] AssertInvalid _Fully implemented_ (it should not require to do validation separate from compilation) -- [x] AssertMalformed _Fully implemented_ -- [ ] AssertUninstantiable _not implemented yet_ -- [ ] AssertExhaustion _not implemented yet_ -- [ ] Register _not implemented yet_ -- [x] PerformAction _partially implemented, only function invokations for now_ +- [x] `module` _mostly implemented_ (it should support named modules `(module $Xx)`). +- [x] `assert_return` _mostly implemented_ (it should support calls to named modules `(invoke $Xx "call")`). +- [x] `assert_return_canonical_nan` _fully implemented_ +- [x] `assert_return_arithmetic_nan` _fully implemented_ +- [x] `assert_trap` _fully implemented_ +- [x] `assert_invalid` _fully implemented_ (it should not require validation to be performed separate from compilation) +- [x] `assert_malformed` _fully implemented_ +- [ ] `assert_uninstantiable` _not implemented yet_ +- [ ] `assert_exhaustion` _not implemented yet_ +- [ ] `register` _not implemented yet_ +- [x] `perform_action` _partially implemented, only function invocations for now_ -### Covered spectests +### Covered spec tests -This spectests are currently covered: +The following spec tests are currently covered: -- address.wast ✅ -- align.wast ✅ -- binary.wast ✅ -- block.wast ✅ -- br.wast ✅ -- br_if.wast ✅ -- br_table.wast ✅ -- break-drop.wast ✅ -- call.wast ✅ -- call_indirect.wast ✅ -- comments.wast ✅ -- const.wast ✅ -- conversions.wast ✅ -- custom.wast ✅ -- data.wast ✅ -- elem.wast -- endianness.wast ✅ -- exports.wast ✅ -- f32.wast ✅ -- f32_bitwise.wast ✅ -- f32_cmp.wast ✅ -- f64.wast ✅ -- f64_bitwise.wast ✅ -- f64_cmp.wast ✅ -- fac.wast ✅ -- float_exprs.wast ✅ -- float_literals.wast ✅ -- float_memory.wast ✅ -- float_misc.wast ✅ -- forward.wast ✅ -- func.wast ✅ -- func_ptrs.wast ✅ -- get_local.wast ✅ -- globals.wast ✅ -- i32.wast ✅ -- i64.wast ✅ -- if.wast ✅ -- imports.wast -- inline-module.wast -- int_exprs.wast ✅ -- int_literals.wast ✅ -- labels.wast ✅ -- left-to-right.wast ✅ -- linking.wast -- loop.wast ✅ -- memory.wast ✅ -- memory_grow.wast ✅ -- memory_redundancy.wast ✅ -- memory_trap.wast ✅ -- names.wast ✅ -- nop.wast ✅ -- return.wast ✅ -- select.wast ✅ -- set_local.wast ✅ -- skip-stack-guard-page.wast -- stack.wast ✅ -- start.wast ✅ -- store_retval.wast ✅ -- switch.wast ✅ -- tee_local.wast ✅ -- token.wast ✅ -- traps.wast ✅ -- type.wast ✅ -- typecheck.wast ✅ -- unreachable.wast -- unreached-invalid.wast -- unwind.wast ✅ -- utf8-custom-section-id.wast -- utf8-import-field.wast -- utf8-import-module.wast -- utf8-invalid-encoding.wast +- [x] address.wast +- [x] align.wast +- [x] binary.wast +- [x] block.wast +- [x] br.wast +- [x] br_if.wast +- [x] br_table.wast +- [x] break-drop.wast +- [x] call.wast +- [x] call_indirect.wast +- [x] comments.wast +- [x] const.wast +- [x] conversions.wast +- [x] custom.wast +- [x] data.wast +- [ ] elem.wast +- [x] endianness.wast +- [x] exports.wast +- [x] f32.wast +- [x] f32_bitwise.wast +- [x] f32_cmp.wast +- [x] f64.wast +- [x] f64_bitwise.wast +- [x] f64_cmp.wast +- [x] fac.wast +- [x] float_exprs.wast +- [x] float_literals.wast +- [x] float_memory.wast +- [x] float_misc.wast +- [x] forward.wast +- [x] func.wast +- [x] func_ptrs.wast +- [x] get_local.wast +- [x] globals.wast +- [x] i32.wast +- [x] i64.wast +- [x] if.wast +- [ ] imports.wast +- [ ] inline-module.wast +- [x] int_exprs.wast +- [x] int_literals.wast +- [x] labels.wast +- [x] left-to-right.wast +- [ ] linking.wast +- [x] loop.wast +- [x] memory.wast +- [x] memory_grow.wast +- [x] memory_redundancy.wast +- [x] memory_trap.wast +- [x] names.wast +- [x] nop.wast +- [x] return.wast +- [x] select.wast +- [x] set_local.wast +- [ ] skip-stack-guard-page.wast +- [x] stack.wast +- [x] start.wast +- [x] store_retval.wast +- [x] switch.wast +- [x] tee_local.wast +- [x] token.wast +- [x] traps.wast +- [x] type.wast +- [x] typecheck.wast +- [ ] unreachable.wast +- [ ] unreached-invalid.wast +- [x] unwind.wast +- [ ] utf8-custom-section-id.wast +- [ ] utf8-import-field.wast +- [ ] utf8-import-module.wast +- [ ] utf8-invalid-encoding.wast ### Specific non-supported cases -There are some cases that we decided to skip for now to fasten the time to release: +There are some cases that we decided to skip for now to accelerate the release schedule: -- `SKIP_MUTABLE_GLOBALS`: Right now the WASM parser can't validate a module with imported/exported mut globals. We decided to skip the tests until Cranelift and wasmparser can handle this (original spec proposal: https://github.com/WebAssembly/mutable-global). Spectests affected: +- `SKIP_MUTABLE_GLOBALS`: Right now the Wasm parser can't validate a module with imported/exported `mut` globals. We decided to skip the tests until Cranelift and wasmparser can handle this (see [original spec proposal](https://github.com/WebAssembly/mutable-global)). Spec tests affected: - `globals.wast` -- `SKIP_CALL_INDIRECT_TYPE_MISMATCH`: we implemented traps in a fast way. We haven't covered yet the type mismatch on `call_indirect`. Specs affected: +- `SKIP_CALL_INDIRECT_TYPE_MISMATCH`: we implemented traps in a fast way. We haven't yet covered the type mismatch on `call_indirect`. Specs affected: - `call_indirect.wast` - `SKIP_CALL_UNDEFINED_ELEMENT` - Tables are imported into every spec module, even for modules that don't expect it. We need to figure out a way to prevent import of objects that are not explicitly imported into the module. + Tables are imported into every spec module, even for modules that don't expect it. We need to figure out a way to prevent importing of objects that are not explicitly imported into the module. -Currently cranelift_wasm::ModuleEnvironment does not provide `declare_table_import`, etc. so there is no meaningful way of fixing this yet. +Currently `cranelift_wasm::ModuleEnvironment` does not provide `declare_table_import`, etc. so there is no meaningful way of fixing this yet. - `call_indirect.wast` - `SKIP_SHARED_TABLE` [elem.wast] - Currently sharing tables between instances/modules does not work. Below are some of the reasons it is hard to achieve. + Currently sharing tables between instances/modules does not work. Below are some of the reasons it is hard to achieve: - Rust naturally prevents such because of the possibility of race conditions - - ImportObject is just a wrapper, what we really care about is references to its content. - - Instance::new contains a mutation points, the part where after getting the object (memory or table) we push values to it - table[table_element_index] = func_addr - - Instance has its own created memories and tables and references to them must outlive Instance::new() - - Possible strategy + - `ImportObject` is just a wrapper, what we really care about is references to its content. + - `Instance::new` contains a mutation points, the part where after getting the object (memory or table) we push values to it + `table[table_element_index] = func_addr` + - Instance has its own created memories and tables and references to them must outlive `Instance::new()` + - Possible strategy: ```rust // ImportObject should be passed by ref From b073145dbb09912dd83c13baa86e00322a072f4b Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Wed, 20 Feb 2019 09:52:42 -0600 Subject: [PATCH 076/262] Clone import in instantiate to prevent import move --- lib/runtime-c-api/src/lib.rs | 3 +-- lib/runtime-c-api/tests/test-import-function.c | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index d4286a9ca..5b1dd1955 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -467,7 +467,7 @@ pub unsafe extern "C" fn wasmer_instantiate( wasmer_import_export_kind::WASM_GLOBAL => import.value.global as *mut Export, wasmer_import_export_kind::WASM_TABLE => import.value.table as *mut Export, }; - namespace.insert(import_name, unsafe { *Box::from_raw(export) }); // TODO Review + namespace.insert(import_name, unsafe { (&*export).clone() }); } for (module_name, namespace) in namespaces.into_iter() { import_object.register(module_name, namespace); @@ -488,7 +488,6 @@ pub unsafe extern "C" fn wasmer_instantiate( } }; unsafe { *instance = Box::into_raw(Box::new(new_instance)) as *mut wasmer_instance_t }; - Box::into_raw(Box::new(import_object)); wasmer_result_t::WASMER_OK } diff --git a/lib/runtime-c-api/tests/test-import-function.c b/lib/runtime-c-api/tests/test-import-function.c index bd09938d5..e7caed874 100644 --- a/lib/runtime-c-api/tests/test-import-function.c +++ b/lib/runtime-c-api/tests/test-import-function.c @@ -84,7 +84,7 @@ int main() assert(0 == strcmp(actual_str, "Hello, World!")); printf("Destroying func\n"); - // wasmer_func_destroy(func); + wasmer_func_destroy(func); printf("Destroy instance\n"); wasmer_instance_destroy(instance); return 0; From 14e5fb0e76acec214ff070f5c54106f670cdf5d4 Mon Sep 17 00:00:00 2001 From: Mackenzie Clark Date: Wed, 20 Feb 2019 13:58:30 -0800 Subject: [PATCH 077/262] move the installer and update appveyor --- .appveyor.yml | 4 ++-- {installer => src/installer}/wasmer.iss | 0 2 files changed, 2 insertions(+), 2 deletions(-) rename {installer => src/installer}/wasmer.iss (100%) diff --git a/.appveyor.yml b/.appveyor.yml index 16432ed6b..e90075bd2 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -27,9 +27,9 @@ test_script: - cd ./lib/spectests && cargo test -- --test-threads 1 && cd ../.. before_deploy: - - cd installer + - cd ./src/installer - iscc wasmer.iss - - copy /y .\WasmerInstaller.exe ..\WasmerInstaller-%APPVEYOR_REPO_TAG_NAME%.exe + - copy /y .\WasmerInstaller.exe ..\..\WasmerInstaller-%APPVEYOR_REPO_TAG_NAME%.exe - appveyor PushArtifact WasmerInstaller-%APPVEYOR_REPO_TAG_NAME%.exe artifacts: diff --git a/installer/wasmer.iss b/src/installer/wasmer.iss similarity index 100% rename from installer/wasmer.iss rename to src/installer/wasmer.iss From 1a951a9abf4530dc30268464d495f7ce80dfafe9 Mon Sep 17 00:00:00 2001 From: Mackenzie Clark Date: Wed, 20 Feb 2019 14:05:12 -0800 Subject: [PATCH 078/262] stub wasm32-unknown-emscripten target imports (#193) --- lib/emscripten/src/emscripten_target.rs | 175 ++++++++++++++++++++++++ lib/emscripten/src/lib.rs | 67 ++++++++- 2 files changed, 241 insertions(+), 1 deletion(-) create mode 100644 lib/emscripten/src/emscripten_target.rs diff --git a/lib/emscripten/src/emscripten_target.rs b/lib/emscripten/src/emscripten_target.rs new file mode 100644 index 000000000..4f831e909 --- /dev/null +++ b/lib/emscripten/src/emscripten_target.rs @@ -0,0 +1,175 @@ +use crate::env::get_emscripten_data; +use wasmer_runtime_core::vm::Ctx; + +pub fn setTempRet0(ctx: &mut Ctx, a: i32) { + debug!("emscripten::setTempRet0"); +} +pub fn getTempRet0(ctx: &mut Ctx) -> i32 { + debug!("emscripten::getTempRet0"); + 0 +} +pub fn nullFunc_ji(ctx: &mut Ctx, a: i32) { + debug!("emscripten::nullFunc_ji"); +} +pub fn invoke_i(ctx: &mut Ctx, index: i32) -> i32 { + debug!("emscripten::invoke_i"); + if let Some(dyn_call_i) = &get_emscripten_data(ctx).dyn_call_i { + dyn_call_i.call(index).unwrap() + } else { + panic!("dyn_call_i is set to None"); + } +} +pub fn invoke_ii(ctx: &mut Ctx, index: i32, a1: i32) -> i32 { + debug!("emscripten::invoke_ii"); + if let Some(dyn_call_ii) = &get_emscripten_data(ctx).dyn_call_ii { + dyn_call_ii.call(index, a1).unwrap() + } else { + panic!("dyn_call_ii is set to None"); + } +} +pub fn invoke_iii(ctx: &mut Ctx, index: i32, a1: i32, a2: i32) -> i32 { + debug!("emscripten::invoke_iii"); + if let Some(dyn_call_iii) = &get_emscripten_data(ctx).dyn_call_iii { + dyn_call_iii.call(index, a1, a2).unwrap() + } else { + panic!("dyn_call_iii is set to None"); + } +} +pub fn invoke_iiii(ctx: &mut Ctx, index: i32, a1: i32, a2: i32, a3: i32) -> i32 { + debug!("emscripten::invoke_iiii"); + if let Some(dyn_call_iiii) = &get_emscripten_data(ctx).dyn_call_iiii { + dyn_call_iiii.call(index, a1, a2, a3).unwrap() + } else { + panic!("dyn_call_iiii is set to None"); + } +} +pub fn invoke_v(ctx: &mut Ctx, index: i32) { + debug!("emscripten::invoke_v"); + if let Some(dyn_call_v) = &get_emscripten_data(ctx).dyn_call_v { + dyn_call_v.call(index).unwrap(); + } else { + panic!("dyn_call_v is set to None"); + } +} +pub fn invoke_vi(ctx: &mut Ctx, index: i32, a1: i32) { + debug!("emscripten::invoke_vi"); + if let Some(dyn_call_vi) = &get_emscripten_data(ctx).dyn_call_vi { + dyn_call_vi.call(index, a1).unwrap(); + } else { + panic!("dyn_call_vi is set to None"); + } +} +pub fn invoke_vii(ctx: &mut Ctx, index: i32, a1: i32, a2: i32) { + debug!("emscripten::invoke_vii"); + if let Some(dyn_call_vii) = &get_emscripten_data(ctx).dyn_call_vii { + dyn_call_vii.call(index, a1, a2).unwrap(); + } else { + panic!("dyn_call_vii is set to None"); + } +} +pub fn invoke_viii(ctx: &mut Ctx, index: i32, a1: i32, a2: i32, a3: i32) { + debug!("emscripten::invoke_viii"); + if let Some(dyn_call_viii) = &get_emscripten_data(ctx).dyn_call_viii { + dyn_call_viii.call(index, a1, a2, a3).unwrap(); + } else { + panic!("dyn_call_viii is set to None"); + } +} +pub fn invoke_viiii(ctx: &mut Ctx, index: i32, a1: i32, a2: i32, a3: i32, a4: i32) { + debug!("emscripten::invoke_viiii"); + if let Some(dyn_call_viiii) = &get_emscripten_data(ctx).dyn_call_viiii { + dyn_call_viiii.call(index, a1, a2, a3, a4).unwrap(); + } else { + panic!("dyn_call_viiii is set to None"); + } +} +pub fn __Unwind_Backtrace(ctx: &mut Ctx, a: i32, b: i32) -> i32 { + debug!("emscripten::__Unwind_Backtrace"); + 0 +} +pub fn __Unwind_FindEnclosingFunction(ctx: &mut Ctx, a: i32) -> i32 { + debug!("emscripten::__Unwind_FindEnclosingFunction"); + 0 +} +pub fn __Unwind_GetIPInfo(ctx: &mut Ctx, a: i32, b: i32) -> i32 { + debug!("emscripten::__Unwind_GetIPInfo"); + 0 +} +pub fn ___cxa_find_matching_catch_2(ctx: &mut Ctx) -> i32 { + debug!("emscripten::___cxa_find_matching_catch_2"); + 0 +} +pub fn ___cxa_find_matching_catch_3(ctx: &mut Ctx, a: i32) -> i32 { + debug!("emscripten::___cxa_find_matching_catch_3"); + 0 +} +pub fn ___cxa_free_exception(ctx: &mut Ctx, a: i32) { + debug!("emscripten::___cxa_free_exception"); +} +pub fn ___resumeException(ctx: &mut Ctx, a: i32) { + debug!("emscripten::___resumeException"); +} +pub fn _dladdr(ctx: &mut Ctx, a: i32, b: i32) -> i32 { + debug!("emscripten::_dladdr"); + 0 +} +pub fn _pthread_cond_destroy(ctx: &mut Ctx, a: i32) -> i32 { + debug!("emscripten::_pthread_cond_destroy"); + 0 +} +pub fn _pthread_cond_init(ctx: &mut Ctx, a: i32, b: i32) -> i32 { + debug!("emscripten::_pthread_cond_init"); + 0 +} +pub fn _pthread_cond_signal(ctx: &mut Ctx, a: i32) -> i32 { + debug!("emscripten::_pthread_cond_signal"); + 0 +} +pub fn _pthread_cond_wait(ctx: &mut Ctx, a: i32, b: i32) -> i32 { + debug!("emscripten::_pthread_cond_wait"); + 0 +} +pub fn _pthread_condattr_destroy(ctx: &mut Ctx, a: i32) -> i32 { + debug!("emscripten::_pthread_condattr_destroy"); + 0 +} +pub fn _pthread_condattr_init(ctx: &mut Ctx, a: i32) -> i32 { + debug!("emscripten::_pthread_condattr_init"); + 0 +} +pub fn _pthread_condattr_setclock(ctx: &mut Ctx, a: i32, b: i32) -> i32 { + debug!("emscripten::_pthread_condattr_setclock"); + 0 +} +pub fn _pthread_mutex_destroy(ctx: &mut Ctx, a: i32) -> i32 { + debug!("emscripten::_pthread_mutex_destroy"); + 0 +} +pub fn _pthread_mutex_init(ctx: &mut Ctx, a: i32, b: i32) -> i32 { + debug!("emscripten::_pthread_mutex_init"); + 0 +} +pub fn _pthread_mutexattr_destroy(ctx: &mut Ctx, a: i32) -> i32 { + debug!("emscripten::_pthread_mutexattr_destroy"); + 0 +} +pub fn _pthread_mutexattr_init(ctx: &mut Ctx, a: i32) -> i32 { + debug!("emscripten::_pthread_mutexattr_init"); + 0 +} +pub fn _pthread_mutexattr_settype(ctx: &mut Ctx, a: i32, b: i32) -> i32 { + debug!("emscripten::_pthread_mutexattr_settype"); + 0 +} +pub fn _pthread_rwlock_rdlock(ctx: &mut Ctx, a: i32) -> i32 { + debug!("emscripten::_pthread_rwlock_rdlock"); + 0 +} +pub fn _pthread_rwlock_unlock(ctx: &mut Ctx, a: i32) -> i32 { + debug!("emscripten::_pthread_rwlock_unlock"); + 0 +} +pub fn ___gxx_personality_v0(ctx: &mut Ctx, a: i32, b: i32, c: i32, d: i32, e: i32, f: i32) -> i32 { + debug!("emscripten::___gxx_personality_v0"); + 0 +} diff --git a/lib/emscripten/src/lib.rs b/lib/emscripten/src/lib.rs index 3ed5c36dd..a58b3b118 100644 --- a/lib/emscripten/src/lib.rs +++ b/lib/emscripten/src/lib.rs @@ -27,6 +27,7 @@ mod file_descriptor; pub mod stdio; // EMSCRIPTEN APIS +mod emscripten_target; mod env; mod errno; mod exception; @@ -92,8 +93,17 @@ pub struct EmscriptenData<'a> { pub memalign: Option>, pub memset: Func<'a, (u32, u32, u32), u32>, pub stack_alloc: Func<'a, u32, u32>, - pub jumps: Vec>, + + pub dyn_call_i: Option>, + pub dyn_call_ii: Option>, + pub dyn_call_iii: Option>, + pub dyn_call_iiii: Option>, + pub dyn_call_v: Option>, + pub dyn_call_vi: Option>, + pub dyn_call_vii: Option>, + pub dyn_call_viii: Option>, + pub dyn_call_viiii: Option>, } impl<'a> EmscriptenData<'a> { @@ -108,6 +118,16 @@ impl<'a> EmscriptenData<'a> { let memset = instance.func("_memset").unwrap(); let stack_alloc = instance.func("stackAlloc").unwrap(); + let dyn_call_i = instance.func("dynCall_i").ok(); + let dyn_call_ii = instance.func("dynCall_ii").ok(); + let dyn_call_iii = instance.func("dynCall_iii").ok(); + let dyn_call_iiii = instance.func("dynCall_iiii").ok(); + let dyn_call_v = instance.func("dynCall_v").ok(); + let dyn_call_vi = instance.func("dynCall_vi").ok(); + let dyn_call_vii = instance.func("dynCall_vii").ok(); + let dyn_call_viii = instance.func("dynCall_viii").ok(); + let dyn_call_viiii = instance.func("dynCall_viiii").ok(); + EmscriptenData { malloc, free, @@ -115,6 +135,15 @@ impl<'a> EmscriptenData<'a> { memset, stack_alloc, jumps: Vec::new(), + dyn_call_i, + dyn_call_ii, + dyn_call_iii, + dyn_call_iiii, + dyn_call_v, + dyn_call_vi, + dyn_call_vii, + dyn_call_viii, + dyn_call_viiii, } } } @@ -491,6 +520,42 @@ pub fn generate_emscripten_env(globals: &mut EmscriptenGlobals) -> ImportObject "_dlopen" => func!(crate::linking::_dlopen), "_dlsym" => func!(crate::linking::_dlsym), + // wasm32-unknown-emscripten + "setTempRet0" => func!(crate::emscripten_target::setTempRet0), + "getTempRet0" => func!(crate::emscripten_target::getTempRet0), + "nullFunc_ji" => func!(crate::emscripten_target::nullFunc_ji), + "invoke_i" => func!(crate::emscripten_target::invoke_i), + "invoke_ii" => func!(crate::emscripten_target::invoke_ii), + "invoke_iii" => func!(crate::emscripten_target::invoke_iii), + "invoke_iiii" => func!(crate::emscripten_target::invoke_iiii), + "invoke_v" => func!(crate::emscripten_target::invoke_v), + "invoke_vi" => func!(crate::emscripten_target::invoke_vi), + "invoke_vii" => func!(crate::emscripten_target::invoke_vii), + "invoke_viii" => func!(crate::emscripten_target::invoke_viii), + "invoke_viiii" => func!(crate::emscripten_target::invoke_viiii), + "__Unwind_Backtrace" => func!(crate::emscripten_target::__Unwind_Backtrace), + "__Unwind_FindEnclosingFunction" => func!(crate::emscripten_target::__Unwind_FindEnclosingFunction), + "__Unwind_GetIPInfo" => func!(crate::emscripten_target::__Unwind_GetIPInfo), + "___cxa_find_matching_catch_2" => func!(crate::emscripten_target::___cxa_find_matching_catch_2), + "___cxa_find_matching_catch_3" => func!(crate::emscripten_target::___cxa_find_matching_catch_3), + "___cxa_free_exception" => func!(crate::emscripten_target::___cxa_free_exception), + "___resumeException" => func!(crate::emscripten_target::___resumeException), + "_dladdr" => func!(crate::emscripten_target::_dladdr), + "_pthread_cond_destroy" => func!(crate::emscripten_target::_pthread_cond_destroy), + "_pthread_cond_init" => func!(crate::emscripten_target::_pthread_cond_init), + "_pthread_cond_signal" => func!(crate::emscripten_target::_pthread_cond_signal), + "_pthread_cond_wait" => func!(crate::emscripten_target::_pthread_cond_wait), + "_pthread_condattr_destroy" => func!(crate::emscripten_target::_pthread_condattr_destroy), + "_pthread_condattr_init" => func!(crate::emscripten_target::_pthread_condattr_init), + "_pthread_condattr_setclock" => func!(crate::emscripten_target::_pthread_condattr_setclock), + "_pthread_mutex_destroy" => func!(crate::emscripten_target::_pthread_mutex_destroy), + "_pthread_mutex_init" => func!(crate::emscripten_target::_pthread_mutex_init), + "_pthread_mutexattr_destroy" => func!(crate::emscripten_target::_pthread_mutexattr_destroy), + "_pthread_mutexattr_init" => func!(crate::emscripten_target::_pthread_mutexattr_init), + "_pthread_mutexattr_settype" => func!(crate::emscripten_target::_pthread_mutexattr_settype), + "_pthread_rwlock_rdlock" => func!(crate::emscripten_target::_pthread_rwlock_rdlock), + "_pthread_rwlock_unlock" => func!(crate::emscripten_target::_pthread_rwlock_unlock), + "___gxx_personality_v0" => func!(crate::emscripten_target::___gxx_personality_v0), }, "global" => { "NaN" => Global::new(Value::F64(f64::NAN)), From c3065a3869af343308e8573518a2bcaa8c17eef8 Mon Sep 17 00:00:00 2001 From: Mackenzie Clark Date: Wed, 20 Feb 2019 15:42:07 -0800 Subject: [PATCH 079/262] add cargo cache for appveyor (#194) --- .appveyor.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.appveyor.yml b/.appveyor.yml index e90075bd2..488e400fd 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -12,6 +12,9 @@ environment: ABI: msvc TARGET: x86_64-pc-windows-msvc +cache: + - 'C:\Users\appveyor\.cargo' + install: - appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe - rustup-init.exe -yv --default-host %target% From 9f40eedba87a1ca4a810f537cf712fbbaadf16bd Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Wed, 20 Feb 2019 16:41:41 -0800 Subject: [PATCH 080/262] Get caching working again --- lib/clif-backend/src/cache.rs | 45 +++---- lib/clif-backend/src/func_env.rs | 130 +++++++++++---------- lib/clif-backend/src/lib.rs | 11 +- lib/clif-backend/src/module.rs | 48 ++++---- lib/clif-backend/src/relocation.rs | 24 ++-- lib/clif-backend/src/resolver.rs | 45 ++++--- lib/clif-backend/src/signal/mod.rs | 6 +- lib/clif-backend/src/trampoline.rs | 3 - lib/emscripten/src/lib.rs | 10 +- lib/emscripten/src/utils.rs | 11 +- lib/runtime-core/src/backend.rs | 14 +-- lib/runtime-core/src/cache.rs | 12 +- lib/runtime-core/src/lib.rs | 5 +- lib/runtime-core/src/module.rs | 40 +++---- lib/runtime-core/src/structures/map.rs | 3 +- lib/runtime-core/src/sys/mod.rs | 3 - lib/runtime-core/src/sys/unix/memory.rs | 16 ++- lib/runtime-core/src/sys/windows/memory.rs | 16 ++- lib/runtime-core/src/types.rs | 30 ++--- lib/runtime-core/src/units.rs | 6 +- lib/runtime-core/src/vm.rs | 12 +- 21 files changed, 244 insertions(+), 246 deletions(-) diff --git a/lib/clif-backend/src/cache.rs b/lib/clif-backend/src/cache.rs index 7e805271b..84db980b0 100644 --- a/lib/clif-backend/src/cache.rs +++ b/lib/clif-backend/src/cache.rs @@ -1,20 +1,14 @@ use crate::relocation::{ExternalRelocation, TrapSink}; use hashbrown::HashMap; +use std::sync::Arc; use wasmer_runtime_core::{ - backend::{ - sys::Memory, - CacheGen, - }, + backend::{sys::Memory, CacheGen}, cache::{Cache, Error}, module::{ModuleInfo, ModuleInner}, structures::Map, types::{LocalFuncIndex, SigIndex}, }; -use std::{ - sync::Arc, - cell::UnsafeCell, -}; use serde_bench::{deserialize, serialize}; @@ -25,14 +19,29 @@ pub struct CacheGenerator { impl CacheGenerator { pub fn new(backend_cache: BackendCache, memory: Arc) -> Self { - Self { backend_cache, memory } + Self { + backend_cache, + memory, + } } } impl CacheGen for CacheGenerator { - fn generate_cache(&self, module: &ModuleInner) -> Result<(Box, Box<[u8]>, Arc), Error> { + fn generate_cache( + &self, + module: &ModuleInner, + ) -> Result<(Box, Box<[u8]>, Memory), Error> { let info = Box::new(module.info.clone()); - Ok((info, self.backend_cache.into_backend_data()?.into_boxed_slice(), Arc::clone(&self.memory))) + + // Clone the memory to a new location. This could take a long time, + // depending on the throughput of your memcpy implementation. + let compiled_code = (*self.memory).clone(); + + Ok(( + info, + self.backend_cache.into_backend_data()?.into_boxed_slice(), + compiled_code, + )) } } @@ -53,18 +62,10 @@ pub struct BackendCache { impl BackendCache { pub fn from_cache(cache: Cache) -> Result<(ModuleInfo, Memory, Self), Error> { - let (info, backend_data, compiled_code_arc) = cache.consume(); + let (info, backend_data, compiled_code) = cache.consume(); - // If this is the only references to this arc, move the memory out. - // else, clone the memory to a new location. This could take a long time, - // depending on the throughput of your memcpy implementation. - let compiled_code = match Arc::try_unwrap(compiled_code_arc) { - Ok(code) => code, - Err(arc) => (*arc).clone(), - }; - - let backend_cache = deserialize(&backend_data) - .map_err(|e| Error::DeserializeError(e.to_string()))?; + let backend_cache = + deserialize(&backend_data).map_err(|e| Error::DeserializeError(e.to_string()))?; Ok((info, compiled_code, backend_cache)) } diff --git a/lib/clif-backend/src/func_env.rs b/lib/clif-backend/src/func_env.rs index e222f2e07..b08f56dd2 100644 --- a/lib/clif-backend/src/func_env.rs +++ b/lib/clif-backend/src/func_env.rs @@ -145,48 +145,49 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> { let vmctx = func.create_global_value(ir::GlobalValueData::VMContext); let ptr_type = self.pointer_type(); - let (local_memory_ptr_ptr, description) = match mem_index.local_or_import(&self.env.module.info) { - LocalOrImport::Local(local_mem_index) => { - let memories_base_addr = func.create_global_value(ir::GlobalValueData::Load { - base: vmctx, - offset: (vm::Ctx::offset_memories() as i32).into(), - global_type: ptr_type, - readonly: true, - }); - - let local_memory_ptr_offset = - local_mem_index.index() * mem::size_of::<*mut vm::LocalMemory>(); - - ( - func.create_global_value(ir::GlobalValueData::IAddImm { - base: memories_base_addr, - offset: (local_memory_ptr_offset as i64).into(), + let (local_memory_ptr_ptr, description) = + match mem_index.local_or_import(&self.env.module.info) { + LocalOrImport::Local(local_mem_index) => { + let memories_base_addr = func.create_global_value(ir::GlobalValueData::Load { + base: vmctx, + offset: (vm::Ctx::offset_memories() as i32).into(), global_type: ptr_type, - }), - self.env.module.info.memories[local_mem_index], - ) - } - LocalOrImport::Import(import_mem_index) => { - let memories_base_addr = func.create_global_value(ir::GlobalValueData::Load { - base: vmctx, - offset: (vm::Ctx::offset_imported_memories() as i32).into(), - global_type: ptr_type, - readonly: true, - }); + readonly: true, + }); - let local_memory_ptr_offset = - import_mem_index.index() * mem::size_of::<*mut vm::LocalMemory>(); + let local_memory_ptr_offset = + local_mem_index.index() * mem::size_of::<*mut vm::LocalMemory>(); - ( - func.create_global_value(ir::GlobalValueData::IAddImm { - base: memories_base_addr, - offset: (local_memory_ptr_offset as i64).into(), + ( + func.create_global_value(ir::GlobalValueData::IAddImm { + base: memories_base_addr, + offset: (local_memory_ptr_offset as i64).into(), + global_type: ptr_type, + }), + self.env.module.info.memories[local_mem_index], + ) + } + LocalOrImport::Import(import_mem_index) => { + let memories_base_addr = func.create_global_value(ir::GlobalValueData::Load { + base: vmctx, + offset: (vm::Ctx::offset_imported_memories() as i32).into(), global_type: ptr_type, - }), - self.env.module.info.imported_memories[import_mem_index].1, - ) - } - }; + readonly: true, + }); + + let local_memory_ptr_offset = + import_mem_index.index() * mem::size_of::<*mut vm::LocalMemory>(); + + ( + func.create_global_value(ir::GlobalValueData::IAddImm { + base: memories_base_addr, + offset: (local_memory_ptr_offset as i64).into(), + global_type: ptr_type, + }), + self.env.module.info.imported_memories[import_mem_index].1, + ) + } + }; let (local_memory_ptr, local_memory_base) = { let local_memory_ptr = func.create_global_value(ir::GlobalValueData::Load { @@ -253,7 +254,8 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> { let vmctx = func.create_global_value(ir::GlobalValueData::VMContext); let ptr_type = self.pointer_type(); - let (table_struct_ptr_ptr, description) = match table_index.local_or_import(&self.env.module.info) + let (table_struct_ptr_ptr, description) = match table_index + .local_or_import(&self.env.module.info) { LocalOrImport::Local(local_table_index) => { let tables_base = func.create_global_value(ir::GlobalValueData::Load { @@ -568,18 +570,19 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> { let mem_index: MemoryIndex = Converter(clif_mem_index).into(); - let (namespace, mem_index, description) = match mem_index.local_or_import(&self.env.module.info) { - LocalOrImport::Local(local_mem_index) => ( - call_names::LOCAL_NAMESPACE, - local_mem_index.index(), - self.env.module.info.memories[local_mem_index], - ), - LocalOrImport::Import(import_mem_index) => ( - call_names::IMPORT_NAMESPACE, - import_mem_index.index(), - self.env.module.info.imported_memories[import_mem_index].1, - ), - }; + let (namespace, mem_index, description) = + match mem_index.local_or_import(&self.env.module.info) { + LocalOrImport::Local(local_mem_index) => ( + call_names::LOCAL_NAMESPACE, + local_mem_index.index(), + self.env.module.info.memories[local_mem_index], + ), + LocalOrImport::Import(import_mem_index) => ( + call_names::IMPORT_NAMESPACE, + import_mem_index.index(), + self.env.module.info.imported_memories[import_mem_index].1, + ), + }; let name_index = match description.memory_type() { MemoryType::Dynamic => call_names::DYNAMIC_MEM_GROW, @@ -631,18 +634,19 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> { let mem_index: MemoryIndex = Converter(clif_mem_index).into(); - let (namespace, mem_index, description) = match mem_index.local_or_import(&self.env.module.info) { - LocalOrImport::Local(local_mem_index) => ( - call_names::LOCAL_NAMESPACE, - local_mem_index.index(), - self.env.module.info.memories[local_mem_index], - ), - LocalOrImport::Import(import_mem_index) => ( - call_names::IMPORT_NAMESPACE, - import_mem_index.index(), - self.env.module.info.imported_memories[import_mem_index].1, - ), - }; + let (namespace, mem_index, description) = + match mem_index.local_or_import(&self.env.module.info) { + LocalOrImport::Local(local_mem_index) => ( + call_names::LOCAL_NAMESPACE, + local_mem_index.index(), + self.env.module.info.memories[local_mem_index], + ), + LocalOrImport::Import(import_mem_index) => ( + call_names::IMPORT_NAMESPACE, + import_mem_index.index(), + self.env.module.info.imported_memories[import_mem_index].1, + ), + }; let name_index = match description.memory_type() { MemoryType::Dynamic => call_names::DYNAMIC_MEM_SIZE, diff --git a/lib/clif-backend/src/lib.rs b/lib/clif-backend/src/lib.rs index 42d56552b..8d756420e 100644 --- a/lib/clif-backend/src/lib.rs +++ b/lib/clif-backend/src/lib.rs @@ -1,4 +1,3 @@ - mod cache; mod func_env; mod libcalls; @@ -15,11 +14,7 @@ use cranelift_codegen::{ }; use target_lexicon::Triple; -use wasmer_runtime_core::{ - backend::sys::Memory, - cache::{Cache, Error as CacheError}, - module::ModuleInfo, -}; +use wasmer_runtime_core::cache::{Cache, Error as CacheError}; use wasmer_runtime_core::{ backend::{Compiler, Token}, error::{CompileError, CompileResult}, @@ -57,12 +52,12 @@ impl Compiler for CraneliftCompiler { } /// Create a wasmer Module from an already-compiled cache. - + unsafe fn from_cache(&self, cache: Cache, _: Token) -> Result { module::Module::from_cache(cache) } - // + // // fn compile_to_backend_cache_data( // &self, // wasm: &[u8], diff --git a/lib/clif-backend/src/module.rs b/lib/clif-backend/src/module.rs index 29eea5f2c..0d0c66d7c 100644 --- a/lib/clif-backend/src/module.rs +++ b/lib/clif-backend/src/module.rs @@ -1,4 +1,3 @@ - use crate::cache::{BackendCache, CacheGenerator}; use crate::{resolver::FuncResolverBuilder, signal::Caller, trampoline::Trampolines}; @@ -8,11 +7,7 @@ use cranelift_wasm; use hashbrown::HashMap; use std::sync::Arc; - -use wasmer_runtime_core::{ - backend::sys::Memory, - cache::{Cache, Error as CacheError}, -}; +use wasmer_runtime_core::cache::{Cache, Error as CacheError}; use wasmer_runtime_core::{ backend::Backend, @@ -58,7 +53,6 @@ impl Module { namespace_table: StringTable::new(), name_table: StringTable::new(), - wasm_hash: WasmHash::generate(wasm), }, } @@ -74,45 +68,53 @@ impl Module { let trampolines = Arc::new(Trampolines::new(isa, &self.info)); - let (func_resolver, backend_cache) = - func_resolver_builder.finalize(&self.info.signatures, Arc::clone(&trampolines), handler_data.clone())?; + let (func_resolver, backend_cache) = func_resolver_builder.finalize( + &self.info.signatures, + Arc::clone(&trampolines), + handler_data.clone(), + )?; - let protected_caller = - Caller::new(&self.info, handler_data, trampolines); - - - let cache_gen = Box::new(CacheGenerator::new(backend_cache, Arc::clone(&func_resolver.memory))); + let protected_caller = Caller::new(&self.info, handler_data, trampolines); + + let cache_gen = Box::new(CacheGenerator::new( + backend_cache, + Arc::clone(&func_resolver.memory), + )); Ok(ModuleInner { func_resolver: Box::new(func_resolver), protected_caller: Box::new(protected_caller), - cache_gen, + cache_gen, info: self.info, }) } - pub fn from_cache(cache: Cache) -> Result { let (info, compiled_code, backend_cache) = BackendCache::from_cache(cache)?; let (func_resolver_builder, trampolines, handler_data) = FuncResolverBuilder::new_from_backend_cache(backend_cache, compiled_code, &info)?; - let (func_resolver, backend_cache) = - func_resolver_builder - .finalize(&info.signatures, Arc::clone(&trampolines), handler_data.clone()) - .map_err(|e| CacheError::Unknown(format!("{:?}", e)))?; + let (func_resolver, backend_cache) = func_resolver_builder + .finalize( + &info.signatures, + Arc::clone(&trampolines), + handler_data.clone(), + ) + .map_err(|e| CacheError::Unknown(format!("{:?}", e)))?; let protected_caller = Caller::new(&info, handler_data, trampolines); - - let cache_gen = Box::new(CacheGenerator::new(backend_cache, Arc::clone(&func_resolver.memory))); + let cache_gen = Box::new(CacheGenerator::new( + backend_cache, + Arc::clone(&func_resolver.memory), + )); Ok(ModuleInner { func_resolver: Box::new(func_resolver), protected_caller: Box::new(protected_caller), - cache_gen, + cache_gen, info, }) diff --git a/lib/clif-backend/src/relocation.rs b/lib/clif-backend/src/relocation.rs index 03adbc4bb..92ef0485a 100644 --- a/lib/clif-backend/src/relocation.rs +++ b/lib/clif-backend/src/relocation.rs @@ -22,16 +22,14 @@ pub mod call_names { pub const DYNAMIC_MEM_SIZE: u32 = 5; } -#[derive(Serialize, Deserialize)] -#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[derive(Serialize, Deserialize, Debug, Copy, Clone, PartialEq, Eq)] pub enum Reloc { Abs8, X86PCRel4, X86CallPCRel4, } -#[derive(Serialize, Deserialize)] -#[derive(Debug, Copy, Clone)] +#[derive(Serialize, Deserialize, Debug, Copy, Clone)] pub enum LibCall { Probestack, CeilF32, @@ -44,8 +42,7 @@ pub enum LibCall { NearestF64, } -#[derive(Serialize, Deserialize)] -#[derive(Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone)] pub struct ExternalRelocation { /// The relocation code. pub reloc: Reloc, @@ -66,8 +63,7 @@ pub struct LocalRelocation { pub target: FuncIndex, } -#[derive(Serialize, Deserialize)] -#[derive(Debug, Clone, Copy)] +#[derive(Serialize, Deserialize, Debug, Clone, Copy)] pub enum VmCallKind { StaticMemoryGrow, StaticMemorySize, @@ -79,16 +75,14 @@ pub enum VmCallKind { DynamicMemorySize, } -#[derive(Serialize, Deserialize)] -#[derive(Debug, Clone, Copy)] +#[derive(Serialize, Deserialize, Debug, Clone, Copy)] pub enum VmCall { Local(VmCallKind), Import(VmCallKind), } /// Specify the type of relocation -#[derive(Serialize, Deserialize)] -#[derive(Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone)] pub enum RelocationType { Intrinsic(String), LibCall(LibCall), @@ -218,8 +212,7 @@ impl binemit::RelocSink for RelocSink { } } -#[derive(Serialize, Deserialize)] -#[derive(Debug, Clone, Copy)] +#[derive(Serialize, Deserialize, Debug, Clone, Copy)] pub enum TrapCode { StackOverflow, HeapOutOfBounds, @@ -244,8 +237,7 @@ impl RelocSink { } } -#[derive(Serialize, Deserialize)] -#[derive(Debug, Clone, Copy)] +#[derive(Serialize, Deserialize, Debug, Clone, Copy)] pub struct TrapData { pub trapcode: TrapCode, pub srcloc: u32, diff --git a/lib/clif-backend/src/resolver.rs b/lib/clif-backend/src/resolver.rs index 06b678a5b..604778f01 100644 --- a/lib/clif-backend/src/resolver.rs +++ b/lib/clif-backend/src/resolver.rs @@ -1,8 +1,4 @@ - -use crate::{ - cache::{BackendCache, TrampolineCache}, - trampoline::Trampolines, -}; +use crate::{cache::BackendCache, trampoline::Trampolines}; use crate::{ libcalls, relocation::{ @@ -17,7 +13,6 @@ use cranelift_codegen::{ir, isa, Context}; use std::{ mem, ptr::{write_unaligned, NonNull}, - cell::UnsafeCell, sync::Arc, }; @@ -43,7 +38,11 @@ extern "C" { pub fn __chkstk(); } -fn lookup_func(map: &SliceMap, memory: &Memory, local_func_index: LocalFuncIndex) -> Option> { +fn lookup_func( + map: &SliceMap, + memory: &Memory, + local_func_index: LocalFuncIndex, +) -> Option> { let offset = *map.get(local_func_index)?; let ptr = unsafe { memory.as_ptr().add(offset) }; @@ -60,7 +59,6 @@ pub struct FuncResolverBuilder { } impl FuncResolverBuilder { - pub fn new_from_backend_cache( backend_cache: BackendCache, mut code: Memory, @@ -82,7 +80,9 @@ impl FuncResolverBuilder { external_relocs: backend_cache.external_relocs, import_len: info.imported_functions.len(), }, - Arc::new(Trampolines::from_trampoline_cache(backend_cache.trampolines)), + Arc::new(Trampolines::from_trampoline_cache( + backend_cache.trampolines, + )), handler_data, )) } @@ -158,7 +158,8 @@ impl FuncResolverBuilder { previous_end = new_end; } - let handler_data = HandlerData::new(Arc::new(trap_sink), memory.as_ptr() as _, memory.size()); + let handler_data = + HandlerData::new(Arc::new(trap_sink), memory.as_ptr() as _, memory.size()); let mut func_resolver_builder = Self { map, @@ -177,12 +178,15 @@ impl FuncResolverBuilder { for (index, relocs) in self.local_relocs.iter() { for ref reloc in relocs.iter() { let local_func_index = LocalFuncIndex::new(reloc.target.index() - self.import_len); - let target_func_address = - lookup_func(&self.map, &self.memory, local_func_index).unwrap().as_ptr() as usize; + let target_func_address = lookup_func(&self.map, &self.memory, local_func_index) + .unwrap() + .as_ptr() as usize; // We need the address of the current function // because these calls are relative. - let func_addr = lookup_func(&self.map, &self.memory, index).unwrap().as_ptr() as usize; + let func_addr = lookup_func(&self.map, &self.memory, index) + .unwrap() + .as_ptr() as usize; unsafe { let reloc_address = func_addr + reloc.offset as usize; @@ -273,7 +277,9 @@ impl FuncResolverBuilder { // We need the address of the current function // because some of these calls are relative. - let func_addr = lookup_func(&self.map, &self.memory, index).unwrap().as_ptr() as usize; + let func_addr = lookup_func(&self.map, &self.memory, index) + .unwrap() + .as_ptr() as usize; // Determine relocation type and apply relocation. match reloc.reloc { @@ -313,10 +319,13 @@ impl FuncResolverBuilder { trampolines: trampolines.to_trampoline_cache(), }; - Ok((FuncResolver { - map: self.map, - memory: Arc::new(self.memory), - }, backend_cache)) + Ok(( + FuncResolver { + map: self.map, + memory: Arc::new(self.memory), + }, + backend_cache, + )) } } diff --git a/lib/clif-backend/src/signal/mod.rs b/lib/clif-backend/src/signal/mod.rs index bedcff87a..9ccbf1822 100644 --- a/lib/clif-backend/src/signal/mod.rs +++ b/lib/clif-backend/src/signal/mod.rs @@ -44,7 +44,11 @@ pub struct Caller { } impl Caller { - pub fn new(module: &ModuleInfo, handler_data: HandlerData, trampolines: Arc) -> Self { + pub fn new( + module: &ModuleInfo, + handler_data: HandlerData, + trampolines: Arc, + ) -> Self { let mut func_export_set = HashSet::new(); for export_index in module.exports.values() { if let ExportIndex::Func(func_index) = export_index { diff --git a/lib/clif-backend/src/trampoline.rs b/lib/clif-backend/src/trampoline.rs index 7a90c085e..b20109ef0 100644 --- a/lib/clif-backend/src/trampoline.rs +++ b/lib/clif-backend/src/trampoline.rs @@ -1,4 +1,3 @@ - use crate::cache::TrampolineCache; use cranelift_codegen::{ binemit::{NullTrapSink, Reloc, RelocSink}, @@ -33,7 +32,6 @@ pub struct Trampolines { } impl Trampolines { - pub fn from_trampoline_cache(cache: TrampolineCache) -> Self { // pub struct TrampolineCache { // #[serde(with = "serde_bytes")] @@ -57,7 +55,6 @@ impl Trampolines { } } - pub fn to_trampoline_cache(&self) -> TrampolineCache { let mut code = vec![0; self.memory.size()]; diff --git a/lib/emscripten/src/lib.rs b/lib/emscripten/src/lib.rs index 3ed5c36dd..5c2a04e57 100644 --- a/lib/emscripten/src/lib.rs +++ b/lib/emscripten/src/lib.rs @@ -220,13 +220,13 @@ impl EmscriptenGlobals { namespace_index, name_index, }, - ) in &module.0.info.imported_functions + ) in &module.info().imported_functions { - let namespace = module.0.info.namespace_table.get(*namespace_index); - let name = module.0.info.name_table.get(*name_index); + let namespace = module.info().namespace_table.get(*namespace_index); + let name = module.info().name_table.get(*name_index); if name == "abortOnCannotGrowMemory" && namespace == "env" { - let sig_index = module.0.info.func_assoc[index.convert_up(&module.0)]; - let expected_sig = &module.0.info.signatures[sig_index]; + let sig_index = module.info().func_assoc[index.convert_up(module.info())]; + let expected_sig = &module.info().signatures[sig_index]; if **expected_sig == *OLD_ABORT_ON_CANNOT_GROW_MEMORY_SIG { use_old_abort_on_cannot_grow_memory = true; } diff --git a/lib/emscripten/src/utils.rs b/lib/emscripten/src/utils.rs index 82ab0f251..678032374 100644 --- a/lib/emscripten/src/utils.rs +++ b/lib/emscripten/src/utils.rs @@ -16,13 +16,12 @@ use wasmer_runtime_core::{ /// We check if a provided module is an Emscripten generated one pub fn is_emscripten_module(module: &Module) -> bool { - for (_, import_name) in &module.0.info.imported_functions { + for (_, import_name) in &module.info().imported_functions { let namespace = module - .0 - .info + .info() .namespace_table .get(import_name.namespace_index); - let field = module.0.info.name_table.get(import_name.name_index); + let field = module.info().name_table.get(import_name.name_index); if field == "_emscripten_memcpy_big" && namespace == "env" { return true; } @@ -31,12 +30,12 @@ pub fn is_emscripten_module(module: &Module) -> bool { } pub fn get_emscripten_table_size(module: &Module) -> (u32, Option) { - let (_, table) = &module.0.info.imported_tables[ImportedTableIndex::new(0)]; + let (_, table) = &module.info().imported_tables[ImportedTableIndex::new(0)]; (table.minimum, table.maximum) } pub fn get_emscripten_memory_size(module: &Module) -> (Pages, Option) { - let (_, memory) = &module.0.info.imported_memories[ImportedMemoryIndex::new(0)]; + let (_, memory) = &module.info().imported_memories[ImportedMemoryIndex::new(0)]; (memory.minimum, memory.maximum) } diff --git a/lib/runtime-core/src/backend.rs b/lib/runtime-core/src/backend.rs index a4afe2ee5..e490b5e3e 100644 --- a/lib/runtime-core/src/backend.rs +++ b/lib/runtime-core/src/backend.rs @@ -2,7 +2,7 @@ use crate::{ backing::ImportBacking, error::CompileResult, error::RuntimeResult, - module::{ModuleInner}, + module::ModuleInner, types::{FuncIndex, LocalFuncIndex, Value}, vm, }; @@ -21,8 +21,7 @@ pub mod sys { } pub use crate::sig_registry::SigRegistry; -#[derive(Serialize, Deserialize)] -#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[derive(Serialize, Deserialize, Debug, Copy, Clone, PartialEq, Eq)] pub enum Backend { Cranelift, } @@ -45,7 +44,6 @@ pub trait Compiler { /// be called from inside the runtime. fn compile(&self, wasm: &[u8], _: Token) -> CompileResult; - unsafe fn from_cache(&self, cache: Cache, _: Token) -> Result; } @@ -95,7 +93,9 @@ pub trait FuncResolver: Send + Sync { ) -> Option>; } - pub trait CacheGen: Send + Sync { - fn generate_cache(&self, module: &ModuleInner) -> Result<(Box, Box<[u8]>, Arc), CacheError>; -} \ No newline at end of file + fn generate_cache( + &self, + module: &ModuleInner, + ) -> Result<(Box, Box<[u8]>, Memory), CacheError>; +} diff --git a/lib/runtime-core/src/cache.rs b/lib/runtime-core/src/cache.rs index b60301e94..d49dd4215 100644 --- a/lib/runtime-core/src/cache.rs +++ b/lib/runtime-core/src/cache.rs @@ -6,9 +6,9 @@ use std::{ fs::File, io::{self, Seek, SeekFrom, Write}, mem, - sync::Arc, path::Path, slice, + sync::Arc, }; #[derive(Debug)] @@ -69,7 +69,7 @@ struct CacheInner { info: Box, #[serde(with = "serde_bytes")] backend_metadata: Box<[u8]>, - compiled_code: Arc, + compiled_code: Memory, } pub struct Cache { @@ -80,7 +80,7 @@ impl Cache { pub(crate) fn from_parts( info: Box, backend_metadata: Box<[u8]>, - compiled_code: Arc, + compiled_code: Memory, ) -> Self { Self { inner: CacheInner { @@ -104,9 +104,7 @@ impl Cache { let inner = deserialize(body_slice).map_err(|e| Error::DeserializeError(format!("{:#?}", e)))?; - Ok(Cache { - inner, - }) + Ok(Cache { inner }) } pub fn info(&self) -> &ModuleInfo { @@ -114,7 +112,7 @@ impl Cache { } #[doc(hidden)] - pub fn consume(self) -> (ModuleInfo, Box<[u8]>, Arc) { + pub fn consume(self) -> (ModuleInfo, Box<[u8]>, Memory) { ( *self.inner.info, self.inner.backend_metadata, diff --git a/lib/runtime-core/src/lib.rs b/lib/runtime-core/src/lib.rs index 18cf2a703..7025acf5a 100644 --- a/lib/runtime-core/src/lib.rs +++ b/lib/runtime-core/src/lib.rs @@ -2,7 +2,6 @@ #[macro_use] extern crate field_offset; - #[macro_use] extern crate serde_derive; @@ -44,7 +43,6 @@ pub use self::module::Module; pub use self::typed_func::Func; use std::sync::Arc; - use self::cache::{Cache, Error as CacheError}; pub mod prelude { @@ -90,7 +88,7 @@ pub fn validate(wasm: &[u8]) -> bool { } } -// +// // pub fn compile_to_cache_with( // wasm: &[u8], // compiler: &dyn backend::Compiler, @@ -102,7 +100,6 @@ pub fn validate(wasm: &[u8]) -> bool { // Ok(Cache::new(wasm, info, backend_metadata, compiled_code)) // } - pub unsafe fn load_cache_with( cache: Cache, compiler: &dyn backend::Compiler, diff --git a/lib/runtime-core/src/module.rs b/lib/runtime-core/src/module.rs index 0526c0ad4..5cb1b5b21 100644 --- a/lib/runtime-core/src/module.rs +++ b/lib/runtime-core/src/module.rs @@ -1,5 +1,6 @@ use crate::{ backend::{Backend, FuncResolver, ProtectedCaller}, + cache::{Cache, Error as CacheError}, error, import::ImportObject, structures::{Map, TypedIndex}, @@ -10,7 +11,6 @@ use crate::{ LocalGlobalIndex, LocalMemoryIndex, LocalTableIndex, MemoryDescriptor, MemoryIndex, SigIndex, TableDescriptor, TableIndex, }, - cache::{Cache, Error as CacheError}, Instance, }; @@ -25,14 +25,12 @@ pub struct ModuleInner { pub func_resolver: Box, pub protected_caller: Box, - pub cache_gen: Box, pub info: ModuleInfo, } -#[derive(Clone)] -#[derive(Serialize, Deserialize)] +#[derive(Clone, Serialize, Deserialize)] pub struct ModuleInfo { // This are strictly local and the typsystem ensures that. pub memories: Map, @@ -62,12 +60,9 @@ pub struct ModuleInfo { pub wasm_hash: WasmHash, } - -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -#[derive(Serialize, Deserialize)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct WasmHash([u8; 32]); - impl WasmHash { pub fn generate(wasm: &[u8]) -> Self { WasmHash(crate::cache::hash_data(wasm)) @@ -125,23 +120,25 @@ impl Module { } pub fn cache(&self) -> Result { - let (info, backend_cache, code) = self.inner.cache_gen.generate_cache(&self.inner)?; - + let (info, backend_metadata, code) = self.inner.cache_gen.generate_cache(&self.inner)?; + Ok(Cache::from_parts(info, backend_metadata, code)) + } + + pub fn info(&self) -> &ModuleInfo { + &self.inner.info } } impl ModuleInner {} #[doc(hidden)] -#[derive(Serialize, Deserialize)] -#[derive(Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone)] pub struct ImportName { pub namespace_index: NamespaceIndex, pub name_index: NameIndex, } -#[derive(Serialize, Deserialize)] -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq)] pub enum ExportIndex { Func(FuncIndex), Memory(MemoryIndex), @@ -150,8 +147,7 @@ pub enum ExportIndex { } /// A data initializer for linear memory. -#[derive(Serialize, Deserialize)] -#[derive(Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone)] pub struct DataInitializer { /// The index of the memory to initialize. pub memory_index: MemoryIndex, @@ -163,8 +159,7 @@ pub struct DataInitializer { } /// A WebAssembly table initializer. -#[derive(Serialize, Deserialize)] -#[derive(Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone)] pub struct TableInitializer { /// The index of a table to initialize. pub table_index: TableIndex, @@ -225,8 +220,7 @@ impl StringTableBuilder { } } -#[derive(Serialize, Deserialize)] -#[derive(Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone)] pub struct StringTable { table: Map, buffer: String, @@ -249,8 +243,7 @@ impl StringTable { } } -#[derive(Serialize, Deserialize)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Serialize, Deserialize, Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct NamespaceIndex(u32); impl TypedIndex for NamespaceIndex { @@ -265,8 +258,7 @@ impl TypedIndex for NamespaceIndex { } } -#[derive(Serialize, Deserialize)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Serialize, Deserialize, Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct NameIndex(u32); impl TypedIndex for NameIndex { diff --git a/lib/runtime-core/src/structures/map.rs b/lib/runtime-core/src/structures/map.rs index df95fe652..d7177c427 100644 --- a/lib/runtime-core/src/structures/map.rs +++ b/lib/runtime-core/src/structures/map.rs @@ -8,8 +8,7 @@ use std::{ }; /// Dense item map -#[derive(Serialize, Deserialize)] -#[derive(Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone)] pub struct Map where K: TypedIndex, diff --git a/lib/runtime-core/src/sys/mod.rs b/lib/runtime-core/src/sys/mod.rs index 2fdc1ef0f..0bfc134c2 100644 --- a/lib/runtime-core/src/sys/mod.rs +++ b/lib/runtime-core/src/sys/mod.rs @@ -10,7 +10,6 @@ pub use self::unix::*; #[cfg(windows)] pub use self::windows::*; - use serde::{ de::{self, SeqAccess, Visitor}, ser::SerializeStruct, @@ -21,7 +20,6 @@ use serde_bytes::Bytes; use std::fmt; - impl Serialize for Memory { fn serialize(&self, serializer: S) -> Result where @@ -36,7 +34,6 @@ impl Serialize for Memory { } } - impl<'de> Deserialize<'de> for Memory { fn deserialize(deserializer: D) -> Result where diff --git a/lib/runtime-core/src/sys/unix/memory.rs b/lib/runtime-core/src/sys/unix/memory.rs index 7154f34f9..8c76e6c14 100644 --- a/lib/runtime-core/src/sys/unix/memory.rs +++ b/lib/runtime-core/src/sys/unix/memory.rs @@ -207,16 +207,26 @@ impl Drop for Memory { impl Clone for Memory { fn clone(&self) -> Self { - let mut new = Memory::with_size_protect(self.size, self.protection).unwrap(); + let temp_protection = if self.protection.is_writable() { + self.protection + } else { + Protect::ReadWrite + }; + + let mut new = Memory::with_size_protect(self.size, temp_protection).unwrap(); unsafe { new.as_slice_mut().copy_from_slice(self.as_slice()); + + if temp_protection != self.protection { + new.protect(.., self.protection).unwrap(); + } } + new } } -#[derive(Serialize, Deserialize)] -#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[derive(Serialize, Deserialize, Debug, Copy, Clone, PartialEq, Eq)] #[allow(dead_code)] pub enum Protect { None, diff --git a/lib/runtime-core/src/sys/windows/memory.rs b/lib/runtime-core/src/sys/windows/memory.rs index 578070a3e..771ac6788 100644 --- a/lib/runtime-core/src/sys/windows/memory.rs +++ b/lib/runtime-core/src/sys/windows/memory.rs @@ -158,16 +158,26 @@ impl Drop for Memory { impl Clone for Memory { fn clone(&self) -> Self { - let mut new = Memory::with_size_protect(self.size, self.protection).unwrap(); + let temp_protection = if self.protection.is_writable() { + self.protection + } else { + Protect::ReadWrite + }; + + let mut new = Memory::with_size_protect(self.size, temp_protection).unwrap(); unsafe { new.as_slice_mut().copy_from_slice(self.as_slice()); + + if temp_protection != self.protection { + new.protect(.., self.protection).unwrap(); + } } + new } } -#[derive(Serialize, Deserialize)] -#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[derive(Serialize, Deserialize, Debug, Copy, Clone, PartialEq, Eq)] #[allow(dead_code)] pub enum Protect { None, diff --git a/lib/runtime-core/src/types.rs b/lib/runtime-core/src/types.rs index f19e73a6e..9ee5270dd 100644 --- a/lib/runtime-core/src/types.rs +++ b/lib/runtime-core/src/types.rs @@ -2,8 +2,7 @@ use crate::{memory::MemoryType, module::ModuleInfo, structures::TypedIndex, unit use std::{borrow::Cow, mem}; /// Represents a WebAssembly type. -#[derive(Serialize, Deserialize)] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum Type { /// The `i32` type. I32, @@ -25,8 +24,7 @@ impl std::fmt::Display for Type { /// /// As the number of types in WebAssembly expand, /// this structure will expand as well. -#[derive(Serialize, Deserialize)] -#[derive(Debug, Clone, PartialEq)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub enum Value { /// The `i32` type. I32(i32), @@ -171,15 +169,13 @@ impl ValueType for f64 { } } -#[derive(Serialize, Deserialize)] -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq)] pub enum ElementType { /// Any wasm function. Anyfunc, } -#[derive(Serialize, Deserialize)] -#[derive(Debug, Clone, Copy)] +#[derive(Serialize, Deserialize, Debug, Clone, Copy)] pub struct TableDescriptor { /// Type of data stored in this table. pub element: ElementType, @@ -203,8 +199,7 @@ impl TableDescriptor { /// A const value initializer. /// Over time, this will be able to represent more and more /// complex expressions. -#[derive(Serialize, Deserialize)] -#[derive(Debug, Clone, PartialEq)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub enum Initializer { /// Corresponds to a `const.*` instruction. Const(Value), @@ -212,24 +207,21 @@ pub enum Initializer { GetGlobal(ImportedGlobalIndex), } -#[derive(Serialize, Deserialize)] -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq)] pub struct GlobalDescriptor { pub mutable: bool, pub ty: Type, } /// A wasm global. -#[derive(Serialize, Deserialize)] -#[derive(Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone)] pub struct GlobalInit { pub desc: GlobalDescriptor, pub init: Initializer, } /// A wasm memory. -#[derive(Serialize, Deserialize)] -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq)] pub struct MemoryDescriptor { /// The minimum number of allowed pages. pub minimum: Pages, @@ -261,8 +253,7 @@ impl MemoryDescriptor { /// The signature of a function that is either implemented /// in a wasm module or exposed to wasm by the host. -#[derive(Serialize, Deserialize)] -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash)] pub struct FuncSig { params: Cow<'static, [Type]>, returns: Cow<'static, [Type]>, @@ -400,8 +391,7 @@ define_local_or_import![ (GlobalIndex | (LocalGlobalIndex, ImportedGlobalIndex): imported_globals), ]; -#[derive(Serialize, Deserialize)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Serialize, Deserialize, Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct SigIndex(u32); impl TypedIndex for SigIndex { #[doc(hidden)] diff --git a/lib/runtime-core/src/units.rs b/lib/runtime-core/src/units.rs index 6a1582e9e..2486c5738 100644 --- a/lib/runtime-core/src/units.rs +++ b/lib/runtime-core/src/units.rs @@ -7,8 +7,7 @@ const WASM_PAGE_SIZE: usize = 65_536; const WASM_MAX_PAGES: usize = 65_536; /// Units of WebAssembly pages (as specified to be 65,536 bytes). -#[derive(Serialize, Deserialize)] -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Serialize, Deserialize, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] pub struct Pages(pub u32); impl Pages { @@ -33,8 +32,7 @@ impl fmt::Debug for Pages { } /// Units of WebAssembly memory in terms of 8-bit bytes. -#[derive(Serialize, Deserialize)] -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Serialize, Deserialize, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] pub struct Bytes(pub usize); impl fmt::Debug for Bytes { diff --git a/lib/runtime-core/src/vm.rs b/lib/runtime-core/src/vm.rs index 79d18255a..4d6e6880d 100644 --- a/lib/runtime-core/src/vm.rs +++ b/lib/runtime-core/src/vm.rs @@ -494,11 +494,13 @@ mod vm_ctx_tests { fn generate_module() -> ModuleInner { use super::Func; - use crate::backend::{Backend, FuncResolver, ProtectedCaller, Token, UserTrapper, CacheGen, sys::Memory}; + use crate::backend::{ + sys::Memory, Backend, CacheGen, FuncResolver, ProtectedCaller, Token, UserTrapper, + }; use crate::cache::Error as CacheError; use crate::error::RuntimeResult; - use crate::types::{FuncIndex, LocalFuncIndex, Value}; use crate::module::WasmHash; + use crate::types::{FuncIndex, LocalFuncIndex, Value}; use hashbrown::HashMap; use std::ptr::NonNull; struct Placeholder; @@ -528,11 +530,13 @@ mod vm_ctx_tests { } } impl CacheGen for Placeholder { - fn generate_cache(&self, module: &ModuleInner) -> Result<(Box, Box<[u8]>, Memory), CacheError> { + fn generate_cache( + &self, + module: &ModuleInner, + ) -> Result<(Box, Box<[u8]>, Memory), CacheError> { unimplemented!() } } - ModuleInner { func_resolver: Box::new(Placeholder), From 336c1d9c5f6b8f78d788a033f403e49370cb9f4f Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Wed, 20 Feb 2019 17:00:48 -0800 Subject: [PATCH 081/262] Fix lint --- lib/runtime/src/cache.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/runtime/src/cache.rs b/lib/runtime/src/cache.rs index b0db19fe8..01bf90c25 100644 --- a/lib/runtime/src/cache.rs +++ b/lib/runtime/src/cache.rs @@ -1,7 +1,7 @@ use crate::Module; use std::path::Path; use wasmer_runtime_core::cache::{hash_data, Cache as CoreCache}; -use wasmer_runtime_core::module::{WasmHash}; +use wasmer_runtime_core::module::WasmHash; pub use wasmer_runtime_core::cache::Error; @@ -136,4 +136,3 @@ pub trait Cache { unsafe fn load(&self, key: Self::Key) -> Result; fn store(&mut self, module: Module) -> Result; } - From ac57a1bc717f8205c9d84f6f3f528fe7a67ce1a9 Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Wed, 20 Feb 2019 23:08:23 -0600 Subject: [PATCH 082/262] Add C API module_instantiate function --- lib/runtime-c-api/src/lib.rs | 72 +++++++++++++++++++++++++++ lib/runtime-c-api/tests/test-module.c | 26 ++++++++++ lib/runtime-c-api/wasmer.h | 11 ++++ lib/runtime-c-api/wasmer.hh | 9 ++++ 4 files changed, 118 insertions(+) diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index 5b1dd1955..f19380cdb 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -398,6 +398,78 @@ pub unsafe extern "C" fn wasmer_compile( wasmer_result_t::WASMER_OK } +/// Creates a new Instance from the given module and imports. +/// +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub unsafe extern "C" fn wasmer_module_instantiate( + module: *mut wasmer_module_t, + mut instance: *mut *mut wasmer_instance_t, + imports: *mut wasmer_import_t, + imports_len: c_int, +) -> wasmer_result_t { + let imports: &[wasmer_import_t] = slice::from_raw_parts(imports, imports_len as usize); + let mut import_object = ImportObject::new(); + let mut namespaces = HashMap::new(); + for import in imports { + let module_name = slice::from_raw_parts( + import.module_name.bytes, + import.module_name.bytes_len as usize, + ); + let module_name = if let Ok(s) = std::str::from_utf8(module_name) { + s + } else { + update_last_error(CApiError { + msg: "error converting module name to string".to_string(), + }); + return wasmer_result_t::WASMER_ERROR; + }; + let import_name = slice::from_raw_parts( + import.import_name.bytes, + import.import_name.bytes_len as usize, + ); + let import_name = if let Ok(s) = std::str::from_utf8(import_name) { + s + } else { + update_last_error(CApiError { + msg: "error converting import_name to string".to_string(), + }); + return wasmer_result_t::WASMER_ERROR; + }; + + let namespace = namespaces + .entry(module_name) + .or_insert_with(|| Namespace::new()); + + let export = match import.tag { + wasmer_import_export_kind::WASM_MEMORY => import.value.memory as *mut Export, + wasmer_import_export_kind::WASM_FUNCTION => import.value.func as *mut Export, + wasmer_import_export_kind::WASM_GLOBAL => import.value.global as *mut Export, + wasmer_import_export_kind::WASM_TABLE => import.value.table as *mut Export, + }; + namespace.insert(import_name, unsafe { (&*export).clone() }); + } + for (module_name, namespace) in namespaces.into_iter() { + import_object.register(module_name, namespace); + } + + let module = unsafe { &*(module as *mut Module) }; + let new_instance = if let Ok(res) = module.instantiate(&import_object) { + res + } else { + update_last_error(CApiError { + msg: "error instantiating from module".to_string(), + }); + return wasmer_result_t::WASMER_ERROR; + }; + unsafe { *instance = Box::into_raw(Box::new(new_instance)) as *mut wasmer_instance_t }; + wasmer_result_t::WASMER_OK +} + /// Frees memory for the given Module #[allow(clippy::cast_ptr_alignment)] #[no_mangle] diff --git a/lib/runtime-c-api/tests/test-module.c b/lib/runtime-c-api/tests/test-module.c index bacd37c3a..062caf5b8 100644 --- a/lib/runtime-c-api/tests/test-module.c +++ b/lib/runtime-c-api/tests/test-module.c @@ -19,6 +19,32 @@ int main() printf("Compile result: %d\n", compile_result); assert(compile_result == WASMER_OK); + wasmer_import_t imports[] = {}; + wasmer_instance_t *instance = NULL; + wasmer_result_t instantiate_result = wasmer_module_instantiate(module, &instance, imports, 0); + printf("Instantiate result: %d\n", compile_result); + assert(instantiate_result == WASMER_OK); + + wasmer_value_t param_one; + param_one.tag = WASM_I32; + param_one.value.I32 = 7; + wasmer_value_t param_two; + param_two.tag = WASM_I32; + param_two.value.I32 = 8; + wasmer_value_t params[] = {param_one, param_two}; + + wasmer_value_t result_one; + wasmer_value_t results[] = {result_one}; + + wasmer_result_t call_result = wasmer_instance_call(instance, "sum", params, 2, results, 1); + printf("Call result: %d\n", call_result); + printf("Result: %d\n", results[0].value.I32); + assert(results[0].value.I32 == 15); + assert(call_result == WASMER_OK); + + printf("Destroy instance\n"); + wasmer_instance_destroy(instance); + printf("Destroy module\n"); wasmer_module_destroy(module); return 0; diff --git a/lib/runtime-c-api/wasmer.h b/lib/runtime-c-api/wasmer.h index 8d328836f..6c0494e01 100644 --- a/lib/runtime-c-api/wasmer.h +++ b/lib/runtime-c-api/wasmer.h @@ -345,6 +345,17 @@ wasmer_result_t wasmer_memory_new(wasmer_memory_t **memory, wasmer_limits_t limi */ void wasmer_module_destroy(wasmer_module_t *module); +/** + * Creates a new Instance from the given module and imports. + * Returns `wasmer_result_t::WASMER_OK` upon success. + * Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` + * and `wasmer_last_error_message` to get an error message. + */ +wasmer_result_t wasmer_module_instantiate(wasmer_module_t *module, + wasmer_instance_t **instance, + wasmer_import_t *imports, + int imports_len); + /** * Frees memory for the given Table */ diff --git a/lib/runtime-c-api/wasmer.hh b/lib/runtime-c-api/wasmer.hh index ab2808bf3..2bb55de45 100644 --- a/lib/runtime-c-api/wasmer.hh +++ b/lib/runtime-c-api/wasmer.hh @@ -278,6 +278,15 @@ wasmer_result_t wasmer_memory_new(wasmer_memory_t **memory, wasmer_limits_t limi /// Frees memory for the given Module void wasmer_module_destroy(wasmer_module_t *module); +/// Creates a new Instance from the given module and imports. +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +wasmer_result_t wasmer_module_instantiate(wasmer_module_t *module, + wasmer_instance_t **instance, + wasmer_import_t *imports, + int imports_len); + /// Frees memory for the given Table void wasmer_table_destroy(wasmer_table_t *table); From 7fa818ea06559dc0f84da38647336d4feaca7e87 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Thu, 21 Feb 2019 11:47:28 -0800 Subject: [PATCH 083/262] Finalize new cache api --- Cargo.lock | 13 +++- lib/clif-backend/src/cache.rs | 4 +- lib/clif-backend/src/lib.rs | 8 ++- lib/clif-backend/src/module.rs | 6 +- lib/runtime-core/Cargo.toml | 1 + lib/runtime-core/src/backend.rs | 10 +-- lib/runtime-core/src/cache.rs | 76 +++++++++++++++------- lib/runtime-core/src/lib.rs | 16 +---- lib/runtime-core/src/module.rs | 19 +----- lib/runtime/src/cache.rs | 112 ++++++++++++++++++-------------- lib/runtime/src/lib.rs | 6 +- 11 files changed, 150 insertions(+), 121 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6d301f57f..2eaad2339 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -81,7 +81,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "block-buffer" -version = "0.7.2" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "block-padding 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -360,6 +360,11 @@ dependencies = [ "unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "hex" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "humantime" version = "1.2.0" @@ -791,7 +796,7 @@ name = "sha2" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "block-buffer 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "block-buffer 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1060,6 +1065,7 @@ dependencies = [ "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)", "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1172,7 +1178,7 @@ dependencies = [ "checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6" "checksum bindgen 0.46.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8f7f7f0701772b17de73e4f5cbcb1dd6926f4706cba4c1ab62c5367f8bdc94e1" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" -"checksum block-buffer 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "509de513cca6d92b6aacf9c61acfe7eaa160837323a81068d690cc1f8e5740da" +"checksum block-buffer 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49665c62e0e700857531fa5d3763e91b539ff1abeebd56808d378b495870d60d" "checksum block-padding 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d75255892aeb580d3c566f213a2b6fdc1c66667839f45719ee1d30ebf2aea591" "checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" "checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" @@ -1206,6 +1212,7 @@ dependencies = [ "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" "checksum hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3bae29b6653b3412c2e71e9d486db9f9df5d701941d86683005efb9f2d28e3da" "checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" +"checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" "checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114" "checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d" "checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" diff --git a/lib/clif-backend/src/cache.rs b/lib/clif-backend/src/cache.rs index 84db980b0..3c38a5266 100644 --- a/lib/clif-backend/src/cache.rs +++ b/lib/clif-backend/src/cache.rs @@ -4,7 +4,7 @@ use hashbrown::HashMap; use std::sync::Arc; use wasmer_runtime_core::{ backend::{sys::Memory, CacheGen}, - cache::{Cache, Error}, + cache::{Error, SerializedCache}, module::{ModuleInfo, ModuleInner}, structures::Map, types::{LocalFuncIndex, SigIndex}, @@ -61,7 +61,7 @@ pub struct BackendCache { } impl BackendCache { - pub fn from_cache(cache: Cache) -> Result<(ModuleInfo, Memory, Self), Error> { + pub fn from_cache(cache: SerializedCache) -> Result<(ModuleInfo, Memory, Self), Error> { let (info, backend_data, compiled_code) = cache.consume(); let backend_cache = diff --git a/lib/clif-backend/src/lib.rs b/lib/clif-backend/src/lib.rs index 8d756420e..daef34c5d 100644 --- a/lib/clif-backend/src/lib.rs +++ b/lib/clif-backend/src/lib.rs @@ -14,7 +14,7 @@ use cranelift_codegen::{ }; use target_lexicon::Triple; -use wasmer_runtime_core::cache::{Cache, Error as CacheError}; +use wasmer_runtime_core::cache::{Error as CacheError, SerializedCache}; use wasmer_runtime_core::{ backend::{Compiler, Token}, error::{CompileError, CompileResult}, @@ -53,7 +53,11 @@ impl Compiler for CraneliftCompiler { /// Create a wasmer Module from an already-compiled cache. - unsafe fn from_cache(&self, cache: Cache, _: Token) -> Result { + unsafe fn from_cache( + &self, + cache: SerializedCache, + _: Token, + ) -> Result { module::Module::from_cache(cache) } diff --git a/lib/clif-backend/src/module.rs b/lib/clif-backend/src/module.rs index 0d0c66d7c..002d5185c 100644 --- a/lib/clif-backend/src/module.rs +++ b/lib/clif-backend/src/module.rs @@ -7,7 +7,7 @@ use cranelift_wasm; use hashbrown::HashMap; use std::sync::Arc; -use wasmer_runtime_core::cache::{Cache, Error as CacheError}; +use wasmer_runtime_core::cache::{Error as CacheError, SerializedCache, WasmHash}; use wasmer_runtime_core::{ backend::Backend, @@ -19,8 +19,6 @@ use wasmer_runtime_core::{ }, }; -use wasmer_runtime_core::module::WasmHash; - /// This contains all of the items in a `ModuleInner` except the `func_resolver`. pub struct Module { pub info: ModuleInfo, @@ -90,7 +88,7 @@ impl Module { }) } - pub fn from_cache(cache: Cache) -> Result { + pub fn from_cache(cache: SerializedCache) -> Result { let (info, compiled_code, backend_cache) = BackendCache::from_cache(cache)?; let (func_resolver_builder, trampolines, handler_data) = diff --git a/lib/runtime-core/Cargo.toml b/lib/runtime-core/Cargo.toml index 4781751af..75e49840c 100644 --- a/lib/runtime-core/Cargo.toml +++ b/lib/runtime-core/Cargo.toml @@ -16,6 +16,7 @@ lazy_static = "1.2.0" indexmap = "1.0.2" errno = "0.2.4" libc = "0.2.48" +hex = "0.3.2" # Dependencies for caching. [dependencies.serde] diff --git a/lib/runtime-core/src/backend.rs b/lib/runtime-core/src/backend.rs index e490b5e3e..ab7c27d53 100644 --- a/lib/runtime-core/src/backend.rs +++ b/lib/runtime-core/src/backend.rs @@ -8,14 +8,12 @@ use crate::{ }; use crate::{ - cache::{Cache, Error as CacheError}, + cache::{Error as CacheError, SerializedCache}, module::ModuleInfo, sys::Memory, }; use std::ptr::NonNull; -use std::sync::Arc; - pub mod sys { pub use crate::sys::*; } @@ -44,7 +42,11 @@ pub trait Compiler { /// be called from inside the runtime. fn compile(&self, wasm: &[u8], _: Token) -> CompileResult; - unsafe fn from_cache(&self, cache: Cache, _: Token) -> Result; + unsafe fn from_cache( + &self, + cache: SerializedCache, + _: Token, + ) -> Result; } /// The functionality exposed by this trait is expected to be used diff --git a/lib/runtime-core/src/cache.rs b/lib/runtime-core/src/cache.rs index d49dd4215..34c09c3aa 100644 --- a/lib/runtime-core/src/cache.rs +++ b/lib/runtime-core/src/cache.rs @@ -1,4 +1,7 @@ -use crate::{module::ModuleInfo, sys::Memory}; +use crate::{ + module::{Module, ModuleInfo}, + sys::Memory, +}; use memmap::Mmap; use serde_bench::{deserialize, serialize}; use sha2::{Digest, Sha256}; @@ -8,7 +11,6 @@ use std::{ mem, path::Path, slice, - sync::Arc, }; #[derive(Debug)] @@ -27,23 +29,43 @@ pub enum Error { InvalidatedCache, } +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub struct WasmHash([u8; 32]); + +impl WasmHash { + pub fn generate(wasm: &[u8]) -> Self { + let mut array = [0u8; 32]; + array.copy_from_slice(Sha256::digest(wasm).as_slice()); + WasmHash(array) + } + + pub fn encode(self) -> String { + hex::encode(self.0) + } + + pub(crate) fn into_array(self) -> [u8; 32] { + self.0 + } +} + const CURRENT_CACHE_VERSION: u64 = 0; /// The header of a cache file. #[repr(C, packed)] -struct CacheHeader { +struct SerializedCacheHeader { magic: [u8; 8], // [W, A, S, M, E, R, \0, \0] version: u64, data_len: u64, wasm_hash: [u8; 32], // Sha256 of the wasm in binary format. } -impl CacheHeader { - pub fn read_from_slice(buffer: &[u8]) -> Result<(&CacheHeader, &[u8]), Error> { - if buffer.len() >= mem::size_of::() { +impl SerializedCacheHeader { + pub fn read_from_slice(buffer: &[u8]) -> Result<(&Self, &[u8]), Error> { + if buffer.len() >= mem::size_of::() { if &buffer[..8] == "WASMER\0\0".as_bytes() { - let (header_slice, body_slice) = buffer.split_at(mem::size_of::()); - let header = unsafe { &*(header_slice.as_ptr() as *const CacheHeader) }; + let (header_slice, body_slice) = + buffer.split_at(mem::size_of::()); + let header = unsafe { &*(header_slice.as_ptr() as *const SerializedCacheHeader) }; if header.version == CURRENT_CACHE_VERSION { Ok((header, body_slice)) @@ -59,31 +81,31 @@ impl CacheHeader { } pub fn as_slice(&self) -> &[u8] { - let ptr = self as *const CacheHeader as *const u8; - unsafe { slice::from_raw_parts(ptr, mem::size_of::()) } + let ptr = self as *const SerializedCacheHeader as *const u8; + unsafe { slice::from_raw_parts(ptr, mem::size_of::()) } } } #[derive(Serialize, Deserialize)] -struct CacheInner { +struct SerializedCacheInner { info: Box, #[serde(with = "serde_bytes")] backend_metadata: Box<[u8]>, compiled_code: Memory, } -pub struct Cache { - inner: CacheInner, +pub struct SerializedCache { + inner: SerializedCacheInner, } -impl Cache { +impl SerializedCache { pub(crate) fn from_parts( info: Box, backend_metadata: Box<[u8]>, compiled_code: Memory, ) -> Self { Self { - inner: CacheInner { + inner: SerializedCacheInner { info, backend_metadata, compiled_code, @@ -91,7 +113,7 @@ impl Cache { } } - pub fn open

(path: P) -> Result + pub fn open

(path: P) -> Result where P: AsRef, { @@ -99,12 +121,12 @@ impl Cache { let mmap = unsafe { Mmap::map(&file).map_err(|e| Error::IoError(e))? }; - let (header, body_slice) = CacheHeader::read_from_slice(&mmap[..])?; + let (_header, body_slice) = SerializedCacheHeader::read_from_slice(&mmap[..])?; let inner = deserialize(body_slice).map_err(|e| Error::DeserializeError(format!("{:#?}", e)))?; - Ok(Cache { inner }) + Ok(SerializedCache { inner }) } pub fn info(&self) -> &ModuleInfo { @@ -132,8 +154,10 @@ impl Cache { let data_len = buffer.len() as u64; - file.seek(SeekFrom::Start(mem::size_of::() as u64)) - .map_err(|e| Error::IoError(e))?; + file.seek(SeekFrom::Start( + mem::size_of::() as u64 + )) + .map_err(|e| Error::IoError(e))?; file.write(buffer.as_slice()) .map_err(|e| Error::IoError(e))?; @@ -143,7 +167,7 @@ impl Cache { let wasm_hash = self.inner.info.wasm_hash.into_array(); - let cache_header = CacheHeader { + let cache_header = SerializedCacheHeader { magic: [ 'W' as u8, 'A' as u8, 'S' as u8, 'M' as u8, 'E' as u8, 'R' as u8, 0, 0, ], @@ -159,8 +183,10 @@ impl Cache { } } -pub fn hash_data(data: &[u8]) -> [u8; 32] { - let mut array = [0u8; 32]; - array.copy_from_slice(Sha256::digest(data).as_slice()); - array +pub trait Cache { + type LoadError; + type StoreError; + + unsafe fn load(&self, key: WasmHash) -> Result; + fn store(&mut self, module: Module) -> Result; } diff --git a/lib/runtime-core/src/lib.rs b/lib/runtime-core/src/lib.rs index 7025acf5a..0e42531b8 100644 --- a/lib/runtime-core/src/lib.rs +++ b/lib/runtime-core/src/lib.rs @@ -43,7 +43,7 @@ pub use self::module::Module; pub use self::typed_func::Func; use std::sync::Arc; -use self::cache::{Cache, Error as CacheError}; +use self::cache::{Error as CacheError, SerializedCache}; pub mod prelude { pub use crate::import::{ImportObject, Namespace}; @@ -88,20 +88,8 @@ pub fn validate(wasm: &[u8]) -> bool { } } -// -// pub fn compile_to_cache_with( -// wasm: &[u8], -// compiler: &dyn backend::Compiler, -// ) -> CompileResult { -// let token = backend::Token::generate(); -// let (info, backend_metadata, compiled_code) = -// compiler.compile_to_backend_cache_data(wasm, token)?; - -// Ok(Cache::new(wasm, info, backend_metadata, compiled_code)) -// } - pub unsafe fn load_cache_with( - cache: Cache, + cache: SerializedCache, compiler: &dyn backend::Compiler, ) -> std::result::Result { let token = backend::Token::generate(); diff --git a/lib/runtime-core/src/module.rs b/lib/runtime-core/src/module.rs index 5cb1b5b21..43deb7c4d 100644 --- a/lib/runtime-core/src/module.rs +++ b/lib/runtime-core/src/module.rs @@ -1,6 +1,6 @@ use crate::{ backend::{Backend, FuncResolver, ProtectedCaller}, - cache::{Cache, Error as CacheError}, + cache::{Error as CacheError, SerializedCache, WasmHash}, error, import::ImportObject, structures::{Map, TypedIndex}, @@ -60,19 +60,6 @@ pub struct ModuleInfo { pub wasm_hash: WasmHash, } -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub struct WasmHash([u8; 32]); - -impl WasmHash { - pub fn generate(wasm: &[u8]) -> Self { - WasmHash(crate::cache::hash_data(wasm)) - } - - pub(crate) fn into_array(self) -> [u8; 32] { - self.0 - } -} - /// A compiled WebAssembly module. /// /// `Module` is returned by the [`compile`] and @@ -119,9 +106,9 @@ impl Module { Instance::new(Arc::clone(&self.inner), import_object) } - pub fn cache(&self) -> Result { + pub fn cache(&self) -> Result { let (info, backend_metadata, code) = self.inner.cache_gen.generate_cache(&self.inner)?; - Ok(Cache::from_parts(info, backend_metadata, code)) + Ok(SerializedCache::from_parts(info, backend_metadata, code)) } pub fn info(&self) -> &ModuleInfo { diff --git a/lib/runtime/src/cache.rs b/lib/runtime/src/cache.rs index 01bf90c25..2fbf7f47b 100644 --- a/lib/runtime/src/cache.rs +++ b/lib/runtime/src/cache.rs @@ -1,46 +1,9 @@ use crate::Module; -use std::path::Path; -use wasmer_runtime_core::cache::{hash_data, Cache as CoreCache}; -use wasmer_runtime_core::module::WasmHash; +use std::{fs::create_dir_all, io, path::PathBuf}; -pub use wasmer_runtime_core::cache::Error; +pub use wasmer_runtime_core::cache::{Cache, WasmHash}; +use wasmer_runtime_core::cache::{Error as CacheError, SerializedCache}; -// /// On-disk storage of compiled WebAssembly. -// /// -// /// A `Cache` can be used to quickly reload already -// /// compiled WebAssembly from a previous execution -// /// during which the wasm was explicitly compiled -// /// as a `Cache`. -// /// -// /// # Usage: -// /// -// /// ``` -// /// use wasmer_runtime::{compile_cache, Cache}; -// /// -// /// # use wasmer_runtime::error::{CompileResult, CacheError}; -// /// # fn make_cache(wasm: &[u8]) -> CompileResult<()> { -// /// // Make a cache. -// /// let cache = compile_cache(wasm)?; -// /// -// /// # Ok(()) -// /// # } -// /// # fn usage_cache(cache: Cache) -> Result<(), CacheError> { -// /// // Store the cache in a file. -// /// cache.store("some_cache_file")?; -// /// -// /// // Load the cache. -// /// let cache = Cache::load("some_cache_file")?; -// /// let module = unsafe { cache.into_module()? }; -// /// # Ok(()) -// /// # } -// /// ``` -// /// -// /// # Performance Characteristics: -// /// -// /// Loading caches from files has been optimized for latency. -// /// There is still more work to do that will reduce -// /// loading time, especially for very large modules, -// /// but it will require signifigant internal work. // /// // /// # Drawbacks: // /// @@ -128,11 +91,66 @@ pub use wasmer_runtime_core::cache::Error; // } // } -pub trait Cache { - type Key; - type LoadError; - type StoreError; - - unsafe fn load(&self, key: Self::Key) -> Result; - fn store(&mut self, module: Module) -> Result; +pub struct FSCache { + path: PathBuf, +} + +impl FSCache { + pub fn open>(path: P) -> io::Result { + let path: PathBuf = path.into(); + + if path.exists() { + let metadata = path.metadata()?; + if metadata.is_dir() { + if !metadata.permissions().readonly() { + Ok(Self { path }) + } else { + // This directory is readonly. + Err(io::Error::new( + io::ErrorKind::PermissionDenied, + format!("the supplied path is readonly: {}", path.display()), + )) + } + } else { + // This path points to a file. + Err(io::Error::new( + io::ErrorKind::PermissionDenied, + format!( + "the supplied path already points to a file: {}", + path.display() + ), + )) + } + } else { + // Create the directory and any parent directories if they don't yet exist. + create_dir_all(&path)?; + Ok(Self { path }) + } + } +} + +impl Cache for FSCache { + type LoadError = CacheError; + type StoreError = CacheError; + + unsafe fn load(&self, key: WasmHash) -> Result { + let filename = key.encode(); + let mut new_path_buf = self.path.clone(); + new_path_buf.push(filename); + + let serialized_cache = SerializedCache::open(new_path_buf)?; + wasmer_runtime_core::load_cache_with(serialized_cache, super::default_compiler()) + } + + fn store(&mut self, module: Module) -> Result { + let key = module.info().wasm_hash; + let filename = key.encode(); + let mut new_path_buf = self.path.clone(); + new_path_buf.push(filename); + + let serialized_cache = module.cache()?; + serialized_cache.store(new_path_buf)?; + + Ok(key) + } } diff --git a/lib/runtime/src/lib.rs b/lib/runtime/src/lib.rs index 48a4c27f5..012bdb593 100644 --- a/lib/runtime/src/lib.rs +++ b/lib/runtime/src/lib.rs @@ -99,7 +99,7 @@ pub mod wasm { } pub mod error { - pub use super::cache::Error as CacheError; + pub use wasmer_runtime_core::cache::Error as CacheError; pub use wasmer_runtime_core::error::*; } @@ -108,12 +108,10 @@ pub mod units { pub use wasmer_runtime_core::units::{Bytes, Pages}; } -mod cache; +pub mod cache; use wasmer_runtime_core::backend::Compiler; -pub use self::cache::Cache; - /// Compile WebAssembly binary code into a [`Module`]. /// This function is useful if it is necessary to /// compile a module before it can be instantiated From f18da0690e7c1306dffd9ef0571be372c426f412 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Thu, 21 Feb 2019 11:54:39 -0800 Subject: [PATCH 084/262] Fix test compilation --- lib/runtime-core/src/vm.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/runtime-core/src/vm.rs b/lib/runtime-core/src/vm.rs index 4d6e6880d..6646b3271 100644 --- a/lib/runtime-core/src/vm.rs +++ b/lib/runtime-core/src/vm.rs @@ -497,9 +497,8 @@ mod vm_ctx_tests { use crate::backend::{ sys::Memory, Backend, CacheGen, FuncResolver, ProtectedCaller, Token, UserTrapper, }; - use crate::cache::Error as CacheError; + use crate::cache::{Error as CacheError, WashHash}; use crate::error::RuntimeResult; - use crate::module::WasmHash; use crate::types::{FuncIndex, LocalFuncIndex, Value}; use hashbrown::HashMap; use std::ptr::NonNull; From c78d4a8674d9fb147ba12f0a48e1f1b35598098c Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Thu, 21 Feb 2019 12:54:53 -0800 Subject: [PATCH 085/262] Fix test compilation 2 --- lib/runtime-core/src/vm.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/runtime-core/src/vm.rs b/lib/runtime-core/src/vm.rs index 6646b3271..ab386401b 100644 --- a/lib/runtime-core/src/vm.rs +++ b/lib/runtime-core/src/vm.rs @@ -497,7 +497,7 @@ mod vm_ctx_tests { use crate::backend::{ sys::Memory, Backend, CacheGen, FuncResolver, ProtectedCaller, Token, UserTrapper, }; - use crate::cache::{Error as CacheError, WashHash}; + use crate::cache::{Error as CacheError, WasmHash}; use crate::error::RuntimeResult; use crate::types::{FuncIndex, LocalFuncIndex, Value}; use hashbrown::HashMap; From f9d7d56195a487331cd1ae6ad76f2ea3ac0ac8f6 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Thu, 21 Feb 2019 14:00:33 -0800 Subject: [PATCH 086/262] Add documentation and make load safe --- lib/runtime-core/src/cache.rs | 23 ++++++++++++++++++- lib/runtime/src/cache.rs | 42 ++++++++++++++++++++++++++++++----- 2 files changed, 58 insertions(+), 7 deletions(-) diff --git a/lib/runtime-core/src/cache.rs b/lib/runtime-core/src/cache.rs index 34c09c3aa..2e9b29250 100644 --- a/lib/runtime-core/src/cache.rs +++ b/lib/runtime-core/src/cache.rs @@ -29,16 +29,34 @@ pub enum Error { InvalidatedCache, } +impl From for Error { + fn from(io_err: io::Error) -> Self { + Error::IoError(io_err) + } +} + +/// The hash of a wasm module. +/// +/// Used as a key when loading and storing modules in a [`Cache`]. +/// +/// [`Cache`]: trait.Cache.html #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct WasmHash([u8; 32]); impl WasmHash { + /// Hash a wasm module. + /// + /// # Note: + /// This does no verification that the supplied data + /// is, in fact, a wasm module. pub fn generate(wasm: &[u8]) -> Self { let mut array = [0u8; 32]; array.copy_from_slice(Sha256::digest(wasm).as_slice()); WasmHash(array) } + /// Create the hexadecimal representation of the + /// stored hash. pub fn encode(self) -> String { hex::encode(self.0) } @@ -183,10 +201,13 @@ impl SerializedCache { } } +/// A generic cache for storing and loading compiled wasm modules. +/// +/// The `wasmer-runtime` supplies a naive `FileSystemCache` api. pub trait Cache { type LoadError; type StoreError; - unsafe fn load(&self, key: WasmHash) -> Result; + fn load(&self, key: WasmHash) -> Result; fn store(&mut self, module: Module) -> Result; } diff --git a/lib/runtime/src/cache.rs b/lib/runtime/src/cache.rs index 2fbf7f47b..e6664d046 100644 --- a/lib/runtime/src/cache.rs +++ b/lib/runtime/src/cache.rs @@ -91,12 +91,42 @@ use wasmer_runtime_core::cache::{Error as CacheError, SerializedCache}; // } // } -pub struct FSCache { +/// Representation of a directory that contains compiled wasm artifacts. +/// +/// The `FileSystemCache` type implements the [`Cache`] trait, which allows it to be used +/// generically when some sort of cache is required. +/// +/// [`Cache`]: trait.Cache.html +/// +/// # Usage: +/// +/// ```rust +/// use wasmer_runtime::cache::{Cache, FileSystemCache}; +/// +/// # use wasmer_runtime::{Module, error::CacheError}; +/// fn store_and_load_module(module: Module) -> Result { +/// // Create a new file system cache. +/// // This is unsafe because we can't ensure that the artifact wasn't +/// // corrupted or tampered with. +/// let mut fs_cache = unsafe { FileSystemCache::new("some/directory/goes/here")? }; +/// // Store a module into the cache. +/// // The returned `key` is equivalent to `module.info().wasm_hash`. +/// let key = fs_cache.store(module)?; +/// // Load the module back from the cache with the `key`. +/// fs_cache.load(key) +/// } +/// ``` +pub struct FileSystemCache { path: PathBuf, } -impl FSCache { - pub fn open>(path: P) -> io::Result { +impl FileSystemCache { + /// Construct a new `FileSystemCache` around the specified directory. + /// + /// # Note: + /// This method is unsafe because there's no way to ensure the artifacts + /// stored in this cache haven't been corrupted or tampered with. + pub unsafe fn new>(path: P) -> io::Result { let path: PathBuf = path.into(); if path.exists() { @@ -129,17 +159,17 @@ impl FSCache { } } -impl Cache for FSCache { +impl Cache for FileSystemCache { type LoadError = CacheError; type StoreError = CacheError; - unsafe fn load(&self, key: WasmHash) -> Result { + fn load(&self, key: WasmHash) -> Result { let filename = key.encode(); let mut new_path_buf = self.path.clone(); new_path_buf.push(filename); let serialized_cache = SerializedCache::open(new_path_buf)?; - wasmer_runtime_core::load_cache_with(serialized_cache, super::default_compiler()) + unsafe { wasmer_runtime_core::load_cache_with(serialized_cache, super::default_compiler()) } } fn store(&mut self, module: Module) -> Result { From 244308374c94fc6020d8c1f9e0b01a3875d81206 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Thu, 21 Feb 2019 15:27:20 -0800 Subject: [PATCH 087/262] Fix formatting --- lib/runtime-core/src/cache.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/runtime-core/src/cache.rs b/lib/runtime-core/src/cache.rs index 2e9b29250..a58cc05f1 100644 --- a/lib/runtime-core/src/cache.rs +++ b/lib/runtime-core/src/cache.rs @@ -36,17 +36,17 @@ impl From for Error { } /// The hash of a wasm module. -/// +/// /// Used as a key when loading and storing modules in a [`Cache`]. -/// +/// /// [`Cache`]: trait.Cache.html #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct WasmHash([u8; 32]); impl WasmHash { /// Hash a wasm module. - /// - /// # Note: + /// + /// # Note: /// This does no verification that the supplied data /// is, in fact, a wasm module. pub fn generate(wasm: &[u8]) -> Self { @@ -202,7 +202,7 @@ impl SerializedCache { } /// A generic cache for storing and loading compiled wasm modules. -/// +/// /// The `wasmer-runtime` supplies a naive `FileSystemCache` api. pub trait Cache { type LoadError; From 64eadad7fa78390e729f88f034c90d1eef3941f4 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Thu, 21 Feb 2019 15:31:20 -0800 Subject: [PATCH 088/262] Fix review comments --- lib/runtime/src/cache.rs | 87 ---------------------------------------- lib/runtime/src/lib.rs | 24 ----------- 2 files changed, 111 deletions(-) diff --git a/lib/runtime/src/cache.rs b/lib/runtime/src/cache.rs index e6664d046..b8f261c95 100644 --- a/lib/runtime/src/cache.rs +++ b/lib/runtime/src/cache.rs @@ -4,93 +4,6 @@ use std::{fs::create_dir_all, io, path::PathBuf}; pub use wasmer_runtime_core::cache::{Cache, WasmHash}; use wasmer_runtime_core::cache::{Error as CacheError, SerializedCache}; -// /// -// /// # Drawbacks: -// /// -// /// Due to internal shortcomings, you cannot convert -// /// a module into a `Cache`. This means that compiling -// /// into a `Cache` and then converting into a module -// /// has more overhead than directly compiling -// /// into a [`Module`]. -// /// -// /// [`Module`]: struct.Module.html -// pub struct Cache(pub(crate) CoreCache); - -// impl Cache { -// /// Load a `Cache` from the file specified by `path`. -// /// -// /// # Usage: -// /// -// /// ``` -// /// use wasmer_runtime::Cache; -// /// # use wasmer_runtime::error::CacheError; -// /// -// /// # fn load_cache() -> Result<(), CacheError> { -// /// let cache = Cache::load("some_file.cache")?; -// /// # Ok(()) -// /// # } -// /// ``` -// pub fn load>(path: P) -> Result { -// CoreCache::open(path).map(|core_cache| Cache(core_cache)) -// } - -// /// Convert a `Cache` into a [`Module`]. -// /// -// /// [`Module`]: struct.Module.html -// /// -// /// # Usage: -// /// -// /// ``` -// /// use wasmer_runtime::Cache; -// /// -// /// # use wasmer_runtime::error::CacheError; -// /// # fn cache2module(cache: Cache) -> Result<(), CacheError> { -// /// let module = unsafe { cache.into_module()? }; -// /// # Ok(()) -// /// # } -// /// ``` -// /// -// /// # Notes: -// /// -// /// This method is unsafe because the runtime cannot confirm -// /// that this cache was not tampered with or corrupted. -// pub unsafe fn into_module(self) -> Result { -// let default_compiler = super::default_compiler(); - -// wasmer_runtime_core::load_cache_with(self.0, default_compiler) -// } - -// /// Compare the Sha256 hash of the wasm this cache was build -// /// from with some other WebAssembly. -// /// -// /// The main use-case for this is invalidating old caches. -// pub fn compare_wasm(&self, wasm: &[u8]) -> bool { -// let param_wasm_hash = hash_data(wasm); -// self.0.wasm_hash() as &[u8] == ¶m_wasm_hash as &[u8] -// } - -// /// Store this cache in a file. -// /// -// /// # Notes: -// /// -// /// If a file exists at the specified path, it will be overwritten. -// /// -// /// # Usage: -// /// -// /// ``` -// /// use wasmer_runtime::Cache; -// /// -// /// # use wasmer_runtime::error::CacheError; -// /// # fn store_cache(cache: Cache) -> Result<(), CacheError> { -// /// cache.store("some_file.cache")?; -// /// # Ok(()) -// /// # } -// /// ``` -// pub fn store>(&self, path: P) -> Result<(), Error> { -// self.0.store(path) -// } -// } - /// Representation of a directory that contains compiled wasm artifacts. /// /// The `FileSystemCache` type implements the [`Cache`] trait, which allows it to be used diff --git a/lib/runtime/src/lib.rs b/lib/runtime/src/lib.rs index 012bdb593..c7e3b3826 100644 --- a/lib/runtime/src/lib.rs +++ b/lib/runtime/src/lib.rs @@ -152,30 +152,6 @@ pub fn instantiate(wasm: &[u8], import_object: &ImportObject) -> error::Result CompileResult<()> { -// /// let cache = compile_cache(wasm)?; -// /// # Ok(()) -// /// # } -// /// ``` -// pub fn compile_cache(wasm: &[u8]) -> error::CompileResult { -// let default_compiler = default_compiler(); - -// wasmer_runtime_core::compile_to_cache_with(wasm, default_compiler) -// .map(|core_cache| Cache(core_cache)) -// } - fn default_compiler() -> &'static dyn Compiler { use lazy_static::lazy_static; use wasmer_clif_backend::CraneliftCompiler; From 696fd8fce35173fca4c3a6d4cd829b256cff10fb Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Thu, 21 Feb 2019 17:06:49 -0800 Subject: [PATCH 089/262] Update api again and change SerializedCache to Artifact --- Cargo.lock | 2 +- lib/clif-backend/src/cache.rs | 4 +- lib/clif-backend/src/lib.rs | 8 +-- lib/clif-backend/src/module.rs | 4 +- lib/runtime-core/Cargo.toml | 2 - lib/runtime-core/src/backend.rs | 8 +-- lib/runtime-core/src/cache.rs | 122 ++++++++++++++------------------ lib/runtime-core/src/lib.rs | 4 +- lib/runtime-core/src/module.rs | 6 +- lib/runtime/Cargo.toml | 1 + lib/runtime/src/cache.rs | 20 ++++-- 11 files changed, 84 insertions(+), 97 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ebfe7ac0d..aa14e70be 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1101,6 +1101,7 @@ name = "wasmer-runtime" version = "0.1.4" dependencies = [ "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-clif-backend 0.1.2", "wasmer-runtime-core 0.1.2", ] @@ -1126,7 +1127,6 @@ dependencies = [ "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "nix 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "page_size 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/lib/clif-backend/src/cache.rs b/lib/clif-backend/src/cache.rs index 3c38a5266..5af708703 100644 --- a/lib/clif-backend/src/cache.rs +++ b/lib/clif-backend/src/cache.rs @@ -4,7 +4,7 @@ use hashbrown::HashMap; use std::sync::Arc; use wasmer_runtime_core::{ backend::{sys::Memory, CacheGen}, - cache::{Error, SerializedCache}, + cache::{Artifact, Error}, module::{ModuleInfo, ModuleInner}, structures::Map, types::{LocalFuncIndex, SigIndex}, @@ -61,7 +61,7 @@ pub struct BackendCache { } impl BackendCache { - pub fn from_cache(cache: SerializedCache) -> Result<(ModuleInfo, Memory, Self), Error> { + pub fn from_cache(cache: Artifact) -> Result<(ModuleInfo, Memory, Self), Error> { let (info, backend_data, compiled_code) = cache.consume(); let backend_cache = diff --git a/lib/clif-backend/src/lib.rs b/lib/clif-backend/src/lib.rs index daef34c5d..df2e4e208 100644 --- a/lib/clif-backend/src/lib.rs +++ b/lib/clif-backend/src/lib.rs @@ -14,7 +14,7 @@ use cranelift_codegen::{ }; use target_lexicon::Triple; -use wasmer_runtime_core::cache::{Error as CacheError, SerializedCache}; +use wasmer_runtime_core::cache::{Artifact, Error as CacheError}; use wasmer_runtime_core::{ backend::{Compiler, Token}, error::{CompileError, CompileResult}, @@ -53,11 +53,7 @@ impl Compiler for CraneliftCompiler { /// Create a wasmer Module from an already-compiled cache. - unsafe fn from_cache( - &self, - cache: SerializedCache, - _: Token, - ) -> Result { + unsafe fn from_cache(&self, cache: Artifact, _: Token) -> Result { module::Module::from_cache(cache) } diff --git a/lib/clif-backend/src/module.rs b/lib/clif-backend/src/module.rs index 002d5185c..6f95ea828 100644 --- a/lib/clif-backend/src/module.rs +++ b/lib/clif-backend/src/module.rs @@ -7,7 +7,7 @@ use cranelift_wasm; use hashbrown::HashMap; use std::sync::Arc; -use wasmer_runtime_core::cache::{Error as CacheError, SerializedCache, WasmHash}; +use wasmer_runtime_core::cache::{Artifact, Error as CacheError, WasmHash}; use wasmer_runtime_core::{ backend::Backend, @@ -88,7 +88,7 @@ impl Module { }) } - pub fn from_cache(cache: SerializedCache) -> Result { + pub fn from_cache(cache: Artifact) -> Result { let (info, compiled_code, backend_cache) = BackendCache::from_cache(cache)?; let (func_resolver_builder, trampolines, handler_data) = diff --git a/lib/runtime-core/Cargo.toml b/lib/runtime-core/Cargo.toml index 75e49840c..03d4e5ae6 100644 --- a/lib/runtime-core/Cargo.toml +++ b/lib/runtime-core/Cargo.toml @@ -28,8 +28,6 @@ version = "1.0" version = "0.10" [dependencies.serde-bench] version = "0.0.7" -[dependencies.memmap] -version = "0.7.0" [dependencies.sha2] version = "0.8.0" [dependencies.hashbrown] diff --git a/lib/runtime-core/src/backend.rs b/lib/runtime-core/src/backend.rs index ab7c27d53..e88383800 100644 --- a/lib/runtime-core/src/backend.rs +++ b/lib/runtime-core/src/backend.rs @@ -8,7 +8,7 @@ use crate::{ }; use crate::{ - cache::{Error as CacheError, SerializedCache}, + cache::{Artifact, Error as CacheError}, module::ModuleInfo, sys::Memory, }; @@ -42,11 +42,7 @@ pub trait Compiler { /// be called from inside the runtime. fn compile(&self, wasm: &[u8], _: Token) -> CompileResult; - unsafe fn from_cache( - &self, - cache: SerializedCache, - _: Token, - ) -> Result; + unsafe fn from_cache(&self, cache: Artifact, _: Token) -> Result; } /// The functionality exposed by this trait is expected to be used diff --git a/lib/runtime-core/src/cache.rs b/lib/runtime-core/src/cache.rs index a58cc05f1..3d894bb09 100644 --- a/lib/runtime-core/src/cache.rs +++ b/lib/runtime-core/src/cache.rs @@ -2,16 +2,8 @@ use crate::{ module::{Module, ModuleInfo}, sys::Memory, }; -use memmap::Mmap; -use serde_bench::{deserialize, serialize}; use sha2::{Digest, Sha256}; -use std::{ - fs::File, - io::{self, Seek, SeekFrom, Write}, - mem, - path::Path, - slice, -}; +use std::{io, mem, slice}; #[derive(Debug)] pub enum InvalidFileType { @@ -67,23 +59,43 @@ impl WasmHash { } const CURRENT_CACHE_VERSION: u64 = 0; +static WASMER_CACHE_MAGIC: [u8; 8] = *b"WASMER\0\0"; /// The header of a cache file. #[repr(C, packed)] -struct SerializedCacheHeader { +struct ArtifactHeader { magic: [u8; 8], // [W, A, S, M, E, R, \0, \0] version: u64, data_len: u64, wasm_hash: [u8; 32], // Sha256 of the wasm in binary format. } -impl SerializedCacheHeader { +impl ArtifactHeader { pub fn read_from_slice(buffer: &[u8]) -> Result<(&Self, &[u8]), Error> { - if buffer.len() >= mem::size_of::() { - if &buffer[..8] == "WASMER\0\0".as_bytes() { + if buffer.len() >= mem::size_of::() { + if &buffer[..8] == &WASMER_CACHE_MAGIC { + let (header_slice, body_slice) = buffer.split_at(mem::size_of::()); + let header = unsafe { &*(header_slice.as_ptr() as *const ArtifactHeader) }; + + if header.version == CURRENT_CACHE_VERSION { + Ok((header, body_slice)) + } else { + Err(Error::InvalidatedCache) + } + } else { + Err(Error::InvalidFile(InvalidFileType::InvalidMagic)) + } + } else { + Err(Error::InvalidFile(InvalidFileType::InvalidSize)) + } + } + + pub fn read_from_slice_mut(buffer: &mut [u8]) -> Result<(&mut Self, &mut [u8]), Error> { + if buffer.len() >= mem::size_of::() { + if &buffer[..8] == &WASMER_CACHE_MAGIC { let (header_slice, body_slice) = - buffer.split_at(mem::size_of::()); - let header = unsafe { &*(header_slice.as_ptr() as *const SerializedCacheHeader) }; + buffer.split_at_mut(mem::size_of::()); + let header = unsafe { &mut *(header_slice.as_ptr() as *mut ArtifactHeader) }; if header.version == CURRENT_CACHE_VERSION { Ok((header, body_slice)) @@ -99,31 +111,31 @@ impl SerializedCacheHeader { } pub fn as_slice(&self) -> &[u8] { - let ptr = self as *const SerializedCacheHeader as *const u8; - unsafe { slice::from_raw_parts(ptr, mem::size_of::()) } + let ptr = self as *const ArtifactHeader as *const u8; + unsafe { slice::from_raw_parts(ptr, mem::size_of::()) } } } #[derive(Serialize, Deserialize)] -struct SerializedCacheInner { +struct ArtifactInner { info: Box, #[serde(with = "serde_bytes")] backend_metadata: Box<[u8]>, compiled_code: Memory, } -pub struct SerializedCache { - inner: SerializedCacheInner, +pub struct Artifact { + inner: ArtifactInner, } -impl SerializedCache { +impl Artifact { pub(crate) fn from_parts( info: Box, backend_metadata: Box<[u8]>, compiled_code: Memory, ) -> Self { Self { - inner: SerializedCacheInner { + inner: ArtifactInner { info, backend_metadata, compiled_code, @@ -131,20 +143,13 @@ impl SerializedCache { } } - pub fn open

(path: P) -> Result - where - P: AsRef, - { - let file = File::open(path).map_err(|e| Error::IoError(e))?; + pub fn deserialize(bytes: &[u8]) -> Result { + let (_, body_slice) = ArtifactHeader::read_from_slice(bytes)?; - let mmap = unsafe { Mmap::map(&file).map_err(|e| Error::IoError(e))? }; + let inner = serde_bench::deserialize(body_slice) + .map_err(|e| Error::DeserializeError(format!("{:#?}", e)))?; - let (_header, body_slice) = SerializedCacheHeader::read_from_slice(&mmap[..])?; - - let inner = - deserialize(body_slice).map_err(|e| Error::DeserializeError(format!("{:#?}", e)))?; - - Ok(SerializedCache { inner }) + Ok(Artifact { inner }) } pub fn info(&self) -> &ModuleInfo { @@ -160,44 +165,25 @@ impl SerializedCache { ) } - pub fn store

(&self, path: P) -> Result<(), Error> - where - P: AsRef, - { - let mut file = File::create(path).map_err(|e| Error::IoError(e))?; - - let mut buffer = Vec::new(); - - serialize(&mut buffer, &self.inner).map_err(|e| Error::SerializeError(e.to_string()))?; - - let data_len = buffer.len() as u64; - - file.seek(SeekFrom::Start( - mem::size_of::() as u64 - )) - .map_err(|e| Error::IoError(e))?; - - file.write(buffer.as_slice()) - .map_err(|e| Error::IoError(e))?; - - file.seek(SeekFrom::Start(0)) - .map_err(|e| Error::Unknown(e.to_string()))?; - - let wasm_hash = self.inner.info.wasm_hash.into_array(); - - let cache_header = SerializedCacheHeader { - magic: [ - 'W' as u8, 'A' as u8, 'S' as u8, 'M' as u8, 'E' as u8, 'R' as u8, 0, 0, - ], + pub fn serialize(&self) -> Result, Error> { + let cache_header = ArtifactHeader { + magic: WASMER_CACHE_MAGIC, version: CURRENT_CACHE_VERSION, - data_len, - wasm_hash, + data_len: 0, + wasm_hash: self.inner.info.wasm_hash.into_array(), }; - file.write(cache_header.as_slice()) - .map_err(|e| Error::IoError(e))?; + let mut buffer = cache_header.as_slice().to_vec(); - Ok(()) + serde_bench::serialize(&mut buffer, &self.inner) + .map_err(|e| Error::SerializeError(e.to_string()))?; + + let data_len = (buffer.len() - mem::size_of::()) as u64; + + let (header, _) = ArtifactHeader::read_from_slice_mut(&mut buffer)?; + header.data_len = data_len; + + Ok(buffer) } } diff --git a/lib/runtime-core/src/lib.rs b/lib/runtime-core/src/lib.rs index 0e42531b8..663e17534 100644 --- a/lib/runtime-core/src/lib.rs +++ b/lib/runtime-core/src/lib.rs @@ -43,7 +43,7 @@ pub use self::module::Module; pub use self::typed_func::Func; use std::sync::Arc; -use self::cache::{Error as CacheError, SerializedCache}; +use self::cache::{Artifact, Error as CacheError}; pub mod prelude { pub use crate::import::{ImportObject, Namespace}; @@ -89,7 +89,7 @@ pub fn validate(wasm: &[u8]) -> bool { } pub unsafe fn load_cache_with( - cache: SerializedCache, + cache: Artifact, compiler: &dyn backend::Compiler, ) -> std::result::Result { let token = backend::Token::generate(); diff --git a/lib/runtime-core/src/module.rs b/lib/runtime-core/src/module.rs index 43deb7c4d..130082491 100644 --- a/lib/runtime-core/src/module.rs +++ b/lib/runtime-core/src/module.rs @@ -1,6 +1,6 @@ use crate::{ backend::{Backend, FuncResolver, ProtectedCaller}, - cache::{Error as CacheError, SerializedCache, WasmHash}, + cache::{Artifact, Error as CacheError, WasmHash}, error, import::ImportObject, structures::{Map, TypedIndex}, @@ -106,9 +106,9 @@ impl Module { Instance::new(Arc::clone(&self.inner), import_object) } - pub fn cache(&self) -> Result { + pub fn cache(&self) -> Result { let (info, backend_metadata, code) = self.inner.cache_gen.generate_cache(&self.inner)?; - Ok(SerializedCache::from_parts(info, backend_metadata, code)) + Ok(Artifact::from_parts(info, backend_metadata, code)) } pub fn info(&self) -> &ModuleInfo { diff --git a/lib/runtime/Cargo.toml b/lib/runtime/Cargo.toml index 29af96844..e4169a652 100644 --- a/lib/runtime/Cargo.toml +++ b/lib/runtime/Cargo.toml @@ -10,6 +10,7 @@ readme = "README.md" [dependencies] lazy_static = "1.2.0" +memmap = "0.7.0" [dependencies.wasmer-runtime-core] path = "../runtime-core" diff --git a/lib/runtime/src/cache.rs b/lib/runtime/src/cache.rs index b8f261c95..50507d802 100644 --- a/lib/runtime/src/cache.rs +++ b/lib/runtime/src/cache.rs @@ -1,8 +1,13 @@ use crate::Module; -use std::{fs::create_dir_all, io, path::PathBuf}; +use memmap::Mmap; +use std::{ + fs::{create_dir_all, File}, + io::{self, Write}, + path::PathBuf, +}; -pub use wasmer_runtime_core::cache::{Cache, WasmHash}; -use wasmer_runtime_core::cache::{Error as CacheError, SerializedCache}; +use wasmer_runtime_core::cache::Error as CacheError; +pub use wasmer_runtime_core::cache::{Artifact, Cache, WasmHash}; /// Representation of a directory that contains compiled wasm artifacts. /// @@ -80,8 +85,10 @@ impl Cache for FileSystemCache { let filename = key.encode(); let mut new_path_buf = self.path.clone(); new_path_buf.push(filename); + let file = File::open(new_path_buf)?; + let mmap = unsafe { Mmap::map(&file)? }; - let serialized_cache = SerializedCache::open(new_path_buf)?; + let serialized_cache = Artifact::deserialize(&mmap[..])?; unsafe { wasmer_runtime_core::load_cache_with(serialized_cache, super::default_compiler()) } } @@ -92,7 +99,10 @@ impl Cache for FileSystemCache { new_path_buf.push(filename); let serialized_cache = module.cache()?; - serialized_cache.store(new_path_buf)?; + let buffer = serialized_cache.serialize()?; + + let mut file = File::create(new_path_buf)?; + file.write(&buffer)?; Ok(key) } From 199cabd0af05ca55439ab485d75efc9ae8f75054 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Thu, 21 Feb 2019 17:09:32 -0800 Subject: [PATCH 090/262] Add comment about serde feature --- lib/runtime-core/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/runtime-core/Cargo.toml b/lib/runtime-core/Cargo.toml index 03d4e5ae6..cb5a6b4b1 100644 --- a/lib/runtime-core/Cargo.toml +++ b/lib/runtime-core/Cargo.toml @@ -21,6 +21,7 @@ hex = "0.3.2" # Dependencies for caching. [dependencies.serde] version = "1.0" +# This feature is required for serde to support serializing/deserializing reference counted pointers (e.g. Rc and Arc). features = ["rc"] [dependencies.serde_derive] version = "1.0" From f1b190743bcad7331d4fdfe9aaf12800d2eac096 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Thu, 21 Feb 2019 17:11:28 -0800 Subject: [PATCH 091/262] Change file.write to file.write_all --- lib/runtime/src/cache.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/runtime/src/cache.rs b/lib/runtime/src/cache.rs index 50507d802..09a93356b 100644 --- a/lib/runtime/src/cache.rs +++ b/lib/runtime/src/cache.rs @@ -102,7 +102,7 @@ impl Cache for FileSystemCache { let buffer = serialized_cache.serialize()?; let mut file = File::create(new_path_buf)?; - file.write(&buffer)?; + file.write_all(&buffer)?; Ok(key) } From a6d72bdec958cf253b2510f37a4b1e1e31200290 Mon Sep 17 00:00:00 2001 From: Mackenzie Clark Date: Fri, 22 Feb 2019 10:42:38 -0800 Subject: [PATCH 092/262] more emscripten stubs and urandom hack (#199) --- Cargo.lock | 1 + lib/emscripten/Cargo.toml | 3 + lib/emscripten/src/emscripten_target.rs | 390 ++++++++++++++++++++++++ lib/emscripten/src/env/windows/mod.rs | 1 + lib/emscripten/src/lib.rs | 133 ++++++++ lib/emscripten/src/syscalls/mod.rs | 18 +- lib/emscripten/src/syscalls/unix.rs | 17 ++ lib/emscripten/src/syscalls/windows.rs | 52 ++++ lib/runtime-core/src/typed_func.rs | 1 + 9 files changed, 599 insertions(+), 17 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index aa14e70be..4bb493f9b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1090,6 +1090,7 @@ dependencies = [ "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.48 (git+https://github.com/rust-lang/libc)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-clif-backend 0.1.2", diff --git a/lib/emscripten/Cargo.toml b/lib/emscripten/Cargo.toml index 648817eec..ec5e035d6 100644 --- a/lib/emscripten/Cargo.toml +++ b/lib/emscripten/Cargo.toml @@ -15,6 +15,9 @@ libc = { git = "https://github.com/rust-lang/libc" } byteorder = "1" time = "0.1.41" +[target.'cfg(windows)'.dependencies] +rand = "0.6" + [dev-dependencies] wasmer-clif-backend = { path = "../clif-backend", version = "0.1.0" } wabt = "0.7.2" diff --git a/lib/emscripten/src/emscripten_target.rs b/lib/emscripten/src/emscripten_target.rs index 4f831e909..e850757f6 100644 --- a/lib/emscripten/src/emscripten_target.rs +++ b/lib/emscripten/src/emscripten_target.rs @@ -173,3 +173,393 @@ pub fn ___gxx_personality_v0(ctx: &mut Ctx, a: i32, b: i32, c: i32, d: i32, e: i debug!("emscripten::___gxx_personality_v0"); 0 } +// round 2 +pub fn nullFunc_dii(ctx: &mut Ctx, index: i32) { + debug!("emscripten::nullFunc_dii"); +} +pub fn nullFunc_diiii(ctx: &mut Ctx, index: i32) { + debug!("emscripten::nullFunc_diiii"); +} +pub fn nullFunc_iiji(ctx: &mut Ctx, index: i32) { + debug!("emscripten::nullFunc_iiji"); +} +pub fn nullFunc_j(ctx: &mut Ctx, index: i32) { + debug!("emscripten::nullFunc_j"); +} +pub fn nullFunc_jij(ctx: &mut Ctx, index: i32) { + debug!("emscripten::nullFunc_jij"); +} +pub fn nullFunc_jjj(ctx: &mut Ctx, index: i32) { + debug!("emscripten::nullFunc_jjj"); +} +pub fn nullFunc_vd(ctx: &mut Ctx, index: i32) { + debug!("emscripten::nullFunc_vd"); +} +pub fn nullFunc_viiiiiii(ctx: &mut Ctx, index: i32) { + debug!("emscripten::nullFunc_viiiiiii"); +} +pub fn nullFunc_viiiiiiii(ctx: &mut Ctx, index: i32) { + debug!("emscripten::nullFunc_viiiiiiii"); +} +pub fn nullFunc_viiiiiiiii(ctx: &mut Ctx, index: i32) { + debug!("emscripten::nullFunc_viiiiiiiii"); +} +pub fn nullFunc_viiij(ctx: &mut Ctx, index: i32) { + debug!("emscripten::nullFunc_viiij"); +} +pub fn nullFunc_viiijiiii(ctx: &mut Ctx, index: i32) { + debug!("emscripten::nullFunc_viiijiiii"); +} +pub fn nullFunc_viiijiiiiii(ctx: &mut Ctx, index: i32) { + debug!("emscripten::nullFunc_viiijiiiiii"); +} +pub fn nullFunc_viij(ctx: &mut Ctx, index: i32) { + debug!("emscripten::nullFunc_viij"); +} +pub fn nullFunc_viiji(ctx: &mut Ctx, index: i32) { + debug!("emscripten::nullFunc_viiji"); +} +pub fn nullFunc_viijiii(ctx: &mut Ctx, index: i32) { + debug!("emscripten::nullFunc_viijiii"); +} +pub fn nullFunc_viijj(ctx: &mut Ctx, index: i32) { + debug!("emscripten::nullFunc_viijj"); +} +pub fn nullFunc_vij(ctx: &mut Ctx, index: i32) { + debug!("emscripten::nullFunc_vij"); +} +pub fn nullFunc_viji(ctx: &mut Ctx, index: i32) { + debug!("emscripten::nullFunc_viji"); +} +pub fn nullFunc_vijiii(ctx: &mut Ctx, index: i32) { + debug!("emscripten::nullFunc_vijiii"); +} +pub fn nullFunc_vijj(ctx: &mut Ctx, index: i32) { + debug!("emscripten::nullFunc_vijj"); +} +pub fn invoke_dii(ctx: &mut Ctx, index: i32, a1: i32, a2: i32) -> f64 { + debug!("emscripten::invoke_dii"); + if let Some(dyn_call_dii) = &get_emscripten_data(ctx).dyn_call_dii { + dyn_call_dii.call(index, a1, a2).unwrap() + } else { + panic!("dyn_call_dii is set to None"); + } +} +pub fn invoke_diiii(ctx: &mut Ctx, index: i32, a1: i32, a2: i32, a3: i32, a4: i32) -> f64 { + debug!("emscripten::invoke_diiii"); + if let Some(dyn_call_diiii) = &get_emscripten_data(ctx).dyn_call_diiii { + dyn_call_diiii.call(index, a1, a2, a3, a4).unwrap() + } else { + panic!("dyn_call_diiii is set to None"); + } +} +pub fn invoke_iiiii(ctx: &mut Ctx, index: i32, a1: i32, a2: i32, a3: i32, a4: i32) -> i32 { + debug!("emscripten::invoke_iiiii"); + if let Some(dyn_call_iiiii) = &get_emscripten_data(ctx).dyn_call_iiiii { + dyn_call_iiiii.call(index, a1, a2, a3, a4).unwrap() + } else { + panic!("dyn_call_iiiii is set to None"); + } +} +pub fn invoke_iiiiii( + ctx: &mut Ctx, + index: i32, + a1: i32, + a2: i32, + a3: i32, + a4: i32, + a5: i32, +) -> i32 { + debug!("emscripten::invoke_iiiiii"); + if let Some(dyn_call_iiiiii) = &get_emscripten_data(ctx).dyn_call_iiiiii { + dyn_call_iiiiii.call(index, a1, a2, a3, a4, a5).unwrap() + } else { + panic!("dyn_call_iiiiii is set to None"); + } +} +pub fn invoke_vd(ctx: &mut Ctx, index: i32, a1: f64) { + debug!("emscripten::invoke_vd"); + if let Some(dyn_call_vd) = &get_emscripten_data(ctx).dyn_call_vd { + dyn_call_vd.call(index, a1).unwrap(); + } else { + panic!("dyn_call_vd is set to None"); + } +} +pub fn invoke_viiiii(ctx: &mut Ctx, index: i32, a1: i32, a2: i32, a3: i32, a4: i32, a5: i32) { + debug!("emscripten::invoke_viiiii"); + if let Some(dyn_call_viiiii) = &get_emscripten_data(ctx).dyn_call_viiiii { + dyn_call_viiiii.call(index, a1, a2, a3, a4, a5).unwrap(); + } else { + panic!("dyn_call_viiiii is set to None"); + } +} +pub fn invoke_viiiiii( + ctx: &mut Ctx, + index: i32, + a1: i32, + a2: i32, + a3: i32, + a4: i32, + a5: i32, + a6: i32, +) { + debug!("emscripten::invoke_viiiiii"); + if let Some(dyn_call_viiiiii) = &get_emscripten_data(ctx).dyn_call_viiiiii { + dyn_call_viiiiii + .call(index, a1, a2, a3, a4, a5, a6) + .unwrap(); + } else { + panic!("dyn_call_viiiiii is set to None"); + } +} +pub fn invoke_viiiiiii( + ctx: &mut Ctx, + index: i32, + a1: i32, + a2: i32, + a3: i32, + a4: i32, + a5: i32, + a6: i32, + a7: i32, +) { + debug!("emscripten::invoke_viiiiiii"); + if let Some(dyn_call_viiiiiii) = &get_emscripten_data(ctx).dyn_call_viiiiiii { + dyn_call_viiiiiii + .call(index, a1, a2, a3, a4, a5, a6, a7) + .unwrap(); + } else { + panic!("dyn_call_viiiiiii is set to None"); + } +} +pub fn invoke_viiiiiiii( + ctx: &mut Ctx, + index: i32, + a1: i32, + a2: i32, + a3: i32, + a4: i32, + a5: i32, + a6: i32, + a7: i32, + a8: i32, +) { + debug!("emscripten::invoke_viiiiiiii"); + if let Some(dyn_call_viiiiiiii) = &get_emscripten_data(ctx).dyn_call_viiiiiiii { + dyn_call_viiiiiiii + .call(index, a1, a2, a3, a4, a5, a6, a7, a8) + .unwrap(); + } else { + panic!("dyn_call_viiiiiiii is set to None"); + } +} +pub fn invoke_viiiiiiiii( + ctx: &mut Ctx, + index: i32, + a1: i32, + a2: i32, + a3: i32, + a4: i32, + a5: i32, + a6: i32, + a7: i32, + a8: i32, + a9: i32, +) { + debug!("emscripten::invoke_viiiiiiiii"); + if let Some(dyn_call_viiiiiiiii) = &get_emscripten_data(ctx).dyn_call_viiiiiiiii { + dyn_call_viiiiiiiii + .call(index, a1, a2, a3, a4, a5, a6, a7, a8, a9) + .unwrap(); + } else { + panic!("dyn_call_viiiiiiiii is set to None"); + } +} +pub fn invoke_iiji(ctx: &mut Ctx, index: i32, a1: i32, a2: i32, a3: i32, a4: i32) -> i32 { + debug!("emscripten::invoke_iiji"); + if let Some(dyn_call_iiji) = &get_emscripten_data(ctx).dyn_call_iiji { + dyn_call_iiji.call(index, a1, a2, a3, a4).unwrap() + } else { + panic!("dyn_call_iiji is set to None"); + } +} +pub fn invoke_j(ctx: &mut Ctx, index: i32) -> i32 { + debug!("emscripten::invoke_j"); + if let Some(dyn_call_j) = &get_emscripten_data(ctx).dyn_call_j { + dyn_call_j.call(index).unwrap() + } else { + panic!("dyn_call_j is set to None"); + } +} +pub fn invoke_ji(ctx: &mut Ctx, index: i32, a1: i32) -> i32 { + debug!("emscripten::invoke_ji"); + if let Some(dyn_call_ji) = &get_emscripten_data(ctx).dyn_call_ji { + dyn_call_ji.call(index, a1).unwrap() + } else { + panic!("dyn_call_ji is set to None"); + } +} +pub fn invoke_jij(ctx: &mut Ctx, index: i32, a1: i32, a2: i32, a3: i32) -> i32 { + debug!("emscripten::invoke_jij"); + if let Some(dyn_call_jij) = &get_emscripten_data(ctx).dyn_call_jij { + dyn_call_jij.call(index, a1, a2, a3).unwrap() + } else { + panic!("dyn_call_jij is set to None"); + } +} +pub fn invoke_jjj(ctx: &mut Ctx, index: i32, a1: i32, a2: i32, a3: i32, a4: i32) -> i32 { + debug!("emscripten::invoke_jjj"); + if let Some(dyn_call_jjj) = &get_emscripten_data(ctx).dyn_call_jjj { + dyn_call_jjj.call(index, a1, a2, a3, a4).unwrap() + } else { + panic!("dyn_call_jjj is set to None"); + } +} +pub fn invoke_viiij(ctx: &mut Ctx, index: i32, a1: i32, a2: i32, a3: i32, a4: i32, a5: i32) { + debug!("emscripten::invoke_viiij"); + if let Some(dyn_call_viiij) = &get_emscripten_data(ctx).dyn_call_viiij { + dyn_call_viiij.call(index, a1, a2, a3, a4, a5).unwrap(); + } else { + panic!("dyn_call_viiij is set to None"); + } +} +pub fn invoke_viiijiiii( + ctx: &mut Ctx, + index: i32, + a1: i32, + a2: i32, + a3: i32, + a4: i32, + a5: i32, + a6: i32, + a7: i32, + a8: i32, + a9: i32, +) { + debug!("emscripten::invoke_viiijiiii"); + if let Some(dyn_call_viiijiiii) = &get_emscripten_data(ctx).dyn_call_viiijiiii { + dyn_call_viiijiiii + .call(index, a1, a2, a3, a4, a5, a6, a7, a8, a9) + .unwrap(); + } else { + panic!("dyn_call_viiijiiii is set to None"); + } +} +pub fn invoke_viiijiiiiii( + ctx: &mut Ctx, + index: i32, + a1: i32, + a2: i32, + a3: i32, + a4: i32, + a5: i32, + a6: i32, + a7: i32, + a8: i32, + a9: i32, + a10: i32, + a11: i32, +) { + debug!("emscripten::invoke_viiijiiiiii"); + if let Some(dyn_call_viiijiiiiii) = &get_emscripten_data(ctx).dyn_call_viiijiiiiii { + dyn_call_viiijiiiiii + .call(index, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11) + .unwrap(); + } else { + panic!("dyn_call_viiijiiiiii is set to None"); + } +} +pub fn invoke_viij(ctx: &mut Ctx, index: i32, a1: i32, a2: i32, a3: i32, a4: i32) { + debug!("emscripten::invoke_viij"); + if let Some(dyn_call_viij) = &get_emscripten_data(ctx).dyn_call_viij { + dyn_call_viij.call(index, a1, a2, a3, a4).unwrap(); + } else { + panic!("dyn_call_viij is set to None"); + } +} +pub fn invoke_viiji(ctx: &mut Ctx, index: i32, a1: i32, a2: i32, a3: i32, a4: i32, a5: i32) { + debug!("emscripten::invoke_viiji"); + if let Some(dyn_call_viiji) = &get_emscripten_data(ctx).dyn_call_viiji { + dyn_call_viiji.call(index, a1, a2, a3, a4, a5).unwrap(); + } else { + panic!("dyn_call_viiji is set to None"); + } +} +pub fn invoke_viijiii( + ctx: &mut Ctx, + index: i32, + a1: i32, + a2: i32, + a3: i32, + a4: i32, + a5: i32, + a6: i32, + a7: i32, +) { + debug!("emscripten::invoke_viijiii"); + if let Some(dyn_call_viijiii) = &get_emscripten_data(ctx).dyn_call_viijiii { + dyn_call_viijiii + .call(index, a1, a2, a3, a4, a5, a6, a7) + .unwrap(); + } else { + panic!("dyn_call_viijiii is set to None"); + } +} +pub fn invoke_viijj( + ctx: &mut Ctx, + index: i32, + a1: i32, + a2: i32, + a3: i32, + a4: i32, + a5: i32, + a6: i32, +) { + debug!("emscripten::invoke_viijj"); + if let Some(dyn_call_viijj) = &get_emscripten_data(ctx).dyn_call_viijj { + dyn_call_viijj.call(index, a1, a2, a3, a4, a5, a6).unwrap(); + } else { + panic!("dyn_call_viijj is set to None"); + } +} +pub fn invoke_vij(ctx: &mut Ctx, index: i32, a1: i32, a2: i32, a3: i32) { + debug!("emscripten::invoke_vij"); + if let Some(dyn_call_vij) = &get_emscripten_data(ctx).dyn_call_vij { + dyn_call_vij.call(index, a1, a2, a3).unwrap(); + } else { + panic!("dyn_call_vij is set to None"); + } +} +pub fn invoke_viji(ctx: &mut Ctx, index: i32, a1: i32, a2: i32, a3: i32, a4: i32) { + debug!("emscripten::invoke_viji"); + if let Some(dyn_call_viji) = &get_emscripten_data(ctx).dyn_call_viji { + dyn_call_viji.call(index, a1, a2, a3, a4).unwrap() + } else { + panic!("dyn_call_viji is set to None"); + } +} +pub fn invoke_vijiii( + ctx: &mut Ctx, + index: i32, + a1: i32, + a2: i32, + a3: i32, + a4: i32, + a5: i32, + a6: i32, +) { + debug!("emscripten::invoke_vijiii"); + if let Some(dyn_call_vijiii) = &get_emscripten_data(ctx).dyn_call_vijiii { + dyn_call_vijiii.call(index, a1, a2, a3, a4, a5, a6).unwrap() + } else { + panic!("dyn_call_vijiii is set to None"); + } +} +pub fn invoke_vijj(ctx: &mut Ctx, index: i32, a1: i32, a2: i32, a3: i32, a4: i32, a5: i32) { + debug!("emscripten::invoke_vijj"); + if let Some(dyn_call_vijj) = &get_emscripten_data(ctx).dyn_call_vijj { + dyn_call_vijj.call(index, a1, a2, a3, a4, a5).unwrap() + } else { + panic!("dyn_call_vijj is set to None"); + } +} diff --git a/lib/emscripten/src/env/windows/mod.rs b/lib/emscripten/src/env/windows/mod.rs index b4ee6ecff..e95a66ec2 100644 --- a/lib/emscripten/src/env/windows/mod.rs +++ b/lib/emscripten/src/env/windows/mod.rs @@ -7,6 +7,7 @@ use std::os::raw::c_char; use crate::env::call_malloc; use crate::utils::{copy_cstr_into_wasm, read_string_from_wasm}; +use std::ffi::CStr; use wasmer_runtime_core::vm::Ctx; extern "C" { diff --git a/lib/emscripten/src/lib.rs b/lib/emscripten/src/lib.rs index 8911b823d..5a7f008f1 100644 --- a/lib/emscripten/src/lib.rs +++ b/lib/emscripten/src/lib.rs @@ -104,6 +104,35 @@ pub struct EmscriptenData<'a> { pub dyn_call_vii: Option>, pub dyn_call_viii: Option>, pub dyn_call_viiii: Option>, + + // round 2 + pub dyn_call_dii: Option>, + pub dyn_call_diiii: Option>, + pub dyn_call_iiiii: Option>, + pub dyn_call_iiiiii: Option>, + pub dyn_call_vd: Option>, + pub dyn_call_viiiii: Option>, + pub dyn_call_viiiiii: Option>, + pub dyn_call_viiiiiii: Option>, + pub dyn_call_viiiiiiii: Option>, + pub dyn_call_viiiiiiiii: Option>, + pub dyn_call_iiji: Option>, + pub dyn_call_j: Option>, + pub dyn_call_ji: Option>, + pub dyn_call_jij: Option>, + pub dyn_call_jjj: Option>, + pub dyn_call_viiij: Option>, + pub dyn_call_viiijiiii: Option>, + pub dyn_call_viiijiiiiii: + Option>, + pub dyn_call_viij: Option>, + pub dyn_call_viiji: Option>, + pub dyn_call_viijiii: Option>, + pub dyn_call_viijj: Option>, + pub dyn_call_vij: Option>, + pub dyn_call_viji: Option>, + pub dyn_call_vijiii: Option>, + pub dyn_call_vijj: Option>, } impl<'a> EmscriptenData<'a> { @@ -128,6 +157,34 @@ impl<'a> EmscriptenData<'a> { let dyn_call_viii = instance.func("dynCall_viii").ok(); let dyn_call_viiii = instance.func("dynCall_viiii").ok(); + // round 2 + let dyn_call_dii = instance.func("dynCall_dii").ok(); + let dyn_call_diiii = instance.func("dynCall_diiii").ok(); + let dyn_call_iiiii = instance.func("dynCall_iiiii").ok(); + let dyn_call_iiiiii = instance.func("dynCall_iiiiii").ok(); + let dyn_call_vd = instance.func("dynCall_vd").ok(); + let dyn_call_viiiii = instance.func("dynCall_viiiii").ok(); + let dyn_call_viiiiii = instance.func("dynCall_viiiiii").ok(); + let dyn_call_viiiiiii = instance.func("dynCall_viiiiiii").ok(); + let dyn_call_viiiiiiii = instance.func("dynCall_viiiiiiii").ok(); + let dyn_call_viiiiiiiii = instance.func("dynCall_viiiiiiiii").ok(); + let dyn_call_iiji = instance.func("dynCall_iiji").ok(); + let dyn_call_j = instance.func("dynCall_j").ok(); + let dyn_call_ji = instance.func("dynCall_ji").ok(); + let dyn_call_jij = instance.func("dynCall_jij").ok(); + let dyn_call_jjj = instance.func("dynCall_jjj").ok(); + let dyn_call_viiij = instance.func("dynCall_viiij").ok(); + let dyn_call_viiijiiii = instance.func("dynCall_viiijiiii").ok(); + let dyn_call_viiijiiiiii = instance.func("dynCall_viiijiiiiii").ok(); + let dyn_call_viij = instance.func("dynCall_viij").ok(); + let dyn_call_viiji = instance.func("dynCall_viiji").ok(); + let dyn_call_viijiii = instance.func("dynCall_viijiii").ok(); + let dyn_call_viijj = instance.func("dynCall_viijj").ok(); + let dyn_call_vij = instance.func("dynCall_vij").ok(); + let dyn_call_viji = instance.func("dynCall_viji").ok(); + let dyn_call_vijiii = instance.func("dynCall_vijiii").ok(); + let dyn_call_vijj = instance.func("dynCall_vijj").ok(); + EmscriptenData { malloc, free, @@ -144,6 +201,34 @@ impl<'a> EmscriptenData<'a> { dyn_call_vii, dyn_call_viii, dyn_call_viiii, + + // round 2 + dyn_call_dii, + dyn_call_diiii, + dyn_call_iiiii, + dyn_call_iiiiii, + dyn_call_vd, + dyn_call_viiiii, + dyn_call_viiiiii, + dyn_call_viiiiiii, + dyn_call_viiiiiiii, + dyn_call_viiiiiiiii, + dyn_call_iiji, + dyn_call_j, + dyn_call_ji, + dyn_call_jij, + dyn_call_jjj, + dyn_call_viiij, + dyn_call_viiijiiii, + dyn_call_viiijiiiiii, + dyn_call_viij, + dyn_call_viiji, + dyn_call_viijiii, + dyn_call_viijj, + dyn_call_vij, + dyn_call_viji, + dyn_call_vijiii, + dyn_call_vijj, } } } @@ -556,6 +641,54 @@ pub fn generate_emscripten_env(globals: &mut EmscriptenGlobals) -> ImportObject "_pthread_rwlock_rdlock" => func!(crate::emscripten_target::_pthread_rwlock_rdlock), "_pthread_rwlock_unlock" => func!(crate::emscripten_target::_pthread_rwlock_unlock), "___gxx_personality_v0" => func!(crate::emscripten_target::___gxx_personality_v0), + // round 2 + "nullFunc_dii" => func!(crate::emscripten_target::nullFunc_dii), + "nullFunc_diiii" => func!(crate::emscripten_target::nullFunc_diiii), + "nullFunc_iiji" => func!(crate::emscripten_target::nullFunc_iiji), + "nullFunc_j" => func!(crate::emscripten_target::nullFunc_j), + "nullFunc_jij" => func!(crate::emscripten_target::nullFunc_jij), + "nullFunc_jjj" => func!(crate::emscripten_target::nullFunc_jjj), + "nullFunc_vd" => func!(crate::emscripten_target::nullFunc_vd), + "nullFunc_viiiiiii" => func!(crate::emscripten_target::nullFunc_viiiiiii), + "nullFunc_viiiiiiii" => func!(crate::emscripten_target::nullFunc_viiiiiiii), + "nullFunc_viiiiiiiii" => func!(crate::emscripten_target::nullFunc_viiiiiiiii), + "nullFunc_viiij" => func!(crate::emscripten_target::nullFunc_viiij), + "nullFunc_viiijiiii" => func!(crate::emscripten_target::nullFunc_viiijiiii), + "nullFunc_viiijiiiiii" => func!(crate::emscripten_target::nullFunc_viiijiiiiii), + "nullFunc_viij" => func!(crate::emscripten_target::nullFunc_viij), + "nullFunc_viiji" => func!(crate::emscripten_target::nullFunc_viiji), + "nullFunc_viijiii" => func!(crate::emscripten_target::nullFunc_viijiii), + "nullFunc_viijj" => func!(crate::emscripten_target::nullFunc_viijj), + "nullFunc_vij" => func!(crate::emscripten_target::nullFunc_vij), + "nullFunc_viji" => func!(crate::emscripten_target::nullFunc_viji), + "nullFunc_vijiii" => func!(crate::emscripten_target::nullFunc_vijiii), + "nullFunc_vijj" => func!(crate::emscripten_target::nullFunc_vijj), + "invoke_dii" => func!(crate::emscripten_target::invoke_dii), + "invoke_diiii" => func!(crate::emscripten_target::invoke_diiii), + "invoke_iiiii" => func!(crate::emscripten_target::invoke_iiiii), + "invoke_iiiiii" => func!(crate::emscripten_target::invoke_iiiiii), + "invoke_vd" => func!(crate::emscripten_target::invoke_vd), + "invoke_viiiii" => func!(crate::emscripten_target::invoke_viiiii), + "invoke_viiiiii" => func!(crate::emscripten_target::invoke_viiiiii), + "invoke_viiiiiii" => func!(crate::emscripten_target::invoke_viiiiiii), + "invoke_viiiiiiii" => func!(crate::emscripten_target::invoke_viiiiiiii), + "invoke_viiiiiiiii" => func!(crate::emscripten_target::invoke_viiiiiiiii), + "invoke_iiji" => func!(crate::emscripten_target::invoke_iiji), + "invoke_j" => func!(crate::emscripten_target::invoke_j), + "invoke_ji" => func!(crate::emscripten_target::invoke_ji), + "invoke_jij" => func!(crate::emscripten_target::invoke_jij), + "invoke_jjj" => func!(crate::emscripten_target::invoke_jjj), + "invoke_viiij" => func!(crate::emscripten_target::invoke_viiij), + "invoke_viiijiiii" => func!(crate::emscripten_target::invoke_viiijiiii), + "invoke_viiijiiiiii" => func!(crate::emscripten_target::invoke_viiijiiiiii), + "invoke_viij" => func!(crate::emscripten_target::invoke_viij), + "invoke_viiji" => func!(crate::emscripten_target::invoke_viiji), + "invoke_viijiii" => func!(crate::emscripten_target::invoke_viijiii), + "invoke_viijj" => func!(crate::emscripten_target::invoke_viijj), + "invoke_vij" => func!(crate::emscripten_target::invoke_vij), + "invoke_viji" => func!(crate::emscripten_target::invoke_viji), + "invoke_vijiii" => func!(crate::emscripten_target::invoke_vijiii), + "invoke_vijj" => func!(crate::emscripten_target::invoke_vijj), }, "global" => { "NaN" => Global::new(Value::F64(f64::NAN)), diff --git a/lib/emscripten/src/syscalls/mod.rs b/lib/emscripten/src/syscalls/mod.rs index c722e3a79..ef9ef40ee 100644 --- a/lib/emscripten/src/syscalls/mod.rs +++ b/lib/emscripten/src/syscalls/mod.rs @@ -28,7 +28,7 @@ use libc::{ getpid, // iovec, lseek, - open, + // open, read, // readv, rmdir, @@ -85,22 +85,6 @@ pub fn ___syscall4(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int { unsafe { write(fd, buf_addr, count) as i32 } } -/// open -pub fn ___syscall5(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int { - debug!("emscripten::___syscall5 (open) {}", which); - let pathname: u32 = varargs.get(ctx); - let flags: i32 = varargs.get(ctx); - let mode: u32 = varargs.get(ctx); - let pathname_addr = emscripten_memory_pointer!(ctx.memory(0), pathname) as *const i8; - let path_str = unsafe { std::ffi::CStr::from_ptr(pathname_addr).to_str().unwrap() }; - let fd = unsafe { open(pathname_addr, flags, mode) }; - debug!( - "=> pathname: {}, flags: {}, mode: {} = fd: {}\npath: {}", - pathname, flags, mode, fd, path_str - ); - fd -} - /// close pub fn ___syscall6(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall6 (close) {}", which); diff --git a/lib/emscripten/src/syscalls/unix.rs b/lib/emscripten/src/syscalls/unix.rs index c95c8c7dd..a73456d09 100644 --- a/lib/emscripten/src/syscalls/unix.rs +++ b/lib/emscripten/src/syscalls/unix.rs @@ -24,6 +24,7 @@ use libc::{ listen, mkdir, msghdr, + open, pid_t, pread, pwrite, @@ -76,6 +77,22 @@ use libc::SO_NOSIGPIPE; #[cfg(not(target_os = "darwin"))] const SO_NOSIGPIPE: c_int = 0; +/// open +pub fn ___syscall5(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int { + debug!("emscripten::___syscall5 (open) {}", which); + let pathname: u32 = varargs.get(ctx); + let flags: i32 = varargs.get(ctx); + let mode: u32 = varargs.get(ctx); + let pathname_addr = emscripten_memory_pointer!(ctx.memory(0), pathname) as *const i8; + let path_str = unsafe { std::ffi::CStr::from_ptr(pathname_addr).to_str().unwrap() }; + let fd = unsafe { open(pathname_addr, flags, mode) }; + debug!( + "=> pathname: {}, flags: {}, mode: {} = fd: {}\npath: {}", + pathname, flags, mode, fd, path_str + ); + fd +} + // chown pub fn ___syscall212(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall212 (chown) {}", which); diff --git a/lib/emscripten/src/syscalls/windows.rs b/lib/emscripten/src/syscalls/windows.rs index 41c4cf7eb..d2584bbd4 100644 --- a/lib/emscripten/src/syscalls/windows.rs +++ b/lib/emscripten/src/syscalls/windows.rs @@ -1,10 +1,62 @@ +use crate::utils::copy_cstr_into_wasm; +use crate::utils::read_string_from_wasm; use crate::varargs::VarArgs; use libc::mkdir; +use libc::open; +use rand::Rng; +use std::env; +use std::ffi::CStr; +use std::ffi::CString; +use std::fs::File; +use std::io::Write; use std::os::raw::c_int; use wasmer_runtime_core::vm::Ctx; type pid_t = c_int; +/// open +pub fn ___syscall5(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int { + debug!("emscripten::___syscall5 (open) {}", which); + let pathname: u32 = varargs.get(ctx); + let flags: i32 = varargs.get(ctx); + let mode: u32 = varargs.get(ctx); + let pathname_addr = emscripten_memory_pointer!(ctx.memory(0), pathname) as *const i8; + let path_str = unsafe { std::ffi::CStr::from_ptr(pathname_addr).to_str().unwrap() }; + match path_str { + "/dev/urandom" => { + // create a fake urandom file for windows, super hacky + // put it in the temp directory so we can just forget about it + let mut tmp_dir = env::temp_dir(); + tmp_dir.push("urandom"); + let tmp_dir_str = tmp_dir.to_str().unwrap(); + let tmp_dir_c_str = CString::new(tmp_dir_str).unwrap(); + let ptr = tmp_dir_c_str.as_ptr() as *const i8; + let mut urandom_file = File::create(tmp_dir).unwrap(); + // create some random bytes and put them into the file + let random_bytes = rand::thread_rng().gen::<[u8; 32]>(); + urandom_file.write_all(&random_bytes); + // put the file path string into wasm memory + let urandom_file_offset = unsafe { copy_cstr_into_wasm(ctx, ptr) }; + let raw_pointer_to_urandom_file = + emscripten_memory_pointer!(ctx.memory(0), urandom_file_offset) as *const i8; + let fd = unsafe { open(raw_pointer_to_urandom_file, flags, mode) }; + debug!( + "=> pathname: {}, flags: {}, mode: {} = fd: {}\npath: {}", + pathname, flags, mode, fd, s + ); + fd + } + _ => { + let fd = unsafe { open(pathname_addr, flags, mode) }; + debug!( + "=> pathname: {}, flags: {}, mode: {} = fd: {}\npath: {}", + pathname, flags, mode, fd, path_str + ); + fd + } + } +} + // chown pub fn ___syscall212(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall212 (chown) {}", which); diff --git a/lib/runtime-core/src/typed_func.rs b/lib/runtime-core/src/typed_func.rs index 19efcbe4e..6e59d0d4a 100644 --- a/lib/runtime-core/src/typed_func.rs +++ b/lib/runtime-core/src/typed_func.rs @@ -246,6 +246,7 @@ impl_traits!([C] S8, A, B, C, D, E, F, G, H); impl_traits!([C] S9, A, B, C, D, E, F, G, H, I); impl_traits!([C] S10, A, B, C, D, E, F, G, H, I, J); impl_traits!([C] S11, A, B, C, D, E, F, G, H, I, J, K); +impl_traits!([C] S12, A, B, C, D, E, F, G, H, I, J, K, L); impl<'a, Args, Rets, Safety> IsExport for Func<'a, Args, Rets, Safety> where From c9969f269c1f3cb6f661b44d0199cc92e8d23522 Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Fri, 22 Feb 2019 13:16:15 -0600 Subject: [PATCH 093/262] Use minimum limit as initial table size (#196) --- lib/runtime-c-api/tests/test-tables.c | 2 +- lib/runtime-core/src/memory/mod.rs | 18 ++++++++++++++++++ lib/runtime-core/src/table/anyfunc.rs | 5 +---- lib/runtime-core/src/table/mod.rs | 18 ++++++++++++++++++ 4 files changed, 38 insertions(+), 5 deletions(-) diff --git a/lib/runtime-c-api/tests/test-tables.c b/lib/runtime-c-api/tests/test-tables.c index 66ebf832d..48b7be710 100644 --- a/lib/runtime-c-api/tests/test-tables.c +++ b/lib/runtime-c-api/tests/test-tables.c @@ -19,7 +19,7 @@ int main() uint32_t len = wasmer_table_length(table); printf("Table length: %d\n", len); - assert(len == 15); + assert(len == 10); // wasmer_result_t grow_result1 = wasmer_table_grow(table, 5); // assert(grow_result1 == WASMER_OK); diff --git a/lib/runtime-core/src/memory/mod.rs b/lib/runtime-core/src/memory/mod.rs index 56d4c643b..bc706b564 100644 --- a/lib/runtime-core/src/memory/mod.rs +++ b/lib/runtime-core/src/memory/mod.rs @@ -306,3 +306,21 @@ impl Clone for SharedMemory { unimplemented!() } } + +#[cfg(test)] +mod memory_tests { + + use super::{Memory, MemoryDescriptor, Pages}; + + #[test] + fn test_initial_memory_size() { + let unshared_memory = Memory::new(MemoryDescriptor { + minimum: Pages(10), + maximum: Some(Pages(20)), + shared: false, + }) + .unwrap(); + assert_eq!(unshared_memory.size(), Pages(10)); + } + +} diff --git a/lib/runtime-core/src/table/anyfunc.rs b/lib/runtime-core/src/table/anyfunc.rs index 161e26097..789f67ada 100644 --- a/lib/runtime-core/src/table/anyfunc.rs +++ b/lib/runtime-core/src/table/anyfunc.rs @@ -53,10 +53,7 @@ impl AnyfuncTable { desc: TableDescriptor, local: &mut vm::LocalTable, ) -> Result, CreationError> { - let initial_table_backing_len = match desc.maximum { - Some(max) => max, - None => desc.minimum, - } as usize; + let initial_table_backing_len = desc.minimum as usize; let mut storage = Box::new(AnyfuncTable { backing: vec![vm::Anyfunc::null(); initial_table_backing_len], diff --git a/lib/runtime-core/src/table/mod.rs b/lib/runtime-core/src/table/mod.rs index 1bad9a3c4..a45593802 100644 --- a/lib/runtime-core/src/table/mod.rs +++ b/lib/runtime-core/src/table/mod.rs @@ -148,3 +148,21 @@ impl fmt::Debug for Table { .finish() } } + +#[cfg(test)] +mod table_tests { + + use super::{ElementType, Table, TableDescriptor}; + + #[test] + fn test_initial_table_size() { + let table = Table::new(TableDescriptor { + element: ElementType::Anyfunc, + minimum: 10, + maximum: Some(20), + }) + .unwrap(); + assert_eq!(table.size(), 10); + } + +} From fdb2a675794f632711e216d9314b8f105f1562c9 Mon Sep 17 00:00:00 2001 From: Syrus Date: Fri, 22 Feb 2019 11:42:30 -0800 Subject: [PATCH 094/262] Added cache into standalone app --- install.sh | 2 +- lib/clif-backend/src/module.rs | 2 - lib/runtime-core/src/cache.rs | 4 +- lib/runtime-core/src/module.rs | 10 ++++- lib/runtime-core/src/vm.rs | 2 - lib/runtime/src/cache.rs | 18 ++++----- src/bin/wasmer.rs | 69 +++++++++++++++++++++++++++++++++- 7 files changed, 85 insertions(+), 22 deletions(-) diff --git a/install.sh b/install.sh index 196fab7d5..04b5f364a 100755 --- a/install.sh +++ b/install.sh @@ -130,7 +130,7 @@ wasmer_link() { printf "$cyan> Adding to bash profile...$reset\n" WASMER_PROFILE="$(wasmer_detect_profile)" LOAD_STR="\n# Wasmer\nexport WASMER_DIR=\"\$HOME/.wasmer\"\n[ -s \"\$WASMER_DIR/wasmer.sh\" ] && source \"\$WASMER_DIR/wasmer.sh\" # This loads wasmer\n" - SOURCE_STR="# Wasmer config\nexport WASMER_DIR=\"\$HOME/.wasmer\"\nexport PATH=\"\$HOME/.wasmer/bin:\$PATH\"\n" + SOURCE_STR="# Wasmer config\nexport WASMER_DIR=\"\$HOME/.wasmer\"\nexport WASMER_CACHE_DIR=\"\$WASMER_DIR/cache\"\nexport PATH=\"\$HOME/.wasmer/bin:\$PATH\"\n" # We create the wasmer.sh file echo "$SOURCE_STR" > "$HOME/.wasmer/wasmer.sh" diff --git a/lib/clif-backend/src/module.rs b/lib/clif-backend/src/module.rs index 6f95ea828..38a657625 100644 --- a/lib/clif-backend/src/module.rs +++ b/lib/clif-backend/src/module.rs @@ -50,8 +50,6 @@ impl Module { namespace_table: StringTable::new(), name_table: StringTable::new(), - - wasm_hash: WasmHash::generate(wasm), }, } } diff --git a/lib/runtime-core/src/cache.rs b/lib/runtime-core/src/cache.rs index 3d894bb09..e47a944d3 100644 --- a/lib/runtime-core/src/cache.rs +++ b/lib/runtime-core/src/cache.rs @@ -67,7 +67,6 @@ struct ArtifactHeader { magic: [u8; 8], // [W, A, S, M, E, R, \0, \0] version: u64, data_len: u64, - wasm_hash: [u8; 32], // Sha256 of the wasm in binary format. } impl ArtifactHeader { @@ -170,7 +169,6 @@ impl Artifact { magic: WASMER_CACHE_MAGIC, version: CURRENT_CACHE_VERSION, data_len: 0, - wasm_hash: self.inner.info.wasm_hash.into_array(), }; let mut buffer = cache_header.as_slice().to_vec(); @@ -195,5 +193,5 @@ pub trait Cache { type StoreError; fn load(&self, key: WasmHash) -> Result; - fn store(&mut self, module: Module) -> Result; + fn store(&mut self, key: WasmHash, module: Module) -> Result<(), Self::StoreError>; } diff --git a/lib/runtime-core/src/module.rs b/lib/runtime-core/src/module.rs index 130082491..cac375b66 100644 --- a/lib/runtime-core/src/module.rs +++ b/lib/runtime-core/src/module.rs @@ -56,8 +56,6 @@ pub struct ModuleInfo { pub namespace_table: StringTable, pub name_table: StringTable, - - pub wasm_hash: WasmHash, } /// A compiled WebAssembly module. @@ -116,6 +114,14 @@ impl Module { } } +impl Clone for Module { + fn clone(&self) -> Self { + Self { + inner: Arc::clone(&self.inner), + } + } +} + impl ModuleInner {} #[doc(hidden)] diff --git a/lib/runtime-core/src/vm.rs b/lib/runtime-core/src/vm.rs index ab386401b..71400af70 100644 --- a/lib/runtime-core/src/vm.rs +++ b/lib/runtime-core/src/vm.rs @@ -565,8 +565,6 @@ mod vm_ctx_tests { namespace_table: StringTable::new(), name_table: StringTable::new(), - - wasm_hash: WasmHash::generate(&[]), }, } } diff --git a/lib/runtime/src/cache.rs b/lib/runtime/src/cache.rs index 09a93356b..2489598c0 100644 --- a/lib/runtime/src/cache.rs +++ b/lib/runtime/src/cache.rs @@ -19,19 +19,18 @@ pub use wasmer_runtime_core::cache::{Artifact, Cache, WasmHash}; /// # Usage: /// /// ```rust -/// use wasmer_runtime::cache::{Cache, FileSystemCache}; +/// use wasmer_runtime::cache::{Cache, FileSystemCache, WasmHash}; /// /// # use wasmer_runtime::{Module, error::CacheError}; -/// fn store_and_load_module(module: Module) -> Result { +/// fn store_module(module: Module) -> Result { /// // Create a new file system cache. /// // This is unsafe because we can't ensure that the artifact wasn't /// // corrupted or tampered with. /// let mut fs_cache = unsafe { FileSystemCache::new("some/directory/goes/here")? }; -/// // Store a module into the cache. -/// // The returned `key` is equivalent to `module.info().wasm_hash`. -/// let key = fs_cache.store(module)?; -/// // Load the module back from the cache with the `key`. -/// fs_cache.load(key) +/// // Compute a key for a given WebAssembly module +/// let key = WasmHash::generate(module) +/// // Store a module into the cache given a key +/// fs_cache.store(key, module)?; /// } /// ``` pub struct FileSystemCache { @@ -92,8 +91,7 @@ impl Cache for FileSystemCache { unsafe { wasmer_runtime_core::load_cache_with(serialized_cache, super::default_compiler()) } } - fn store(&mut self, module: Module) -> Result { - let key = module.info().wasm_hash; + fn store(&mut self, key: WasmHash, module: Module) -> Result<(), CacheError> { let filename = key.encode(); let mut new_path_buf = self.path.clone(); new_path_buf.push(filename); @@ -104,6 +102,6 @@ impl Cache for FileSystemCache { let mut file = File::create(new_path_buf)?; file.write_all(&buffer)?; - Ok(key) + Ok(()) } } diff --git a/src/bin/wasmer.rs b/src/bin/wasmer.rs index 2ec707f83..59d753e1a 100644 --- a/src/bin/wasmer.rs +++ b/src/bin/wasmer.rs @@ -1,5 +1,7 @@ extern crate structopt; +use std::env; +use std::fs; use std::fs::File; use std::io; use std::io::Read; @@ -11,6 +13,8 @@ use structopt::StructOpt; use wasmer::webassembly::InstanceABI; use wasmer::*; use wasmer_emscripten; +use wasmer_runtime::cache::{Cache as BaseCache, FileSystemCache, WasmHash}; +use wasmer_runtime::error::CacheError; #[derive(Debug, StructOpt)] #[structopt(name = "wasmer", about = "Wasm execution runtime.")] @@ -20,6 +24,10 @@ enum CLIOptions { #[structopt(name = "run")] Run(Run), + /// Wasmer cache + #[structopt(name = "cache")] + Cache(Cache), + /// Update wasmer to the latest version #[structopt(name = "self-update")] SelfUpdate, @@ -39,6 +47,15 @@ struct Run { args: Vec, } +#[derive(Debug, StructOpt)] +enum Cache { + #[structopt(name = "clean")] + Clean, + + #[structopt(name = "dir")] + Dir, +} + /// Read the contents of a file fn read_file_contents(path: &PathBuf) -> Result, io::Error> { let mut buffer: Vec = Vec::new(); @@ -49,6 +66,18 @@ fn read_file_contents(path: &PathBuf) -> Result, io::Error> { Ok(buffer) } +fn get_cache_dir() -> PathBuf { + match env::var("WASMER_CACHE_DIR") { + Ok(dir) => PathBuf::from(dir), + Err(_) => { + // We use a temporal directory for saving cache files + let mut temp_dir = env::temp_dir(); + temp_dir.push("wasmer"); + temp_dir + } + } +} + /// Execute a wasm/wat file fn execute_wasm(options: &Run) -> Result<(), String> { let wasm_path = &options.path; @@ -66,8 +95,34 @@ fn execute_wasm(options: &Run) -> Result<(), String> { .map_err(|e| format!("Can't convert from wast to wasm: {:?}", e))?; } - let module = webassembly::compile(&wasm_binary[..]) - .map_err(|e| format!("Can't compile module: {:?}", e))?; + let hash = WasmHash::generate(&wasm_binary); + + let wasmer_cache_dir = get_cache_dir(); + + // We create a new cache instance. + // It could be possible to use any other kinds of caching, as long as they + // implement the Cache trait (with save and load functions) + let mut cache = unsafe { + FileSystemCache::new(wasmer_cache_dir).map_err(|e| format!("Cache error: {:?}", e))? + }; + + // cache.load will return the Module if it's able to deserialize it properly, and an error if: + // * The file is not found + // * The file exists, but it's corrupted or can't be converted to a module + let module = match cache.load(hash) { + Ok(module) => { + // We are able to load the module from cache + module + } + Err(_) => { + let module = webassembly::compile(&wasm_binary[..]) + .map_err(|e| format!("Can't compile module: {:?}", e))?; + + // We save the module into a cache file + cache.store(hash, module.clone()).unwrap(); + module + } + }; let (_abi, import_object, _em_globals) = if wasmer_emscripten::is_emscripten_module(&module) { let mut emscripten_globals = wasmer_emscripten::EmscriptenGlobals::new(&module); @@ -119,5 +174,15 @@ fn main() { CLIOptions::SelfUpdate => { println!("Self update is not supported on Windows. Use install instructions on the Wasmer homepage: https://wasmer.io"); } + CLIOptions::Cache(cache) => match cache { + Cache::Clean => { + let cache_dir = get_cache_dir(); + fs::remove_dir_all(cache_dir.clone()).expect("Can't remove cache dir"); + fs::create_dir(cache_dir.clone()).expect("Can't create cache dir"); + } + Cache::Dir => { + println!("{}", get_cache_dir().to_string_lossy()); + } + }, } } From 84042cecb334ad62d8521595901c3548e675cd9e Mon Sep 17 00:00:00 2001 From: Syrus Date: Fri, 22 Feb 2019 12:00:30 -0800 Subject: [PATCH 095/262] Fixed wrong syntax --- lib/runtime/src/cache.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/runtime/src/cache.rs b/lib/runtime/src/cache.rs index 2489598c0..8f42e9e49 100644 --- a/lib/runtime/src/cache.rs +++ b/lib/runtime/src/cache.rs @@ -27,8 +27,8 @@ pub use wasmer_runtime_core::cache::{Artifact, Cache, WasmHash}; /// // This is unsafe because we can't ensure that the artifact wasn't /// // corrupted or tampered with. /// let mut fs_cache = unsafe { FileSystemCache::new("some/directory/goes/here")? }; -/// // Compute a key for a given WebAssembly module -/// let key = WasmHash::generate(module) +/// // Compute a key for a given WebAssembly binary +/// let key = WasmHash::generate(&[]); /// // Store a module into the cache given a key /// fs_cache.store(key, module)?; /// } From 13e1cb11691a047850f8d9e889d098883b420801 Mon Sep 17 00:00:00 2001 From: Syrus Date: Fri, 22 Feb 2019 12:01:03 -0800 Subject: [PATCH 096/262] =?UTF-8?q?Added=20a=20=E2=80=94disable-cache=20cl?= =?UTF-8?q?i=20flag=20for=20wasmer=20run?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/bin/wasmer.rs | 60 +++++++++++++++++++++++++++++------------------ 1 file changed, 37 insertions(+), 23 deletions(-) diff --git a/src/bin/wasmer.rs b/src/bin/wasmer.rs index 59d753e1a..6b8c9b54b 100644 --- a/src/bin/wasmer.rs +++ b/src/bin/wasmer.rs @@ -38,6 +38,10 @@ struct Run { #[structopt(short = "d", long = "debug")] debug: bool, + // Disable the cache + #[structopt(long = "disable-cache")] + disable_cache: bool, + /// Input file #[structopt(parse(from_os_str))] path: PathBuf, @@ -95,33 +99,43 @@ fn execute_wasm(options: &Run) -> Result<(), String> { .map_err(|e| format!("Can't convert from wast to wasm: {:?}", e))?; } - let hash = WasmHash::generate(&wasm_binary); + let module = if !options.disable_cache { + // If we have cache enabled - let wasmer_cache_dir = get_cache_dir(); + // We generate a hash for the given binary, so we can use it as key + // for the Filesystem cache + let hash = WasmHash::generate(&wasm_binary); - // We create a new cache instance. - // It could be possible to use any other kinds of caching, as long as they - // implement the Cache trait (with save and load functions) - let mut cache = unsafe { - FileSystemCache::new(wasmer_cache_dir).map_err(|e| format!("Cache error: {:?}", e))? - }; + let wasmer_cache_dir = get_cache_dir(); - // cache.load will return the Module if it's able to deserialize it properly, and an error if: - // * The file is not found - // * The file exists, but it's corrupted or can't be converted to a module - let module = match cache.load(hash) { - Ok(module) => { - // We are able to load the module from cache - module - } - Err(_) => { - let module = webassembly::compile(&wasm_binary[..]) - .map_err(|e| format!("Can't compile module: {:?}", e))?; + // We create a new cache instance. + // It could be possible to use any other kinds of caching, as long as they + // implement the Cache trait (with save and load functions) + let mut cache = unsafe { + FileSystemCache::new(wasmer_cache_dir).map_err(|e| format!("Cache error: {:?}", e))? + }; - // We save the module into a cache file - cache.store(hash, module.clone()).unwrap(); - module - } + // cache.load will return the Module if it's able to deserialize it properly, and an error if: + // * The file is not found + // * The file exists, but it's corrupted or can't be converted to a module + let module = match cache.load(hash) { + Ok(module) => { + // We are able to load the module from cache + module + } + Err(_) => { + let module = webassembly::compile(&wasm_binary[..]) + .map_err(|e| format!("Can't compile module: {:?}", e))?; + + // We save the module into a cache file + cache.store(hash, module.clone()).unwrap(); + module + } + }; + module + } else { + webassembly::compile(&wasm_binary[..]) + .map_err(|e| format!("Can't compile module: {:?}", e))? }; let (_abi, import_object, _em_globals) = if wasmer_emscripten::is_emscripten_module(&module) { From b3dd47bce8d91fe1fffddbf1c0b0e9636226f045 Mon Sep 17 00:00:00 2001 From: Syrus Date: Fri, 22 Feb 2019 12:06:22 -0800 Subject: [PATCH 097/262] Fixed runtime example --- lib/runtime/src/cache.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/runtime/src/cache.rs b/lib/runtime/src/cache.rs index 8f42e9e49..c174af4ac 100644 --- a/lib/runtime/src/cache.rs +++ b/lib/runtime/src/cache.rs @@ -30,7 +30,8 @@ pub use wasmer_runtime_core::cache::{Artifact, Cache, WasmHash}; /// // Compute a key for a given WebAssembly binary /// let key = WasmHash::generate(&[]); /// // Store a module into the cache given a key -/// fs_cache.store(key, module)?; +/// fs_cache.store(key, module.clone())?; +/// module /// } /// ``` pub struct FileSystemCache { From 17901f992a0f10285814aeaf5f132db4804e2b57 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Fri, 22 Feb 2019 12:07:07 -0800 Subject: [PATCH 098/262] Add benchmark runner and nginx compile vs. load bench --- Cargo.lock | 207 ++++++++++++++++++++++++++++++++++ lib/runtime-core/src/cache.rs | 6 +- lib/runtime/Cargo.toml | 7 ++ lib/runtime/benches/nginx.rs | 39 +++++++ 4 files changed, 256 insertions(+), 3 deletions(-) create mode 100644 lib/runtime/benches/nginx.rs diff --git a/Cargo.lock b/Cargo.lock index aa14e70be..229eb1638 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -16,6 +16,14 @@ dependencies = [ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "arrayvec" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "atty" version = "0.2.11" @@ -256,6 +264,88 @@ dependencies = [ "wasmparser 0.22.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "criterion" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", + "criterion-plot 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "csv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_xoshiro 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "tinytemplate 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "criterion-plot" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-deque" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-utils" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "csv" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "csv-core 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "csv-core" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "digest" version = "0.8.0" @@ -264,6 +354,11 @@ dependencies = [ "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "either" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "env_logger" version = "0.6.0" @@ -393,6 +488,14 @@ name = "indexmap" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "itertools" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "either 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "itoa" version = "0.4.3" @@ -452,6 +555,9 @@ dependencies = [ name = "memchr" version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "memmap" @@ -462,6 +568,11 @@ dependencies = [ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "memoffset" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "nix" version = "0.12.0" @@ -486,6 +597,11 @@ dependencies = [ "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "nodrop" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "nom" version = "4.2.0" @@ -495,6 +611,19 @@ dependencies = [ "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "num-traits" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "num_cpus" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "opaque-debug" version = "0.2.2" @@ -677,6 +806,15 @@ dependencies = [ "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rand_xoshiro" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "raw-cpuid" version = "6.1.0" @@ -687,6 +825,27 @@ dependencies = [ "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rayon" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rayon-core" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rdrand" version = "0.4.0" @@ -754,6 +913,14 @@ name = "ryu" version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "same-file" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "scopeguard" version = "0.3.3" @@ -964,6 +1131,15 @@ dependencies = [ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "tinytemplate" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "toml" version = "0.4.10" @@ -1046,6 +1222,16 @@ dependencies = [ "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "walkdir" +version = "2.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "wasmer" version = "0.1.4" @@ -1100,6 +1286,7 @@ dependencies = [ name = "wasmer-runtime" version = "0.1.4" dependencies = [ + "criterion 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-clif-backend 0.1.2", @@ -1229,6 +1416,7 @@ dependencies = [ [metadata] "checksum aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1e9a933f4e58658d7b12defcf96dc5c720f20832deebe3e0a19efd3b6aaeeb9e" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" +"checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" "checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799" "checksum backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "b5b493b66e03090ebc4343eb02f94ff944e0cbc9ac6571491d170ba026741eb5" @@ -1255,7 +1443,15 @@ dependencies = [ "checksum cranelift-frontend 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "789907218eeebebcea8122c2053d71affac91c96ce72cea35ebfdbbf547e82af" "checksum cranelift-native 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "474bee81d620a473bf43411a3d6f10ffbf7965141dc5e5b76d8d2151dde3285d" "checksum cranelift-wasm 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49723365dab9a48b354bdc24cb6d9d5719bc1d3b858ffd2ea179d0d7d885804a" +"checksum criterion 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "1c6e5ee5b9652d4f851418c448af105642e1f99e9a2741a8ff45c0d2c911b1e0" +"checksum criterion-plot 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4107e4a5abb94267e0149922b8ff49dc70a87cc202820fdbfc0d3e1edbdc4b16" +"checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3" +"checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150" +"checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9" +"checksum csv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "9fd1c44c58078cfbeaf11fbb3eac9ae5534c23004ed770cc4bfb48e658ae4f04" +"checksum csv-core 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa5cdef62f37e6ffe7d1f07a381bc0db32b7a3ff1cac0de56cb0d81e71f53d65" "checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c" +"checksum either 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c67353c641dc847124ea1902d69bd753dee9bb3beff9aa3662ecf86c971d1fac" "checksum env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "afb070faf94c85d17d50ca44f6ad076bce18ae92f0037d350947240a36e9d42e" "checksum errno 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c2a071601ed01b988f896ab14b95e67335d1eeb50190932a1320f7fe3cadc84e" "checksum errno-dragonfly 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "14ca354e36190500e1e1fb267c647932382b54053c50b14970856c0b00a35067" @@ -1273,6 +1469,7 @@ dependencies = [ "checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" "checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114" "checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d" +"checksum itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358" "checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1" @@ -1283,9 +1480,13 @@ dependencies = [ "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" "checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39" "checksum memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" +"checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" "checksum nix 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "921f61dc817b379d0834e45d5ec45beaacfae97082090a49c2cf30dcbc30206f" "checksum nix 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46f0f3210768d796e8fa79ec70ee6af172dacbe7147f5e69be5240a47778302b" +"checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" "checksum nom 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b30adc557058ce00c9d0d7cb3c6e0b5bc6f36e2e2eabe74b0ba726d194abd588" +"checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" +"checksum num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a23f0ed30a54abaa0c7e83b1d2d87ada7c3c23078d1d87815af3e3b6385fbba" "checksum opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "93f5bb2e8e8dec81642920ccff6b61f1eb94fa3020c5a325c9851ff604152409" "checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" "checksum page_size 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f89ef58b3d32420dbd1a43d2f38ae92f6239ef12bb556ab09ca55445f5a67242" @@ -1307,7 +1508,10 @@ dependencies = [ "checksum rand_os 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f46fbd5550acf75b0c2730f5dd1873751daf9beb8f11b44027778fae50d7feca" "checksum rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "086bd09a33c7044e56bb44d5bdde5a60e7f119a9e95b0775f545de759a32fe05" "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" +"checksum rand_xoshiro 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "03b418169fb9c46533f326efd6eed2576699c44ca92d3052a066214a8d828929" "checksum raw-cpuid 6.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "30a9d219c32c9132f7be513c18be77c9881c7107d2ab5569d205a6a0f0e6dc7d" +"checksum rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "373814f27745b2686b350dd261bfd24576a6fb0e2c5919b3a2b6005f820b0473" +"checksum rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b055d1e92aba6877574d8fe604a63c8b5df60f60e5982bf7ccbb1338ea527356" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" "checksum redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)" = "423e376fffca3dfa06c9e9790a9ccd282fafb3cc6e6397d01dbf64f9bacc6b85" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" @@ -1317,6 +1521,7 @@ dependencies = [ "checksum rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "adacaae16d02b6ec37fdc7acfcddf365978de76d1983d3ee22afc260e1ca9619" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7" +"checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" @@ -1341,6 +1546,7 @@ dependencies = [ "checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" +"checksum tinytemplate 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7655088894274afb52b807bd3c87072daa1fedd155068b8705cabfd628956115" "checksum toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "758664fc71a3a69038656bee8b6be6477d2a6c315a6b81f7081f591bffa4111f" "checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" "checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" @@ -1354,6 +1560,7 @@ dependencies = [ "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" "checksum wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "74e463a508e390cc7447e70f640fbf44ad52e1bd095314ace1fdf99516d32add" "checksum wabt-sys 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a6265b25719e82598d104b3717375e37661d41753e2c84cde3f51050c7ed7e3c" +"checksum walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d9d7ed3431229a144296213105a390676cc49c9b6a72bd19f3176c98e129fa1" "checksum wasmparser 0.22.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f46e666ecb4a406483a59a49f9d0c17f327e70da53a128eccddae2eadb95865c" "checksum wasmparser 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b5e01c420bc7d36e778bd242e1167b079562ba8b34087122cc9057187026d060" "checksum which 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b57acb10231b9493c8472b20cb57317d0679a49e0bdbee44b3b803a6473af164" diff --git a/lib/runtime-core/src/cache.rs b/lib/runtime-core/src/cache.rs index 3d894bb09..a00e0f6f2 100644 --- a/lib/runtime-core/src/cache.rs +++ b/lib/runtime-core/src/cache.rs @@ -3,7 +3,7 @@ use crate::{ sys::Memory, }; use sha2::{Digest, Sha256}; -use std::{io, mem, slice}; +use std::{io, mem, slice, fmt}; #[derive(Debug)] pub enum InvalidFileType { @@ -191,8 +191,8 @@ impl Artifact { /// /// The `wasmer-runtime` supplies a naive `FileSystemCache` api. pub trait Cache { - type LoadError; - type StoreError; + type LoadError: fmt::Debug; + type StoreError: fmt::Debug; fn load(&self, key: WasmHash) -> Result; fn store(&mut self, module: Module) -> Result; diff --git a/lib/runtime/Cargo.toml b/lib/runtime/Cargo.toml index e4169a652..d7a7effa7 100644 --- a/lib/runtime/Cargo.toml +++ b/lib/runtime/Cargo.toml @@ -20,5 +20,12 @@ version = "0.1.2" path = "../clif-backend" version = "0.1.2" +[dev-dependencies] +criterion = "0.2" + [features] debug = ["wasmer-clif-backend/debug", "wasmer-runtime-core/debug"] + +[[bench]] +name = "nginx" +harness = false \ No newline at end of file diff --git a/lib/runtime/benches/nginx.rs b/lib/runtime/benches/nginx.rs new file mode 100644 index 000000000..f7f2244b9 --- /dev/null +++ b/lib/runtime/benches/nginx.rs @@ -0,0 +1,39 @@ +#[macro_use] +extern crate criterion; +use criterion::Criterion; +use wasmer_runtime::{ + cache::{Cache, FileSystemCache, WasmHash}, + compile, +}; + +static NGINX_WASM: &'static [u8] = include_bytes!("../../../examples/nginx/nginx.wasm"); + +fn compile_module() { + compile(NGINX_WASM).unwrap(); +} + +fn load_module(cache: &impl Cache) { + let wasm_hash = WasmHash::generate(NGINX_WASM); + cache.load(wasm_hash).unwrap(); +} + +fn compile_benchmark(c: &mut Criterion) { + c.bench_function("nginx compile", |b| b.iter(|| compile_module())); +} + +fn load_benchmark(c: &mut Criterion) { + c.bench_function("nginx load", |b| { + let mut cache = unsafe { FileSystemCache::new(".").unwrap() }; + let module = compile(NGINX_WASM).unwrap(); + cache.store(module).unwrap(); + + b.iter(|| load_module(&cache)) + }); +} + +criterion_group! { + name = benches; + config = Criterion::default().sample_size(10); + targets = compile_benchmark, load_benchmark +} +criterion_main!(benches); From 6d092dc1215ad1af6312e59f9db688966164a96c Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Fri, 22 Feb 2019 12:08:56 -0800 Subject: [PATCH 099/262] Fix lint --- lib/runtime-core/src/cache.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/runtime-core/src/cache.rs b/lib/runtime-core/src/cache.rs index a00e0f6f2..dd1e24a9d 100644 --- a/lib/runtime-core/src/cache.rs +++ b/lib/runtime-core/src/cache.rs @@ -3,7 +3,7 @@ use crate::{ sys::Memory, }; use sha2::{Digest, Sha256}; -use std::{io, mem, slice, fmt}; +use std::{fmt, io, mem, slice}; #[derive(Debug)] pub enum InvalidFileType { From 16d62ace52dadf719d56b6c4582c533b56d2e284 Mon Sep 17 00:00:00 2001 From: Syrus Date: Fri, 22 Feb 2019 12:17:49 -0800 Subject: [PATCH 100/262] Fixed cache example (again) --- lib/runtime/src/cache.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/runtime/src/cache.rs b/lib/runtime/src/cache.rs index c174af4ac..6ebbf1017 100644 --- a/lib/runtime/src/cache.rs +++ b/lib/runtime/src/cache.rs @@ -31,7 +31,7 @@ pub use wasmer_runtime_core::cache::{Artifact, Cache, WasmHash}; /// let key = WasmHash::generate(&[]); /// // Store a module into the cache given a key /// fs_cache.store(key, module.clone())?; -/// module +/// Ok(module) /// } /// ``` pub struct FileSystemCache { From 687f70df8928654d2b728a63aa9a43322eb0b965 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Fri, 22 Feb 2019 12:20:16 -0800 Subject: [PATCH 101/262] Add validation benchmark --- lib/runtime/benches/nginx.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/runtime/benches/nginx.rs b/lib/runtime/benches/nginx.rs index f7f2244b9..f1287dee8 100644 --- a/lib/runtime/benches/nginx.rs +++ b/lib/runtime/benches/nginx.rs @@ -3,7 +3,7 @@ extern crate criterion; use criterion::Criterion; use wasmer_runtime::{ cache::{Cache, FileSystemCache, WasmHash}, - compile, + compile, validate, }; static NGINX_WASM: &'static [u8] = include_bytes!("../../../examples/nginx/nginx.wasm"); @@ -17,6 +17,10 @@ fn load_module(cache: &impl Cache) { cache.load(wasm_hash).unwrap(); } +fn validate_benchmark(c: &mut Criterion) { + c.bench_function("nginx validate", |b| b.iter(|| validate(NGINX_WASM))); +} + fn compile_benchmark(c: &mut Criterion) { c.bench_function("nginx compile", |b| b.iter(|| compile_module())); } @@ -34,6 +38,6 @@ fn load_benchmark(c: &mut Criterion) { criterion_group! { name = benches; config = Criterion::default().sample_size(10); - targets = compile_benchmark, load_benchmark + targets = validate_benchmark, compile_benchmark, load_benchmark } criterion_main!(benches); From cb84894d42f63ae43b8954266c39a3cf9ddd0800 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Fri, 22 Feb 2019 12:31:31 -0800 Subject: [PATCH 102/262] Add section about benchmarking to readme --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index bdb921afd..74e9ef575 100644 --- a/README.md +++ b/README.md @@ -142,6 +142,14 @@ You can also run integration tests with: make integration-tests ``` +## Benchmarking + +Benchmarks can be run with: + +```sh +cargo bench --all +``` + ## Roadmap Wasmer is an open project guided by strong principles, aiming to be modular, flexible and fast. It is open to the community to help set its direction. From ad3d361f76fb123633d29d30c2331a7abb03847a Mon Sep 17 00:00:00 2001 From: Mackenzie Clark Date: Fri, 22 Feb 2019 12:32:14 -0800 Subject: [PATCH 103/262] add the syscall and create a test --- lib/emscripten/emtests/test_getcwd.c | 10 +++++++++ lib/emscripten/emtests/test_getcwd.out | 1 + lib/emscripten/emtests/test_getcwd.wasm | Bin 0 -> 22468 bytes lib/emscripten/src/lib.rs | 1 + lib/emscripten/src/syscalls/mod.rs | 23 ++++++++++++++++++++ lib/emscripten/tests/emtests/test_getcwd.rs | 9 ++++++++ 6 files changed, 44 insertions(+) create mode 100644 lib/emscripten/emtests/test_getcwd.c create mode 100644 lib/emscripten/emtests/test_getcwd.out create mode 100644 lib/emscripten/emtests/test_getcwd.wasm create mode 100644 lib/emscripten/tests/emtests/test_getcwd.rs diff --git a/lib/emscripten/emtests/test_getcwd.c b/lib/emscripten/emtests/test_getcwd.c new file mode 100644 index 000000000..a3955d470 --- /dev/null +++ b/lib/emscripten/emtests/test_getcwd.c @@ -0,0 +1,10 @@ +#include +#include + +int main() { + const unsigned int size = 256; + char cwd[size] = {}; + char* buf = getcwd(cwd, size); + printf("getcwd\n"); + return 0; +} diff --git a/lib/emscripten/emtests/test_getcwd.out b/lib/emscripten/emtests/test_getcwd.out new file mode 100644 index 000000000..263db4c74 --- /dev/null +++ b/lib/emscripten/emtests/test_getcwd.out @@ -0,0 +1 @@ +getcwd diff --git a/lib/emscripten/emtests/test_getcwd.wasm b/lib/emscripten/emtests/test_getcwd.wasm new file mode 100644 index 0000000000000000000000000000000000000000..5f93e3aa2931553d2a51b3b3910c18d16ab17c6d GIT binary patch literal 22468 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 ImportObject "___syscall168" => func!(crate::syscalls::___syscall168), "___syscall180" => func!(crate::syscalls::___syscall180), "___syscall181" => func!(crate::syscalls::___syscall181), + "___syscall183" => func!(crate::syscalls::___syscall183), "___syscall191" => func!(crate::syscalls::___syscall191), "___syscall192" => func!(crate::syscalls::___syscall192), "___syscall194" => func!(crate::syscalls::___syscall194), diff --git a/lib/emscripten/src/syscalls/mod.rs b/lib/emscripten/src/syscalls/mod.rs index ef9ef40ee..c6590cb2d 100644 --- a/lib/emscripten/src/syscalls/mod.rs +++ b/lib/emscripten/src/syscalls/mod.rs @@ -48,6 +48,10 @@ use std::slice; // Other platforms do otherwise. #[cfg(target_os = "darwin")] use libc::SO_NOSIGPIPE; +use crate::utils::copy_cstr_into_wasm; +use crate::env::get_emscripten_data; +use std::ffi::CString; + #[cfg(not(target_os = "darwin"))] const SO_NOSIGPIPE: c_int = 0; @@ -186,6 +190,25 @@ pub fn ___syscall110(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { -1 } +// getcwd +pub fn ___syscall183(ctx: &mut Ctx, buf: u32, _size: u32) -> u32 { + debug!("emscripten::___syscall183"); + use std::env; + let path = env::current_dir(); + match path { + Ok(path_buf) => { + // write path into buffer + let path_string = path_buf.display().to_string(); + let path_c_string = CString::new(path_string).unwrap(); + let offset = unsafe { copy_cstr_into_wasm(ctx, path_c_string.as_ptr()) }; + offset + } + Err(e) => { + unimplemented!() + } + } +} + // mmap2 pub fn ___syscall192(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall192 (mmap2) {}", which); diff --git a/lib/emscripten/tests/emtests/test_getcwd.rs b/lib/emscripten/tests/emtests/test_getcwd.rs new file mode 100644 index 000000000..ec770b505 --- /dev/null +++ b/lib/emscripten/tests/emtests/test_getcwd.rs @@ -0,0 +1,9 @@ +#[test] +fn test_getcwd() { + assert_emscripten_output!( + "../../emtests/test_getcwd.wasm", + "getcwd", + vec![], + "../../emtests/test_getcwd.out" + ); +} From 0f9369c67d67a3d4794ad0edc7ceab0190db43d3 Mon Sep 17 00:00:00 2001 From: Mackenzie Clark Date: Fri, 22 Feb 2019 12:39:19 -0800 Subject: [PATCH 104/262] cargo fmt and better error message --- lib/emscripten/src/syscalls/mod.rs | 8 +++----- lib/emscripten/tests/emtests/mod.rs | 1 + 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/lib/emscripten/src/syscalls/mod.rs b/lib/emscripten/src/syscalls/mod.rs index c6590cb2d..71cd43549 100644 --- a/lib/emscripten/src/syscalls/mod.rs +++ b/lib/emscripten/src/syscalls/mod.rs @@ -46,10 +46,10 @@ use std::slice; // Another conditional constant for name resolution: Macos et iOS use // SO_NOSIGPIPE as a setsockopt flag to disable SIGPIPE emission on socket. // Other platforms do otherwise. +use crate::env::get_emscripten_data; +use crate::utils::copy_cstr_into_wasm; #[cfg(target_os = "darwin")] use libc::SO_NOSIGPIPE; -use crate::utils::copy_cstr_into_wasm; -use crate::env::get_emscripten_data; use std::ffi::CString; #[cfg(not(target_os = "darwin"))] @@ -203,9 +203,7 @@ pub fn ___syscall183(ctx: &mut Ctx, buf: u32, _size: u32) -> u32 { let offset = unsafe { copy_cstr_into_wasm(ctx, path_c_string.as_ptr()) }; offset } - Err(e) => { - unimplemented!() - } + Err(e) => panic!("Failed to read current directory from environment."), } } diff --git a/lib/emscripten/tests/emtests/mod.rs b/lib/emscripten/tests/emtests/mod.rs index 37c88a041..a280fc48a 100644 --- a/lib/emscripten/tests/emtests/mod.rs +++ b/lib/emscripten/tests/emtests/mod.rs @@ -54,6 +54,7 @@ mod test_funcptrfunc; mod test_funcs; mod test_functionpointer_libfunc_varargs; mod test_fwrite_0; +mod test_getcwd; mod test_getgep; mod test_getloadavg; mod test_getopt; From 4042cff91460876679803501ed8614503199dd4f Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Fri, 22 Feb 2019 13:02:28 -0800 Subject: [PATCH 105/262] Change hashing algorithm from sha1 to meowhash --- Cargo.lock | 70 ++++++++--------------------------- lib/runtime-core/Cargo.toml | 4 +- lib/runtime-core/src/cache.rs | 26 ++++++++----- lib/runtime/Cargo.toml | 1 + lib/runtime/benches/nginx.rs | 17 ++++++--- 5 files changed, 47 insertions(+), 71 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 87bf6802d..83051c53f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -87,30 +87,6 @@ name = "bitflags" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "block-buffer" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "block-padding 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "block-padding" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "byte-tools" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "byteorder" version = "1.3.1" @@ -132,7 +108,7 @@ dependencies = [ "serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", - "tempfile 3.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -410,11 +386,6 @@ dependencies = [ "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "fake-simd" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "field-offset" version = "0.1.1" @@ -573,6 +544,14 @@ name = "memoffset" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "meowhash" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "nix" version = "0.12.0" @@ -624,11 +603,6 @@ dependencies = [ "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "opaque-debug" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "owning_ref" version = "0.4.0" @@ -984,17 +958,6 @@ dependencies = [ "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "sha2" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "block-buffer 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "smallvec" version = "0.6.8" @@ -1076,7 +1039,7 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.0.6" +version = "3.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1290,6 +1253,7 @@ dependencies = [ "criterion 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-clif-backend 0.1.2", "wasmer-runtime-core 0.1.2", ] @@ -1308,6 +1272,7 @@ dependencies = [ name = "wasmer-runtime-core" version = "0.1.2" dependencies = [ + "digest 0.8.0 (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)", "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1315,6 +1280,7 @@ dependencies = [ "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "meowhash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "nix 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "page_size 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1322,7 +1288,6 @@ dependencies = [ "serde-bench 0.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", - "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-clif-backend 0.1.2", "wasmparser 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1424,9 +1389,6 @@ dependencies = [ "checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6" "checksum bindgen 0.46.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8f7f7f0701772b17de73e4f5cbcb1dd6926f4706cba4c1ab62c5367f8bdc94e1" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" -"checksum block-buffer 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49665c62e0e700857531fa5d3763e91b539ff1abeebd56808d378b495870d60d" -"checksum block-padding 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d75255892aeb580d3c566f213a2b6fdc1c66667839f45719ee1d30ebf2aea591" -"checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" "checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" "checksum cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "926013f2860c46252efceabb19f4a6b308197505082c609025aa6706c011d427" "checksum cbindgen 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "32e01024aaf5390d6a8145047371a4f5b0063a14c1e411bc731353bd2278ca44" @@ -1458,7 +1420,6 @@ dependencies = [ "checksum errno-dragonfly 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "14ca354e36190500e1e1fb267c647932382b54053c50b14970856c0b00a35067" "checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" "checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" -"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" "checksum field-offset 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "64e9bc339e426139e02601fa69d101e96a92aee71b58bc01697ec2a63a5c9e68" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" @@ -1482,13 +1443,13 @@ dependencies = [ "checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39" "checksum memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" +"checksum meowhash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b00a85ae2fa3525c3f0e6e7b87bec96ab5587100d7ba7b3e30e1885960a8230b" "checksum nix 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "921f61dc817b379d0834e45d5ec45beaacfae97082090a49c2cf30dcbc30206f" "checksum nix 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46f0f3210768d796e8fa79ec70ee6af172dacbe7147f5e69be5240a47778302b" "checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" "checksum nom 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b30adc557058ce00c9d0d7cb3c6e0b5bc6f36e2e2eabe74b0ba726d194abd588" "checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" "checksum num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a23f0ed30a54abaa0c7e83b1d2d87ada7c3c23078d1d87815af3e3b6385fbba" -"checksum opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "93f5bb2e8e8dec81642920ccff6b61f1eb94fa3020c5a325c9851ff604152409" "checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" "checksum page_size 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f89ef58b3d32420dbd1a43d2f38ae92f6239ef12bb556ab09ca55445f5a67242" "checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" @@ -1531,7 +1492,6 @@ dependencies = [ "checksum serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)" = "adb6e51a6b3696b301bc221d785f898b4457c619b51d7ce195a6d20baecb37b3" "checksum serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)" = "ac38f51a52a556cd17545798e29536885fb1a3fa63d6399f5ef650f4a7d35901" "checksum serde_json 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)" = "4b90a9fbe1211e57d3e1c15670f1cb00802988fb23a1a4aad7a2b63544f1920e" -"checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d" "checksum smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "88aea073965ab29f6edb5493faf96ad662fb18aa9eeb186a3b7057951605ed15" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" @@ -1541,7 +1501,7 @@ dependencies = [ "checksum syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)" = "f92e629aa1d9c827b2bb8297046c1ccffc57c99b947a680d3ccff1f136a3bee9" "checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" "checksum target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4af5e2227f0b887d591d3724b796a96eff04226104d872f5b3883fcd427d64b9" -"checksum tempfile 3.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "37daa55a7240c4931c84559f03b3cad7d19535840d1c4a0cc4e9b2fb0dcf70ff" +"checksum tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b86c784c88d98c801132806dadd3819ed29d8600836c4088e855cdf3e178ed8a" "checksum termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" "checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6" diff --git a/lib/runtime-core/Cargo.toml b/lib/runtime-core/Cargo.toml index cb5a6b4b1..cd0648613 100644 --- a/lib/runtime-core/Cargo.toml +++ b/lib/runtime-core/Cargo.toml @@ -29,7 +29,9 @@ version = "1.0" version = "0.10" [dependencies.serde-bench] version = "0.0.7" -[dependencies.sha2] +[dependencies.meowhash] +version = "0.1.2" +[dependencies.digest] version = "0.8.0" [dependencies.hashbrown] version = "0.1" diff --git a/lib/runtime-core/src/cache.rs b/lib/runtime-core/src/cache.rs index dd1e24a9d..4d2a7b385 100644 --- a/lib/runtime-core/src/cache.rs +++ b/lib/runtime-core/src/cache.rs @@ -2,7 +2,8 @@ use crate::{ module::{Module, ModuleInfo}, sys::Memory, }; -use sha2::{Digest, Sha256}; +use digest::Digest; +use meowhash::MeowHasher; use std::{fmt, io, mem, slice}; #[derive(Debug)] @@ -33,7 +34,7 @@ impl From for Error { /// /// [`Cache`]: trait.Cache.html #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub struct WasmHash([u8; 32]); +pub struct WasmHash([u8; 32], [u8; 32]); impl WasmHash { /// Hash a wasm module. @@ -42,19 +43,26 @@ impl WasmHash { /// This does no verification that the supplied data /// is, in fact, a wasm module. pub fn generate(wasm: &[u8]) -> Self { - let mut array = [0u8; 32]; - array.copy_from_slice(Sha256::digest(wasm).as_slice()); - WasmHash(array) + let mut first_part = [0u8; 32]; + let mut second_part = [0u8; 32]; + let generic_array = MeowHasher::digest(wasm); + + first_part.copy_from_slice(&generic_array[0..32]); + second_part.copy_from_slice(&generic_array[32..64]); + WasmHash(first_part, second_part) } /// Create the hexadecimal representation of the /// stored hash. pub fn encode(self) -> String { - hex::encode(self.0) + hex::encode(&self.into_array() as &[u8]) } - pub(crate) fn into_array(self) -> [u8; 32] { - self.0 + pub(crate) fn into_array(self) -> [u8; 64] { + let mut total = [0u8; 64]; + total[0..32].copy_from_slice(&self.0); + total[32..64].copy_from_slice(&self.1); + total } } @@ -67,7 +75,7 @@ struct ArtifactHeader { magic: [u8; 8], // [W, A, S, M, E, R, \0, \0] version: u64, data_len: u64, - wasm_hash: [u8; 32], // Sha256 of the wasm in binary format. + wasm_hash: [u8; 64], // Sha256 of the wasm in binary format. } impl ArtifactHeader { diff --git a/lib/runtime/Cargo.toml b/lib/runtime/Cargo.toml index d7a7effa7..979fae140 100644 --- a/lib/runtime/Cargo.toml +++ b/lib/runtime/Cargo.toml @@ -21,6 +21,7 @@ path = "../clif-backend" version = "0.1.2" [dev-dependencies] +tempfile = "3.0.7" criterion = "0.2" [features] diff --git a/lib/runtime/benches/nginx.rs b/lib/runtime/benches/nginx.rs index f1287dee8..542a87d7d 100644 --- a/lib/runtime/benches/nginx.rs +++ b/lib/runtime/benches/nginx.rs @@ -1,6 +1,7 @@ #[macro_use] extern crate criterion; use criterion::Criterion; +use tempfile::tempdir; use wasmer_runtime::{ cache::{Cache, FileSystemCache, WasmHash}, compile, validate, @@ -12,9 +13,12 @@ fn compile_module() { compile(NGINX_WASM).unwrap(); } -fn load_module(cache: &impl Cache) { - let wasm_hash = WasmHash::generate(NGINX_WASM); - cache.load(wasm_hash).unwrap(); +fn load_module(hash: WasmHash, cache: &impl Cache) { + cache.load(hash).unwrap(); +} + +fn hashing_benchmark(c: &mut Criterion) { + c.bench_function("nginx HASH", |b| b.iter(|| WasmHash::generate(NGINX_WASM))); } fn validate_benchmark(c: &mut Criterion) { @@ -27,17 +31,18 @@ fn compile_benchmark(c: &mut Criterion) { fn load_benchmark(c: &mut Criterion) { c.bench_function("nginx load", |b| { - let mut cache = unsafe { FileSystemCache::new(".").unwrap() }; + let mut cache = unsafe { FileSystemCache::new(tempdir().unwrap().path()).unwrap() }; let module = compile(NGINX_WASM).unwrap(); cache.store(module).unwrap(); + let wasm_hash = WasmHash::generate(NGINX_WASM); - b.iter(|| load_module(&cache)) + b.iter(|| load_module(wasm_hash, &cache)) }); } criterion_group! { name = benches; config = Criterion::default().sample_size(10); - targets = validate_benchmark, compile_benchmark, load_benchmark + targets = validate_benchmark, hashing_benchmark, compile_benchmark, load_benchmark } criterion_main!(benches); From 0c1982442522aebad289fa6008604173f3be1e07 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Fri, 22 Feb 2019 14:07:03 -0800 Subject: [PATCH 106/262] Fix after merge --- lib/clif-backend/src/module.rs | 2 +- lib/runtime-core/src/cache.rs | 1 - lib/runtime-core/src/module.rs | 2 +- lib/runtime/benches/nginx.rs | 11 ++++++++--- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/lib/clif-backend/src/module.rs b/lib/clif-backend/src/module.rs index 38a657625..07efe9bd3 100644 --- a/lib/clif-backend/src/module.rs +++ b/lib/clif-backend/src/module.rs @@ -7,7 +7,7 @@ use cranelift_wasm; use hashbrown::HashMap; use std::sync::Arc; -use wasmer_runtime_core::cache::{Artifact, Error as CacheError, WasmHash}; +use wasmer_runtime_core::cache::{Artifact, Error as CacheError}; use wasmer_runtime_core::{ backend::Backend, diff --git a/lib/runtime-core/src/cache.rs b/lib/runtime-core/src/cache.rs index 64fe3e182..4859bd390 100644 --- a/lib/runtime-core/src/cache.rs +++ b/lib/runtime-core/src/cache.rs @@ -75,7 +75,6 @@ struct ArtifactHeader { magic: [u8; 8], // [W, A, S, M, E, R, \0, \0] version: u64, data_len: u64, - wasm_hash: [u8; 64], // Sha256 of the wasm in binary format. } impl ArtifactHeader { diff --git a/lib/runtime-core/src/module.rs b/lib/runtime-core/src/module.rs index cac375b66..43c9be9dc 100644 --- a/lib/runtime-core/src/module.rs +++ b/lib/runtime-core/src/module.rs @@ -1,6 +1,6 @@ use crate::{ backend::{Backend, FuncResolver, ProtectedCaller}, - cache::{Artifact, Error as CacheError, WasmHash}, + cache::{Artifact, Error as CacheError}, error, import::ImportObject, structures::{Map, TypedIndex}, diff --git a/lib/runtime/benches/nginx.rs b/lib/runtime/benches/nginx.rs index 542a87d7d..1466addb1 100644 --- a/lib/runtime/benches/nginx.rs +++ b/lib/runtime/benches/nginx.rs @@ -14,7 +14,7 @@ fn compile_module() { } fn load_module(hash: WasmHash, cache: &impl Cache) { - cache.load(hash).unwrap(); + cache.load(hash).expect("could not load module"); } fn hashing_benchmark(c: &mut Criterion) { @@ -31,10 +31,15 @@ fn compile_benchmark(c: &mut Criterion) { fn load_benchmark(c: &mut Criterion) { c.bench_function("nginx load", |b| { - let mut cache = unsafe { FileSystemCache::new(tempdir().unwrap().path()).unwrap() }; + let tempdir = tempdir().unwrap(); + let mut cache = unsafe { + FileSystemCache::new(tempdir.path()).expect("unable to create file system cache") + }; let module = compile(NGINX_WASM).unwrap(); - cache.store(module).unwrap(); let wasm_hash = WasmHash::generate(NGINX_WASM); + cache + .store(wasm_hash, module) + .expect("unable to store into cache"); b.iter(|| load_module(wasm_hash, &cache)) }); From 966be3ee8f7760fffb6e414c577199e2ed480b6f Mon Sep 17 00:00:00 2001 From: Mackenzie Clark Date: Fri, 22 Feb 2019 14:54:01 -0800 Subject: [PATCH 107/262] right to the out buffer that was passed in syscall183 --- lib/emscripten/src/syscalls/mod.rs | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/lib/emscripten/src/syscalls/mod.rs b/lib/emscripten/src/syscalls/mod.rs index 71cd43549..3f310be06 100644 --- a/lib/emscripten/src/syscalls/mod.rs +++ b/lib/emscripten/src/syscalls/mod.rs @@ -48,6 +48,7 @@ use std::slice; // Other platforms do otherwise. use crate::env::get_emscripten_data; use crate::utils::copy_cstr_into_wasm; +use crate::utils::read_string_from_wasm; #[cfg(target_os = "darwin")] use libc::SO_NOSIGPIPE; use std::ffi::CString; @@ -191,20 +192,21 @@ pub fn ___syscall110(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { } // getcwd -pub fn ___syscall183(ctx: &mut Ctx, buf: u32, _size: u32) -> u32 { +pub fn ___syscall183(ctx: &mut Ctx, buf_offset: u32, _size: u32) -> u32 { debug!("emscripten::___syscall183"); use std::env; let path = env::current_dir(); - match path { - Ok(path_buf) => { - // write path into buffer - let path_string = path_buf.display().to_string(); - let path_c_string = CString::new(path_string).unwrap(); - let offset = unsafe { copy_cstr_into_wasm(ctx, path_c_string.as_ptr()) }; - offset + let path_string = path.unwrap().display().to_string(); + let len = path_string.len(); + unsafe { + let pointer_to_buffer = emscripten_memory_pointer!(ctx.memory(0), buf_offset) as *mut libc::c_char; + let slice = slice::from_raw_parts_mut(pointer_to_buffer, len.clone()); + for (byte, loc) in path_string.bytes().zip(slice.iter_mut()) { + *loc = byte as _; } - Err(e) => panic!("Failed to read current directory from environment."), + *pointer_to_buffer.add(len.clone()) = 0; } + buf_offset } // mmap2 From b5056d676acb8f30ae9126cc84dce86e5652e690 Mon Sep 17 00:00:00 2001 From: Mackenzie Clark Date: Fri, 22 Feb 2019 15:07:55 -0800 Subject: [PATCH 108/262] update wasm file --- lib/emscripten/emtests/test_getcwd.wasm | Bin 22468 -> 45896 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/lib/emscripten/emtests/test_getcwd.wasm b/lib/emscripten/emtests/test_getcwd.wasm index 5f93e3aa2931553d2a51b3b3910c18d16ab17c6d..0cf6f73a2dcc92510cd370ef0a968f67c65463c5 100644 GIT binary patch literal 45896 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 delta 2827 zcmZvee{2-T6~}kxX7A2E_w2np10lZio3o9N*dmz5Ka!Xxi-QxZIHjdXt*PWX#2^ks zV;hlD+MHXQ1c8NIjTNlmf(@p1g{9b>E71Uv|8P`SIH^NvLnBHMKUx$K2{jJ5#8La+ z>}~T;rP1wYzWa9Gn>TZBX8Ip|>Ma&9S~_41gUk$=9l&u%QSVi?lMZv=FS&7wi}7;7x(O}L%Zf}+l=KoUv;qii29bN zKDTU9d3nK-#pUJY+51LVObvVNy62cLRTPxoqM+T&lf}WJU{UV#;%V&U83FK0ZX43D zySQY4h>%yh6bYXo1qkT@uc{H-d9S5Tih6#=QlE+@>NS|%yx&Uy$*f_dX8E+*>O0AY zEtTVch{RHV6`3~sJLCNp{N7u|4SU#vj|kwJi9V#MwT0tT z736H-eO9_XXNX0ItpqpZEQ2fD_Ux7)F!+GkY?r*qY;^NzP`lY0?94_t=##vto563> z_tm)-jD}6-U7%sp)!|A;f$xkAldd9*w3}^p{+Dx%Tgc55md6Ekmh=@AQr$${mVmsQJyGRk73wGCX8ToD<81b%h6bLz=C~( z|rVy8%$&pa0* zj>DOVdM+kIwO6bibCKR z%lg6?pN*)O3ddMNN%$%L9)&2s6H(`3Ge`5dtm4xV)g+(6SI6WyM-ShLe|K?0UKMav z*r|H?v4D>;c=)r(OQ`el(#VYVeqF$IVT%rVL)hqWK3?lj$Xgf>TGbYv``)Cs`b+?} zbxAoVFglpilbO=5J{Q=9&&4<8JpuP9JyRKjKqj&G1>DyYoEQ9Qm?x7#oKtZkHE2O2 zrY&I4Ml{%$BCw9~cqNlRX92zx_JjprYNunClj$i7w;GvFx-erQlQQkXB@3C9Sr@KY z$fR5*&`WmH!VXE-T)1N)lXBaIISZMTyDltP$fV4>&>cc1rOSn$5HczIUFZuTlhUgp zg)|Vt4oUqk42O_O8FXPZgiOka3lkw^QpQ|37eXfGj0;mCWKt$wm@GZ_H&*|Hx5Ml5*EBpIth zQ)zAfyx!G^OncOVL-fML-KkEMene&C^~4tX;FSBpd}1~J=c!1H>kr21MUDsr0=UIV zK5arHoHiR|+Jv;JcfPabQO3X1?`ZJ!?&XJBY(U%p-2`lZGn4YFi4nn7?FmajSy>TP zxAkR_dv)1;$4g~btkh+X2O@rWmjeGCMPv-`zV)h(+l{G&lX8})(2;O_QNFn)`uBb&W&n^{YmWF z{-mQI|NpvhIieO}r!+wme7{|8qMO03x=-_+XxcHF z_IlX?9omWd=QAx|!$tXtUX#7FBpcV3(wY6r+TD7$G{cK0Cu!jOm?- zmx)P?u*WRCPtfK-#$)#)gNw|WEv|b@!%9A8rB%ZX5AVuXKW@Ab2{2BVDsJP= zB`d?}wxclfj3}7yOh( z%pOI6iNpCBGHTk6o&{NX#WEYRWi*f%R~18RSXAvAs$wPT)KDDndhZXdWJT&fLq(62 zNC1#5hX=sOi_*f;h$Yx5!9^;;6FDxKiQQOw-SHqx|KUW3$a)p;uy&U}@QOM-Ue5Om L_3rrd+z|f-xrN`C From 7fb7529b4803ad487650919d5bd981387b63c03d Mon Sep 17 00:00:00 2001 From: Mackenzie Clark Date: Fri, 22 Feb 2019 15:16:07 -0800 Subject: [PATCH 109/262] cargo fmt --- lib/emscripten/src/syscalls/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/emscripten/src/syscalls/mod.rs b/lib/emscripten/src/syscalls/mod.rs index 3f310be06..2143599f7 100644 --- a/lib/emscripten/src/syscalls/mod.rs +++ b/lib/emscripten/src/syscalls/mod.rs @@ -199,7 +199,8 @@ pub fn ___syscall183(ctx: &mut Ctx, buf_offset: u32, _size: u32) -> u32 { let path_string = path.unwrap().display().to_string(); let len = path_string.len(); unsafe { - let pointer_to_buffer = emscripten_memory_pointer!(ctx.memory(0), buf_offset) as *mut libc::c_char; + let pointer_to_buffer = + emscripten_memory_pointer!(ctx.memory(0), buf_offset) as *mut libc::c_char; let slice = slice::from_raw_parts_mut(pointer_to_buffer, len.clone()); for (byte, loc) in path_string.bytes().zip(slice.iter_mut()) { *loc = byte as _; From 07c8975304524dba8c6c6e790f61bc4a9b9bade2 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Fri, 22 Feb 2019 16:20:26 -0800 Subject: [PATCH 110/262] Fix clif backend --- lib/clif-backend/src/lib.rs | 2 +- lib/clif-backend/src/module.rs | 4 ++-- lib/clif-backend/src/module_env.rs | 1 - lib/clif-backend/src/resolver.rs | 2 +- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/lib/clif-backend/src/lib.rs b/lib/clif-backend/src/lib.rs index df2e4e208..967cdd5ed 100644 --- a/lib/clif-backend/src/lib.rs +++ b/lib/clif-backend/src/lib.rs @@ -43,7 +43,7 @@ impl Compiler for CraneliftCompiler { let isa = get_isa(); - let mut module = module::Module::new(wasm); + let mut module = module::Module::new(); let module_env = module_env::ModuleEnv::new(&mut module, &*isa); let func_bodies = module_env.translate(wasm)?; diff --git a/lib/clif-backend/src/module.rs b/lib/clif-backend/src/module.rs index 38a657625..9e934ee0a 100644 --- a/lib/clif-backend/src/module.rs +++ b/lib/clif-backend/src/module.rs @@ -7,7 +7,7 @@ use cranelift_wasm; use hashbrown::HashMap; use std::sync::Arc; -use wasmer_runtime_core::cache::{Artifact, Error as CacheError, WasmHash}; +use wasmer_runtime_core::cache::{Artifact, Error as CacheError}; use wasmer_runtime_core::{ backend::Backend, @@ -25,7 +25,7 @@ pub struct Module { } impl Module { - pub fn new(wasm: &[u8]) -> Self { + pub fn new() -> Self { Self { info: ModuleInfo { memories: Map::new(), diff --git a/lib/clif-backend/src/module_env.rs b/lib/clif-backend/src/module_env.rs index 643679a5f..7c6cd6731 100644 --- a/lib/clif-backend/src/module_env.rs +++ b/lib/clif-backend/src/module_env.rs @@ -4,7 +4,6 @@ use crate::{ }; use cranelift_codegen::{ir, isa}; use cranelift_wasm::{self, translate_module, FuncTranslator, ModuleEnvironment}; -use std::sync::Arc; use wasmer_runtime_core::{ error::{CompileError, CompileResult}, module::{ diff --git a/lib/clif-backend/src/resolver.rs b/lib/clif-backend/src/resolver.rs index 05af6e3d0..3095e8882 100644 --- a/lib/clif-backend/src/resolver.rs +++ b/lib/clif-backend/src/resolver.rs @@ -202,7 +202,7 @@ impl FuncResolverBuilder { pub fn finalize( mut self, - signatures: &SliceMap>, + signatures: &SliceMap, trampolines: Arc, handler_data: HandlerData, ) -> CompileResult<(FuncResolver, BackendCache)> { From 2a913f5663a90d0255ee2a116c7a4fe2c5364d64 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Fri, 22 Feb 2019 17:34:55 -0800 Subject: [PATCH 111/262] Implement table, partial call_indirect --- Cargo.lock | 177 ++++++++++++++++------------- lib/llvm-backend/src/code.rs | 79 ++++++++++++- lib/llvm-backend/src/intrinsics.rs | 113 +++++++++++++++++- lib/llvm-backend/src/lib.rs | 98 +++++++++++----- 4 files changed, 356 insertions(+), 111 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f4394c573..ca2129890 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ [[package]] name = "aho-corasick" -version = "0.6.9" +version = "0.6.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -19,7 +19,7 @@ name = "atty" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -31,13 +31,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "backtrace" -version = "0.3.13" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -48,7 +48,7 @@ version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -118,11 +118,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", - "tempfile 3.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -150,7 +150,7 @@ version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -264,7 +264,7 @@ dependencies = [ [[package]] name = "either" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -294,7 +294,7 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "errno-dragonfly 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -304,7 +304,7 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -312,7 +312,7 @@ name = "failure" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -377,7 +377,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -409,19 +409,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "inkwell" version = "0.1.0" -source = "git+https://github.com/TheDan64/inkwell?branch=llvm7-0#715423bc67f46518ec489343b52455a27c1ff761" +source = "git+https://github.com/TheDan64/inkwell?branch=llvm7-0#e66f8941061a45299ef73533c747c32bcd5d696a" dependencies = [ - "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "enum-methods 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "inkwell_internal_macros 0.1.0 (git+https://github.com/TheDan64/inkwell?branch=llvm7-0)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "llvm-sys 70.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "inkwell_internal_macros" version = "0.1.0" -source = "git+https://github.com/TheDan64/inkwell?branch=llvm7-0#715423bc67f46518ec489343b52455a27c1ff761" +source = "git+https://github.com/TheDan64/inkwell?branch=llvm7-0#e66f8941061a45299ef73533c747c32bcd5d696a" dependencies = [ "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", @@ -448,13 +448,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.48" -source = "registry+https://github.com/rust-lang/crates.io-index" +version = "0.2.49" +source = "git+https://github.com/rust-lang/libc#68701e7e673da580de8ba6197c544316bd38e84a" [[package]] name = "libc" version = "0.2.49" -source = "git+https://github.com/rust-lang/libc#9a9e2e05c9532557362e5b24b0622259851392fa" +source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libloading" @@ -472,7 +472,7 @@ dependencies = [ "goblin 0.0.20 (registry+https://github.com/rust-lang/crates.io-index)", "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "inkwell 0.1.0 (git+https://github.com/TheDan64/inkwell?branch=llvm7-0)", - "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-runtime-core 0.1.2", "wasmparser 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -485,7 +485,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -517,7 +517,7 @@ name = "memmap" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -529,7 +529,7 @@ dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -541,7 +541,7 @@ dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -573,7 +573,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -591,10 +591,10 @@ name = "parking_lot_core" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -608,6 +608,14 @@ name = "plain" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "proc-macro2" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "proc-macro2" version = "0.4.27" @@ -626,6 +634,14 @@ name = "quote" version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "quote" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "quote" version = "0.6.11" @@ -640,7 +656,7 @@ version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -695,7 +711,7 @@ name = "rand_jitter" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -707,7 +723,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (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.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -766,7 +782,7 @@ name = "regex" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -846,7 +862,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.87" +version = "1.0.88" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", @@ -858,7 +874,7 @@ version = "0.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -866,17 +882,17 @@ name = "serde_bytes" version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_derive" -version = "1.0.87" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.13.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -886,7 +902,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -902,11 +918,8 @@ dependencies = [ [[package]] name = "smallvec" -version = "0.6.8" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "stable_deref_trait" @@ -948,6 +961,16 @@ dependencies = [ "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "syn" +version = "0.13.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "syn" version = "0.15.26" @@ -989,11 +1012,11 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.0.6" +version = "3.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1013,7 +1036,7 @@ name = "termion" version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1039,7 +1062,7 @@ name = "time" version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1049,7 +1072,7 @@ name = "toml" version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1082,14 +1105,6 @@ name = "unicode-xid" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "unreachable" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "utf8-ranges" version = "1.0.2" @@ -1115,8 +1130,8 @@ name = "wabt" version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", "wabt-sys 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1154,12 +1169,12 @@ dependencies = [ "cranelift-native 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", "cranelift-wasm 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "nix 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", "serde-bench 0.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", "target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-runtime-core 0.1.2", "wasmer-win-exception-handler 0.0.1", @@ -1173,8 +1188,8 @@ version = "0.1.0" dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (git+https://github.com/rust-lang/libc)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (git+https://github.com/rust-lang/libc)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1197,7 +1212,7 @@ name = "wasmer-runtime-c-api" version = "0.1.4" dependencies = [ "cbindgen 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-runtime 0.1.4", "wasmer-runtime-core 0.1.2", ] @@ -1212,14 +1227,14 @@ dependencies = [ "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "nix 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "page_size 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", "serde-bench 0.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-clif-backend 0.1.2", "wasmparser 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1241,7 +1256,7 @@ version = "0.0.1" dependencies = [ "bindgen 0.46.0 (registry+https://github.com/rust-lang/crates.io-index)", "cmake 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-runtime-core 0.1.2", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1268,7 +1283,7 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1318,11 +1333,11 @@ dependencies = [ ] [metadata] -"checksum aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1e9a933f4e58658d7b12defcf96dc5c720f20832deebe3e0a19efd3b6aaeeb9e" +"checksum aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "81ce3d38065e618af2d7b77e10c5ad9a069859b4be3c2250f674af3840d9c8a5" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" "checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799" -"checksum backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "b5b493b66e03090ebc4343eb02f94ff944e0cbc9ac6571491d170ba026741eb5" +"checksum backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "cd5a90e2b463010cd0e0ce9a11d4a9d5d58d9f41d4a6ba3dcaf9e68b466e88b4" "checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6" "checksum bindgen 0.46.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8f7f7f0701772b17de73e4f5cbcb1dd6926f4706cba4c1ab62c5367f8bdc94e1" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" @@ -1331,8 +1346,8 @@ dependencies = [ "checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" "checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" "checksum cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "926013f2860c46252efceabb19f4a6b308197505082c609025aa6706c011d427" -"checksum cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)" = "4390a3b5f4f6bce9c1d0c00128379df433e53777fdd30e92f16a529332baec4e" "checksum cbindgen 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "32e01024aaf5390d6a8145047371a4f5b0063a14c1e411bc731353bd2278ca44" +"checksum cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)" = "4390a3b5f4f6bce9c1d0c00128379df433e53777fdd30e92f16a529332baec4e" "checksum cexpr 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "644d693ecfa91955ed32dcc7eda4914e1be97a641fb6f0645a37348e20b230da" "checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" "checksum clang-sys 0.26.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6ef0c1bcf2e99c649104bd7a7012d8f8802684400e03db0ec0af48583c6fa0e4" @@ -1347,7 +1362,7 @@ dependencies = [ "checksum cranelift-native 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "474bee81d620a473bf43411a3d6f10ffbf7965141dc5e5b76d8d2151dde3285d" "checksum cranelift-wasm 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49723365dab9a48b354bdc24cb6d9d5719bc1d3b858ffd2ea179d0d7d885804a" "checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c" -"checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0" +"checksum either 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c67353c641dc847124ea1902d69bd753dee9bb3beff9aa3662ecf86c971d1fac" "checksum enum-methods 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7798e7da2d4cb0d6d6fc467e8d6b5bf247e9e989f786dde1732d79899c32bb10" "checksum env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "afb070faf94c85d17d50ca44f6ad076bce18ae92f0037d350947240a36e9d42e" "checksum errno 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c2a071601ed01b988f896ab14b95e67335d1eeb50190932a1320f7fe3cadc84e" @@ -1371,8 +1386,8 @@ dependencies = [ "checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1" -"checksum libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)" = "e962c7641008ac010fa60a7dfdc1712449f29c44ef2d4702394aea943ee75047" "checksum libc 0.2.49 (git+https://github.com/rust-lang/libc)" = "" +"checksum libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)" = "413f3dfc802c5dc91dc570b05125b6cda9855edfaa9825c9849807876376e70e" "checksum libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3ad660d7cb8c5822cd83d10897b0f1f1526792737a179e73896152f85b88c2" "checksum llvm-sys 70.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60a9ee82fe0fa72ae6ef6d018b407296085863836451c7a97384f84ed7e26b9f" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" @@ -1389,9 +1404,11 @@ dependencies = [ "checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" "checksum peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" "checksum plain 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" +"checksum proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1b06e2f335f48d24442b35a19df506a835fb3547bc3c06ef27340da9acf5cae7" "checksum proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" +"checksum quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9949cfe66888ffe1d53e6ec9d9f3b70714083854be20fd5e271b232a017401e8" "checksum quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cdd8e04bd9c52e0342b406469d494fcb033be4bdbe5c606016defbb1681411e1" "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" "checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" @@ -1418,23 +1435,24 @@ dependencies = [ "checksum scroll_derive 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8f1aa96c45e7f5a91cb7fabe7b279f02fea7126239fc40b732316e8b6a2d0fcb" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)" = "2e20fde37801e83c891a2dc4ebd3b81f0da4d1fb67a9e0a2a3b921e2536a58ee" +"checksum serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)" = "9f301d728f2b94c9a7691c90f07b0b4e8a4517181d9461be94c04bddeb4bd850" "checksum serde-bench 0.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "d733da87e79faaac25616e33d26299a41143fd4cd42746cbb0e91d8feea243fd" "checksum serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)" = "adb6e51a6b3696b301bc221d785f898b4457c619b51d7ce195a6d20baecb37b3" -"checksum serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)" = "633e97856567e518b59ffb2ad7c7a4fd4c5d91d9c7f32dd38a27b2bf7e8114ea" +"checksum serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)" = "ac38f51a52a556cd17545798e29536885fb1a3fa63d6399f5ef650f4a7d35901" "checksum serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)" = "27dce848e7467aa0e2fcaf0a413641499c0b745452aaca1194d24dedde9e13c9" "checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d" -"checksum smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "88aea073965ab29f6edb5493faf96ad662fb18aa9eeb186a3b7057951605ed15" +"checksum smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c4488ae950c49d403731982257768f48fada354a5203fe81f9bb6f43ca9002be" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" "checksum structopt 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "670ad348dc73012fcf78c71f06f9d942232cdd4c859d4b6975e27836c3efc0c3" "checksum structopt-derive 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "ef98172b1a00b0bec738508d3726540edcbd186d50dfd326f2b1febbb3559f04" "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" +"checksum syn 0.13.11 (registry+https://github.com/rust-lang/crates.io-index)" = "14f9bf6292f3a61d2c716723fdb789a41bbe104168e6f496dc6497e531ea1b9b" "checksum syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)" = "f92e629aa1d9c827b2bb8297046c1ccffc57c99b947a680d3ccff1f136a3bee9" "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" "checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" "checksum target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4af5e2227f0b887d591d3724b796a96eff04226104d872f5b3883fcd427d64b9" -"checksum tempfile 3.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "37daa55a7240c4931c84559f03b3cad7d19535840d1c4a0cc4e9b2fb0dcf70ff" +"checksum tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b86c784c88d98c801132806dadd3819ed29d8600836c4088e855cdf3e178ed8a" "checksum termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" "checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6" @@ -1447,7 +1465,6 @@ dependencies = [ "checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" -"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" "checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index 48c477f4a..d72659fd9 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -13,7 +13,8 @@ use wasmer_runtime_core::{ module::ModuleInfo, structures::{Map, SliceMap, TypedIndex}, types::{ - FuncIndex, FuncSig, GlobalIndex, LocalFuncIndex, LocalOrImport, MemoryIndex, SigIndex, Type, + FuncIndex, FuncSig, GlobalIndex, LocalFuncIndex, LocalOrImport, MemoryIndex, SigIndex, + TableIndex, Type, }, }; use wasmparser::{ @@ -622,6 +623,82 @@ fn parse_function( } } Operator::CallIndirect { index, table_index } => { + let expected_dynamic_sigindex = ctx.dynamic_sigindex(SigIndex::new(index as usize)); + let (table_base, table_bound) = ctx.table(TableIndex::new(table_index as usize)); + let func_index = state.pop1()?.into_int_value(); + + // We assume the table has the `anyfunc` element type. + let casted_table_base = builder.build_pointer_cast( + table_base, + intrinsics.anyfunc_ty.ptr_type(AddressSpace::Generic), + "casted_table_base", + ); + + let anyfunc_struct_ptr = unsafe { + builder.build_in_bounds_gep( + casted_table_base, + &[func_index], + "anyfunc_struct_ptr", + ) + }; + + // Load things from the anyfunc data structure. + let (func_ptr, ctx_ptr, found_dynamic_sigindex) = unsafe { + ( + builder + .build_load( + builder.build_struct_gep(anyfunc_struct_ptr, 0, "func_ptr_ptr"), + "func_ptr", + ) + .into_pointer_value(), + builder + .build_load( + builder.build_struct_gep(anyfunc_struct_ptr, 1, "ctx_ptr_ptr"), + "ctx_ptr", + ) + .into_pointer_value(), + builder + .build_load( + builder.build_struct_gep(anyfunc_struct_ptr, 2, "sigindex_ptr"), + "sigindex", + ) + .into_int_value(), + ) + }; + + let sigindices_equal = builder.build_int_compare( + IntPredicate::EQ, + expected_dynamic_sigindex, + found_dynamic_sigindex, + "sigindices_equal", + ); + + // Tell llvm that `expected_dynamic_sigindex` should equal `found_dynamic_sigindex`. + let sigindices_equal = builder + .build_call( + intrinsics.expect_i1, + &[ + sigindices_equal.as_basic_value_enum(), + intrinsics.i1_ty.const_int(1, false).as_basic_value_enum(), + ], + "sigindices_equal_expect", + ) + .try_as_basic_value() + .left() + .unwrap(); + + let continue_block = context.append_basic_block(&function, "continue_block"); + let sigindices_notequal_block = + context.append_basic_block(&function, "sigindices_notequal_block"); + + builder.position_at_end(&sigindices_notequal_block); + builder.build_unreachable(); + builder.position_at_end(&continue_block); + + println!("func ptr: {:#?}", func_ptr); + println!("ctx ptr: {:#?}", ctx_ptr); + println!("found dynamic sigindex: {:#?}", found_dynamic_sigindex); + unimplemented!("{}, {}", index, table_index); } diff --git a/lib/llvm-backend/src/intrinsics.rs b/lib/llvm-backend/src/intrinsics.rs index 6ffbb6ea6..ccc0081bf 100644 --- a/lib/llvm-backend/src/intrinsics.rs +++ b/lib/llvm-backend/src/intrinsics.rs @@ -12,7 +12,9 @@ use wasmer_runtime_core::{ memory::MemoryType, module::ModuleInfo, structures::TypedIndex, - types::{GlobalIndex, ImportedFuncIndex, LocalOrImport, MemoryIndex, TableIndex, Type}, + types::{ + GlobalIndex, ImportedFuncIndex, LocalOrImport, MemoryIndex, SigIndex, TableIndex, Type, + }, }; fn type_to_llvm_ptr(intrinsics: &Intrinsics, ty: Type) -> PointerType { @@ -61,6 +63,8 @@ pub struct Intrinsics { pub copysign_f32: FunctionValue, pub copysign_f64: FunctionValue, + pub expect_i1: FunctionValue, + pub void_ty: VoidType, pub i1_ty: IntType, pub i8_ty: IntType, @@ -77,6 +81,8 @@ pub struct Intrinsics { pub f32_ptr_ty: PointerType, pub f64_ptr_ty: PointerType, + pub anyfunc_ty: StructType, + pub i1_zero: IntValue, pub i32_zero: IntValue, pub i64_zero: IntValue, @@ -142,6 +148,17 @@ impl Intrinsics { let local_global_ty = i64_ty; let imported_func_ty = context.struct_type(&[i8_ptr_ty_basic, ctx_ptr_ty.as_basic_type_enum()], false); + let sigindex_ty = i32_ty; + + let anyfunc_ty = context.struct_type( + &[ + i8_ptr_ty_basic, + ctx_ptr_ty.as_basic_type_enum(), + sigindex_ty.as_basic_type_enum(), + ], + false, + ); + ctx_ty.set_body( &[ local_memory_ty @@ -172,6 +189,9 @@ impl Intrinsics { .ptr_type(AddressSpace::Generic) .ptr_type(AddressSpace::Generic) .as_basic_type_enum(), + sigindex_ty + .ptr_type(AddressSpace::Generic) + .as_basic_type_enum(), ], false, ); @@ -195,6 +215,8 @@ impl Intrinsics { let ret_i32_take_ctx_i32 = i32_ty.fn_type(&[ctx_ptr_ty.as_basic_type_enum(), i32_ty_basic], false); + let ret_i1_take_i1_i1 = i1_ty.fn_type(&[i1_ty_basic, i1_ty_basic], false); + Self { ctlz_i32: module.add_function("llvm.ctlz.i32", ret_i32_take_i32_i1, None), ctlz_i64: module.add_function("llvm.ctlz.i64", ret_i64_take_i64_i1, None), @@ -232,6 +254,8 @@ impl Intrinsics { copysign_f32: module.add_function("llvm.copysign.f32", ret_f32_take_f32_f32, None), copysign_f64: module.add_function("llvm.copysign.f64", ret_f64_take_f64_f64, None), + expect_i1: module.add_function("llvm.expect.i1", ret_i1_take_i1_i1, None), + void_ty, i1_ty, i8_ty, @@ -248,6 +272,8 @@ impl Intrinsics { f32_ptr_ty, f64_ptr_ty, + anyfunc_ty, + i1_zero, i32_zero, i64_zero, @@ -340,6 +366,7 @@ impl Intrinsics { cached_memories: HashMap::new(), cached_tables: HashMap::new(), + cached_sigindices: HashMap::new(), cached_globals: HashMap::new(), cached_imported_functions: HashMap::new(), @@ -389,6 +416,7 @@ pub struct CtxType<'a> { cached_memories: HashMap, cached_tables: HashMap, + cached_sigindices: HashMap, cached_globals: HashMap, cached_imported_functions: HashMap, @@ -473,6 +501,89 @@ impl<'a> CtxType<'a> { } } + pub fn table(&mut self, index: TableIndex) -> (PointerValue, IntValue) { + let (cached_tables, builder, info, ctx_ptr_value, intrinsics) = ( + &mut self.cached_tables, + self.builder, + self.info, + self.ctx_ptr_value, + self.intrinsics, + ); + + let TableCache { + ptr_to_base_ptr, + ptr_to_bounds, + } = *cached_tables.entry(index).or_insert_with(|| { + let (table_array_ptr_ptr, index) = match index.local_or_import(info) { + LocalOrImport::Local(local_table_index) => ( + unsafe { builder.build_struct_gep(ctx_ptr_value, 1, "table_array_ptr_ptr") }, + local_table_index.index() as u64, + ), + LocalOrImport::Import(import_table_index) => ( + unsafe { builder.build_struct_gep(ctx_ptr_value, 4, "table_array_ptr_ptr") }, + import_table_index.index() as u64, + ), + }; + + let table_array_ptr = builder + .build_load(table_array_ptr_ptr, "table_array_ptr") + .into_pointer_value(); + let const_index = intrinsics.i32_ty.const_int(index, false); + let table_ptr_ptr = unsafe { + builder.build_in_bounds_gep(table_array_ptr, &[const_index], "table_ptr_ptr") + }; + let table_ptr = builder + .build_load(table_ptr_ptr, "table_ptr") + .into_pointer_value(); + + let (ptr_to_base_ptr, ptr_to_bounds) = unsafe { + ( + builder.build_struct_gep(table_ptr, 0, "base_ptr"), + builder.build_struct_gep(table_ptr, 1, "bounds_ptr"), + ) + }; + + TableCache { + ptr_to_base_ptr, + ptr_to_bounds, + } + }); + + ( + builder + .build_load(ptr_to_base_ptr, "base_ptr") + .into_pointer_value(), + builder.build_load(ptr_to_bounds, "bounds").into_int_value(), + ) + } + + pub fn dynamic_sigindex(&mut self, index: SigIndex) -> IntValue { + let (cached_sigindices, builder, info, ctx_ptr_value, intrinsics) = ( + &mut self.cached_sigindices, + self.builder, + self.info, + self.ctx_ptr_value, + self.intrinsics, + ); + + *cached_sigindices.entry(index).or_insert_with(|| { + let sigindex_array_ptr_ptr = + unsafe { builder.build_struct_gep(ctx_ptr_value, 7, "sigindex_array_ptr_ptr") }; + let sigindex_array_ptr = builder + .build_load(sigindex_array_ptr_ptr, "sigindex_array_ptr") + .into_pointer_value(); + let const_index = intrinsics.i32_ty.const_int(index.index() as u64, false); + + let sigindex_ptr = unsafe { + builder.build_in_bounds_gep(sigindex_array_ptr, &[const_index], "sigindex_ptr") + }; + + builder + .build_load(sigindex_ptr, "sigindex") + .into_int_value() + }) + } + pub fn global_cache(&mut self, index: GlobalIndex) -> GlobalCache { let (cached_globals, builder, ctx_ptr_value, info, intrinsics) = ( &mut self.cached_globals, diff --git a/lib/llvm-backend/src/lib.rs b/lib/llvm-backend/src/lib.rs index 6279aa8e1..e70af96c0 100644 --- a/lib/llvm-backend/src/lib.rs +++ b/lib/llvm-backend/src/lib.rs @@ -1,13 +1,14 @@ -use wasmer_runtime_core::{ - backend::{Compiler, Token}, - error::CompileError, - module::ModuleInner, -}; use inkwell::{ execution_engine::JitFunction, - targets::{TargetMachine, Target, RelocMode, CodeModel, InitializationConfig, FileType}, + targets::{CodeModel, FileType, InitializationConfig, RelocMode, Target, TargetMachine}, OptimizationLevel, }; +use wasmer_runtime_core::{ + backend::{Compiler, Token}, + cache::{Artifact, Error as CacheError}, + error::CompileError, + module::ModuleInner, +}; mod code; mod intrinsics; @@ -31,22 +32,29 @@ impl Compiler for LLVMCompiler { unimplemented!() } + + unsafe fn from_cache(&self, _artifact: Artifact, _: Token) -> Result { + unimplemented!() + } } #[test] fn test_read_module() { - use wasmer_runtime_core::vmcalls; use wabt::wat2wasm; + use wasmer_runtime_core::vmcalls; // let wasm = include_bytes!("../../spectests/examples/simple/simple.wasm") as &[u8]; let wat = r#" (module (type $t0 (func (param i32) (result i32))) (type $t1 (func (result i32))) (memory 1) + (table 10 anyfunc) + (elem (i32.const 0) $foobar) (global $g0 (mut i32) (i32.const 0)) (func $foo (type $t0) (param i32) (result i32) get_local 0 - call $foobar + i32.const 0 + call_indirect (type $t0) memory.grow ) (func $foobar (type $t0) @@ -74,19 +82,23 @@ fn test_read_module() { }); let triple = TargetMachine::get_default_triple().to_string(); let target = Target::from_triple(&triple).unwrap(); - let target_machine = target.create_target_machine( - &triple, - &TargetMachine::get_host_cpu_name().to_string(), - &TargetMachine::get_host_cpu_features().to_string(), - OptimizationLevel::Default, - RelocMode::PIC, - CodeModel::Default, - ).unwrap(); + let target_machine = target + .create_target_machine( + &triple, + &TargetMachine::get_host_cpu_name().to_string(), + &TargetMachine::get_host_cpu_features().to_string(), + OptimizationLevel::Default, + RelocMode::PIC, + CodeModel::Default, + ) + .unwrap(); - let memory_buffer = target_machine.write_to_memory_buffer(&module, FileType::Object).unwrap(); + let memory_buffer = target_machine + .write_to_memory_buffer(&module, FileType::Object) + .unwrap(); // std::fs::write("memory_buffer", memory_buffer.as_slice()).unwrap(); let mem_buf_slice = memory_buffer.as_slice(); - + let macho = goblin::mach::MachO::parse(mem_buf_slice, 0).unwrap(); let symbols = macho.symbols.as_ref().unwrap(); let relocations = macho.relocations().unwrap(); @@ -95,22 +107,50 @@ fn test_read_module() { for reloc_info in reloc_iter { let reloc_info = reloc_info.unwrap(); println!("\treloc_info: {:#?}", reloc_info); - println!("\tsymbol: {:#?}", symbols.get(reloc_info.r_symbolnum()).unwrap()); + println!( + "\tsymbol: {:#?}", + symbols.get(reloc_info.r_symbolnum()).unwrap() + ); } } } - - let exec_engine = module.create_jit_execution_engine(OptimizationLevel::Default).unwrap(); + let exec_engine = module + .create_jit_execution_engine(OptimizationLevel::Default) + .unwrap(); - exec_engine.add_global_mapping(&intrinsics.memory_grow_dynamic_local, vmcalls::local_dynamic_memory_grow as usize); - exec_engine.add_global_mapping(&intrinsics.memory_grow_static_local, vmcalls::local_static_memory_grow as usize); - exec_engine.add_global_mapping(&intrinsics.memory_grow_dynamic_import, vmcalls::imported_dynamic_memory_grow as usize); - exec_engine.add_global_mapping(&intrinsics.memory_grow_static_import, vmcalls::imported_static_memory_grow as usize); - exec_engine.add_global_mapping(&intrinsics.memory_size_dynamic_local, vmcalls::local_dynamic_memory_size as usize); - exec_engine.add_global_mapping(&intrinsics.memory_size_static_local, vmcalls::local_static_memory_size as usize); - exec_engine.add_global_mapping(&intrinsics.memory_size_dynamic_import, vmcalls::imported_dynamic_memory_size as usize); - exec_engine.add_global_mapping(&intrinsics.memory_size_static_import, vmcalls::imported_static_memory_size as usize); + exec_engine.add_global_mapping( + &intrinsics.memory_grow_dynamic_local, + vmcalls::local_dynamic_memory_grow as usize, + ); + exec_engine.add_global_mapping( + &intrinsics.memory_grow_static_local, + vmcalls::local_static_memory_grow as usize, + ); + exec_engine.add_global_mapping( + &intrinsics.memory_grow_dynamic_import, + vmcalls::imported_dynamic_memory_grow as usize, + ); + exec_engine.add_global_mapping( + &intrinsics.memory_grow_static_import, + vmcalls::imported_static_memory_grow as usize, + ); + exec_engine.add_global_mapping( + &intrinsics.memory_size_dynamic_local, + vmcalls::local_dynamic_memory_size as usize, + ); + exec_engine.add_global_mapping( + &intrinsics.memory_size_static_local, + vmcalls::local_static_memory_size as usize, + ); + exec_engine.add_global_mapping( + &intrinsics.memory_size_dynamic_import, + vmcalls::imported_dynamic_memory_size as usize, + ); + exec_engine.add_global_mapping( + &intrinsics.memory_size_static_import, + vmcalls::imported_static_memory_size as usize, + ); // unsafe { // let func: JitFunction i32> = exec_engine.get_function("fn0").unwrap(); From fa596d2d2325ab07ef3646029602d2f4c30a7f22 Mon Sep 17 00:00:00 2001 From: Syrus Akbary Date: Fri, 22 Feb 2019 17:38:28 -0800 Subject: [PATCH 112/262] Update Cargo.toml --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 67fbda1b7..15b09e542 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer" -version = "0.1.4" +version = "0.2.0" authors = ["The Wasmer Engineering Team "] edition = "2018" repository = "https://github.com/wasmerio/wasmer" From 82eef13f41f3031b35b62e42336ddedec0103216 Mon Sep 17 00:00:00 2001 From: Mackenzie Clark Date: Fri, 22 Feb 2019 22:18:59 -0800 Subject: [PATCH 113/262] Create a grow error and refactor grow impl to return result (#191) --- Cargo.lock | 2 +- lib/runtime-c-api/src/lib.rs | 30 +++-- lib/runtime-c-api/tests/test-memory.c | 37 ++++--- lib/runtime-c-api/tests/test-tables.c | 41 +++---- lib/runtime-core/src/error.rs | 103 ++++++++++++++++++ lib/runtime-core/src/memory/dynamic.rs | 24 ++-- lib/runtime-core/src/memory/mod.rs | 10 +- .../src/memory/static_/unshared.rs | 20 ++-- lib/runtime-core/src/sys/unix/memory.rs | 28 +++-- lib/runtime-core/src/sys/windows/memory.rs | 17 ++- lib/runtime-core/src/table/mod.rs | 11 +- lib/runtime-core/src/units.rs | 11 +- lib/runtime-core/src/vmcalls.rs | 28 ++--- 13 files changed, 250 insertions(+), 112 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 83051c53f..0b062168f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1197,7 +1197,7 @@ dependencies = [ [[package]] name = "wasmer" -version = "0.1.4" +version = "0.2.0" dependencies = [ "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "structopt 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index f19380cdb..f52076d28 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -208,14 +208,13 @@ pub extern "C" fn wasmer_memory_grow( delta: uint32_t, ) -> wasmer_result_t { let memory = unsafe { &*(memory as *mut Memory) }; - let maybe_delta = memory.grow(Pages(delta)); - if let Some(_delta) = maybe_delta { - wasmer_result_t::WASMER_OK - } else { - update_last_error(CApiError { - msg: "unable to grow memory".to_string(), - }); - wasmer_result_t::WASMER_ERROR + let delta_result = memory.grow(Pages(delta)); + match delta_result { + Ok(_) => wasmer_result_t::WASMER_OK, + Err(grow_error) => { + update_last_error(grow_error); + wasmer_result_t::WASMER_ERROR + } } } @@ -277,14 +276,13 @@ pub extern "C" fn wasmer_table_grow( delta: uint32_t, ) -> wasmer_result_t { let table = unsafe { &*(table as *mut Table) }; - let maybe_delta = table.grow(delta); - if let Some(_delta) = maybe_delta { - wasmer_result_t::WASMER_OK - } else { - update_last_error(CApiError { - msg: "unable to grow table".to_string(), - }); - wasmer_result_t::WASMER_ERROR + let delta_result = table.grow(delta); + match delta_result { + Ok(_) => wasmer_result_t::WASMER_OK, + Err(grow_error) => { + update_last_error(grow_error); + wasmer_result_t::WASMER_ERROR + } } } diff --git a/lib/runtime-c-api/tests/test-memory.c b/lib/runtime-c-api/tests/test-memory.c index 63913c73b..64e028693 100644 --- a/lib/runtime-c-api/tests/test-memory.c +++ b/lib/runtime-c-api/tests/test-memory.c @@ -23,13 +23,13 @@ int main() wasmer_result_t grow_result = wasmer_memory_grow(memory, 2); assert(grow_result == WASMER_OK); - uint32_t new_len = wasmer_memory_length(memory); + uint32_t new_len = wasmer_memory_length(memory); printf("Memory pages length: %d\n", new_len); assert(new_len == 12); - uint32_t bytes_len = wasmer_memory_data_length(memory); + uint32_t bytes_len = wasmer_memory_data_length(memory); printf("Memory bytes length: %d\n", bytes_len); - assert(bytes_len == 12 * 65536); + assert(bytes_len == 12 * 65536); // Err, grow beyond max wasmer_result_t grow_result2 = wasmer_memory_grow(memory, 10); @@ -38,23 +38,26 @@ int main() char *error_str = malloc(error_len); wasmer_last_error_message(error_str, error_len); printf("Error str: `%s`\n", error_str); - assert(0 == strcmp(error_str, "unable to grow memory")); + assert(0 == strcmp(error_str, "Failed to add pages because would exceed maximum number of pages for the memory. Left: 22, Added: 15")); free(error_str); + wasmer_memory_t *bad_memory = NULL; + wasmer_limits_t bad_descriptor; + bad_descriptor.min = 15; + wasmer_limit_option_t max2; + max2.has_some = true; + max2.some = 10; + bad_descriptor.max = max2; + wasmer_result_t bad_memory_result = wasmer_memory_new(&bad_memory, bad_descriptor); + printf("Bad memory result: %d\n", bad_memory_result); + assert(bad_memory_result == WASMER_ERROR); -// wasmer_memory_t *bad_memory = NULL; -// wasmer_limits_t bad_descriptor; -// bad_descriptor.min = 15; -// bad_descriptor.max = 10; -// wasmer_result_t bad_memory_result = wasmer_memory_new(&bad_memory, bad_descriptor); -// printf("Bad memory result: %d\n", bad_memory_result); -// assert(memory_result == WASMER_MEMORY_ERROR); -// -// int error_len = wasmer_last_error_length(); -// char *error_str = malloc(error_len); -// wasmer_last_error_message(error_str, error_len); -// assert(0 == strcmp(error_str, "Creation error")); -// free(error_str); + int error_len2 = wasmer_last_error_length(); + char *error_str2 = malloc(error_len2); + wasmer_last_error_message(error_str2, error_len2); + printf("Error str 2: `%s`\n", error_str2); + assert(0 == strcmp(error_str2, "Unable to create because the supplied descriptor is invalid: \"Max number of memory pages is less than the minimum number of pages\"")); + free(error_str2); printf("Destroy memory\n"); wasmer_memory_destroy(memory); diff --git a/lib/runtime-c-api/tests/test-tables.c b/lib/runtime-c-api/tests/test-tables.c index 48b7be710..ac093d182 100644 --- a/lib/runtime-c-api/tests/test-tables.c +++ b/lib/runtime-c-api/tests/test-tables.c @@ -9,7 +9,7 @@ int main() wasmer_limits_t descriptor; descriptor.min = 10; wasmer_limit_option_t max; -// max.has_some = false; + // max.has_some = false; max.has_some = true; max.some = 15; descriptor.max = max; @@ -21,26 +21,29 @@ int main() printf("Table length: %d\n", len); assert(len == 10); -// wasmer_result_t grow_result1 = wasmer_table_grow(table, 5); -// assert(grow_result1 == WASMER_OK); -// uint32_t len_grow1 = wasmer_table_length(table); -// printf("Table length: %d\n", len_grow1); -// assert(len_grow1 == 15); + wasmer_result_t grow_result1 = wasmer_table_grow(table, 5); + assert(grow_result1 == WASMER_OK); + uint32_t len_grow1 = wasmer_table_length(table); + printf("Table length: %d\n", len_grow1); + assert(len_grow1 == 15); - // // Try to grow beyond max - // wasmer_result_t grow_result2 = wasmer_table_grow(&table, 1); - // assert(grow_result2 == WASMER_ERROR); - // uint32_t len_grow2 = wasmer_table_length(table); - // printf("Table length: %d\n", len_grow2); - // assert(len_grow2 == 15); + // Try to grow beyond max + wasmer_result_t grow_result2 = wasmer_table_grow(table, 1); + assert(grow_result2 == WASMER_ERROR); + uint32_t len_grow2 = wasmer_table_length(table); + printf("Table length: %d\n", len_grow2); + assert(len_grow2 == 15); -// wasmer_table_t *table_bad = NULL; -// wasmer_limits_t bad_descriptor; -// bad_descriptor.min = 15; -// bad_descriptor.max = 10; -// wasmer_result_t table_bad_result = wasmer_table_new(&table_bad, bad_descriptor); -// printf("Table result: %d\n", table_bad_result); -// assert(table_result == WASMER_ERROR); + wasmer_table_t *table_bad = NULL; + wasmer_limits_t bad_descriptor; + bad_descriptor.min = 15; + wasmer_limit_option_t max2; + max2.has_some = true; + max2.some = 10; + bad_descriptor.max = max2; + wasmer_result_t table_bad_result = wasmer_table_new(&table_bad, bad_descriptor); + printf("Table result: %d\n", table_bad_result); + assert(table_bad_result == WASMER_ERROR); printf("Destroy table\n"); wasmer_table_destroy(table); diff --git a/lib/runtime-core/src/error.rs b/lib/runtime-core/src/error.rs index 33c9fd15f..1f9f60c61 100644 --- a/lib/runtime-core/src/error.rs +++ b/lib/runtime-core/src/error.rs @@ -1,3 +1,4 @@ +use crate::sys::Memory; use crate::types::{ FuncSig, GlobalDescriptor, MemoryDescriptor, MemoryIndex, TableDescriptor, TableIndex, Type, }; @@ -369,3 +370,105 @@ impl std::fmt::Display for Error { } impl std::error::Error for Error {} + +#[derive(Debug)] +pub enum GrowError { + MemoryGrowError, + TableGrowError, + ExceededMaxPages(PageError), + ExceededMaxPagesForMemory(usize, usize), + CouldNotProtectMemory(MemoryProtectionError), + CouldNotCreateMemory(MemoryCreationError), +} + +impl std::fmt::Display for GrowError { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + GrowError::MemoryGrowError => write!(f, "Unable to grow memory"), + GrowError::TableGrowError => write!(f, "Unable to grow table"), + GrowError::ExceededMaxPages(e) => write!(f, "Grow Error: {}", e), + GrowError::ExceededMaxPagesForMemory(left, added) => write!(f, "Failed to add pages because would exceed maximum number of pages for the memory. Left: {}, Added: {}", left, added), + GrowError::CouldNotCreateMemory(e) => write!(f, "Grow Error: {}", e), + GrowError::CouldNotProtectMemory(e) => write!(f, "Grow Error: {}", e), + } + } +} + +impl std::error::Error for GrowError {} + +#[derive(Debug)] +pub enum PageError { + // left, right, added + ExceededMaxPages(usize, usize, usize), +} + +impl std::fmt::Display for PageError { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + PageError::ExceededMaxPages(left, right, added) => write!(f, "Failed to add pages because would exceed maximum number of pages. Left: {}, Right: {}, Pages added: {}", left, right, added), + } + } +} +impl std::error::Error for PageError {} + +impl Into for PageError { + fn into(self) -> GrowError { + GrowError::ExceededMaxPages(self) + } +} + +#[derive(Debug)] +pub enum MemoryCreationError { + VirtualMemoryAllocationFailed(usize, String), + CouldNotCreateMemoryFromFile(std::io::Error), +} + +impl std::fmt::Display for MemoryCreationError { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + MemoryCreationError::VirtualMemoryAllocationFailed(size, msg) => write!( + f, + "Allocation virtual memory with size {} failed. \nErrno message: {}", + size, msg + ), + MemoryCreationError::CouldNotCreateMemoryFromFile(e) => write!(f, "IO Error: {}", e), + } + } +} +impl std::error::Error for MemoryCreationError {} + +impl Into for MemoryCreationError { + fn into(self) -> GrowError { + GrowError::CouldNotCreateMemory(self) + } +} + +impl From for MemoryCreationError { + fn from(io_error: std::io::Error) -> Self { + MemoryCreationError::CouldNotCreateMemoryFromFile(io_error) + } +} + +#[derive(Debug)] +pub enum MemoryProtectionError { + ProtectionFailed(usize, usize, String), +} + +impl std::fmt::Display for MemoryProtectionError { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + MemoryProtectionError::ProtectionFailed(start, size, msg) => write!( + f, + "Allocation virtual memory starting at {} with size {} failed. \nErrno message: {}", + start, size, msg + ), + } + } +} +impl std::error::Error for MemoryProtectionError {} + +impl Into for MemoryProtectionError { + fn into(self) -> GrowError { + GrowError::CouldNotProtectMemory(self) + } +} diff --git a/lib/runtime-core/src/memory/dynamic.rs b/lib/runtime-core/src/memory/dynamic.rs index bfe731a83..332a37acb 100644 --- a/lib/runtime-core/src/memory/dynamic.rs +++ b/lib/runtime-core/src/memory/dynamic.rs @@ -1,3 +1,4 @@ +use crate::error::GrowError; use crate::{ error::CreationError, sys, @@ -14,9 +15,9 @@ pub const DYNAMIC_GUARD_SIZE: usize = 4096; /// when first created. Over time, as it grows, it may reallocate to /// a different location and size. /// -/// Dynamic memories are signifigantly faster to create than static +/// Dynamic memories are significantly faster to create than static /// memories and use much less virtual memory, however, they require -/// the webassembly module to bounds-check memory accesses. +/// the WebAssembly module to bounds-check memory accesses. /// /// While, a dynamic memory could use a vector of some sort as its /// backing memory, we use mmap (or the platform-equivalent) to allow @@ -65,26 +66,29 @@ impl DynamicMemory { self.current } - pub fn grow(&mut self, delta: Pages, local: &mut vm::LocalMemory) -> Option { + pub fn grow(&mut self, delta: Pages, local: &mut vm::LocalMemory) -> Result { if delta == Pages(0) { - return Some(self.current); + return Ok(self.current); } - let new_pages = self.current.checked_add(delta)?; + let new_pages = self.current.checked_add(delta).map_err(|e| e.into())?; if let Some(max) = self.max { if new_pages > max { - return None; + return Err(GrowError::ExceededMaxPagesForMemory( + new_pages.0 as usize, + max.0 as usize, + )); } } - let mut new_memory = - sys::Memory::with_size(new_pages.bytes().0 + DYNAMIC_GUARD_SIZE).ok()?; + let mut new_memory = sys::Memory::with_size(new_pages.bytes().0 + DYNAMIC_GUARD_SIZE) + .map_err(|e| e.into())?; unsafe { new_memory .protect(0..new_pages.bytes().0, sys::Protect::ReadWrite) - .ok()?; + .map_err(|e| e.into())?; new_memory.as_slice_mut()[..self.current.bytes().0] .copy_from_slice(&self.memory.as_slice()[..self.current.bytes().0]); @@ -97,7 +101,7 @@ impl DynamicMemory { let old_pages = self.current; self.current = new_pages; - Some(old_pages) + Ok(old_pages) } pub fn as_slice(&self) -> &[u8] { diff --git a/lib/runtime-core/src/memory/mod.rs b/lib/runtime-core/src/memory/mod.rs index bc706b564..4a9dccba7 100644 --- a/lib/runtime-core/src/memory/mod.rs +++ b/lib/runtime-core/src/memory/mod.rs @@ -1,5 +1,5 @@ use crate::{ - error::CreationError, + error::{CreationError, GrowError}, export::Export, import::IsExport, memory::dynamic::DYNAMIC_GUARD_SIZE, @@ -89,8 +89,8 @@ impl Memory { self.desc } - /// Grow this memory by the specfied number of pages. - pub fn grow(&self, delta: Pages) -> Option { + /// Grow this memory by the specified number of pages. + pub fn grow(&self, delta: Pages) -> Result { match &self.variant { MemoryVariant::Unshared(unshared_mem) => unshared_mem.grow(delta), MemoryVariant::Shared(shared_mem) => shared_mem.grow(delta), @@ -244,7 +244,7 @@ impl UnsharedMemory { }) } - pub fn grow(&self, delta: Pages) -> Option { + pub fn grow(&self, delta: Pages) -> Result { let mut storage = self.internal.storage.borrow_mut(); let mut local = self.internal.local.get(); @@ -292,7 +292,7 @@ impl SharedMemory { Ok(Self { desc }) } - pub fn grow(&self, _delta: Pages) -> Option { + pub fn grow(&self, _delta: Pages) -> Result { unimplemented!() } diff --git a/lib/runtime-core/src/memory/static_/unshared.rs b/lib/runtime-core/src/memory/static_/unshared.rs index 420fdc716..b9e66de0a 100644 --- a/lib/runtime-core/src/memory/static_/unshared.rs +++ b/lib/runtime-core/src/memory/static_/unshared.rs @@ -1,3 +1,4 @@ +use crate::error::GrowError; use crate::{ error::CreationError, memory::static_::{SAFE_STATIC_GUARD_SIZE, SAFE_STATIC_HEAP_SIZE}, @@ -61,27 +62,30 @@ impl StaticMemory { self.current } - pub fn grow(&mut self, delta: Pages, local: &mut vm::LocalMemory) -> Option { + pub fn grow(&mut self, delta: Pages, local: &mut vm::LocalMemory) -> Result { if delta == Pages(0) { - return Some(self.current); + return Ok(self.current); } - let new_pages = self.current.checked_add(delta)?; + let new_pages = self.current.checked_add(delta).map_err(|e| e.into())?; if let Some(max) = self.max { if new_pages > max { - return None; + return Err(GrowError::ExceededMaxPagesForMemory( + new_pages.0 as usize, + max.0 as usize, + )); } } - unsafe { + let _ = unsafe { self.memory .protect( self.current.bytes().0..new_pages.bytes().0, sys::Protect::ReadWrite, ) - .ok()?; - } + .map_err(|e| e.into()) + }?; local.bound = new_pages.bytes().0; @@ -89,7 +93,7 @@ impl StaticMemory { self.current = new_pages; - Some(old_pages) + Ok(old_pages) } pub fn as_slice(&self) -> &[u8] { diff --git a/lib/runtime-core/src/sys/unix/memory.rs b/lib/runtime-core/src/sys/unix/memory.rs index 8c76e6c14..338024d09 100644 --- a/lib/runtime-core/src/sys/unix/memory.rs +++ b/lib/runtime-core/src/sys/unix/memory.rs @@ -1,3 +1,5 @@ +use crate::error::MemoryCreationError; +use crate::error::MemoryProtectionError; use errno; use nix::libc; use page_size; @@ -16,13 +18,13 @@ pub struct Memory { } impl Memory { - pub fn from_file_path

(path: P, protection: Protect) -> Result + pub fn from_file_path

(path: P, protection: Protect) -> Result where P: AsRef, { - let file = File::open(path).map_err(|e| e.to_string())?; + let file = File::open(path)?; - let file_len = file.metadata().map_err(|e| e.to_string())?.len(); + let file_len = file.metadata()?.len(); let raw_fd = RawFd::from_file(file); @@ -38,7 +40,10 @@ impl Memory { }; if ptr == -1 as _ { - Err(errno::errno().to_string()) + Err(MemoryCreationError::VirtualMemoryAllocationFailed( + file_len as usize, + errno::errno().to_string(), + )) } else { Ok(Self { ptr: ptr as *mut u8, @@ -84,7 +89,7 @@ impl Memory { } } - pub fn with_size(size: usize) -> Result { + pub fn with_size(size: usize) -> Result { if size == 0 { return Ok(Self { ptr: ptr::null_mut(), @@ -108,7 +113,10 @@ impl Memory { }; if ptr == -1 as _ { - Err(errno::errno().to_string()) + Err(MemoryCreationError::VirtualMemoryAllocationFailed( + size, + errno::errno().to_string(), + )) } else { Ok(Self { ptr: ptr as *mut u8, @@ -123,7 +131,7 @@ impl Memory { &mut self, range: impl RangeBounds, protection: Protect, - ) -> Result<(), String> { + ) -> Result<(), MemoryProtectionError> { let protect = protection.to_protect_const(); let range_start = match range.start_bound() { @@ -147,7 +155,11 @@ impl Memory { let success = libc::mprotect(start as _, size, protect as i32); if success == -1 { - Err(errno::errno().to_string()) + Err(MemoryProtectionError::ProtectionFailed( + start as usize, + size, + errno::errno().to_string(), + )) } else { self.protection = protection; Ok(()) diff --git a/lib/runtime-core/src/sys/windows/memory.rs b/lib/runtime-core/src/sys/windows/memory.rs index 771ac6788..d47388170 100644 --- a/lib/runtime-core/src/sys/windows/memory.rs +++ b/lib/runtime-core/src/sys/windows/memory.rs @@ -1,3 +1,5 @@ +use crate::error::MemoryCreationError; +use crate::error::MemoryProtectionError; use page_size; use std::ops::{Bound, RangeBounds}; use std::{ptr, slice}; @@ -44,7 +46,7 @@ impl Memory { } } - pub fn with_size(size: usize) -> Result { + pub fn with_size(size: usize) -> Result { if size == 0 { return Ok(Self { ptr: ptr::null_mut(), @@ -58,7 +60,10 @@ impl Memory { let ptr = unsafe { VirtualAlloc(ptr::null_mut(), size, MEM_RESERVE, PAGE_NOACCESS) }; if ptr.is_null() { - Err("unable to allocate memory".to_string()) + Err(MemoryCreationError::VirtualMemoryAllocationFailed( + size, + "unable to allocate memory".to_string(), + )) } else { Ok(Self { ptr: ptr as *mut u8, @@ -72,7 +77,7 @@ impl Memory { &mut self, range: impl RangeBounds, protect: Protect, - ) -> Result<(), String> { + ) -> Result<(), MemoryProtectionError> { let protect_const = protect.to_protect_const(); let range_start = match range.start_bound() { @@ -98,7 +103,11 @@ impl Memory { let ptr = VirtualAlloc(start as _, size, MEM_COMMIT, protect_const); if ptr.is_null() { - Err("unable to protect memory".to_string()) + Err(MemoryProtectionError::ProtectionFailed( + start as usize, + size, + "unable to protect memory".to_string(), + )) } else { self.protection = protect; Ok(()) diff --git a/lib/runtime-core/src/table/mod.rs b/lib/runtime-core/src/table/mod.rs index a45593802..1c97b89f3 100644 --- a/lib/runtime-core/src/table/mod.rs +++ b/lib/runtime-core/src/table/mod.rs @@ -11,6 +11,7 @@ mod anyfunc; pub use self::anyfunc::Anyfunc; use self::anyfunc::AnyfuncTable; +use crate::error::GrowError; pub enum Element<'a> { Anyfunc(Anyfunc<'a>), @@ -108,15 +109,15 @@ impl Table { } /// Grow this table by `delta`. - pub fn grow(&self, delta: u32) -> Option { + pub fn grow(&self, delta: u32) -> Result { if delta == 0 { - return Some(self.size()); + return Ok(self.size()); } match &mut *self.storage.borrow_mut() { - (TableStorage::Anyfunc(ref mut anyfunc_table), ref mut local) => { - anyfunc_table.grow(delta, local) - } + (TableStorage::Anyfunc(ref mut anyfunc_table), ref mut local) => anyfunc_table + .grow(delta, local) + .ok_or(GrowError::TableGrowError), } } diff --git a/lib/runtime-core/src/units.rs b/lib/runtime-core/src/units.rs index 2486c5738..56d501438 100644 --- a/lib/runtime-core/src/units.rs +++ b/lib/runtime-core/src/units.rs @@ -1,3 +1,4 @@ +use crate::error::PageError; use std::{ fmt, ops::{Add, Sub}, @@ -11,12 +12,16 @@ const WASM_MAX_PAGES: usize = 65_536; pub struct Pages(pub u32); impl Pages { - pub fn checked_add(self, rhs: Pages) -> Option { + pub fn checked_add(self, rhs: Pages) -> Result { let added = (self.0 as usize) + (rhs.0 as usize); if added <= WASM_MAX_PAGES { - Some(Pages(added as u32)) + Ok(Pages(added as u32)) } else { - None + Err(PageError::ExceededMaxPages( + self.0 as usize, + rhs.0 as usize, + added, + )) } } diff --git a/lib/runtime-core/src/vmcalls.rs b/lib/runtime-core/src/vmcalls.rs index 576ca34ce..b428fb24e 100644 --- a/lib/runtime-core/src/vmcalls.rs +++ b/lib/runtime-core/src/vmcalls.rs @@ -20,10 +20,9 @@ pub unsafe extern "C" fn local_static_memory_grow( let local_memory = *ctx.memories.add(memory_index.index()); let memory = (*local_memory).memory as *mut StaticMemory; - if let Some(old) = (*memory).grow(delta, &mut *local_memory) { - old.0 as i32 - } else { - -1 + match (*memory).grow(delta, &mut *local_memory) { + Ok(old) => old.0 as i32, + Err(_) => -1, } } @@ -45,10 +44,9 @@ pub unsafe extern "C" fn local_dynamic_memory_grow( let local_memory = *ctx.memories.add(memory_index.index()); let memory = (*local_memory).memory as *mut DynamicMemory; - if let Some(old) = (*memory).grow(delta, &mut *local_memory) { - old.0 as i32 - } else { - -1 + match (*memory).grow(delta, &mut *local_memory) { + Ok(old) => old.0 as i32, + Err(_) => -1, } } @@ -74,10 +72,9 @@ pub unsafe extern "C" fn imported_static_memory_grow( let local_memory = *ctx.imported_memories.add(import_memory_index.index()); let memory = (*local_memory).memory as *mut StaticMemory; - if let Some(old) = (*memory).grow(delta, &mut *local_memory) { - old.0 as i32 - } else { - -1 + match (*memory).grow(delta, &mut *local_memory) { + Ok(old) => old.0 as i32, + Err(_) => -1, } } @@ -99,10 +96,9 @@ pub unsafe extern "C" fn imported_dynamic_memory_grow( let local_memory = *ctx.imported_memories.add(memory_index.index()); let memory = (*local_memory).memory as *mut DynamicMemory; - if let Some(old) = (*memory).grow(delta, &mut *local_memory) { - old.0 as i32 - } else { - -1 + match (*memory).grow(delta, &mut *local_memory) { + Ok(old) => old.0 as i32, + Err(_) => -1, } } From ed706133c463edfcf61d5b981752ed00e7d92ec4 Mon Sep 17 00:00:00 2001 From: Andrew Cann Date: Sat, 23 Feb 2019 17:00:03 +0800 Subject: [PATCH 114/262] fix stack overflow in Error's Display impl --- lib/runtime-core/src/error.rs | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/lib/runtime-core/src/error.rs b/lib/runtime-core/src/error.rs index 1f9f60c61..fea5c1e2e 100644 --- a/lib/runtime-core/src/error.rs +++ b/lib/runtime-core/src/error.rs @@ -365,7 +365,24 @@ impl From for CallError { impl std::fmt::Display for Error { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(f, "{}", self) + match self { + Error::CompileError(err) => write!(f, "compile error: {}", err), + Error::LinkError(errs) => { + if errs.len() == 1 { + write!(f, "link error: {}", errs[0]) + } else { + write!(f, "{} link errors:", errs.len())?; + for (i, err) in errs.iter().enumerate() { + write!(f, " ({} of {}) {}", i + 1, errs.len(), err)?; + } + Ok(()) + } + }, + Error::RuntimeError(err) => write!(f, "runtime error: {}", err), + Error::ResolveError(err) => write!(f, "resolve error: {}", err), + Error::CallError(err) => write!(f, "call error: {}", err), + Error::CreationError(err) => write!(f, "creation error: {}", err), + } } } From 17fe7bdaea038843c0532c16b6af25ef7ca34106 Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Sat, 23 Feb 2019 15:41:38 -0600 Subject: [PATCH 115/262] Add C API module export descriptors --- lib/runtime-c-api/src/lib.rs | 114 ++++++++++++++++++ lib/runtime-c-api/tests/.gitignore | 1 + lib/runtime-c-api/tests/CMakeLists.txt | 4 + lib/runtime-c-api/tests/test-module-exports.c | 53 ++++++++ lib/runtime-c-api/wasmer.h | 43 ++++++- lib/runtime-c-api/wasmer.hh | 31 ++++- 6 files changed, 244 insertions(+), 2 deletions(-) create mode 100644 lib/runtime-c-api/tests/test-module-exports.c diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index f52076d28..ea56cf7f5 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -13,6 +13,7 @@ use std::{ffi::c_void, ptr}; use wasmer_runtime::{Ctx, Global, ImportObject, Instance, Memory, Module, Table, Value}; use wasmer_runtime_core::export::{Context, Export, FuncPointer}; use wasmer_runtime_core::import::Namespace; +use wasmer_runtime_core::module::ExportIndex; use wasmer_runtime_core::types::{ElementType, FuncSig, MemoryDescriptor, TableDescriptor, Type}; use wasmer_runtime_core::units::{Bytes, Pages}; @@ -120,6 +121,14 @@ pub struct wasmer_export_t; #[derive(Clone)] pub struct wasmer_exports_t; +#[repr(C)] +#[derive(Clone)] +pub struct wasmer_export_descriptor_t; + +#[repr(C)] +#[derive(Clone)] +pub struct wasmer_export_descriptors_t; + #[repr(u32)] #[derive(Clone)] pub enum wasmer_import_export_kind { @@ -468,6 +477,91 @@ pub unsafe extern "C" fn wasmer_module_instantiate( wasmer_result_t::WASMER_OK } +/// Gets export descriptors for the given module +/// +/// The caller owns the object and should call `wasmer_export_descriptors_destroy` to free it. +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub unsafe extern "C" fn wasmer_export_descriptors( + module: *mut wasmer_module_t, + export_descriptors: *mut *mut wasmer_export_descriptors_t, +) { + let mut module = unsafe { &*(module as *mut Module) }; + + let named_export_descriptors: Box = Box::new(NamedExportDescriptors( + module.info().exports.iter().map(|e| e.into()).collect(), + )); + unsafe { + *export_descriptors = + Box::into_raw(named_export_descriptors) as *mut wasmer_export_descriptors_t + }; +} + +pub struct NamedExportDescriptors(Vec); + +/// Frees the memory for the given export descriptors +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub unsafe extern "C" fn wasmer_export_descriptors_destroy( + export_descriptors: *mut wasmer_export_descriptors_t, +) { + if !export_descriptors.is_null() { + drop(unsafe { Box::from_raw(export_descriptors as *mut NamedExportDescriptors) }); + } +} + +/// Gets the length of the export descriptors +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub unsafe extern "C" fn wasmer_export_descriptors_len( + exports: *mut wasmer_export_descriptors_t, +) -> c_int { + if exports.is_null() { + return 0; + } + (*(exports as *mut NamedExportDescriptors)).0.len() as c_int +} + +/// Gets export descriptor by index +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub unsafe extern "C" fn wasmer_export_descriptors_get( + export_descriptors: *mut wasmer_export_descriptors_t, + idx: c_int, +) -> *mut wasmer_export_descriptor_t { + if export_descriptors.is_null() { + return ptr::null_mut(); + } + let mut named_export_descriptors = + unsafe { &mut *(export_descriptors as *mut NamedExportDescriptors) }; + let ptr = &mut (*named_export_descriptors).0[idx as usize] as *mut NamedExportDescriptor + as *mut wasmer_export_descriptor_t; + ptr +} + +/// Gets name for the export descriptor +#[no_mangle] +#[allow(clippy::cast_ptr_alignment)] +pub unsafe extern "C" fn wasmer_export_descriptor_name( + export_descriptor: *mut wasmer_export_descriptor_t, +) -> wasmer_byte_array { + let named_export_descriptor = &*(export_descriptor as *mut NamedExportDescriptor); + wasmer_byte_array { + bytes: named_export_descriptor.name.as_ptr(), + bytes_len: named_export_descriptor.name.len() as u32, + } +} + +/// Gets export descriptor kind +#[no_mangle] +#[allow(clippy::cast_ptr_alignment)] +pub unsafe extern "C" fn wasmer_export_descriptor_kind( + export: *mut wasmer_export_descriptor_t, +) -> wasmer_import_export_kind { + let named_export_descriptor = &*(export as *mut NamedExportDescriptor); + named_export_descriptor.kind.clone() +} + /// Frees memory for the given Module #[allow(clippy::cast_ptr_alignment)] #[no_mangle] @@ -1075,6 +1169,21 @@ impl From<&wasmer_runtime::wasm::Type> for wasmer_value_tag { } } +impl From<(&std::string::String, &ExportIndex)> for NamedExportDescriptor { + fn from((name, export_index): (&String, &ExportIndex)) -> Self { + let kind = match *export_index { + ExportIndex::Memory(_) => wasmer_import_export_kind::WASM_MEMORY, + ExportIndex::Global(_) => wasmer_import_export_kind::WASM_GLOBAL, + ExportIndex::Table(_) => wasmer_import_export_kind::WASM_TABLE, + ExportIndex::Func(_) => wasmer_import_export_kind::WASM_FUNCTION, + }; + NamedExportDescriptor { + name: name.clone(), + kind, + } + } +} + // Error reporting thread_local! { @@ -1173,3 +1282,8 @@ struct NamedExport { name: String, export: Export, } + +struct NamedExportDescriptor { + name: String, + kind: wasmer_import_export_kind, +} diff --git a/lib/runtime-c-api/tests/.gitignore b/lib/runtime-c-api/tests/.gitignore index 6ea57c28d..6ddd85f73 100644 --- a/lib/runtime-c-api/tests/.gitignore +++ b/lib/runtime-c-api/tests/.gitignore @@ -15,6 +15,7 @@ test-instantiate test-import-function test-memory test-module +test-module-exports test-tables test-validate rust-build \ No newline at end of file diff --git a/lib/runtime-c-api/tests/CMakeLists.txt b/lib/runtime-c-api/tests/CMakeLists.txt index 788ee1c6a..111b374e4 100644 --- a/lib/runtime-c-api/tests/CMakeLists.txt +++ b/lib/runtime-c-api/tests/CMakeLists.txt @@ -7,6 +7,7 @@ add_executable(test-instantiate test-instantiate.c) add_executable(test-import-function test-import-function.c) add_executable(test-memory test-memory.c) add_executable(test-module test-module.c) +add_executable(test-module-exports test-module-exports.c) add_executable(test-validate test-validate.c) add_executable(test-tables test-tables.c) @@ -31,6 +32,8 @@ target_link_libraries(test-memory general ${WASMER_LIB}) target_link_libraries(test-module general ${WASMER_LIB}) +target_link_libraries(test-module-exports + general ${WASMER_LIB}) target_link_libraries(test-validate general ${WASMER_LIB}) target_link_libraries(test-tables @@ -43,6 +46,7 @@ add_test(test-instantiate test-instantiate) add_test(test-import-function test-import-function) add_test(test-memory test-memory) add_test(test-module test-module) +add_test(test-module-exports test-module-exports) add_test(test-validate test-validate) add_test(test-tables test-tables) diff --git a/lib/runtime-c-api/tests/test-module-exports.c b/lib/runtime-c-api/tests/test-module-exports.c new file mode 100644 index 000000000..48fe6f25b --- /dev/null +++ b/lib/runtime-c-api/tests/test-module-exports.c @@ -0,0 +1,53 @@ +#include +#include "../wasmer.h" +#include +#include + +int main() +{ + // Read the wasm file bytes + FILE *file = fopen("sum.wasm", "r"); + fseek(file, 0, SEEK_END); + long len = ftell(file); + uint8_t *bytes = malloc(len); + fseek(file, 0, SEEK_SET); + fread(bytes, 1, len, file); + fclose(file); + + wasmer_module_t *module = NULL; + wasmer_result_t compile_result = wasmer_compile(&module, bytes, len); + printf("Compile result: %d\n", compile_result); + assert(compile_result == WASMER_OK); + + wasmer_import_t imports[] = {}; + wasmer_instance_t *instance = NULL; + wasmer_result_t instantiate_result = wasmer_module_instantiate(module, &instance, imports, 0); + printf("Instantiate result: %d\n", compile_result); + assert(instantiate_result == WASMER_OK); + + wasmer_export_descriptors_t *exports = NULL; + wasmer_export_descriptors(module, &exports); + + int exports_len = wasmer_export_descriptors_len(exports); + printf("exports_len: %d\n", exports_len); + assert(exports_len == 1); + + wasmer_export_descriptor_t *export = wasmer_export_descriptors_get(exports, 0); + + wasmer_import_export_kind kind = wasmer_export_descriptor_kind(export); + assert(kind == WASM_FUNCTION); + + wasmer_byte_array name_bytes = wasmer_export_descriptor_name(export); + assert(name_bytes.bytes_len == 3); + char expected[] = {'s', 'u', 'm'}; + for(int idx = 0; idx < 3; idx++){ + printf("%c\n", name_bytes.bytes[idx]); + assert(name_bytes.bytes[idx] == expected[idx]); + } + + printf("Destroy module\n"); + wasmer_module_destroy(module); + printf("Destroy exports\n"); + wasmer_export_descriptors_destroy(exports); + return 0; +} \ No newline at end of file diff --git a/lib/runtime-c-api/wasmer.h b/lib/runtime-c-api/wasmer.h index 6c0494e01..f1d2245c0 100644 --- a/lib/runtime-c-api/wasmer.h +++ b/lib/runtime-c-api/wasmer.h @@ -35,7 +35,7 @@ typedef struct wasmer_module_t wasmer_module_t; typedef struct { -} wasmer_export_t; +} wasmer_export_descriptor_t; typedef struct { const uint8_t *bytes; @@ -44,6 +44,14 @@ typedef struct { typedef struct { +} wasmer_export_descriptors_t; + +typedef struct { + +} wasmer_export_t; + +typedef struct { + } wasmer_func_t; typedef struct { @@ -113,6 +121,39 @@ wasmer_result_t wasmer_compile(wasmer_module_t **module, uint8_t *wasm_bytes, uint32_t wasm_bytes_len); +/** + * Gets export descriptor kind + */ +wasmer_import_export_kind wasmer_export_descriptor_kind(wasmer_export_descriptor_t *export_); + +/** + * Gets name for the export descriptor + */ +wasmer_byte_array wasmer_export_descriptor_name(wasmer_export_descriptor_t *export_descriptor); + +/** + * Gets export descriptors for the given module + * The caller owns the object and should call `wasmer_export_descriptors_destroy` to free it. + */ +void wasmer_export_descriptors(wasmer_module_t *module, + wasmer_export_descriptors_t **export_descriptors); + +/** + * Frees the memory for the given export descriptors + */ +void wasmer_export_descriptors_destroy(wasmer_export_descriptors_t *export_descriptors); + +/** + * Gets export descriptor by index + */ +wasmer_export_descriptor_t *wasmer_export_descriptors_get(wasmer_export_descriptors_t *export_descriptors, + int idx); + +/** + * Gets the length of the export descriptors + */ +int wasmer_export_descriptors_len(wasmer_export_descriptors_t *exports); + /** * Gets wasmer_export kind */ diff --git a/lib/runtime-c-api/wasmer.hh b/lib/runtime-c-api/wasmer.hh index 2bb55de45..c0f2234f5 100644 --- a/lib/runtime-c-api/wasmer.hh +++ b/lib/runtime-c-api/wasmer.hh @@ -30,7 +30,7 @@ struct wasmer_instance_t; struct wasmer_module_t; -struct wasmer_export_t { +struct wasmer_export_descriptor_t { }; @@ -39,6 +39,14 @@ struct wasmer_byte_array { uint32_t bytes_len; }; +struct wasmer_export_descriptors_t { + +}; + +struct wasmer_export_t { + +}; + struct wasmer_func_t { }; @@ -110,6 +118,27 @@ wasmer_result_t wasmer_compile(wasmer_module_t **module, uint8_t *wasm_bytes, uint32_t wasm_bytes_len); +/// Gets export descriptor kind +wasmer_import_export_kind wasmer_export_descriptor_kind(wasmer_export_descriptor_t *export_); + +/// Gets name for the export descriptor +wasmer_byte_array wasmer_export_descriptor_name(wasmer_export_descriptor_t *export_descriptor); + +/// Gets export descriptors for the given module +/// The caller owns the object and should call `wasmer_export_descriptors_destroy` to free it. +void wasmer_export_descriptors(wasmer_module_t *module, + wasmer_export_descriptors_t **export_descriptors); + +/// Frees the memory for the given export descriptors +void wasmer_export_descriptors_destroy(wasmer_export_descriptors_t *export_descriptors); + +/// Gets export descriptor by index +wasmer_export_descriptor_t *wasmer_export_descriptors_get(wasmer_export_descriptors_t *export_descriptors, + int idx); + +/// Gets the length of the export descriptors +int wasmer_export_descriptors_len(wasmer_export_descriptors_t *exports); + /// Gets wasmer_export kind wasmer_import_export_kind wasmer_export_kind(wasmer_export_t *export_); From 1dfa106850ef5d4b3e16368fc2fa2078c51d9d31 Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Sat, 23 Feb 2019 18:25:51 -0600 Subject: [PATCH 116/262] Add C API module import descriptors --- lib/runtime-c-api/src/lib.rs | 194 ++++++++++++++++++ lib/runtime-c-api/tests/.gitignore | 1 + lib/runtime-c-api/tests/CMakeLists.txt | 4 + lib/runtime-c-api/tests/test-module-imports.c | 56 +++++ lib/runtime-c-api/wasmer.h | 46 +++++ lib/runtime-c-api/wasmer.hh | 32 +++ 6 files changed, 333 insertions(+) create mode 100644 lib/runtime-c-api/tests/test-module-imports.c diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index f52076d28..ec19b249c 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -13,6 +13,7 @@ use std::{ffi::c_void, ptr}; use wasmer_runtime::{Ctx, Global, ImportObject, Instance, Memory, Module, Table, Value}; use wasmer_runtime_core::export::{Context, Export, FuncPointer}; use wasmer_runtime_core::import::Namespace; +use wasmer_runtime_core::module::ImportName; use wasmer_runtime_core::types::{ElementType, FuncSig, MemoryDescriptor, TableDescriptor, Type}; use wasmer_runtime_core::units::{Bytes, Pages}; @@ -112,6 +113,14 @@ pub struct wasmer_import_t { value: wasmer_import_export_value, } +#[repr(C)] +#[derive(Clone)] +pub struct wasmer_import_descriptor_t; + +#[repr(C)] +#[derive(Clone)] +pub struct wasmer_import_descriptors_t; + #[repr(C)] #[derive(Clone)] pub struct wasmer_export_t; @@ -477,6 +486,185 @@ pub extern "C" fn wasmer_module_destroy(module: *mut wasmer_module_t) { } } +/// Gets import descriptors for the given module +/// +/// The caller owns the object and should call `wasmer_import_descriptors_destroy` to free it. +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub unsafe extern "C" fn wasmer_import_descriptors( + module: *mut wasmer_module_t, + import_descriptors: *mut *mut wasmer_import_descriptors_t, +) { + let mut module = unsafe { &*(module as *mut Module) }; + let total_imports = module.info().imported_functions.len() + + module.info().imported_tables.len() + + module.info().imported_globals.len() + + module.info().imported_memories.len(); + let mut descriptors: Vec = Vec::with_capacity(total_imports); + + for ( + index, + ImportName { + namespace_index, + name_index, + }, + ) in &module.info().imported_functions + { + let namespace = module.info().namespace_table.get(*namespace_index); + let name = module.info().name_table.get(*name_index); + descriptors.push(NamedImportDescriptor { + module: namespace.to_string(), + name: name.to_string(), + kind: wasmer_import_export_kind::WASM_FUNCTION, + }); + } + + for ( + index, + ( + ImportName { + namespace_index, + name_index, + }, + _, + ), + ) in &module.info().imported_tables + { + let namespace = module.info().namespace_table.get(*namespace_index); + let name = module.info().name_table.get(*name_index); + descriptors.push(NamedImportDescriptor { + module: namespace.to_string(), + name: name.to_string(), + kind: wasmer_import_export_kind::WASM_TABLE, + }); + } + + for ( + index, + ( + ImportName { + namespace_index, + name_index, + }, + _, + ), + ) in &module.info().imported_globals + { + let namespace = module.info().namespace_table.get(*namespace_index); + let name = module.info().name_table.get(*name_index); + descriptors.push(NamedImportDescriptor { + module: namespace.to_string(), + name: name.to_string(), + kind: wasmer_import_export_kind::WASM_GLOBAL, + }); + } + + for ( + index, + ( + ImportName { + namespace_index, + name_index, + }, + _, + ), + ) in &module.info().imported_memories + { + let namespace = module.info().namespace_table.get(*namespace_index); + let name = module.info().name_table.get(*name_index); + descriptors.push(NamedImportDescriptor { + module: namespace.to_string(), + name: name.to_string(), + kind: wasmer_import_export_kind::WASM_MEMORY, + }); + } + + let named_import_descriptors: Box = + Box::new(NamedImportDescriptors(descriptors)); + unsafe { + *import_descriptors = + Box::into_raw(named_import_descriptors) as *mut wasmer_import_descriptors_t + }; +} + +pub struct NamedImportDescriptors(Vec); + +/// Frees the memory for the given import descriptors +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub unsafe extern "C" fn wasmer_import_descriptors_destroy( + import_descriptors: *mut wasmer_import_descriptors_t, +) { + if !import_descriptors.is_null() { + drop(unsafe { Box::from_raw(import_descriptors as *mut NamedImportDescriptors) }); + } +} + +/// Gets the length of the import descriptors +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub unsafe extern "C" fn wasmer_import_descriptors_len( + exports: *mut wasmer_import_descriptors_t, +) -> c_int { + if exports.is_null() { + return 0; + } + (*(exports as *mut NamedImportDescriptors)).0.len() as c_int +} + +/// Gets import descriptor by index +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub unsafe extern "C" fn wasmer_import_descriptors_get( + import_descriptors: *mut wasmer_import_descriptors_t, + idx: c_int, +) -> *mut wasmer_import_descriptor_t { + if import_descriptors.is_null() { + return ptr::null_mut(); + } + let mut named_import_descriptors = + unsafe { &mut *(import_descriptors as *mut NamedImportDescriptors) }; + let ptr = &mut (*named_import_descriptors).0[idx as usize] as *mut NamedImportDescriptor + as *mut wasmer_import_descriptor_t; + ptr +} + +/// Gets name for the import descriptor +#[no_mangle] +#[allow(clippy::cast_ptr_alignment)] +pub unsafe extern "C" fn wasmer_import_descriptor_name( + import_descriptor: *mut wasmer_import_descriptor_t, +) -> wasmer_byte_array { + let named_import_descriptor = &*(import_descriptor as *mut NamedImportDescriptor); + wasmer_byte_array { + bytes: named_import_descriptor.name.as_ptr(), + bytes_len: named_import_descriptor.name.len() as u32, + } +} + +/// Gets module name for the import descriptor +#[no_mangle] +#[allow(clippy::cast_ptr_alignment)] +pub unsafe extern "C" fn wasmer_import_descriptor_module_name( + import_descriptor: *mut wasmer_import_descriptor_t, +) -> wasmer_byte_array { + let named_import_descriptor = &*(import_descriptor as *mut NamedImportDescriptor); + wasmer_byte_array { + bytes: named_import_descriptor.module.as_ptr(), + bytes_len: named_import_descriptor.module.len() as u32, + } +} + +/// Gets export descriptor kind +#[no_mangle] +#[allow(clippy::cast_ptr_alignment)] +pub unsafe extern "C" fn wasmer_import_descriptor_kind( + export: *mut wasmer_import_descriptor_t, +) -> wasmer_import_export_kind { + let named_import_descriptor = &*(export as *mut NamedImportDescriptor); + named_import_descriptor.kind.clone() +} + /// Creates a new Instance from the given wasm bytes and imports. /// /// Returns `wasmer_result_t::WASMER_OK` upon success. @@ -1169,6 +1357,12 @@ impl fmt::Display for CApiError { impl Error for CApiError {} +struct NamedImportDescriptor { + module: String, + name: String, + kind: wasmer_import_export_kind, +} + struct NamedExport { name: String, export: Export, diff --git a/lib/runtime-c-api/tests/.gitignore b/lib/runtime-c-api/tests/.gitignore index 6ea57c28d..773d7f43d 100644 --- a/lib/runtime-c-api/tests/.gitignore +++ b/lib/runtime-c-api/tests/.gitignore @@ -14,6 +14,7 @@ test-exports test-instantiate test-import-function test-memory +test-module-imports test-module test-tables test-validate diff --git a/lib/runtime-c-api/tests/CMakeLists.txt b/lib/runtime-c-api/tests/CMakeLists.txt index 788ee1c6a..2db4f219a 100644 --- a/lib/runtime-c-api/tests/CMakeLists.txt +++ b/lib/runtime-c-api/tests/CMakeLists.txt @@ -6,6 +6,7 @@ add_executable(test-globals test-globals.c) add_executable(test-instantiate test-instantiate.c) add_executable(test-import-function test-import-function.c) add_executable(test-memory test-memory.c) +add_executable(test-module-imports test-module-imports.c) add_executable(test-module test-module.c) add_executable(test-validate test-validate.c) add_executable(test-tables test-tables.c) @@ -29,6 +30,8 @@ target_link_libraries(test-import-function general ${WASMER_LIB}) target_link_libraries(test-memory general ${WASMER_LIB}) +target_link_libraries(test-module-imports + general ${WASMER_LIB}) target_link_libraries(test-module general ${WASMER_LIB}) target_link_libraries(test-validate @@ -42,6 +45,7 @@ add_test(test-globals test-globals) add_test(test-instantiate test-instantiate) add_test(test-import-function test-import-function) add_test(test-memory test-memory) +add_test(test-module-imports test-module-imports) add_test(test-module test-module) add_test(test-validate test-validate) add_test(test-tables test-tables) diff --git a/lib/runtime-c-api/tests/test-module-imports.c b/lib/runtime-c-api/tests/test-module-imports.c new file mode 100644 index 000000000..47757c58c --- /dev/null +++ b/lib/runtime-c-api/tests/test-module-imports.c @@ -0,0 +1,56 @@ +#include +#include "../wasmer.h" +#include +#include + +int main() +{ + // Read the wasm file bytes + FILE *file = fopen("wasm_sample_app.wasm", "r"); + fseek(file, 0, SEEK_END); + long len = ftell(file); + uint8_t *bytes = malloc(len); + fseek(file, 0, SEEK_SET); + fread(bytes, 1, len, file); + fclose(file); + + wasmer_module_t *module = NULL; + wasmer_result_t compile_result = wasmer_compile(&module, bytes, len); + printf("Compile result: %d\n", compile_result); + assert(compile_result == WASMER_OK); + + wasmer_import_descriptors_t *imports = NULL; + wasmer_import_descriptors(module, &imports); + + int imports_len = wasmer_import_descriptors_len(imports); + printf("imports_len: %d\n", imports_len); + assert(imports_len == 1); + + wasmer_import_descriptor_t *import = wasmer_import_descriptors_get(imports, 0); + + wasmer_import_export_kind kind = wasmer_import_descriptor_kind(import); + assert(kind == WASM_FUNCTION); + + wasmer_byte_array name_bytes = wasmer_import_descriptor_name(import); + assert(name_bytes.bytes_len == 9); + char expected[] = {'p', 'r', 'i', 'n', 't', '_', 's', 't', 'r'}; + + for(int idx = 0; idx < 9; idx++){ + printf("%c\n", name_bytes.bytes[idx]); + assert(name_bytes.bytes[idx] == expected[idx]); + } + + wasmer_byte_array module_name_bytes = wasmer_import_descriptor_module_name(import); + assert(module_name_bytes.bytes_len == 3); + char module_expected[] = {'e', 'n', 'v'}; + for(int idx = 0; idx < 3; idx++){ + printf("%c\n", module_name_bytes.bytes[idx]); + assert(module_name_bytes.bytes[idx] == module_expected[idx]); + } + + printf("Destroy module\n"); + wasmer_module_destroy(module); + printf("Destroy imports\n"); + wasmer_import_descriptors_destroy(imports); + return 0; +} \ No newline at end of file diff --git a/lib/runtime-c-api/wasmer.h b/lib/runtime-c-api/wasmer.h index 6c0494e01..5f01ad65a 100644 --- a/lib/runtime-c-api/wasmer.h +++ b/lib/runtime-c-api/wasmer.h @@ -73,6 +73,14 @@ typedef struct { typedef struct { +} wasmer_import_descriptor_t; + +typedef struct { + +} wasmer_import_descriptors_t; + +typedef struct { + } wasmer_memory_t; typedef struct { @@ -231,6 +239,44 @@ wasmer_global_t *wasmer_global_new(wasmer_value_t value, bool mutable_); */ void wasmer_global_set(wasmer_global_t *global, wasmer_value_t value); +/** + * Gets export descriptor kind + */ +wasmer_import_export_kind wasmer_import_descriptor_kind(wasmer_import_descriptor_t *export_); + +/** + * Gets module name for the import descriptor + */ +wasmer_byte_array wasmer_import_descriptor_module_name(wasmer_import_descriptor_t *import_descriptor); + +/** + * Gets name for the import descriptor + */ +wasmer_byte_array wasmer_import_descriptor_name(wasmer_import_descriptor_t *import_descriptor); + +/** + * Gets import descriptors for the given module + * The caller owns the object and should call `wasmer_import_descriptors_destroy` to free it. + */ +void wasmer_import_descriptors(wasmer_module_t *module, + wasmer_import_descriptors_t **import_descriptors); + +/** + * Frees the memory for the given import descriptors + */ +void wasmer_import_descriptors_destroy(wasmer_import_descriptors_t *import_descriptors); + +/** + * Gets import descriptor by index + */ +wasmer_import_descriptor_t *wasmer_import_descriptors_get(wasmer_import_descriptors_t *import_descriptors, + int idx); + +/** + * Gets the length of the import descriptors + */ +int wasmer_import_descriptors_len(wasmer_import_descriptors_t *exports); + /** * Calls an instances exported function by `name` with the provided parameters. * Results are set using the provided `results` pointer. diff --git a/lib/runtime-c-api/wasmer.hh b/lib/runtime-c-api/wasmer.hh index 2bb55de45..2af93433d 100644 --- a/lib/runtime-c-api/wasmer.hh +++ b/lib/runtime-c-api/wasmer.hh @@ -68,6 +68,14 @@ struct wasmer_global_descriptor_t { wasmer_value_tag kind; }; +struct wasmer_import_descriptor_t { + +}; + +struct wasmer_import_descriptors_t { + +}; + struct wasmer_memory_t { }; @@ -192,6 +200,30 @@ wasmer_global_t *wasmer_global_new(wasmer_value_t value, bool mutable_); /// Sets the value stored by the given Global void wasmer_global_set(wasmer_global_t *global, wasmer_value_t value); +/// Gets export descriptor kind +wasmer_import_export_kind wasmer_import_descriptor_kind(wasmer_import_descriptor_t *export_); + +/// Gets module name for the import descriptor +wasmer_byte_array wasmer_import_descriptor_module_name(wasmer_import_descriptor_t *import_descriptor); + +/// Gets name for the import descriptor +wasmer_byte_array wasmer_import_descriptor_name(wasmer_import_descriptor_t *import_descriptor); + +/// Gets import descriptors for the given module +/// The caller owns the object and should call `wasmer_import_descriptors_destroy` to free it. +void wasmer_import_descriptors(wasmer_module_t *module, + wasmer_import_descriptors_t **import_descriptors); + +/// Frees the memory for the given import descriptors +void wasmer_import_descriptors_destroy(wasmer_import_descriptors_t *import_descriptors); + +/// Gets import descriptor by index +wasmer_import_descriptor_t *wasmer_import_descriptors_get(wasmer_import_descriptors_t *import_descriptors, + int idx); + +/// Gets the length of the import descriptors +int wasmer_import_descriptors_len(wasmer_import_descriptors_t *exports); + /// Calls an instances exported function by `name` with the provided parameters. /// Results are set using the provided `results` pointer. /// Returns `wasmer_result_t::WASMER_OK` upon success. From b008a054de2792956bf9b1abd2c7b1fc731e14c8 Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Sun, 24 Feb 2019 12:22:24 -0600 Subject: [PATCH 117/262] Fix C API to allow calling an exported func --- lib/runtime-c-api/src/lib.rs | 322 ++++++++++++------ lib/runtime-c-api/tests/test-exports.c | 40 +-- .../tests/test-import-function.c | 4 +- lib/runtime-c-api/wasmer.h | 200 ++++++----- lib/runtime-c-api/wasmer.hh | 164 +++++---- 5 files changed, 455 insertions(+), 275 deletions(-) diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index f52076d28..25d56821d 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -16,9 +16,6 @@ use wasmer_runtime_core::import::Namespace; use wasmer_runtime_core::types::{ElementType, FuncSig, MemoryDescriptor, TableDescriptor, Type}; use wasmer_runtime_core::units::{Bytes, Pages}; -#[allow(non_camel_case_types)] -pub struct wasmer_import_object_t(); - #[allow(non_camel_case_types)] pub struct wasmer_module_t(); @@ -78,7 +75,11 @@ pub struct wasmer_table_t(); #[repr(C)] #[derive(Clone)] -pub struct wasmer_func_t(); +pub struct wasmer_import_func_t(); + +#[repr(C)] +#[derive(Clone)] +pub struct wasmer_export_func_t(); #[repr(C)] #[derive(Clone)] @@ -96,14 +97,6 @@ pub struct wasmer_limit_option_t { pub some: uint32_t, } -#[repr(C)] -pub struct wasmer_func_signature { - pub params: *const wasmer_value_tag, - pub params_len: c_int, - pub returns: *const wasmer_value_tag, - pub returns_len: c_int, -} - #[repr(C)] pub struct wasmer_import_t { module_name: wasmer_byte_array, @@ -132,7 +125,7 @@ pub enum wasmer_import_export_kind { #[repr(C)] #[derive(Clone, Copy)] pub union wasmer_import_export_value { - func: *const wasmer_func_t, + func: *const wasmer_import_func_t, table: *const wasmer_table_t, memory: *const wasmer_memory_t, global: *const wasmer_global_t, @@ -647,9 +640,16 @@ pub unsafe extern "C" fn wasmer_instance_exports( instance: *mut wasmer_instance_t, exports: *mut *mut wasmer_exports_t, ) { - let mut instance = unsafe { &mut *(instance as *mut Instance) }; - let named_exports: Box = - Box::new(NamedExports(instance.exports().map(|e| e.into()).collect())); + let mut instance_ref = unsafe { &mut *(instance as *mut Instance) }; + let mut exports_vec: Vec = Vec::with_capacity(instance_ref.exports().count()); + for (name, export) in instance_ref.exports() { + exports_vec.push(NamedExport { + name: name.clone(), + export: export.clone(), + instance: instance as *mut Instance, + }); + } + let named_exports: Box = Box::new(NamedExports(exports_vec)); unsafe { *exports = Box::into_raw(named_exports) as *mut wasmer_exports_t }; } @@ -704,18 +704,157 @@ pub unsafe extern "C" fn wasmer_export_kind( } } -/// Creates new func +/// Sets the result parameter to the arity of the params of the wasmer_export_func_t /// -/// The caller owns the object and should call `wasmer_func_destroy` to free it. +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. #[no_mangle] #[allow(clippy::cast_ptr_alignment)] -pub unsafe extern "C" fn wasmer_func_new( +pub unsafe extern "C" fn wasmer_export_func_params_arity( + func: *mut wasmer_export_func_t, + result: *mut uint32_t, +) -> wasmer_result_t { + let mut named_export = unsafe { &*(func as *mut NamedExport) }; + let mut export = &named_export.export; + let result = if let Export::Function { ref signature, .. } = *export { + unsafe { *result = signature.params().len() as uint32_t }; + wasmer_result_t::WASMER_OK + } else { + update_last_error(CApiError { + msg: "func ptr error in wasmer_export_func_params_arity".to_string(), + }); + wasmer_result_t::WASMER_ERROR + }; + result +} + +/// Sets the params buffer to the parameter types of the given wasmer_export_func_t +/// +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +#[no_mangle] +#[allow(clippy::cast_ptr_alignment)] +pub unsafe extern "C" fn wasmer_export_func_params( + func: *mut wasmer_export_func_t, + params: *mut wasmer_value_tag, + params_len: c_int, +) -> wasmer_result_t { + let mut named_export = unsafe { &*(func as *mut NamedExport) }; + let mut export = &named_export.export; + let result = if let Export::Function { ref signature, .. } = *export { + let params: &mut [wasmer_value_tag] = + slice::from_raw_parts_mut(params, params_len as usize); + for (i, item) in signature.params().iter().enumerate() { + params[i] = item.into(); + } + wasmer_result_t::WASMER_OK + } else { + update_last_error(CApiError { + msg: "func ptr error in wasmer_export_func_params".to_string(), + }); + wasmer_result_t::WASMER_ERROR + }; + result +} + +/// Sets the returns buffer to the parameter types of the given wasmer_export_func_t +/// +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +#[no_mangle] +#[allow(clippy::cast_ptr_alignment)] +pub unsafe extern "C" fn wasmer_export_func_returns( + func: *mut wasmer_export_func_t, + returns: *mut wasmer_value_tag, + returns_len: c_int, +) -> wasmer_result_t { + let mut named_export = unsafe { &*(func as *mut NamedExport) }; + let mut export = &named_export.export; + let result = if let Export::Function { ref signature, .. } = *export { + let returns: &mut [wasmer_value_tag] = + slice::from_raw_parts_mut(returns, returns_len as usize); + for (i, item) in signature.returns().iter().enumerate() { + returns[i] = item.into(); + } + wasmer_result_t::WASMER_OK + } else { + update_last_error(CApiError { + msg: "func ptr error in wasmer_export_func_returns".to_string(), + }); + wasmer_result_t::WASMER_ERROR + }; + result +} + +/// Sets the result parameter to the arity of the returns of the wasmer_export_func_t +/// +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +#[no_mangle] +#[allow(clippy::cast_ptr_alignment)] +pub unsafe extern "C" fn wasmer_export_func_returns_arity( + func: *mut wasmer_export_func_t, + result: *mut uint32_t, +) -> wasmer_result_t { + let mut named_export = unsafe { &*(func as *mut NamedExport) }; + let mut export = &named_export.export; + let result = if let Export::Function { ref signature, .. } = *export { + unsafe { *result = signature.returns().len() as uint32_t }; + wasmer_result_t::WASMER_OK + } else { + update_last_error(CApiError { + msg: "func ptr error in wasmer_export_func_results_arity".to_string(), + }); + wasmer_result_t::WASMER_ERROR + }; + result +} + +/// Sets the result parameter to the arity of the params of the wasmer_import_func_t +/// +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +#[no_mangle] +#[allow(clippy::cast_ptr_alignment)] +pub unsafe extern "C" fn wasmer_import_func_params_arity( + func: *mut wasmer_import_func_t, + result: *mut uint32_t, +) -> wasmer_result_t { + let mut export = unsafe { &mut *(func as *mut Export) }; + let result = if let Export::Function { ref signature, .. } = *export { + unsafe { *result = signature.params().len() as uint32_t }; + wasmer_result_t::WASMER_OK + } else { + update_last_error(CApiError { + msg: "func ptr error in wasmer_import_func_params_arity".to_string(), + }); + wasmer_result_t::WASMER_ERROR + }; + result +} + +/// Creates new func +/// +/// The caller owns the object and should call `wasmer_import_func_destroy` to free it. +#[no_mangle] +#[allow(clippy::cast_ptr_alignment)] +pub unsafe extern "C" fn wasmer_import_func_new( func: extern "C" fn(data: *mut c_void), params: *const wasmer_value_tag, params_len: c_int, returns: *const wasmer_value_tag, returns_len: c_int, -) -> *const wasmer_func_t { +) -> *const wasmer_import_func_t { let params: &[wasmer_value_tag] = slice::from_raw_parts(params, params_len as usize); let params: Vec = params.iter().cloned().map(|x| x.into()).collect(); let returns: &[wasmer_value_tag] = slice::from_raw_parts(returns, returns_len as usize); @@ -726,10 +865,10 @@ pub unsafe extern "C" fn wasmer_func_new( ctx: Context::Internal, signature: Arc::new(FuncSig::new(params, returns)), }); - Box::into_raw(export) as *mut wasmer_func_t + Box::into_raw(export) as *mut wasmer_import_func_t } -/// Sets the result parameter to the arity of the params of the wasmer_func_t +/// Sets the params buffer to the parameter types of the given wasmer_import_func_t /// /// Returns `wasmer_result_t::WASMER_OK` upon success. /// @@ -737,33 +876,8 @@ pub unsafe extern "C" fn wasmer_func_new( /// and `wasmer_last_error_message` to get an error message. #[no_mangle] #[allow(clippy::cast_ptr_alignment)] -pub unsafe extern "C" fn wasmer_func_params_arity( - func: *mut wasmer_func_t, - result: *mut uint32_t, -) -> wasmer_result_t { - let mut export = unsafe { &mut *(func as *mut Export) }; - let result = if let Export::Function { ref signature, .. } = *export { - unsafe { *result = signature.params().len() as uint32_t }; - wasmer_result_t::WASMER_OK - } else { - update_last_error(CApiError { - msg: "func ptr error in wasmer_func_params_arity".to_string(), - }); - wasmer_result_t::WASMER_ERROR - }; - result -} - -/// Sets the params buffer to the parameter types of the given wasmer_func_t -/// -/// Returns `wasmer_result_t::WASMER_OK` upon success. -/// -/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` -/// and `wasmer_last_error_message` to get an error message. -#[no_mangle] -#[allow(clippy::cast_ptr_alignment)] -pub unsafe extern "C" fn wasmer_func_params( - func: *mut wasmer_func_t, +pub unsafe extern "C" fn wasmer_import_func_params( + func: *mut wasmer_import_func_t, params: *mut wasmer_value_tag, params_len: c_int, ) -> wasmer_result_t { @@ -777,14 +891,14 @@ pub unsafe extern "C" fn wasmer_func_params( wasmer_result_t::WASMER_OK } else { update_last_error(CApiError { - msg: "func ptr error in wasmer_func_params".to_string(), + msg: "func ptr error in wasmer_import_func_params".to_string(), }); wasmer_result_t::WASMER_ERROR }; result } -/// Sets the returns buffer to the parameter types of the given wasmer_func_t +/// Sets the returns buffer to the parameter types of the given wasmer_import_func_t /// /// Returns `wasmer_result_t::WASMER_OK` upon success. /// @@ -792,8 +906,8 @@ pub unsafe extern "C" fn wasmer_func_params( /// and `wasmer_last_error_message` to get an error message. #[no_mangle] #[allow(clippy::cast_ptr_alignment)] -pub unsafe extern "C" fn wasmer_func_returns( - func: *mut wasmer_func_t, +pub unsafe extern "C" fn wasmer_import_func_returns( + func: *mut wasmer_import_func_t, returns: *mut wasmer_value_tag, returns_len: c_int, ) -> wasmer_result_t { @@ -807,14 +921,14 @@ pub unsafe extern "C" fn wasmer_func_returns( wasmer_result_t::WASMER_OK } else { update_last_error(CApiError { - msg: "func ptr error in wasmer_func_returns".to_string(), + msg: "func ptr error in wasmer_import_func_returns".to_string(), }); wasmer_result_t::WASMER_ERROR }; result } -/// Sets the result parameter to the arity of the returns of the wasmer_func_t +/// Sets the result parameter to the arity of the returns of the wasmer_import_func_t /// /// Returns `wasmer_result_t::WASMER_OK` upon success. /// @@ -822,8 +936,8 @@ pub unsafe extern "C" fn wasmer_func_returns( /// and `wasmer_last_error_message` to get an error message. #[no_mangle] #[allow(clippy::cast_ptr_alignment)] -pub unsafe extern "C" fn wasmer_func_returns_arity( - func: *mut wasmer_func_t, +pub unsafe extern "C" fn wasmer_import_func_returns_arity( + func: *mut wasmer_import_func_t, result: *mut uint32_t, ) -> wasmer_result_t { let mut export = unsafe { &*(func as *mut Export) }; @@ -832,7 +946,7 @@ pub unsafe extern "C" fn wasmer_func_returns_arity( wasmer_result_t::WASMER_OK } else { update_last_error(CApiError { - msg: "func ptr error in wasmer_func_results_arity".to_string(), + msg: "func ptr error in wasmer_import_func_results_arity".to_string(), }); wasmer_result_t::WASMER_ERROR }; @@ -842,20 +956,19 @@ pub unsafe extern "C" fn wasmer_func_returns_arity( /// Frees memory for the given Func #[allow(clippy::cast_ptr_alignment)] #[no_mangle] -pub extern "C" fn wasmer_func_destroy(func: *mut wasmer_func_t) { +pub extern "C" fn wasmer_import_func_destroy(func: *mut wasmer_import_func_t) { if !func.is_null() { drop(unsafe { Box::from_raw(func as *mut Export) }); } } -/// Gets func from wasm_export +/// Gets export func from export #[no_mangle] #[allow(clippy::cast_ptr_alignment)] pub unsafe extern "C" fn wasmer_export_to_func( export: *mut wasmer_export_t, -) -> *const wasmer_func_t { - let named_export = &*(export as *mut NamedExport); - &named_export.export as *const Export as *const wasmer_func_t +) -> *const wasmer_export_func_t { + export as *const wasmer_export_func_t } /// Gets name from wasmer_export @@ -878,8 +991,8 @@ pub unsafe extern "C" fn wasmer_export_name(export: *mut wasmer_export_t) -> was /// and `wasmer_last_error_message` to get an error message. #[allow(clippy::cast_ptr_alignment)] #[no_mangle] -pub unsafe extern "C" fn wasmer_func_call( - func: *mut wasmer_func_t, +pub unsafe extern "C" fn wasmer_export_func_call( + func: *mut wasmer_export_func_t, params: *const wasmer_value_t, params_len: c_int, results: *mut wasmer_value_t, @@ -901,46 +1014,42 @@ pub unsafe extern "C" fn wasmer_func_call( let params: &[wasmer_value_t] = slice::from_raw_parts(params, params_len as usize); let params: Vec = params.iter().cloned().map(|x| x.into()).collect(); - let export_func = unsafe { &*(func as *mut Export) }; + let named_export = unsafe { &*(func as *mut NamedExport) }; let results: &mut [wasmer_value_t] = slice::from_raw_parts_mut(results, results_len as usize); - // TODO implement func.call - update_last_error(CApiError { - msg: "wasmer_func_call not yet implemented".to_string(), - }); - wasmer_result_t::WASMER_ERROR - // let result = instance.call(func_name_r, ¶ms[..]); - // Box::into_raw(export_func); - // match result { - // Ok(results_vec) => { - // if results_vec.len() > 0 { - // let ret = match results_vec[0] { - // Value::I32(x) => wasmer_value_t { - // tag: wasmer_value_tag::WASM_I32, - // value: wasmer_value { I32: x }, - // }, - // Value::I64(x) => wasmer_value_t { - // tag: wasmer_value_tag::WASM_I64, - // value: wasmer_value { I64: x }, - // }, - // Value::F32(x) => wasmer_value_t { - // tag: wasmer_value_tag::WASM_F32, - // value: wasmer_value { F32: x }, - // }, - // Value::F64(x) => wasmer_value_t { - // tag: wasmer_value_tag::WASM_F64, - // value: wasmer_value { F64: x }, - // }, - // }; - // results[0] = ret; - // } - // wasmer_result_t::WASMER_OK - // } - // Err(err) => { - // update_last_error(err); - // wasmer_result_t::WASMER_ERROR - // } - // } + + let instance = &*named_export.instance; + let result = instance.call(&named_export.name, ¶ms[..]); + match result { + Ok(results_vec) => { + if results_vec.len() > 0 { + let ret = match results_vec[0] { + Value::I32(x) => wasmer_value_t { + tag: wasmer_value_tag::WASM_I32, + value: wasmer_value { I32: x }, + }, + Value::I64(x) => wasmer_value_t { + tag: wasmer_value_tag::WASM_I64, + value: wasmer_value { I64: x }, + }, + Value::F32(x) => wasmer_value_t { + tag: wasmer_value_tag::WASM_F32, + value: wasmer_value { F32: x }, + }, + Value::F64(x) => wasmer_value_t { + tag: wasmer_value_tag::WASM_F64, + value: wasmer_value { F64: x }, + }, + }; + results[0] = ret; + } + wasmer_result_t::WASMER_OK + } + Err(err) => { + update_last_error(err); + wasmer_result_t::WASMER_ERROR + } + } } /// Gets the memory within the context at the index `memory_idx`. @@ -1058,12 +1167,6 @@ impl From for Type { } } -impl From<(std::string::String, wasmer_runtime_core::export::Export)> for NamedExport { - fn from((name, export): (String, Export)) -> Self { - NamedExport { name, export } - } -} - impl From<&wasmer_runtime::wasm::Type> for wasmer_value_tag { fn from(ty: &Type) -> Self { match *ty { @@ -1172,4 +1275,5 @@ impl Error for CApiError {} struct NamedExport { name: String, export: Export, + instance: *mut Instance, } diff --git a/lib/runtime-c-api/tests/test-exports.c b/lib/runtime-c-api/tests/test-exports.c index 3f458ebab..75368ad16 100644 --- a/lib/runtime-c-api/tests/test-exports.c +++ b/lib/runtime-c-api/tests/test-exports.c @@ -31,7 +31,7 @@ int main() wasmer_import_export_kind kind = wasmer_export_kind(export); assert(kind == WASM_FUNCTION); - wasmer_func_t *func = wasmer_export_to_func(export); + wasmer_export_func_t *func = wasmer_export_to_func(export); wasmer_byte_array name_bytes = wasmer_export_name(export); assert(name_bytes.bytes_len == 3); @@ -42,40 +42,40 @@ int main() } uint32_t params_arity; - wasmer_func_params_arity(func, ¶ms_arity); + wasmer_export_func_params_arity(func, ¶ms_arity); assert(params_arity == 2); wasmer_value_tag *params_sig = malloc(sizeof(wasmer_value_tag) * params_arity); - wasmer_func_params(func, params_sig , params_arity); + wasmer_export_func_params(func, params_sig , params_arity); assert(params_sig[0] == WASM_I32); assert(params_sig[1] == WASM_I32); free(params_sig); uint32_t returns_arity; - wasmer_func_returns_arity(func, &returns_arity); + wasmer_export_func_returns_arity(func, &returns_arity); assert(returns_arity == 1); wasmer_value_tag *returns_sig = malloc(sizeof(wasmer_value_tag) * returns_arity); - wasmer_func_returns(func, returns_sig , returns_arity); + wasmer_export_func_returns(func, returns_sig , returns_arity); assert(returns_sig[0] == WASM_I32); free(returns_sig); -// wasmer_value_t param_one; -// param_one.tag = WASM_I32; -// param_one.value.I32 = 7; -// wasmer_value_t param_two; -// param_two.tag = WASM_I32; -// param_two.value.I32 = 8; -// wasmer_value_t params[] = {param_one, param_two}; -// wasmer_value_t result_one; -// wasmer_value_t results[] = {result_one}; -// -// wasmer_result_t call_result = wasmer_func_call(func, params, 2, results, 1); -// printf("Call result: %d\n", call_result); -// printf("Result: %d\n", results[0].value.I32); -// assert(results[0].value.I32 == 15); -// assert(call_result == WASMER_OK); + wasmer_value_t param_one; + param_one.tag = WASM_I32; + param_one.value.I32 = 7; + wasmer_value_t param_two; + param_two.tag = WASM_I32; + param_two.value.I32 = 8; + wasmer_value_t params[] = {param_one, param_two}; + wasmer_value_t result_one; + wasmer_value_t results[] = {result_one}; + + wasmer_result_t call_result = wasmer_export_func_call(func, params, 2, results, 1); + printf("Call result: %d\n", call_result); + printf("Result: %d\n", results[0].value.I32); + assert(results[0].value.I32 == 15); + assert(call_result == WASMER_OK); printf("Destroy instance\n"); diff --git a/lib/runtime-c-api/tests/test-import-function.c b/lib/runtime-c-api/tests/test-import-function.c index e7caed874..b28465683 100644 --- a/lib/runtime-c-api/tests/test-import-function.c +++ b/lib/runtime-c-api/tests/test-import-function.c @@ -31,7 +31,7 @@ int main() wasmer_value_tag returns_sig[] = {}; printf("Creating new func\n"); - wasmer_func_t *func = wasmer_func_new(print_str, params_sig, 2, returns_sig, 0); + wasmer_import_func_t *func = wasmer_import_func_new(print_str, params_sig, 2, returns_sig, 0); wasmer_import_t import; char *module_name = "env"; @@ -84,7 +84,7 @@ int main() assert(0 == strcmp(actual_str, "Hello, World!")); printf("Destroying func\n"); - wasmer_func_destroy(func); + wasmer_import_func_destroy(func); printf("Destroy instance\n"); wasmer_instance_destroy(instance); return 0; diff --git a/lib/runtime-c-api/wasmer.h b/lib/runtime-c-api/wasmer.h index 6c0494e01..1744289a5 100644 --- a/lib/runtime-c-api/wasmer.h +++ b/lib/runtime-c-api/wasmer.h @@ -35,20 +35,7 @@ typedef struct wasmer_module_t wasmer_module_t; typedef struct { -} wasmer_export_t; - -typedef struct { - const uint8_t *bytes; - uint32_t bytes_len; -} wasmer_byte_array; - -typedef struct { - -} wasmer_func_t; - -typedef struct { - -} wasmer_exports_t; +} wasmer_export_func_t; typedef union { int32_t I32; @@ -64,6 +51,19 @@ typedef struct { typedef struct { +} wasmer_export_t; + +typedef struct { + const uint8_t *bytes; + uint32_t bytes_len; +} wasmer_byte_array; + +typedef struct { + +} wasmer_exports_t; + +typedef struct { + } wasmer_global_t; typedef struct { @@ -73,6 +73,10 @@ typedef struct { typedef struct { +} wasmer_import_func_t; + +typedef struct { + } wasmer_memory_t; typedef struct { @@ -80,7 +84,7 @@ typedef struct { } wasmer_table_t; typedef union { - const wasmer_func_t *func; + const wasmer_import_func_t *func; const wasmer_table_t *table; const wasmer_memory_t *memory; const wasmer_global_t *global; @@ -113,6 +117,55 @@ wasmer_result_t wasmer_compile(wasmer_module_t **module, uint8_t *wasm_bytes, uint32_t wasm_bytes_len); +/** + * Calls a `func` with the provided parameters. + * Results are set using the provided `results` pointer. + * Returns `wasmer_result_t::WASMER_OK` upon success. + * Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` + * and `wasmer_last_error_message` to get an error message. + */ +wasmer_result_t wasmer_export_func_call(wasmer_export_func_t *func, + const wasmer_value_t *params, + int params_len, + wasmer_value_t *results, + int results_len); + +/** + * Sets the params buffer to the parameter types of the given wasmer_export_func_t + * Returns `wasmer_result_t::WASMER_OK` upon success. + * Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` + * and `wasmer_last_error_message` to get an error message. + */ +wasmer_result_t wasmer_export_func_params(wasmer_export_func_t *func, + wasmer_value_tag *params, + int params_len); + +/** + * Sets the result parameter to the arity of the params of the wasmer_export_func_t + * Returns `wasmer_result_t::WASMER_OK` upon success. + * Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` + * and `wasmer_last_error_message` to get an error message. + */ +wasmer_result_t wasmer_export_func_params_arity(wasmer_export_func_t *func, uint32_t *result); + +/** + * Sets the returns buffer to the parameter types of the given wasmer_export_func_t + * Returns `wasmer_result_t::WASMER_OK` upon success. + * Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` + * and `wasmer_last_error_message` to get an error message. + */ +wasmer_result_t wasmer_export_func_returns(wasmer_export_func_t *func, + wasmer_value_tag *returns, + int returns_len); + +/** + * Sets the result parameter to the arity of the returns of the wasmer_export_func_t + * Returns `wasmer_result_t::WASMER_OK` upon success. + * Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` + * and `wasmer_last_error_message` to get an error message. + */ +wasmer_result_t wasmer_export_func_returns_arity(wasmer_export_func_t *func, uint32_t *result); + /** * Gets wasmer_export kind */ @@ -124,9 +177,9 @@ wasmer_import_export_kind wasmer_export_kind(wasmer_export_t *export_); wasmer_byte_array wasmer_export_name(wasmer_export_t *export_); /** - * Gets func from wasm_export + * Gets export func from export */ -const wasmer_func_t *wasmer_export_to_func(wasmer_export_t *export_); +const wasmer_export_func_t *wasmer_export_to_func(wasmer_export_t *export_); /** * Frees the memory for the given exports @@ -143,68 +196,6 @@ wasmer_export_t *wasmer_exports_get(wasmer_exports_t *exports, int idx); */ int wasmer_exports_len(wasmer_exports_t *exports); -/** - * Calls a `func` with the provided parameters. - * Results are set using the provided `results` pointer. - * Returns `wasmer_result_t::WASMER_OK` upon success. - * Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` - * and `wasmer_last_error_message` to get an error message. - */ -wasmer_result_t wasmer_func_call(wasmer_func_t *func, - const wasmer_value_t *params, - int params_len, - wasmer_value_t *results, - int results_len); - -/** - * Frees memory for the given Func - */ -void wasmer_func_destroy(wasmer_func_t *func); - -/** - * Creates new func - * The caller owns the object and should call `wasmer_func_destroy` to free it. - */ -const wasmer_func_t *wasmer_func_new(void (*func)(void *data), - const wasmer_value_tag *params, - int params_len, - const wasmer_value_tag *returns, - int returns_len); - -/** - * Sets the params buffer to the parameter types of the given wasmer_func_t - * Returns `wasmer_result_t::WASMER_OK` upon success. - * Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` - * and `wasmer_last_error_message` to get an error message. - */ -wasmer_result_t wasmer_func_params(wasmer_func_t *func, wasmer_value_tag *params, int params_len); - -/** - * Sets the result parameter to the arity of the params of the wasmer_func_t - * Returns `wasmer_result_t::WASMER_OK` upon success. - * Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` - * and `wasmer_last_error_message` to get an error message. - */ -wasmer_result_t wasmer_func_params_arity(wasmer_func_t *func, uint32_t *result); - -/** - * Sets the returns buffer to the parameter types of the given wasmer_func_t - * Returns `wasmer_result_t::WASMER_OK` upon success. - * Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` - * and `wasmer_last_error_message` to get an error message. - */ -wasmer_result_t wasmer_func_returns(wasmer_func_t *func, - wasmer_value_tag *returns, - int returns_len); - -/** - * Sets the result parameter to the arity of the returns of the wasmer_func_t - * Returns `wasmer_result_t::WASMER_OK` upon success. - * Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` - * and `wasmer_last_error_message` to get an error message. - */ -wasmer_result_t wasmer_func_returns_arity(wasmer_func_t *func, uint32_t *result); - /** * Frees memory for the given Global */ @@ -231,6 +222,57 @@ wasmer_global_t *wasmer_global_new(wasmer_value_t value, bool mutable_); */ void wasmer_global_set(wasmer_global_t *global, wasmer_value_t value); +/** + * Frees memory for the given Func + */ +void wasmer_import_func_destroy(wasmer_import_func_t *func); + +/** + * Creates new func + * The caller owns the object and should call `wasmer_import_func_destroy` to free it. + */ +const wasmer_import_func_t *wasmer_import_func_new(void (*func)(void *data), + const wasmer_value_tag *params, + int params_len, + const wasmer_value_tag *returns, + int returns_len); + +/** + * Sets the params buffer to the parameter types of the given wasmer_import_func_t + * Returns `wasmer_result_t::WASMER_OK` upon success. + * Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` + * and `wasmer_last_error_message` to get an error message. + */ +wasmer_result_t wasmer_import_func_params(wasmer_import_func_t *func, + wasmer_value_tag *params, + int params_len); + +/** + * Sets the result parameter to the arity of the params of the wasmer_import_func_t + * Returns `wasmer_result_t::WASMER_OK` upon success. + * Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` + * and `wasmer_last_error_message` to get an error message. + */ +wasmer_result_t wasmer_import_func_params_arity(wasmer_import_func_t *func, uint32_t *result); + +/** + * Sets the returns buffer to the parameter types of the given wasmer_import_func_t + * Returns `wasmer_result_t::WASMER_OK` upon success. + * Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` + * and `wasmer_last_error_message` to get an error message. + */ +wasmer_result_t wasmer_import_func_returns(wasmer_import_func_t *func, + wasmer_value_tag *returns, + int returns_len); + +/** + * Sets the result parameter to the arity of the returns of the wasmer_import_func_t + * Returns `wasmer_result_t::WASMER_OK` upon success. + * Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` + * and `wasmer_last_error_message` to get an error message. + */ +wasmer_result_t wasmer_import_func_returns_arity(wasmer_import_func_t *func, uint32_t *result); + /** * Calls an instances exported function by `name` with the provided parameters. * Results are set using the provided `results` pointer. diff --git a/lib/runtime-c-api/wasmer.hh b/lib/runtime-c-api/wasmer.hh index 2bb55de45..f79539f3d 100644 --- a/lib/runtime-c-api/wasmer.hh +++ b/lib/runtime-c-api/wasmer.hh @@ -30,20 +30,7 @@ struct wasmer_instance_t; struct wasmer_module_t; -struct wasmer_export_t { - -}; - -struct wasmer_byte_array { - const uint8_t *bytes; - uint32_t bytes_len; -}; - -struct wasmer_func_t { - -}; - -struct wasmer_exports_t { +struct wasmer_export_func_t { }; @@ -59,6 +46,19 @@ struct wasmer_value_t { wasmer_value value; }; +struct wasmer_export_t { + +}; + +struct wasmer_byte_array { + const uint8_t *bytes; + uint32_t bytes_len; +}; + +struct wasmer_exports_t { + +}; + struct wasmer_global_t { }; @@ -68,6 +68,10 @@ struct wasmer_global_descriptor_t { wasmer_value_tag kind; }; +struct wasmer_import_func_t { + +}; + struct wasmer_memory_t { }; @@ -77,7 +81,7 @@ struct wasmer_table_t { }; union wasmer_import_export_value { - const wasmer_func_t *func; + const wasmer_import_func_t *func; const wasmer_table_t *table; const wasmer_memory_t *memory; const wasmer_global_t *global; @@ -110,14 +114,53 @@ wasmer_result_t wasmer_compile(wasmer_module_t **module, uint8_t *wasm_bytes, uint32_t wasm_bytes_len); +/// Calls a `func` with the provided parameters. +/// Results are set using the provided `results` pointer. +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +wasmer_result_t wasmer_export_func_call(wasmer_export_func_t *func, + const wasmer_value_t *params, + int params_len, + wasmer_value_t *results, + int results_len); + +/// Sets the params buffer to the parameter types of the given wasmer_export_func_t +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +wasmer_result_t wasmer_export_func_params(wasmer_export_func_t *func, + wasmer_value_tag *params, + int params_len); + +/// Sets the result parameter to the arity of the params of the wasmer_export_func_t +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +wasmer_result_t wasmer_export_func_params_arity(wasmer_export_func_t *func, uint32_t *result); + +/// Sets the returns buffer to the parameter types of the given wasmer_export_func_t +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +wasmer_result_t wasmer_export_func_returns(wasmer_export_func_t *func, + wasmer_value_tag *returns, + int returns_len); + +/// Sets the result parameter to the arity of the returns of the wasmer_export_func_t +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +wasmer_result_t wasmer_export_func_returns_arity(wasmer_export_func_t *func, uint32_t *result); + /// Gets wasmer_export kind wasmer_import_export_kind wasmer_export_kind(wasmer_export_t *export_); /// Gets name from wasmer_export wasmer_byte_array wasmer_export_name(wasmer_export_t *export_); -/// Gets func from wasm_export -const wasmer_func_t *wasmer_export_to_func(wasmer_export_t *export_); +/// Gets export func from export +const wasmer_export_func_t *wasmer_export_to_func(wasmer_export_t *export_); /// Frees the memory for the given exports void wasmer_exports_destroy(wasmer_exports_t *exports); @@ -128,54 +171,6 @@ wasmer_export_t *wasmer_exports_get(wasmer_exports_t *exports, int idx); /// Gets the length of the exports int wasmer_exports_len(wasmer_exports_t *exports); -/// Calls a `func` with the provided parameters. -/// Results are set using the provided `results` pointer. -/// Returns `wasmer_result_t::WASMER_OK` upon success. -/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` -/// and `wasmer_last_error_message` to get an error message. -wasmer_result_t wasmer_func_call(wasmer_func_t *func, - const wasmer_value_t *params, - int params_len, - wasmer_value_t *results, - int results_len); - -/// Frees memory for the given Func -void wasmer_func_destroy(wasmer_func_t *func); - -/// Creates new func -/// The caller owns the object and should call `wasmer_func_destroy` to free it. -const wasmer_func_t *wasmer_func_new(void (*func)(void *data), - const wasmer_value_tag *params, - int params_len, - const wasmer_value_tag *returns, - int returns_len); - -/// Sets the params buffer to the parameter types of the given wasmer_func_t -/// Returns `wasmer_result_t::WASMER_OK` upon success. -/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` -/// and `wasmer_last_error_message` to get an error message. -wasmer_result_t wasmer_func_params(wasmer_func_t *func, wasmer_value_tag *params, int params_len); - -/// Sets the result parameter to the arity of the params of the wasmer_func_t -/// Returns `wasmer_result_t::WASMER_OK` upon success. -/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` -/// and `wasmer_last_error_message` to get an error message. -wasmer_result_t wasmer_func_params_arity(wasmer_func_t *func, uint32_t *result); - -/// Sets the returns buffer to the parameter types of the given wasmer_func_t -/// Returns `wasmer_result_t::WASMER_OK` upon success. -/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` -/// and `wasmer_last_error_message` to get an error message. -wasmer_result_t wasmer_func_returns(wasmer_func_t *func, - wasmer_value_tag *returns, - int returns_len); - -/// Sets the result parameter to the arity of the returns of the wasmer_func_t -/// Returns `wasmer_result_t::WASMER_OK` upon success. -/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` -/// and `wasmer_last_error_message` to get an error message. -wasmer_result_t wasmer_func_returns_arity(wasmer_func_t *func, uint32_t *result); - /// Frees memory for the given Global void wasmer_global_destroy(wasmer_global_t *global); @@ -192,6 +187,45 @@ wasmer_global_t *wasmer_global_new(wasmer_value_t value, bool mutable_); /// Sets the value stored by the given Global void wasmer_global_set(wasmer_global_t *global, wasmer_value_t value); +/// Frees memory for the given Func +void wasmer_import_func_destroy(wasmer_import_func_t *func); + +/// Creates new func +/// The caller owns the object and should call `wasmer_import_func_destroy` to free it. +const wasmer_import_func_t *wasmer_import_func_new(void (*func)(void *data), + const wasmer_value_tag *params, + int params_len, + const wasmer_value_tag *returns, + int returns_len); + +/// Sets the params buffer to the parameter types of the given wasmer_import_func_t +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +wasmer_result_t wasmer_import_func_params(wasmer_import_func_t *func, + wasmer_value_tag *params, + int params_len); + +/// Sets the result parameter to the arity of the params of the wasmer_import_func_t +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +wasmer_result_t wasmer_import_func_params_arity(wasmer_import_func_t *func, uint32_t *result); + +/// Sets the returns buffer to the parameter types of the given wasmer_import_func_t +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +wasmer_result_t wasmer_import_func_returns(wasmer_import_func_t *func, + wasmer_value_tag *returns, + int returns_len); + +/// Sets the result parameter to the arity of the returns of the wasmer_import_func_t +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +wasmer_result_t wasmer_import_func_returns_arity(wasmer_import_func_t *func, uint32_t *result); + /// Calls an instances exported function by `name` with the provided parameters. /// Results are set using the provided `results` pointer. /// Returns `wasmer_result_t::WASMER_OK` upon success. From 2f51694815677da344c9c5e4723179795deac2f6 Mon Sep 17 00:00:00 2001 From: Mackenzie Clark Date: Mon, 25 Feb 2019 11:46:48 -0800 Subject: [PATCH 118/262] no caching on windows --- src/bin/wasmer.rs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/bin/wasmer.rs b/src/bin/wasmer.rs index 6b8c9b54b..a96507f9f 100644 --- a/src/bin/wasmer.rs +++ b/src/bin/wasmer.rs @@ -1,7 +1,6 @@ extern crate structopt; use std::env; -use std::fs; use std::fs::File; use std::io; use std::io::Read; @@ -14,7 +13,6 @@ use wasmer::webassembly::InstanceABI; use wasmer::*; use wasmer_emscripten; use wasmer_runtime::cache::{Cache as BaseCache, FileSystemCache, WasmHash}; -use wasmer_runtime::error::CacheError; #[derive(Debug, StructOpt)] #[structopt(name = "wasmer", about = "Wasm execution runtime.")] @@ -84,6 +82,12 @@ fn get_cache_dir() -> PathBuf { /// Execute a wasm/wat file fn execute_wasm(options: &Run) -> Result<(), String> { + // force disable caching on windows + #[cfg(target_os = "windows")] + let disable_cache = true; + #[cfg(not(target_os = "windows"))] + let disable_windows = options.disable_cache; + let wasm_path = &options.path; let mut wasm_binary: Vec = read_file_contents(wasm_path).map_err(|err| { @@ -99,7 +103,7 @@ fn execute_wasm(options: &Run) -> Result<(), String> { .map_err(|e| format!("Can't convert from wast to wasm: {:?}", e))?; } - let module = if !options.disable_cache { + let module = if !disable_cache { // If we have cache enabled // We generate a hash for the given binary, so we can use it as key @@ -188,8 +192,10 @@ fn main() { CLIOptions::SelfUpdate => { println!("Self update is not supported on Windows. Use install instructions on the Wasmer homepage: https://wasmer.io"); } + #[cfg(not(target_os = "windows"))] CLIOptions::Cache(cache) => match cache { Cache::Clean => { + use std::fs; let cache_dir = get_cache_dir(); fs::remove_dir_all(cache_dir.clone()).expect("Can't remove cache dir"); fs::create_dir(cache_dir.clone()).expect("Can't create cache dir"); @@ -198,5 +204,9 @@ fn main() { println!("{}", get_cache_dir().to_string_lossy()); } }, + #[cfg(target_os = "windows")] + CLIOptions::Cache(_) => { + println!("Caching is disabled for Windows."); + } } } From 9aa63804609a88b92224a7af6d2a31a3ae706d25 Mon Sep 17 00:00:00 2001 From: Mackenzie Clark Date: Mon, 25 Feb 2019 11:53:15 -0800 Subject: [PATCH 119/262] lol --- src/bin/wasmer.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bin/wasmer.rs b/src/bin/wasmer.rs index a96507f9f..d5364504b 100644 --- a/src/bin/wasmer.rs +++ b/src/bin/wasmer.rs @@ -86,7 +86,7 @@ fn execute_wasm(options: &Run) -> Result<(), String> { #[cfg(target_os = "windows")] let disable_cache = true; #[cfg(not(target_os = "windows"))] - let disable_windows = options.disable_cache; + let disable_cache = options.disable_cache; let wasm_path = &options.path; From c5c967da00628f49f8e9c70be584fa606b78abce Mon Sep 17 00:00:00 2001 From: Syrus Akbary Date: Mon, 25 Feb 2019 12:03:48 -0800 Subject: [PATCH 120/262] Added parallel compilation (#209) --- Cargo.lock | 1 + lib/clif-backend/Cargo.toml | 1 + lib/clif-backend/src/lib.rs | 1 + lib/clif-backend/src/resolver.rs | 56 +++++++++++++++++--------- lib/runtime-core/src/structures/map.rs | 4 ++ 5 files changed, 45 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0b062168f..1b7b19bc5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1220,6 +1220,7 @@ dependencies = [ "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "nix 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", "serde-bench 0.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/lib/clif-backend/Cargo.toml b/lib/clif-backend/Cargo.toml index 701f821fc..06fd397dc 100644 --- a/lib/clif-backend/Cargo.toml +++ b/lib/clif-backend/Cargo.toml @@ -19,6 +19,7 @@ wasmparser = "0.23.0" byteorder = "1" nix = "0.13.0" libc = "0.2.48" +rayon = "1.0" # Dependencies for caching. [dependencies.serde] diff --git a/lib/clif-backend/src/lib.rs b/lib/clif-backend/src/lib.rs index df2e4e208..c4abf644f 100644 --- a/lib/clif-backend/src/lib.rs +++ b/lib/clif-backend/src/lib.rs @@ -24,6 +24,7 @@ use wasmer_runtime_core::{ #[macro_use] extern crate serde_derive; +extern crate rayon; extern crate serde; use wasmparser::{self, WasmDecoder}; diff --git a/lib/clif-backend/src/resolver.rs b/lib/clif-backend/src/resolver.rs index 604778f01..53b3a789a 100644 --- a/lib/clif-backend/src/resolver.rs +++ b/lib/clif-backend/src/resolver.rs @@ -7,6 +7,7 @@ use crate::{ }, signal::HandlerData, }; +use rayon::prelude::*; use byteorder::{ByteOrder, LittleEndian}; use cranelift_codegen::{ir, isa, Context}; @@ -92,25 +93,45 @@ impl FuncResolverBuilder { function_bodies: Map, info: &ModuleInfo, ) -> CompileResult<(Self, HandlerData)> { - let mut compiled_functions: Vec> = Vec::with_capacity(function_bodies.len()); - let mut local_relocs = Map::with_capacity(function_bodies.len()); - let mut external_relocs = Map::new(); + let num_func_bodies = function_bodies.len(); + let mut compiled_functions: Vec<(Vec, RelocSink)> = Vec::with_capacity(num_func_bodies); + let mut local_relocs = Map::with_capacity(num_func_bodies); + let mut external_relocs = Map::with_capacity(num_func_bodies); let mut trap_sink = TrapSink::new(); - let mut local_trap_sink = LocalTrapSink::new(); - let mut ctx = Context::new(); + let compiled_functions: Result, (RelocSink, LocalTrapSink))>, CompileError> = + function_bodies + .into_vec() + .par_iter() + .map_init( + || Context::new(), + |ctx, func| { + let mut code_buf = Vec::new(); + ctx.func = func.to_owned(); + let mut reloc_sink = RelocSink::new(); + let mut local_trap_sink = LocalTrapSink::new(); + + ctx.compile_and_emit( + isa, + &mut code_buf, + &mut reloc_sink, + &mut local_trap_sink, + ) + .map_err(|e| CompileError::InternalError { msg: e.to_string() })?; + ctx.clear(); + Ok((code_buf, (reloc_sink, local_trap_sink))) + }, + ) + .collect(); + + let compiled_functions = compiled_functions?; let mut total_size = 0; - - for (_, func) in function_bodies { - ctx.func = func; - let mut code_buf = Vec::new(); - let mut reloc_sink = RelocSink::new(); - - ctx.compile_and_emit(isa, &mut code_buf, &mut reloc_sink, &mut local_trap_sink) - .map_err(|e| CompileError::InternalError { msg: e.to_string() })?; - ctx.clear(); - + // We separate into two iterators, one iterable and one into iterable + let (code_bufs, sinks): (Vec>, Vec<(RelocSink, LocalTrapSink)>) = + compiled_functions.into_iter().unzip(); + for (code_buf, (reloc_sink, mut local_trap_sink)) in code_bufs.iter().zip(sinks.into_iter()) + { // Clear the local trap sink and consolidate all trap info // into a single location. trap_sink.drain_local(total_size, &mut local_trap_sink); @@ -118,7 +139,6 @@ impl FuncResolverBuilder { // Round up each function's size to pointer alignment. total_size += round_up(code_buf.len(), mem::size_of::()); - compiled_functions.push(code_buf); local_relocs.push(reloc_sink.local_relocs.into_boxed_slice()); external_relocs.push(reloc_sink.external_relocs.into_boxed_slice()); } @@ -145,10 +165,10 @@ impl FuncResolverBuilder { *i = 0xCC; } - let mut map = Map::with_capacity(compiled_functions.len()); + let mut map = Map::with_capacity(num_func_bodies); let mut previous_end = 0; - for compiled in compiled_functions.iter() { + for compiled in code_bufs.iter() { let new_end = previous_end + round_up(compiled.len(), mem::size_of::()); unsafe { memory.as_slice_mut()[previous_end..previous_end + compiled.len()] diff --git a/lib/runtime-core/src/structures/map.rs b/lib/runtime-core/src/structures/map.rs index d7177c427..add5b0257 100644 --- a/lib/runtime-core/src/structures/map.rs +++ b/lib/runtime-core/src/structures/map.rs @@ -56,6 +56,10 @@ where pub fn into_boxed_map(self) -> BoxedMap { BoxedMap::new(self.elems.into_boxed_slice()) } + + pub fn into_vec(self) -> Vec { + self.elems + } } impl Map From deac24c0bdef7214b652fdd85076bd7d9141b83b Mon Sep 17 00:00:00 2001 From: Mackenzie Clark Date: Mon, 25 Feb 2019 12:06:23 -0800 Subject: [PATCH 121/262] fix windows installer --- src/installer/wasmer.iss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/installer/wasmer.iss b/src/installer/wasmer.iss index 04850eb7a..f844eb4da 100644 --- a/src/installer/wasmer.iss +++ b/src/installer/wasmer.iss @@ -11,7 +11,7 @@ ChangesEnvironment=yes OutputBaseFilename=WasmerInstaller [Files] -Source: "..\target\release\wasmer.exe"; DestDir: "{app}\bin" +Source: "..\..\target\release\wasmer.exe"; DestDir: "{app}\bin" [Code] const EnvironmentKey = 'SYSTEM\CurrentControlSet\Control\Session Manager\Environment'; From f9c0e0c07869306b5fbb027210ae062745e908c8 Mon Sep 17 00:00:00 2001 From: Syrus Date: Mon, 25 Feb 2019 12:25:28 -0800 Subject: [PATCH 122/262] Fix formatting --- lib/runtime-core/src/error.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/runtime-core/src/error.rs b/lib/runtime-core/src/error.rs index fea5c1e2e..abc69cc5e 100644 --- a/lib/runtime-core/src/error.rs +++ b/lib/runtime-core/src/error.rs @@ -377,7 +377,7 @@ impl std::fmt::Display for Error { } Ok(()) } - }, + } Error::RuntimeError(err) => write!(f, "runtime error: {}", err), Error::ResolveError(err) => write!(f, "resolve error: {}", err), Error::CallError(err) => write!(f, "call error: {}", err), From 53c8603464bd2c50fcb3b83cdbbf954e59f3cfa4 Mon Sep 17 00:00:00 2001 From: Syrus Date: Mon, 25 Feb 2019 13:28:37 -0800 Subject: [PATCH 123/262] Updated crates version to 0.2.0 --- Cargo.lock | 107 +++++++++++++-------------- lib/clif-backend/Cargo.toml | 8 +- lib/emscripten/Cargo.toml | 8 +- lib/runtime-c-api/Cargo.toml | 6 +- lib/runtime-core/Cargo.toml | 5 +- lib/runtime/Cargo.toml | 6 +- lib/spectests/Cargo.toml | 6 +- lib/win-exception-handler/Cargo.toml | 6 +- 8 files changed, 72 insertions(+), 80 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1b7b19bc5..2d9f3cca3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -29,7 +29,7 @@ name = "atty" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -47,7 +47,7 @@ dependencies = [ "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -58,7 +58,7 @@ version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -136,7 +136,7 @@ version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -353,7 +353,7 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "errno-dragonfly 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -363,7 +363,7 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -488,12 +488,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.48" -source = "git+https://github.com/rust-lang/libc#42cd3ba27254c423e03f6f4324de57075047f6a0" - -[[package]] -name = "libc" -version = "0.2.48" +version = "0.2.49" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -527,7 +522,7 @@ name = "memchr" version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -535,7 +530,7 @@ name = "memmap" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -560,7 +555,7 @@ dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -572,7 +567,7 @@ dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -600,7 +595,7 @@ name = "num_cpus" version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -617,7 +612,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -635,7 +630,7 @@ name = "parking_lot_core" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -690,7 +685,7 @@ version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -745,7 +740,7 @@ name = "rand_jitter" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -757,7 +752,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (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.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -816,7 +811,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1043,7 +1038,7 @@ version = "3.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1063,7 +1058,7 @@ name = "termion" version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1089,7 +1084,7 @@ name = "time" version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1202,15 +1197,15 @@ dependencies = [ "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "structopt 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", - "wasmer-clif-backend 0.1.2", - "wasmer-emscripten 0.1.0", - "wasmer-runtime 0.1.4", - "wasmer-runtime-core 0.1.2", + "wasmer-clif-backend 0.2.0", + "wasmer-emscripten 0.2.0", + "wasmer-runtime 0.2.0", + "wasmer-runtime-core 0.2.0", ] [[package]] name = "wasmer-clif-backend" -version = "0.1.2" +version = "0.2.0" dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "cranelift-codegen 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1218,7 +1213,7 @@ dependencies = [ "cranelift-native 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", "cranelift-wasm 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "nix 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1226,52 +1221,52 @@ dependencies = [ "serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", "target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "wasmer-runtime-core 0.1.2", - "wasmer-win-exception-handler 0.0.1", + "wasmer-runtime-core 0.2.0", + "wasmer-win-exception-handler 0.2.0", "wasmparser 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "wasmer-emscripten" -version = "0.1.0" +version = "0.2.0" dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (git+https://github.com/rust-lang/libc)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", - "wasmer-clif-backend 0.1.2", - "wasmer-runtime-core 0.1.2", + "wasmer-clif-backend 0.2.0", + "wasmer-runtime-core 0.2.0", ] [[package]] name = "wasmer-runtime" -version = "0.1.4" +version = "0.2.0" dependencies = [ "criterion 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "wasmer-clif-backend 0.1.2", - "wasmer-runtime-core 0.1.2", + "wasmer-clif-backend 0.2.0", + "wasmer-runtime-core 0.2.0", ] [[package]] name = "wasmer-runtime-c-api" -version = "0.1.4" +version = "0.2.0" dependencies = [ "cbindgen 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "wasmer-runtime 0.1.4", - "wasmer-runtime-core 0.1.2", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmer-runtime 0.2.0", + "wasmer-runtime-core 0.2.0", ] [[package]] name = "wasmer-runtime-core" -version = "0.1.2" +version = "0.2.0" dependencies = [ "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "errno 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1280,7 +1275,7 @@ dependencies = [ "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "meowhash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "nix 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "page_size 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1289,29 +1284,28 @@ dependencies = [ "serde-bench 0.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", - "wasmer-clif-backend 0.1.2", "wasmparser 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "wasmer-spectests" -version = "0.1.2" +version = "0.2.0" dependencies = [ "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", - "wasmer-clif-backend 0.1.2", - "wasmer-runtime-core 0.1.2", + "wasmer-clif-backend 0.2.0", + "wasmer-runtime-core 0.2.0", ] [[package]] name = "wasmer-win-exception-handler" -version = "0.0.1" +version = "0.2.0" dependencies = [ "bindgen 0.46.0 (registry+https://github.com/rust-lang/crates.io-index)", "cmake 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "wasmer-runtime-core 0.1.2", + "wasmer-runtime-core 0.2.0", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1331,7 +1325,7 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1436,8 +1430,7 @@ dependencies = [ "checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1" -"checksum libc 0.2.48 (git+https://github.com/rust-lang/libc)" = "" -"checksum libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)" = "e962c7641008ac010fa60a7dfdc1712449f29c44ef2d4702394aea943ee75047" +"checksum libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)" = "413f3dfc802c5dc91dc570b05125b6cda9855edfaa9825c9849807876376e70e" "checksum libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3ad660d7cb8c5822cd83d10897b0f1f1526792737a179e73896152f85b88c2" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" diff --git a/lib/clif-backend/Cargo.toml b/lib/clif-backend/Cargo.toml index 06fd397dc..3ac5105cf 100644 --- a/lib/clif-backend/Cargo.toml +++ b/lib/clif-backend/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-clif-backend" -version = "0.1.2" +version = "0.2.0" description = "Wasmer runtime Cranelift compiler backend" license = "MIT" authors = ["The Wasmer Engineering Team "] @@ -8,7 +8,7 @@ repository = "https://github.com/wasmerio/wasmer" edition = "2018" [dependencies] -wasmer-runtime-core = { path = "../runtime-core", version = "0.1.2" } +wasmer-runtime-core = { path = "../runtime-core", version = "0.2.0" } cranelift-native = "0.26.0" cranelift-codegen = "0.26.0" cranelift-entity = "0.26.0" @@ -18,7 +18,7 @@ target-lexicon = "0.2.0" wasmparser = "0.23.0" byteorder = "1" nix = "0.13.0" -libc = "0.2.48" +libc = "0.2.49" rayon = "1.0" # Dependencies for caching. @@ -33,7 +33,7 @@ version = "0.0.7" [target.'cfg(windows)'.dependencies] winapi = { version = "0.3", features = ["errhandlingapi", "minwindef", "minwinbase", "winnt"] } -wasmer-win-exception-handler = { path = "../win-exception-handler", version = "0.0.1" } +wasmer-win-exception-handler = { path = "../win-exception-handler", version = "0.2.0" } [features] debug = ["wasmer-runtime-core/debug"] diff --git a/lib/emscripten/Cargo.toml b/lib/emscripten/Cargo.toml index ec5e035d6..1300eb124 100644 --- a/lib/emscripten/Cargo.toml +++ b/lib/emscripten/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-emscripten" -version = "0.1.0" +version = "0.2.0" description = "Wasmer runtime emscripten implementation library" license = "MIT" authors = ["The Wasmer Engineering Team "] @@ -9,9 +9,9 @@ edition = "2018" build = "build/mod.rs" [dependencies] -wasmer-runtime-core = { path = "../runtime-core", version = "0.1.0" } +wasmer-runtime-core = { path = "../runtime-core", version = "0.2.0" } lazy_static = "1.2.0" -libc = { git = "https://github.com/rust-lang/libc" } +libc = "0.2.49" byteorder = "1" time = "0.1.41" @@ -19,7 +19,7 @@ time = "0.1.41" rand = "0.6" [dev-dependencies] -wasmer-clif-backend = { path = "../clif-backend", version = "0.1.0" } +wasmer-clif-backend = { path = "../clif-backend", version = "0.2.0" } wabt = "0.7.2" [build-dependencies] diff --git a/lib/runtime-c-api/Cargo.toml b/lib/runtime-c-api/Cargo.toml index 692c03cd7..d2b327c22 100644 --- a/lib/runtime-c-api/Cargo.toml +++ b/lib/runtime-c-api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-runtime-c-api" -version = "0.1.4" +version = "0.2.0" description = "Wasmer c-api library" license = "MIT" authors = ["The Wasmer Engineering Team "] @@ -9,8 +9,8 @@ edition = "2018" readme = "README.md" [dependencies] -wasmer-runtime = { path = "../runtime", version = "0.1.2" } -wasmer-runtime-core = { path = "../runtime-core", version = "0.1.2" } +wasmer-runtime = { path = "../runtime", version = "0.2.0" } +wasmer-runtime-core = { path = "../runtime-core", version = "0.2.0" } libc = "0.2" [lib] diff --git a/lib/runtime-core/Cargo.toml b/lib/runtime-core/Cargo.toml index cd0648613..3d61a858c 100644 --- a/lib/runtime-core/Cargo.toml +++ b/lib/runtime-core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-runtime-core" -version = "0.1.2" +version = "0.2.0" description = "Wasmer runtime core library" license = "MIT" authors = ["The Wasmer Engineering Team "] @@ -15,7 +15,7 @@ parking_lot = "0.7.1" lazy_static = "1.2.0" indexmap = "1.0.2" errno = "0.2.4" -libc = "0.2.48" +libc = "0.2.49" hex = "0.3.2" # Dependencies for caching. @@ -41,7 +41,6 @@ features = ["serde"] winapi = { version = "0.3", features = ["memoryapi"] } [dev-dependencies] -wasmer-clif-backend = { path = "../clif-backend", version = "0.1.2" } field-offset = "0.1.1" [features] diff --git a/lib/runtime/Cargo.toml b/lib/runtime/Cargo.toml index 979fae140..f7aa32cb5 100644 --- a/lib/runtime/Cargo.toml +++ b/lib/runtime/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-runtime" -version = "0.1.4" +version = "0.2.0" description = "Wasmer runtime library" license = "MIT" authors = ["The Wasmer Engineering Team "] @@ -14,11 +14,11 @@ memmap = "0.7.0" [dependencies.wasmer-runtime-core] path = "../runtime-core" -version = "0.1.2" +version = "0.2.0" [dependencies.wasmer-clif-backend] path = "../clif-backend" -version = "0.1.2" +version = "0.2.0" [dev-dependencies] tempfile = "3.0.7" diff --git a/lib/spectests/Cargo.toml b/lib/spectests/Cargo.toml index f69782b40..672013dd9 100644 --- a/lib/spectests/Cargo.toml +++ b/lib/spectests/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-spectests" -version = "0.1.2" +version = "0.2.0" description = "Wasmer spectests library" license = "MIT" authors = ["The Wasmer Engineering Team "] @@ -9,13 +9,13 @@ edition = "2018" build = "build/mod.rs" [dependencies] -wasmer-runtime-core = { path = "../runtime-core" } +wasmer-runtime-core = { path = "../runtime-core", version = "0.2.0" } [build-dependencies] wabt = "0.7.2" [dev-dependencies] -wasmer-clif-backend = { path = "../clif-backend", version = "0.1.2" } +wasmer-clif-backend = { path = "../clif-backend", version = "0.2.0" } wabt = "0.7.2" [features] diff --git a/lib/win-exception-handler/Cargo.toml b/lib/win-exception-handler/Cargo.toml index 043dc3c59..18855212b 100644 --- a/lib/win-exception-handler/Cargo.toml +++ b/lib/win-exception-handler/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-win-exception-handler" -version = "0.0.1" +version = "0.2.0" description = "Wasmer runtime exception handling for Windows" license = "MIT" authors = ["The Wasmer Engineering Team "] @@ -8,9 +8,9 @@ repository = "https://github.com/wasmerio/wasmer" edition = "2018" [target.'cfg(windows)'.dependencies] -wasmer-runtime-core = { path = "../runtime-core", version = "0.1.2" } +wasmer-runtime-core = { path = "../runtime-core", version = "0.2.0" } winapi = { version = "0.3", features = ["winbase", "errhandlingapi", "minwindef", "minwinbase", "winnt"] } -libc = "0.2.48" +libc = "0.2.49" [build-dependencies] cmake = "0.1.35" From 2b1aedfbc40152fff7d34614d4686fcb42b598d2 Mon Sep 17 00:00:00 2001 From: Mackenzie Clark Date: Mon, 25 Feb 2019 14:48:39 -0800 Subject: [PATCH 124/262] install inno setup in appveyor --- .appveyor.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.appveyor.yml b/.appveyor.yml index 488e400fd..4ec05f8c7 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -21,6 +21,10 @@ install: - set PATH=%PATH%;%USERPROFILE%\.cargo\bin - rustc -vV - cargo -vV + # Install InnoSetup + - appveyor-retry appveyor DownloadFile https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/2017-08-22-is.exe + - 2017-08-22-is.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /SP- + - set PATH="C:\Program Files (x86)\Inno Setup 5";%PATH% build_script: - cargo build --verbose From e7d08712b53a01581edae5c220da4bdd2a149a31 Mon Sep 17 00:00:00 2001 From: Syrus Date: Mon, 25 Feb 2019 17:37:33 -0800 Subject: [PATCH 125/262] Use blake2 hashing algorithm --- Cargo.lock | 51 ++++++++++++++++++++++++++++------- lib/runtime-core/Cargo.toml | 4 +-- lib/runtime-core/src/cache.rs | 8 +++--- 3 files changed, 48 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2d9f3cca3..f8b6f496b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -87,6 +87,22 @@ name = "bitflags" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "blake2" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "byte-tools" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "byteorder" version = "1.3.1" @@ -305,6 +321,15 @@ dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "crypto-mac" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "csv" version = "1.0.5" @@ -539,14 +564,6 @@ name = "memoffset" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "meowhash" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "nix" version = "0.12.0" @@ -598,6 +615,11 @@ dependencies = [ "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "opaque-debug" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "owning_ref" version = "0.4.0" @@ -991,6 +1013,11 @@ dependencies = [ "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "subtle" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "syn" version = "0.13.11" @@ -1268,6 +1295,7 @@ dependencies = [ name = "wasmer-runtime-core" version = "0.2.0" dependencies = [ + "blake2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "digest 0.8.0 (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)", @@ -1276,7 +1304,6 @@ dependencies = [ "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", - "meowhash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "nix 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "page_size 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1384,6 +1411,8 @@ dependencies = [ "checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6" "checksum bindgen 0.46.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8f7f7f0701772b17de73e4f5cbcb1dd6926f4706cba4c1ab62c5367f8bdc94e1" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" +"checksum blake2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "91721a6330935673395a0607df4d49a9cb90ae12d259f1b3e0a3f6e1d486872e" +"checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" "checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" "checksum cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "926013f2860c46252efceabb19f4a6b308197505082c609025aa6706c011d427" "checksum cbindgen 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "32e01024aaf5390d6a8145047371a4f5b0063a14c1e411bc731353bd2278ca44" @@ -1406,6 +1435,7 @@ dependencies = [ "checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3" "checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150" "checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9" +"checksum crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5" "checksum csv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "9fd1c44c58078cfbeaf11fbb3eac9ae5534c23004ed770cc4bfb48e658ae4f04" "checksum csv-core 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa5cdef62f37e6ffe7d1f07a381bc0db32b7a3ff1cac0de56cb0d81e71f53d65" "checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c" @@ -1437,13 +1467,13 @@ dependencies = [ "checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39" "checksum memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" -"checksum meowhash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b00a85ae2fa3525c3f0e6e7b87bec96ab5587100d7ba7b3e30e1885960a8230b" "checksum nix 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "921f61dc817b379d0834e45d5ec45beaacfae97082090a49c2cf30dcbc30206f" "checksum nix 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46f0f3210768d796e8fa79ec70ee6af172dacbe7147f5e69be5240a47778302b" "checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" "checksum nom 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b30adc557058ce00c9d0d7cb3c6e0b5bc6f36e2e2eabe74b0ba726d194abd588" "checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" "checksum num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a23f0ed30a54abaa0c7e83b1d2d87ada7c3c23078d1d87815af3e3b6385fbba" +"checksum opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "93f5bb2e8e8dec81642920ccff6b61f1eb94fa3020c5a325c9851ff604152409" "checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" "checksum page_size 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f89ef58b3d32420dbd1a43d2f38ae92f6239ef12bb556ab09ca55445f5a67242" "checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" @@ -1491,6 +1521,7 @@ dependencies = [ "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" "checksum structopt 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "670ad348dc73012fcf78c71f06f9d942232cdd4c859d4b6975e27836c3efc0c3" "checksum structopt-derive 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "ef98172b1a00b0bec738508d3726540edcbd186d50dfd326f2b1febbb3559f04" +"checksum subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" "checksum syn 0.13.11 (registry+https://github.com/rust-lang/crates.io-index)" = "14f9bf6292f3a61d2c716723fdb789a41bbe104168e6f496dc6497e531ea1b9b" "checksum syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)" = "f92e629aa1d9c827b2bb8297046c1ccffc57c99b947a680d3ccff1f136a3bee9" "checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" diff --git a/lib/runtime-core/Cargo.toml b/lib/runtime-core/Cargo.toml index 3d61a858c..5e89c7cde 100644 --- a/lib/runtime-core/Cargo.toml +++ b/lib/runtime-core/Cargo.toml @@ -29,8 +29,8 @@ version = "1.0" version = "0.10" [dependencies.serde-bench] version = "0.0.7" -[dependencies.meowhash] -version = "0.1.2" +[dependencies.blake2] +version = "0.8" [dependencies.digest] version = "0.8.0" [dependencies.hashbrown] diff --git a/lib/runtime-core/src/cache.rs b/lib/runtime-core/src/cache.rs index 4859bd390..d4d01edd9 100644 --- a/lib/runtime-core/src/cache.rs +++ b/lib/runtime-core/src/cache.rs @@ -2,8 +2,7 @@ use crate::{ module::{Module, ModuleInfo}, sys::Memory, }; -use digest::Digest; -use meowhash::MeowHasher; +use blake2::{Blake2b, Digest}; use std::{fmt, io, mem, slice}; #[derive(Debug)] @@ -45,7 +44,10 @@ impl WasmHash { pub fn generate(wasm: &[u8]) -> Self { let mut first_part = [0u8; 32]; let mut second_part = [0u8; 32]; - let generic_array = MeowHasher::digest(wasm); + + let mut hasher = Blake2b::new(); + hasher.input(wasm); + let generic_array = hasher.result(); first_part.copy_from_slice(&generic_array[0..32]); second_part.copy_from_slice(&generic_array[32..64]); From 2d49d58665f6447e1f82939c65ccbd0333b121c0 Mon Sep 17 00:00:00 2001 From: Syrus Date: Mon, 25 Feb 2019 17:43:25 -0800 Subject: [PATCH 126/262] Use blake2b (simd) version instead of blake2 --- Cargo.lock | 56 +++++++++++++---------------------- lib/runtime-core/Cargo.toml | 4 +-- lib/runtime-core/src/cache.rs | 7 ++--- 3 files changed, 25 insertions(+), 42 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f8b6f496b..b2222ed55 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -16,6 +16,11 @@ dependencies = [ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "arrayref" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "arrayvec" version = "0.4.10" @@ -88,21 +93,16 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "blake2" -version = "0.8.0" +name = "blake2b_simd" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "byte-tools" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "byteorder" version = "1.3.1" @@ -186,6 +186,11 @@ dependencies = [ "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "constant_time_eq" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "cranelift-bforest" version = "0.26.0" @@ -321,15 +326,6 @@ dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "crypto-mac" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "csv" version = "1.0.5" @@ -615,11 +611,6 @@ dependencies = [ "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "opaque-debug" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "owning_ref" version = "0.4.0" @@ -1013,11 +1004,6 @@ dependencies = [ "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "subtle" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "syn" version = "0.13.11" @@ -1295,7 +1281,7 @@ dependencies = [ name = "wasmer-runtime-core" version = "0.2.0" dependencies = [ - "blake2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "blake2b_simd 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "digest 0.8.0 (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)", @@ -1404,6 +1390,7 @@ dependencies = [ [metadata] "checksum aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1e9a933f4e58658d7b12defcf96dc5c720f20832deebe3e0a19efd3b6aaeeb9e" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" +"checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" "checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" "checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799" @@ -1411,8 +1398,7 @@ dependencies = [ "checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6" "checksum bindgen 0.46.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8f7f7f0701772b17de73e4f5cbcb1dd6926f4706cba4c1ab62c5367f8bdc94e1" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" -"checksum blake2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "91721a6330935673395a0607df4d49a9cb90ae12d259f1b3e0a3f6e1d486872e" -"checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" +"checksum blake2b_simd 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ce2571a6cd634670daa2977cc894c1cc2ba57c563c498e5a82c35446f34d056e" "checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" "checksum cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "926013f2860c46252efceabb19f4a6b308197505082c609025aa6706c011d427" "checksum cbindgen 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "32e01024aaf5390d6a8145047371a4f5b0063a14c1e411bc731353bd2278ca44" @@ -1423,6 +1409,7 @@ dependencies = [ "checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum cmake 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "6ec65ee4f9c9d16f335091d23693457ed4928657ba4982289d7fafee03bc614a" +"checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" "checksum cranelift-bforest 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "40f8ff24e9a6c89b8a846b14df9a34d2cac17cea7bdb5c81ed6b4744ee0e38bf" "checksum cranelift-codegen 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "42f5b809bd885c368e01aeec8fe04f21dcb07569834b907d75b4a7bed8d067eb" "checksum cranelift-codegen-meta 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "014c23ed3ebdc8377d41540af638245207dd169f421df042dfccc867465734ed" @@ -1435,7 +1422,6 @@ dependencies = [ "checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3" "checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150" "checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9" -"checksum crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5" "checksum csv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "9fd1c44c58078cfbeaf11fbb3eac9ae5534c23004ed770cc4bfb48e658ae4f04" "checksum csv-core 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa5cdef62f37e6ffe7d1f07a381bc0db32b7a3ff1cac0de56cb0d81e71f53d65" "checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c" @@ -1473,7 +1459,6 @@ dependencies = [ "checksum nom 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b30adc557058ce00c9d0d7cb3c6e0b5bc6f36e2e2eabe74b0ba726d194abd588" "checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" "checksum num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a23f0ed30a54abaa0c7e83b1d2d87ada7c3c23078d1d87815af3e3b6385fbba" -"checksum opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "93f5bb2e8e8dec81642920ccff6b61f1eb94fa3020c5a325c9851ff604152409" "checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" "checksum page_size 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f89ef58b3d32420dbd1a43d2f38ae92f6239ef12bb556ab09ca55445f5a67242" "checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" @@ -1521,7 +1506,6 @@ dependencies = [ "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" "checksum structopt 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "670ad348dc73012fcf78c71f06f9d942232cdd4c859d4b6975e27836c3efc0c3" "checksum structopt-derive 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "ef98172b1a00b0bec738508d3726540edcbd186d50dfd326f2b1febbb3559f04" -"checksum subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" "checksum syn 0.13.11 (registry+https://github.com/rust-lang/crates.io-index)" = "14f9bf6292f3a61d2c716723fdb789a41bbe104168e6f496dc6497e531ea1b9b" "checksum syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)" = "f92e629aa1d9c827b2bb8297046c1ccffc57c99b947a680d3ccff1f136a3bee9" "checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" diff --git a/lib/runtime-core/Cargo.toml b/lib/runtime-core/Cargo.toml index 5e89c7cde..00ac57189 100644 --- a/lib/runtime-core/Cargo.toml +++ b/lib/runtime-core/Cargo.toml @@ -29,8 +29,8 @@ version = "1.0" version = "0.10" [dependencies.serde-bench] version = "0.0.7" -[dependencies.blake2] -version = "0.8" +[dependencies.blake2b_simd] +version = "0.4.1" [dependencies.digest] version = "0.8.0" [dependencies.hashbrown] diff --git a/lib/runtime-core/src/cache.rs b/lib/runtime-core/src/cache.rs index d4d01edd9..ec2b0b01f 100644 --- a/lib/runtime-core/src/cache.rs +++ b/lib/runtime-core/src/cache.rs @@ -2,7 +2,7 @@ use crate::{ module::{Module, ModuleInfo}, sys::Memory, }; -use blake2::{Blake2b, Digest}; +use blake2b_simd::blake2b; use std::{fmt, io, mem, slice}; #[derive(Debug)] @@ -45,9 +45,8 @@ impl WasmHash { let mut first_part = [0u8; 32]; let mut second_part = [0u8; 32]; - let mut hasher = Blake2b::new(); - hasher.input(wasm); - let generic_array = hasher.result(); + let mut hasher = blake2b(wasm); + let generic_array = hasher.as_bytes(); first_part.copy_from_slice(&generic_array[0..32]); second_part.copy_from_slice(&generic_array[32..64]); From 44b8d0b1ee4efe198d9ca200e6210c31a7a973ae Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Mon, 25 Feb 2019 18:07:22 -0800 Subject: [PATCH 127/262] Start work on object loader using llvm's RuntimeDyld api. --- Cargo.lock | 30 ++++ lib/llvm-backend/Cargo.toml | 8 + lib/llvm-backend/build.rs | 203 +++++++++++++++++++++++++ lib/llvm-backend/cpp/object_loader.cpp | 96 ++++++++++++ lib/llvm-backend/cpp/object_loader.hh | 40 +++++ lib/llvm-backend/src/backend.rs | 79 +++++++--- lib/llvm-backend/src/code.rs | 52 +++++-- lib/llvm-backend/src/intrinsics.rs | 6 +- lib/llvm-backend/src/lib.rs | 177 ++++++++++----------- 9 files changed, 569 insertions(+), 122 deletions(-) create mode 100644 lib/llvm-backend/build.rs create mode 100644 lib/llvm-backend/cpp/object_loader.cpp create mode 100644 lib/llvm-backend/cpp/object_loader.hh diff --git a/Cargo.lock b/Cargo.lock index ca2129890..9d743e96c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -262,6 +262,28 @@ dependencies = [ "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "dlopen" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "dlopen_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "dlopen_derive" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "either" version = "1.5.1" @@ -469,10 +491,16 @@ dependencies = [ name = "llvm-backend" version = "0.1.0" dependencies = [ + "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "dlopen 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "goblin 0.0.20 (registry+https://github.com/rust-lang/crates.io-index)", "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "inkwell 0.1.0 (git+https://github.com/TheDan64/inkwell?branch=llvm7-0)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-runtime-core 0.1.2", "wasmparser 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1362,6 +1390,8 @@ dependencies = [ "checksum cranelift-native 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "474bee81d620a473bf43411a3d6f10ffbf7965141dc5e5b76d8d2151dde3285d" "checksum cranelift-wasm 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49723365dab9a48b354bdc24cb6d9d5719bc1d3b858ffd2ea179d0d7d885804a" "checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c" +"checksum dlopen 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f8c301a18a3404a48d5d078e86b011ac834a6c4c742217e9aa8ceadd8a7e09e0" +"checksum dlopen_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6e16e4e343d6090ba47113c55bf6aa94e9b1eb5ab0c5abc9510d4c15074f30e9" "checksum either 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c67353c641dc847124ea1902d69bd753dee9bb3beff9aa3662ecf86c971d1fac" "checksum enum-methods 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7798e7da2d4cb0d6d6fc467e8d6b5bf247e9e989f786dde1732d79899c32bb10" "checksum env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "afb070faf94c85d17d50ca44f6ad076bce18ae92f0037d350947240a36e9d42e" diff --git a/lib/llvm-backend/Cargo.toml b/lib/llvm-backend/Cargo.toml index 8ffac375f..3ec83d77c 100644 --- a/lib/llvm-backend/Cargo.toml +++ b/lib/llvm-backend/Cargo.toml @@ -11,6 +11,14 @@ inkwell = { git = "https://github.com/TheDan64/inkwell", branch = "llvm7-0" } hashbrown = "0.1.8" smallvec = "0.6.8" goblin = "0.0.20" +dlopen = "0.1.6" +tempfile = "3.0.7" + +[build-dependencies] +cc = "1.0" +lazy_static = "1.2.0" +regex = "1.1.0" +semver = "0.9" [dev-dependencies] wabt = "0.7.4" diff --git a/lib/llvm-backend/build.rs b/lib/llvm-backend/build.rs new file mode 100644 index 000000000..e38cec034 --- /dev/null +++ b/lib/llvm-backend/build.rs @@ -0,0 +1,203 @@ +//! This file was mostly taken from the llvm-sys crate. +//! (https://bitbucket.org/tari/llvm-sys.rs/src/21ab524ec4df1450035df895209c3f8fbeb8775f/build.rs?at=default&fileviewer=file-view-default) + +use regex::Regex; +use lazy_static::lazy_static; +use semver::Version; +use std::env; +use std::ffi::OsStr; +use std::io::{self, ErrorKind}; +use std::path::PathBuf; +use std::process::Command; + +lazy_static! { + /// LLVM version used by this version of the crate. + static ref CRATE_VERSION: Version = { + let crate_version = Version::parse(env!("CARGO_PKG_VERSION")) + .expect("Crate version is somehow not valid semver"); + Version { + major: crate_version.major / 10, + minor: crate_version.major % 10, + .. crate_version + } + }; + + static ref LLVM_CONFIG_BINARY_NAMES: Vec = { + vec![ + "llvm-config".into(), + // format!("llvm-config-{}", CRATE_VERSION.major), + // format!("llvm-config-{}.{}", CRATE_VERSION.major, CRATE_VERSION.minor), + ] + }; + + /// Filesystem path to an llvm-config binary for the correct version. + static ref LLVM_CONFIG_PATH: PathBuf = { + // Try llvm-config via PATH first. + if let Some(name) = locate_system_llvm_config() { + return name.into(); + } else { + println!("Didn't find usable system-wide LLVM."); + } + + // Did the user give us a binary path to use? If yes, try + // to use that and fail if it doesn't work. + let binary_prefix_var = "LLVM_SYS_70_PREFIX"; + + let path = if let Some(path) = env::var_os(&binary_prefix_var) { + Some(path.to_str().unwrap().to_owned()) + } else if let Ok(mut file) = std::fs::File::open(".llvmenv") { + use std::io::Read; + let mut s = String::new(); + file.read_to_string(&mut s).unwrap(); + Some(s) + } else { + None + }; + + if let Some(path) = path { + for binary_name in LLVM_CONFIG_BINARY_NAMES.iter() { + let mut pb: PathBuf = path.clone().into(); + pb.push("bin"); + pb.push(binary_name); + + let ver = llvm_version(&pb) + .expect(&format!("Failed to execute {:?}", &pb)); + if is_compatible_llvm(&ver) { + return pb; + } else { + println!("LLVM binaries specified by {} are the wrong version. + (Found {}, need {}.)", binary_prefix_var, ver, *CRATE_VERSION); + } + } + } + + println!("No suitable version of LLVM was found system-wide or pointed + to by {}. + + Consider using `llvmenv` to compile an appropriate copy of LLVM, and + refer to the llvm-sys documentation for more information. + + llvm-sys: https://crates.io/crates/llvm-sys + llvmenv: https://crates.io/crates/llvmenv", binary_prefix_var); + panic!("Could not find a compatible version of LLVM"); + }; +} + +/// Try to find a system-wide version of llvm-config that is compatible with +/// this crate. +/// +/// Returns None on failure. +fn locate_system_llvm_config() -> Option<&'static str> { + for binary_name in LLVM_CONFIG_BINARY_NAMES.iter() { + match llvm_version(binary_name) { + Ok(ref version) if is_compatible_llvm(version) => { + // Compatible version found. Nice. + return Some(binary_name); + } + Ok(version) => { + // Version mismatch. Will try further searches, but warn that + // we're not using the system one. + println!("Found LLVM version {} on PATH, but need {}.", + version, + *CRATE_VERSION); + } + Err(ref e) if e.kind() == ErrorKind::NotFound => { + // Looks like we failed to execute any llvm-config. Keep + // searching. + } + // Some other error, probably a weird failure. Give up. + Err(e) => panic!("Failed to search PATH for llvm-config: {}", e), + } + } + + None +} + +/// Check whether the given LLVM version is compatible with this version of +/// the crate. +fn is_compatible_llvm(llvm_version: &Version) -> bool { + let strict = env::var_os(format!("LLVM_SYS_{}_STRICT_VERSIONING", + env!("CARGO_PKG_VERSION_MAJOR"))) + .is_some() || cfg!(feature = "strict-versioning"); + if strict { + llvm_version.major == CRATE_VERSION.major && llvm_version.minor == CRATE_VERSION.minor + } else { + llvm_version.major >= CRATE_VERSION.major || + (llvm_version.major == CRATE_VERSION.major && llvm_version.minor >= CRATE_VERSION.minor) + } +} + +/// Get the output from running `llvm-config` with the given argument. +/// +/// Lazily searches for or compiles LLVM as configured by the environment +/// variables. +fn llvm_config(arg: &str) -> String { + llvm_config_ex(&*LLVM_CONFIG_PATH, arg).expect("Surprising failure from llvm-config") +} + +/// Invoke the specified binary as llvm-config. +/// +/// Explicit version of the `llvm_config` function that bubbles errors +/// up. +fn llvm_config_ex>(binary: S, arg: &str) -> io::Result { + Command::new(binary) + .arg(arg) + .arg("--link-static") // Don't use dylib for >= 3.9 + .output() + .map(|output| String::from_utf8(output.stdout) + .expect("Output from llvm-config was not valid UTF-8")) +} + +/// Get the LLVM version using llvm-config. +fn llvm_version>(binary: S) -> io::Result { + let version_str = llvm_config_ex(binary.as_ref(), "--version")?; + + // LLVM isn't really semver and uses version suffixes to build + // version strings like '3.8.0svn', so limit what we try to parse + // to only the numeric bits. + let re = Regex::new(r"^(?P\d+)\.(?P\d+)(?:\.(?P\d+))??").unwrap(); + let c = re.captures(&version_str).expect("Could not determine LLVM version from llvm-config."); + + // some systems don't have a patch number but Version wants it so we just append .0 if it isn't + // there + let s = match c.name("patch") { + None => format!("{}.0", &c[0]), + Some(_) => c[0].to_string(), + }; + Ok(Version::parse(&s).unwrap()) +} + +fn get_llvm_cxxflags() -> String { + let output = llvm_config("--cxxflags"); + + // llvm-config includes cflags from its own compilation with --cflags that + // may not be relevant to us. In particularly annoying cases, these might + // include flags that aren't understood by the default compiler we're + // using. Unless requested otherwise, clean CFLAGS of options that are + // known to be possibly-harmful. + let no_clean = env::var_os(format!("LLVM_SYS_{}_NO_CLEAN_CFLAGS", + env!("CARGO_PKG_VERSION_MAJOR"))) + .is_some(); + if no_clean || cfg!(target_env = "msvc") { + // MSVC doesn't accept -W... options, so don't try to strip them and + // possibly strip something that should be retained. Also do nothing if + // the user requests it. + return output; + } + + output + .split(&[' ', '\n'][..]) + .filter(|word| !word.starts_with("-W")) + .collect::>() + .join(" ") +} + +fn main() { + std::env::set_var("CXXFLAGS", get_llvm_cxxflags()); + cc::Build::new() + .cpp(true) + .file("cpp/object_loader.cpp") + .compile("llvm-backend"); + + println!("cargo:rustc-link-lib=static=llvm-backend"); +} \ No newline at end of file diff --git a/lib/llvm-backend/cpp/object_loader.cpp b/lib/llvm-backend/cpp/object_loader.cpp new file mode 100644 index 000000000..9ab36f4c3 --- /dev/null +++ b/lib/llvm-backend/cpp/object_loader.cpp @@ -0,0 +1,96 @@ +#include "object_loader.hh" +#include +#include + +class MemoryManager : llvm::RuntimeDyld::MemoryManager { +public: + MemoryManager() {} + + virtual ~MemoryManager() {} + + virtual uint8_t* allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID, llvm::StringRef SectionName) override { + return nullptr; + } + + virtual uint8_t* allocateDataSection(uintptr_t Size, unsigned Alignment, unsigned SectionID, llvm::StringRef SectionName, bool isReadOnly) override { + return nullptr; + } + + virtual void reserveAllocationSpace( + uintptr_t code_size, + uint32_t code_align, + uintptr_t read_data_size, + uint32_t read_data_align, + uintptr_t read_write_data_size, + uint32_t read_write_data_align + ) override { + + } + + /* Turn on the `reserveAllocationSpace` callback. */ + virtual bool needsToReserveAllocationSpace() override { + return true; + } + + virtual void registerEHFrames(uint8_t* Addr, uint64_t LoadAddr, size_t Size) override { + + } + + virtual void deregisterEHFrames() override { + + } + + virtual bool finalizeMemory(std::string *ErrMsg = nullptr) override { + + + return false; + } + + virtual void notifyObjectLoaded(llvm::RuntimeDyld &RTDyld, const llvm::object::ObjectFile &Obj) override { + + } +private: + struct Section { + uint8_t* base; + size_t num_pages; + size_t num_commited_bytes; + }; + + uint8_t *image_base; + size_t num_allocated_pages; + + Section code_section, read_section, readwrite_section; + + +}; + +class SymbolLookup : llvm::JITSymbolResolver { +public: + virtual llvm::Expected lookup(const LookupSet& symbols) override { + LookupResult result; + + for (auto symbol : symbols) { + result.emplace(symbol, symbol_lookup(symbol)); + } + + return result; + } + + virtual llvm::Expected lookupFlags(const LookupSet& symbols) override { + LookupFlagsResult result; + + for (auto symbol : symbols) { + result.emplace(symbol, symbol_lookup(symbol).getFlags()); + } + + return result; + } + +private: + llvm::JITEvaluatedSymbol symbol_lookup(llvm::StringRef name) { + std::cout << "symbol name: " << (std::string)name << std::endl; + uint64_t addr = 0; + + return llvm::JITEvaluatedSymbol(addr, llvm::JITSymbolFlags::None); + } +}; \ No newline at end of file diff --git a/lib/llvm-backend/cpp/object_loader.hh b/lib/llvm-backend/cpp/object_loader.hh new file mode 100644 index 000000000..50b618b38 --- /dev/null +++ b/lib/llvm-backend/cpp/object_loader.hh @@ -0,0 +1,40 @@ +#include +#include + +typedef enum { + PROTECT_NONE, + PROTECT_READ, + PROTECT_READ_WRITE, + PROTECT_READ_EXECUTE, +} mem_protect_t; + +typedef enum { + RESULT_OK, + RESULT_ALLOCATE_FAILURE, + RESULT_PROTECT_FAILURE, + RESULT_DEALLOC_FAILURE, + RESULT_OBJECT_LOAD_FAILURE, +} result_t; + +typedef result_t (*alloc_memory_t)(size_t size, mem_protect_t protect, uint8_t** ptr_out, size_t* size_out); +typedef result_t (*protect_memory_t)(uint8_t* ptr, size_t size, mem_protect_t protect); +typedef result_t (*dealloc_memory_t)(uint8_t* ptr, size_t size); +typedef uintptr_t (*lookup_vm_symbol_t)(char* name_ptr, size_t name_size); + +typedef struct { + /* Memory management. */ + alloc_memory_t alloc_memory; + protect_memory_t protect_memory; + dealloc_memory_t dealloc_memory; + + lookup_vm_symbol_t lookup_vm_symbol; +} callbacks_t; + +extern "C" { + result_t object_load(uint8_t* mem_ptr, size_t mem_size, callbacks_t* callbacks) { + return RESULT_OK; + } + + void test_cpp() { + } +} \ No newline at end of file diff --git a/lib/llvm-backend/src/backend.rs b/lib/llvm-backend/src/backend.rs index 9821eabf6..2b4bb7023 100644 --- a/lib/llvm-backend/src/backend.rs +++ b/lib/llvm-backend/src/backend.rs @@ -1,45 +1,76 @@ +use crate::intrinsics::Intrinsics; +use dlopen::symbor::Library; use inkwell::{ module::Module, - execution_engine::{ExecutionEngine, JitFunction}, + targets::{CodeModel, FileType, InitializationConfig, RelocMode, Target, TargetMachine}, + OptimizationLevel, }; -use crate::intrinsics::Intrinsics; -use std::ptr::NonNull; +use std::{io::Write, ptr::NonNull}; +use tempfile::NamedTempFile; use wasmer_runtime_core::{ - module::ModuleInner, - types::LocalFuncIndex, - structures::TypedIndex, - backend::{FuncResolver, vm}, + backend::FuncResolver, module::ModuleInner, structures::TypedIndex, types::LocalFuncIndex, vm, }; pub struct LLVMBackend { - exec_engine: ExecutionEngine, + tempfile: NamedTempFile, + library: Library, } impl LLVMBackend { pub fn new(module: Module, intrinsics: Intrinsics) -> Self { - let exec_engine = module.create_jit_execution_engine(OptimizationLevel::Default).unwrap(); + Target::initialize_x86(&InitializationConfig { + asm_parser: true, + asm_printer: true, + base: true, + disassembler: true, + info: true, + machine_code: true, + }); + let triple = TargetMachine::get_default_triple().to_string(); + let target = Target::from_triple(&triple).unwrap(); + let target_machine = target + .create_target_machine( + &triple, + &TargetMachine::get_host_cpu_name().to_string(), + &TargetMachine::get_host_cpu_features().to_string(), + OptimizationLevel::Default, + RelocMode::PIC, + CodeModel::Default, + ) + .unwrap(); - exec_engine.add_global_mapping(&intrinsics.memory_grow_dynamic_local, vmcalls::local_dynamic_memory_grow as usize); - exec_engine.add_global_mapping(&intrinsics.memory_grow_static_local, vmcalls::local_static_memory_grow as usize); - exec_engine.add_global_mapping(&intrinsics.memory_grow_dynamic_import, vmcalls::imported_dynamic_memory_grow as usize); - exec_engine.add_global_mapping(&intrinsics.memory_grow_static_import, vmcalls::imported_static_memory_grow as usize); - exec_engine.add_global_mapping(&intrinsics.memory_size_dynamic_local, vmcalls::local_dynamic_memory_size as usize); - exec_engine.add_global_mapping(&intrinsics.memory_size_static_local, vmcalls::local_static_memory_size as usize); - exec_engine.add_global_mapping(&intrinsics.memory_size_dynamic_import, vmcalls::imported_dynamic_memory_size as usize); - exec_engine.add_global_mapping(&intrinsics.memory_size_static_import, vmcalls::imported_static_memory_size as usize); + let memory_buffer = target_machine + .write_to_memory_buffer(&module, FileType::Object) + .unwrap(); - Self { exec_engine } + let mut tempfile = NamedTempFile::new().unwrap(); + tempfile.write_all(memory_buffer.as_slice()).unwrap(); + tempfile.flush().unwrap(); + + let library = Library::open(tempfile.path()).unwrap(); + + Self { tempfile, library } } } impl FuncResolver for LLVMBackend { - fn get(&self, module: &ModuleInner, local_func_index: LocalFuncIndex) -> Option> { + fn get( + &self, + module: &ModuleInner, + local_func_index: LocalFuncIndex, + ) -> Option> { let index = module.info.imported_functions.len() + local_func_index.index(); - let name = format!("fn{}", index); - + let name = if cfg!(macos) { + format!("_fn{}", index) + } else { + format!("fn{}", index) + }; + unsafe { - let func: JitFunction = self.exec_engine.get_function(&name).ok()?; - + self.library + .symbol::>(&name) + .ok() + .map(|symbol| *symbol) } } -} \ No newline at end of file +} diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index d72659fd9..e0f4d984f 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -481,6 +481,7 @@ fn parse_function( // Emit an unreachable instruction. // If llvm cannot prove that this is never touched, // it will emit a `ud2` instruction on x86_64 arches. + ctx.build_trap(); builder.build_unreachable(); state.reachable = false; } @@ -623,7 +624,8 @@ fn parse_function( } } Operator::CallIndirect { index, table_index } => { - let expected_dynamic_sigindex = ctx.dynamic_sigindex(SigIndex::new(index as usize)); + let sig_index = SigIndex::new(index as usize); + let expected_dynamic_sigindex = ctx.dynamic_sigindex(sig_index); let (table_base, table_bound) = ctx.table(TableIndex::new(table_index as usize)); let func_index = state.pop1()?.into_int_value(); @@ -651,12 +653,10 @@ fn parse_function( "func_ptr", ) .into_pointer_value(), - builder - .build_load( - builder.build_struct_gep(anyfunc_struct_ptr, 1, "ctx_ptr_ptr"), - "ctx_ptr", - ) - .into_pointer_value(), + builder.build_load( + builder.build_struct_gep(anyfunc_struct_ptr, 1, "ctx_ptr_ptr"), + "ctx_ptr", + ), builder .build_load( builder.build_struct_gep(anyfunc_struct_ptr, 2, "sigindex_ptr"), @@ -685,21 +685,49 @@ fn parse_function( ) .try_as_basic_value() .left() - .unwrap(); + .unwrap() + .into_int_value(); let continue_block = context.append_basic_block(&function, "continue_block"); let sigindices_notequal_block = context.append_basic_block(&function, "sigindices_notequal_block"); + builder.build_conditional_branch( + sigindices_equal, + &continue_block, + &sigindices_notequal_block, + ); builder.position_at_end(&sigindices_notequal_block); + ctx.build_trap(); builder.build_unreachable(); builder.position_at_end(&continue_block); - println!("func ptr: {:#?}", func_ptr); - println!("ctx ptr: {:#?}", ctx_ptr); - println!("found dynamic sigindex: {:#?}", found_dynamic_sigindex); + let wasmer_fn_sig = &info.signatures[sig_index]; + let fn_ty = signatures[sig_index]; - unimplemented!("{}, {}", index, table_index); + let pushed_args = state.popn_save(wasmer_fn_sig.params().len())?; + + let args: Vec<_> = std::iter::once(ctx_ptr) + .chain(pushed_args.into_iter()) + .collect(); + println!("args: {:?}", args); + + let typed_func_ptr = builder.build_pointer_cast( + func_ptr, + fn_ty.ptr_type(AddressSpace::Generic), + "typed_func_ptr", + ); + + let call_site = builder.build_call(typed_func_ptr, &args, "indirect_call"); + + match wasmer_fn_sig.returns() { + [] => {} + [_] => { + let value = call_site.try_as_basic_value().left().unwrap(); + state.push1(value); + } + returns @ _ => unimplemented!("multi-value returns"), + } } /*************************** diff --git a/lib/llvm-backend/src/intrinsics.rs b/lib/llvm-backend/src/intrinsics.rs index ccc0081bf..f2ec8fd05 100644 --- a/lib/llvm-backend/src/intrinsics.rs +++ b/lib/llvm-backend/src/intrinsics.rs @@ -64,6 +64,7 @@ pub struct Intrinsics { pub copysign_f64: FunctionValue, pub expect_i1: FunctionValue, + pub trap: FunctionValue, pub void_ty: VoidType, pub i1_ty: IntType, @@ -255,6 +256,7 @@ impl Intrinsics { copysign_f64: module.add_function("llvm.copysign.f64", ret_f64_take_f64_f64, None), expect_i1: module.add_function("llvm.expect.i1", ret_i1_take_i1_i1, None), + trap: module.add_function("llvm.trap", void_ty.fn_type(&[], false), None), void_ty, i1_ty, @@ -695,7 +697,9 @@ impl<'a> CtxType<'a> { (imported_func_cache.func_ptr, imported_func_cache.ctx_ptr) } - // pub fn table(&mut self, table_index: TableIndex, elem_index: IntValue) -> + pub fn build_trap(&self) { + self.builder.build_call(self.intrinsics.trap, &[], "trap"); + } } // pub struct Ctx { diff --git a/lib/llvm-backend/src/lib.rs b/lib/llvm-backend/src/lib.rs index e70af96c0..e06b081af 100644 --- a/lib/llvm-backend/src/lib.rs +++ b/lib/llvm-backend/src/lib.rs @@ -10,11 +10,11 @@ use wasmer_runtime_core::{ module::ModuleInner, }; +mod backend; mod code; mod intrinsics; mod read_info; mod state; -// mod backend; pub struct LLVMCompiler { _private: (), @@ -28,13 +28,61 @@ impl LLVMCompiler { impl Compiler for LLVMCompiler { fn compile(&self, wasm: &[u8], _: Token) -> Result { - let (_info, _code_reader) = read_info::read_module(wasm).unwrap(); + let (info, code_reader) = read_info::read_module(wasm).unwrap(); + let (module, intrinsics) = code::parse_function_bodies(&info, code_reader).unwrap(); - unimplemented!() + let backend = backend::LLVMBackend::new(module, intrinsics); + + // Create placeholder values here. + let (protected_caller, cache_gen) = { + use wasmer_runtime_core::backend::{ + sys::Memory, CacheGen, ProtectedCaller, UserTrapper, + }; + use wasmer_runtime_core::cache::Error as CacheError; + use wasmer_runtime_core::error::RuntimeResult; + use wasmer_runtime_core::module::ModuleInfo; + use wasmer_runtime_core::types::{FuncIndex, Value}; + use wasmer_runtime_core::vm; + struct Placeholder; + impl ProtectedCaller for Placeholder { + fn call( + &self, + _module: &ModuleInner, + _func_index: FuncIndex, + _params: &[Value], + _import_backing: &vm::ImportBacking, + _vmctx: *mut vm::Ctx, + _: Token, + ) -> RuntimeResult> { + Ok(vec![]) + } + fn get_early_trapper(&self) -> Box { + unimplemented!() + } + } + impl CacheGen for Placeholder { + fn generate_cache( + &self, + module: &ModuleInner, + ) -> Result<(Box, Box<[u8]>, Memory), CacheError> { + unimplemented!() + } + } + + (Box::new(Placeholder), Box::new(Placeholder)) + }; + + Ok(ModuleInner { + func_resolver: Box::new(backend), + protected_caller, + cache_gen, + + info, + }) } unsafe fn from_cache(&self, _artifact: Artifact, _: Token) -> Result { - unimplemented!() + unimplemented!("the llvm backend doesn't support caching yet") } } @@ -55,14 +103,9 @@ fn test_read_module() { get_local 0 i32.const 0 call_indirect (type $t0) - memory.grow ) (func $foobar (type $t0) get_local 0 - ) - (func $bar (type $t0) (param i32) (result i32) - get_local 0 - call $foo )) "#; let wasm = wat2wasm(wat).unwrap(); @@ -71,86 +114,50 @@ fn test_read_module() { let (module, intrinsics) = code::parse_function_bodies(&info, code_reader).unwrap(); - { - Target::initialize_x86(&InitializationConfig { - asm_parser: true, - asm_printer: true, - base: true, - disassembler: true, - info: true, - machine_code: true, - }); - let triple = TargetMachine::get_default_triple().to_string(); - let target = Target::from_triple(&triple).unwrap(); - let target_machine = target - .create_target_machine( - &triple, - &TargetMachine::get_host_cpu_name().to_string(), - &TargetMachine::get_host_cpu_features().to_string(), - OptimizationLevel::Default, - RelocMode::PIC, - CodeModel::Default, - ) - .unwrap(); + // let backend = backend::LLVMBackend::new(module, intrinsics); - let memory_buffer = target_machine - .write_to_memory_buffer(&module, FileType::Object) - .unwrap(); - // std::fs::write("memory_buffer", memory_buffer.as_slice()).unwrap(); - let mem_buf_slice = memory_buffer.as_slice(); - - let macho = goblin::mach::MachO::parse(mem_buf_slice, 0).unwrap(); - let symbols = macho.symbols.as_ref().unwrap(); - let relocations = macho.relocations().unwrap(); - for (_, reloc_iter, section) in relocations.into_iter() { - println!("section: {:#?}", section); - for reloc_info in reloc_iter { - let reloc_info = reloc_info.unwrap(); - println!("\treloc_info: {:#?}", reloc_info); - println!( - "\tsymbol: {:#?}", - symbols.get(reloc_info.r_symbolnum()).unwrap() - ); - } - } + extern "C" { + fn test_cpp(); } - let exec_engine = module - .create_jit_execution_engine(OptimizationLevel::Default) - .unwrap(); + unsafe { test_cpp() }; - exec_engine.add_global_mapping( - &intrinsics.memory_grow_dynamic_local, - vmcalls::local_dynamic_memory_grow as usize, - ); - exec_engine.add_global_mapping( - &intrinsics.memory_grow_static_local, - vmcalls::local_static_memory_grow as usize, - ); - exec_engine.add_global_mapping( - &intrinsics.memory_grow_dynamic_import, - vmcalls::imported_dynamic_memory_grow as usize, - ); - exec_engine.add_global_mapping( - &intrinsics.memory_grow_static_import, - vmcalls::imported_static_memory_grow as usize, - ); - exec_engine.add_global_mapping( - &intrinsics.memory_size_dynamic_local, - vmcalls::local_dynamic_memory_size as usize, - ); - exec_engine.add_global_mapping( - &intrinsics.memory_size_static_local, - vmcalls::local_static_memory_size as usize, - ); - exec_engine.add_global_mapping( - &intrinsics.memory_size_dynamic_import, - vmcalls::imported_dynamic_memory_size as usize, - ); - exec_engine.add_global_mapping( - &intrinsics.memory_size_static_import, - vmcalls::imported_static_memory_size as usize, - ); + // let exec_engine = module + // .create_jit_execution_engine(OptimizationLevel::Default) + // .unwrap(); + + // exec_engine.add_global_mapping( + // &intrinsics.memory_grow_dynamic_local, + // vmcalls::local_dynamic_memory_grow as usize, + // ); + // exec_engine.add_global_mapping( + // &intrinsics.memory_grow_static_local, + // vmcalls::local_static_memory_grow as usize, + // ); + // exec_engine.add_global_mapping( + // &intrinsics.memory_grow_dynamic_import, + // vmcalls::imported_dynamic_memory_grow as usize, + // ); + // exec_engine.add_global_mapping( + // &intrinsics.memory_grow_static_import, + // vmcalls::imported_static_memory_grow as usize, + // ); + // exec_engine.add_global_mapping( + // &intrinsics.memory_size_dynamic_local, + // vmcalls::local_dynamic_memory_size as usize, + // ); + // exec_engine.add_global_mapping( + // &intrinsics.memory_size_static_local, + // vmcalls::local_static_memory_size as usize, + // ); + // exec_engine.add_global_mapping( + // &intrinsics.memory_size_dynamic_import, + // vmcalls::imported_dynamic_memory_size as usize, + // ); + // exec_engine.add_global_mapping( + // &intrinsics.memory_size_static_import, + // vmcalls::imported_static_memory_size as usize, + // ); // unsafe { // let func: JitFunction i32> = exec_engine.get_function("fn0").unwrap(); From 4f833876e0911fac307371537209708df1da5d9c Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Mon, 25 Feb 2019 18:07:22 -0800 Subject: [PATCH 128/262] Start work on object loader using llvm's RuntimeDyld api. --- Cargo.lock | 30 ++++ lib/llvm-backend/Cargo.toml | 8 + lib/llvm-backend/build.rs | 213 +++++++++++++++++++++++++ lib/llvm-backend/cpp/object_loader.cpp | 96 +++++++++++ lib/llvm-backend/cpp/object_loader.hh | 40 +++++ lib/llvm-backend/src/backend.rs | 79 ++++++--- lib/llvm-backend/src/code.rs | 52 ++++-- lib/llvm-backend/src/intrinsics.rs | 6 +- lib/llvm-backend/src/lib.rs | 177 ++++++++++---------- 9 files changed, 579 insertions(+), 122 deletions(-) create mode 100644 lib/llvm-backend/build.rs create mode 100644 lib/llvm-backend/cpp/object_loader.cpp create mode 100644 lib/llvm-backend/cpp/object_loader.hh diff --git a/Cargo.lock b/Cargo.lock index ca2129890..9d743e96c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -262,6 +262,28 @@ dependencies = [ "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "dlopen" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "dlopen_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "dlopen_derive" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "either" version = "1.5.1" @@ -469,10 +491,16 @@ dependencies = [ name = "llvm-backend" version = "0.1.0" dependencies = [ + "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "dlopen 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "goblin 0.0.20 (registry+https://github.com/rust-lang/crates.io-index)", "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "inkwell 0.1.0 (git+https://github.com/TheDan64/inkwell?branch=llvm7-0)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-runtime-core 0.1.2", "wasmparser 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1362,6 +1390,8 @@ dependencies = [ "checksum cranelift-native 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "474bee81d620a473bf43411a3d6f10ffbf7965141dc5e5b76d8d2151dde3285d" "checksum cranelift-wasm 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49723365dab9a48b354bdc24cb6d9d5719bc1d3b858ffd2ea179d0d7d885804a" "checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c" +"checksum dlopen 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f8c301a18a3404a48d5d078e86b011ac834a6c4c742217e9aa8ceadd8a7e09e0" +"checksum dlopen_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6e16e4e343d6090ba47113c55bf6aa94e9b1eb5ab0c5abc9510d4c15074f30e9" "checksum either 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c67353c641dc847124ea1902d69bd753dee9bb3beff9aa3662ecf86c971d1fac" "checksum enum-methods 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7798e7da2d4cb0d6d6fc467e8d6b5bf247e9e989f786dde1732d79899c32bb10" "checksum env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "afb070faf94c85d17d50ca44f6ad076bce18ae92f0037d350947240a36e9d42e" diff --git a/lib/llvm-backend/Cargo.toml b/lib/llvm-backend/Cargo.toml index 8ffac375f..3ec83d77c 100644 --- a/lib/llvm-backend/Cargo.toml +++ b/lib/llvm-backend/Cargo.toml @@ -11,6 +11,14 @@ inkwell = { git = "https://github.com/TheDan64/inkwell", branch = "llvm7-0" } hashbrown = "0.1.8" smallvec = "0.6.8" goblin = "0.0.20" +dlopen = "0.1.6" +tempfile = "3.0.7" + +[build-dependencies] +cc = "1.0" +lazy_static = "1.2.0" +regex = "1.1.0" +semver = "0.9" [dev-dependencies] wabt = "0.7.4" diff --git a/lib/llvm-backend/build.rs b/lib/llvm-backend/build.rs new file mode 100644 index 000000000..0f4d1f195 --- /dev/null +++ b/lib/llvm-backend/build.rs @@ -0,0 +1,213 @@ +//! This file was mostly taken from the llvm-sys crate. +//! (https://bitbucket.org/tari/llvm-sys.rs/src/21ab524ec4df1450035df895209c3f8fbeb8775f/build.rs?at=default&fileviewer=file-view-default) + +use lazy_static::lazy_static; +use regex::Regex; +use semver::Version; +use std::env; +use std::ffi::OsStr; +use std::io::{self, ErrorKind}; +use std::path::PathBuf; +use std::process::Command; + +lazy_static! { + /// LLVM version used by this version of the crate. + static ref CRATE_VERSION: Version = { + let crate_version = Version::parse(env!("CARGO_PKG_VERSION")) + .expect("Crate version is somehow not valid semver"); + Version { + major: crate_version.major / 10, + minor: crate_version.major % 10, + .. crate_version + } + }; + + static ref LLVM_CONFIG_BINARY_NAMES: Vec = { + vec![ + "llvm-config".into(), + // format!("llvm-config-{}", CRATE_VERSION.major), + // format!("llvm-config-{}.{}", CRATE_VERSION.major, CRATE_VERSION.minor), + ] + }; + + /// Filesystem path to an llvm-config binary for the correct version. + static ref LLVM_CONFIG_PATH: PathBuf = { + // Try llvm-config via PATH first. + if let Some(name) = locate_system_llvm_config() { + return name.into(); + } else { + println!("Didn't find usable system-wide LLVM."); + } + + // Did the user give us a binary path to use? If yes, try + // to use that and fail if it doesn't work. + let binary_prefix_var = "LLVM_SYS_70_PREFIX"; + + let path = if let Some(path) = env::var_os(&binary_prefix_var) { + Some(path.to_str().unwrap().to_owned()) + } else if let Ok(mut file) = std::fs::File::open(".llvmenv") { + use std::io::Read; + let mut s = String::new(); + file.read_to_string(&mut s).unwrap(); + Some(s) + } else { + None + }; + + if let Some(path) = path { + for binary_name in LLVM_CONFIG_BINARY_NAMES.iter() { + let mut pb: PathBuf = path.clone().into(); + pb.push("bin"); + pb.push(binary_name); + + let ver = llvm_version(&pb) + .expect(&format!("Failed to execute {:?}", &pb)); + if is_compatible_llvm(&ver) { + return pb; + } else { + println!("LLVM binaries specified by {} are the wrong version. + (Found {}, need {}.)", binary_prefix_var, ver, *CRATE_VERSION); + } + } + } + + println!("No suitable version of LLVM was found system-wide or pointed + to by {}. + + Consider using `llvmenv` to compile an appropriate copy of LLVM, and + refer to the llvm-sys documentation for more information. + + llvm-sys: https://crates.io/crates/llvm-sys + llvmenv: https://crates.io/crates/llvmenv", binary_prefix_var); + panic!("Could not find a compatible version of LLVM"); + }; +} + +/// Try to find a system-wide version of llvm-config that is compatible with +/// this crate. +/// +/// Returns None on failure. +fn locate_system_llvm_config() -> Option<&'static str> { + for binary_name in LLVM_CONFIG_BINARY_NAMES.iter() { + match llvm_version(binary_name) { + Ok(ref version) if is_compatible_llvm(version) => { + // Compatible version found. Nice. + return Some(binary_name); + } + Ok(version) => { + // Version mismatch. Will try further searches, but warn that + // we're not using the system one. + println!( + "Found LLVM version {} on PATH, but need {}.", + version, *CRATE_VERSION + ); + } + Err(ref e) if e.kind() == ErrorKind::NotFound => { + // Looks like we failed to execute any llvm-config. Keep + // searching. + } + // Some other error, probably a weird failure. Give up. + Err(e) => panic!("Failed to search PATH for llvm-config: {}", e), + } + } + + None +} + +/// Check whether the given LLVM version is compatible with this version of +/// the crate. +fn is_compatible_llvm(llvm_version: &Version) -> bool { + let strict = env::var_os(format!( + "LLVM_SYS_{}_STRICT_VERSIONING", + env!("CARGO_PKG_VERSION_MAJOR") + )) + .is_some() + || cfg!(feature = "strict-versioning"); + if strict { + llvm_version.major == CRATE_VERSION.major && llvm_version.minor == CRATE_VERSION.minor + } else { + llvm_version.major >= CRATE_VERSION.major + || (llvm_version.major == CRATE_VERSION.major + && llvm_version.minor >= CRATE_VERSION.minor) + } +} + +/// Get the output from running `llvm-config` with the given argument. +/// +/// Lazily searches for or compiles LLVM as configured by the environment +/// variables. +fn llvm_config(arg: &str) -> String { + llvm_config_ex(&*LLVM_CONFIG_PATH, arg).expect("Surprising failure from llvm-config") +} + +/// Invoke the specified binary as llvm-config. +/// +/// Explicit version of the `llvm_config` function that bubbles errors +/// up. +fn llvm_config_ex>(binary: S, arg: &str) -> io::Result { + Command::new(binary) + .arg(arg) + .arg("--link-static") // Don't use dylib for >= 3.9 + .output() + .map(|output| { + String::from_utf8(output.stdout).expect("Output from llvm-config was not valid UTF-8") + }) +} + +/// Get the LLVM version using llvm-config. +fn llvm_version>(binary: S) -> io::Result { + let version_str = llvm_config_ex(binary.as_ref(), "--version")?; + + // LLVM isn't really semver and uses version suffixes to build + // version strings like '3.8.0svn', so limit what we try to parse + // to only the numeric bits. + let re = Regex::new(r"^(?P\d+)\.(?P\d+)(?:\.(?P\d+))??").unwrap(); + let c = re + .captures(&version_str) + .expect("Could not determine LLVM version from llvm-config."); + + // some systems don't have a patch number but Version wants it so we just append .0 if it isn't + // there + let s = match c.name("patch") { + None => format!("{}.0", &c[0]), + Some(_) => c[0].to_string(), + }; + Ok(Version::parse(&s).unwrap()) +} + +fn get_llvm_cxxflags() -> String { + let output = llvm_config("--cxxflags"); + + // llvm-config includes cflags from its own compilation with --cflags that + // may not be relevant to us. In particularly annoying cases, these might + // include flags that aren't understood by the default compiler we're + // using. Unless requested otherwise, clean CFLAGS of options that are + // known to be possibly-harmful. + let no_clean = env::var_os(format!( + "LLVM_SYS_{}_NO_CLEAN_CFLAGS", + env!("CARGO_PKG_VERSION_MAJOR") + )) + .is_some(); + if no_clean || cfg!(target_env = "msvc") { + // MSVC doesn't accept -W... options, so don't try to strip them and + // possibly strip something that should be retained. Also do nothing if + // the user requests it. + return output; + } + + output + .split(&[' ', '\n'][..]) + .filter(|word| !word.starts_with("-W")) + .collect::>() + .join(" ") +} + +fn main() { + std::env::set_var("CXXFLAGS", get_llvm_cxxflags()); + cc::Build::new() + .cpp(true) + .file("cpp/object_loader.cpp") + .compile("llvm-backend"); + + println!("cargo:rustc-link-lib=static=llvm-backend"); +} diff --git a/lib/llvm-backend/cpp/object_loader.cpp b/lib/llvm-backend/cpp/object_loader.cpp new file mode 100644 index 000000000..9ab36f4c3 --- /dev/null +++ b/lib/llvm-backend/cpp/object_loader.cpp @@ -0,0 +1,96 @@ +#include "object_loader.hh" +#include +#include + +class MemoryManager : llvm::RuntimeDyld::MemoryManager { +public: + MemoryManager() {} + + virtual ~MemoryManager() {} + + virtual uint8_t* allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID, llvm::StringRef SectionName) override { + return nullptr; + } + + virtual uint8_t* allocateDataSection(uintptr_t Size, unsigned Alignment, unsigned SectionID, llvm::StringRef SectionName, bool isReadOnly) override { + return nullptr; + } + + virtual void reserveAllocationSpace( + uintptr_t code_size, + uint32_t code_align, + uintptr_t read_data_size, + uint32_t read_data_align, + uintptr_t read_write_data_size, + uint32_t read_write_data_align + ) override { + + } + + /* Turn on the `reserveAllocationSpace` callback. */ + virtual bool needsToReserveAllocationSpace() override { + return true; + } + + virtual void registerEHFrames(uint8_t* Addr, uint64_t LoadAddr, size_t Size) override { + + } + + virtual void deregisterEHFrames() override { + + } + + virtual bool finalizeMemory(std::string *ErrMsg = nullptr) override { + + + return false; + } + + virtual void notifyObjectLoaded(llvm::RuntimeDyld &RTDyld, const llvm::object::ObjectFile &Obj) override { + + } +private: + struct Section { + uint8_t* base; + size_t num_pages; + size_t num_commited_bytes; + }; + + uint8_t *image_base; + size_t num_allocated_pages; + + Section code_section, read_section, readwrite_section; + + +}; + +class SymbolLookup : llvm::JITSymbolResolver { +public: + virtual llvm::Expected lookup(const LookupSet& symbols) override { + LookupResult result; + + for (auto symbol : symbols) { + result.emplace(symbol, symbol_lookup(symbol)); + } + + return result; + } + + virtual llvm::Expected lookupFlags(const LookupSet& symbols) override { + LookupFlagsResult result; + + for (auto symbol : symbols) { + result.emplace(symbol, symbol_lookup(symbol).getFlags()); + } + + return result; + } + +private: + llvm::JITEvaluatedSymbol symbol_lookup(llvm::StringRef name) { + std::cout << "symbol name: " << (std::string)name << std::endl; + uint64_t addr = 0; + + return llvm::JITEvaluatedSymbol(addr, llvm::JITSymbolFlags::None); + } +}; \ No newline at end of file diff --git a/lib/llvm-backend/cpp/object_loader.hh b/lib/llvm-backend/cpp/object_loader.hh new file mode 100644 index 000000000..50b618b38 --- /dev/null +++ b/lib/llvm-backend/cpp/object_loader.hh @@ -0,0 +1,40 @@ +#include +#include + +typedef enum { + PROTECT_NONE, + PROTECT_READ, + PROTECT_READ_WRITE, + PROTECT_READ_EXECUTE, +} mem_protect_t; + +typedef enum { + RESULT_OK, + RESULT_ALLOCATE_FAILURE, + RESULT_PROTECT_FAILURE, + RESULT_DEALLOC_FAILURE, + RESULT_OBJECT_LOAD_FAILURE, +} result_t; + +typedef result_t (*alloc_memory_t)(size_t size, mem_protect_t protect, uint8_t** ptr_out, size_t* size_out); +typedef result_t (*protect_memory_t)(uint8_t* ptr, size_t size, mem_protect_t protect); +typedef result_t (*dealloc_memory_t)(uint8_t* ptr, size_t size); +typedef uintptr_t (*lookup_vm_symbol_t)(char* name_ptr, size_t name_size); + +typedef struct { + /* Memory management. */ + alloc_memory_t alloc_memory; + protect_memory_t protect_memory; + dealloc_memory_t dealloc_memory; + + lookup_vm_symbol_t lookup_vm_symbol; +} callbacks_t; + +extern "C" { + result_t object_load(uint8_t* mem_ptr, size_t mem_size, callbacks_t* callbacks) { + return RESULT_OK; + } + + void test_cpp() { + } +} \ No newline at end of file diff --git a/lib/llvm-backend/src/backend.rs b/lib/llvm-backend/src/backend.rs index 9821eabf6..2b4bb7023 100644 --- a/lib/llvm-backend/src/backend.rs +++ b/lib/llvm-backend/src/backend.rs @@ -1,45 +1,76 @@ +use crate::intrinsics::Intrinsics; +use dlopen::symbor::Library; use inkwell::{ module::Module, - execution_engine::{ExecutionEngine, JitFunction}, + targets::{CodeModel, FileType, InitializationConfig, RelocMode, Target, TargetMachine}, + OptimizationLevel, }; -use crate::intrinsics::Intrinsics; -use std::ptr::NonNull; +use std::{io::Write, ptr::NonNull}; +use tempfile::NamedTempFile; use wasmer_runtime_core::{ - module::ModuleInner, - types::LocalFuncIndex, - structures::TypedIndex, - backend::{FuncResolver, vm}, + backend::FuncResolver, module::ModuleInner, structures::TypedIndex, types::LocalFuncIndex, vm, }; pub struct LLVMBackend { - exec_engine: ExecutionEngine, + tempfile: NamedTempFile, + library: Library, } impl LLVMBackend { pub fn new(module: Module, intrinsics: Intrinsics) -> Self { - let exec_engine = module.create_jit_execution_engine(OptimizationLevel::Default).unwrap(); + Target::initialize_x86(&InitializationConfig { + asm_parser: true, + asm_printer: true, + base: true, + disassembler: true, + info: true, + machine_code: true, + }); + let triple = TargetMachine::get_default_triple().to_string(); + let target = Target::from_triple(&triple).unwrap(); + let target_machine = target + .create_target_machine( + &triple, + &TargetMachine::get_host_cpu_name().to_string(), + &TargetMachine::get_host_cpu_features().to_string(), + OptimizationLevel::Default, + RelocMode::PIC, + CodeModel::Default, + ) + .unwrap(); - exec_engine.add_global_mapping(&intrinsics.memory_grow_dynamic_local, vmcalls::local_dynamic_memory_grow as usize); - exec_engine.add_global_mapping(&intrinsics.memory_grow_static_local, vmcalls::local_static_memory_grow as usize); - exec_engine.add_global_mapping(&intrinsics.memory_grow_dynamic_import, vmcalls::imported_dynamic_memory_grow as usize); - exec_engine.add_global_mapping(&intrinsics.memory_grow_static_import, vmcalls::imported_static_memory_grow as usize); - exec_engine.add_global_mapping(&intrinsics.memory_size_dynamic_local, vmcalls::local_dynamic_memory_size as usize); - exec_engine.add_global_mapping(&intrinsics.memory_size_static_local, vmcalls::local_static_memory_size as usize); - exec_engine.add_global_mapping(&intrinsics.memory_size_dynamic_import, vmcalls::imported_dynamic_memory_size as usize); - exec_engine.add_global_mapping(&intrinsics.memory_size_static_import, vmcalls::imported_static_memory_size as usize); + let memory_buffer = target_machine + .write_to_memory_buffer(&module, FileType::Object) + .unwrap(); - Self { exec_engine } + let mut tempfile = NamedTempFile::new().unwrap(); + tempfile.write_all(memory_buffer.as_slice()).unwrap(); + tempfile.flush().unwrap(); + + let library = Library::open(tempfile.path()).unwrap(); + + Self { tempfile, library } } } impl FuncResolver for LLVMBackend { - fn get(&self, module: &ModuleInner, local_func_index: LocalFuncIndex) -> Option> { + fn get( + &self, + module: &ModuleInner, + local_func_index: LocalFuncIndex, + ) -> Option> { let index = module.info.imported_functions.len() + local_func_index.index(); - let name = format!("fn{}", index); - + let name = if cfg!(macos) { + format!("_fn{}", index) + } else { + format!("fn{}", index) + }; + unsafe { - let func: JitFunction = self.exec_engine.get_function(&name).ok()?; - + self.library + .symbol::>(&name) + .ok() + .map(|symbol| *symbol) } } -} \ No newline at end of file +} diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index d72659fd9..e0f4d984f 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -481,6 +481,7 @@ fn parse_function( // Emit an unreachable instruction. // If llvm cannot prove that this is never touched, // it will emit a `ud2` instruction on x86_64 arches. + ctx.build_trap(); builder.build_unreachable(); state.reachable = false; } @@ -623,7 +624,8 @@ fn parse_function( } } Operator::CallIndirect { index, table_index } => { - let expected_dynamic_sigindex = ctx.dynamic_sigindex(SigIndex::new(index as usize)); + let sig_index = SigIndex::new(index as usize); + let expected_dynamic_sigindex = ctx.dynamic_sigindex(sig_index); let (table_base, table_bound) = ctx.table(TableIndex::new(table_index as usize)); let func_index = state.pop1()?.into_int_value(); @@ -651,12 +653,10 @@ fn parse_function( "func_ptr", ) .into_pointer_value(), - builder - .build_load( - builder.build_struct_gep(anyfunc_struct_ptr, 1, "ctx_ptr_ptr"), - "ctx_ptr", - ) - .into_pointer_value(), + builder.build_load( + builder.build_struct_gep(anyfunc_struct_ptr, 1, "ctx_ptr_ptr"), + "ctx_ptr", + ), builder .build_load( builder.build_struct_gep(anyfunc_struct_ptr, 2, "sigindex_ptr"), @@ -685,21 +685,49 @@ fn parse_function( ) .try_as_basic_value() .left() - .unwrap(); + .unwrap() + .into_int_value(); let continue_block = context.append_basic_block(&function, "continue_block"); let sigindices_notequal_block = context.append_basic_block(&function, "sigindices_notequal_block"); + builder.build_conditional_branch( + sigindices_equal, + &continue_block, + &sigindices_notequal_block, + ); builder.position_at_end(&sigindices_notequal_block); + ctx.build_trap(); builder.build_unreachable(); builder.position_at_end(&continue_block); - println!("func ptr: {:#?}", func_ptr); - println!("ctx ptr: {:#?}", ctx_ptr); - println!("found dynamic sigindex: {:#?}", found_dynamic_sigindex); + let wasmer_fn_sig = &info.signatures[sig_index]; + let fn_ty = signatures[sig_index]; - unimplemented!("{}, {}", index, table_index); + let pushed_args = state.popn_save(wasmer_fn_sig.params().len())?; + + let args: Vec<_> = std::iter::once(ctx_ptr) + .chain(pushed_args.into_iter()) + .collect(); + println!("args: {:?}", args); + + let typed_func_ptr = builder.build_pointer_cast( + func_ptr, + fn_ty.ptr_type(AddressSpace::Generic), + "typed_func_ptr", + ); + + let call_site = builder.build_call(typed_func_ptr, &args, "indirect_call"); + + match wasmer_fn_sig.returns() { + [] => {} + [_] => { + let value = call_site.try_as_basic_value().left().unwrap(); + state.push1(value); + } + returns @ _ => unimplemented!("multi-value returns"), + } } /*************************** diff --git a/lib/llvm-backend/src/intrinsics.rs b/lib/llvm-backend/src/intrinsics.rs index ccc0081bf..f2ec8fd05 100644 --- a/lib/llvm-backend/src/intrinsics.rs +++ b/lib/llvm-backend/src/intrinsics.rs @@ -64,6 +64,7 @@ pub struct Intrinsics { pub copysign_f64: FunctionValue, pub expect_i1: FunctionValue, + pub trap: FunctionValue, pub void_ty: VoidType, pub i1_ty: IntType, @@ -255,6 +256,7 @@ impl Intrinsics { copysign_f64: module.add_function("llvm.copysign.f64", ret_f64_take_f64_f64, None), expect_i1: module.add_function("llvm.expect.i1", ret_i1_take_i1_i1, None), + trap: module.add_function("llvm.trap", void_ty.fn_type(&[], false), None), void_ty, i1_ty, @@ -695,7 +697,9 @@ impl<'a> CtxType<'a> { (imported_func_cache.func_ptr, imported_func_cache.ctx_ptr) } - // pub fn table(&mut self, table_index: TableIndex, elem_index: IntValue) -> + pub fn build_trap(&self) { + self.builder.build_call(self.intrinsics.trap, &[], "trap"); + } } // pub struct Ctx { diff --git a/lib/llvm-backend/src/lib.rs b/lib/llvm-backend/src/lib.rs index e70af96c0..e06b081af 100644 --- a/lib/llvm-backend/src/lib.rs +++ b/lib/llvm-backend/src/lib.rs @@ -10,11 +10,11 @@ use wasmer_runtime_core::{ module::ModuleInner, }; +mod backend; mod code; mod intrinsics; mod read_info; mod state; -// mod backend; pub struct LLVMCompiler { _private: (), @@ -28,13 +28,61 @@ impl LLVMCompiler { impl Compiler for LLVMCompiler { fn compile(&self, wasm: &[u8], _: Token) -> Result { - let (_info, _code_reader) = read_info::read_module(wasm).unwrap(); + let (info, code_reader) = read_info::read_module(wasm).unwrap(); + let (module, intrinsics) = code::parse_function_bodies(&info, code_reader).unwrap(); - unimplemented!() + let backend = backend::LLVMBackend::new(module, intrinsics); + + // Create placeholder values here. + let (protected_caller, cache_gen) = { + use wasmer_runtime_core::backend::{ + sys::Memory, CacheGen, ProtectedCaller, UserTrapper, + }; + use wasmer_runtime_core::cache::Error as CacheError; + use wasmer_runtime_core::error::RuntimeResult; + use wasmer_runtime_core::module::ModuleInfo; + use wasmer_runtime_core::types::{FuncIndex, Value}; + use wasmer_runtime_core::vm; + struct Placeholder; + impl ProtectedCaller for Placeholder { + fn call( + &self, + _module: &ModuleInner, + _func_index: FuncIndex, + _params: &[Value], + _import_backing: &vm::ImportBacking, + _vmctx: *mut vm::Ctx, + _: Token, + ) -> RuntimeResult> { + Ok(vec![]) + } + fn get_early_trapper(&self) -> Box { + unimplemented!() + } + } + impl CacheGen for Placeholder { + fn generate_cache( + &self, + module: &ModuleInner, + ) -> Result<(Box, Box<[u8]>, Memory), CacheError> { + unimplemented!() + } + } + + (Box::new(Placeholder), Box::new(Placeholder)) + }; + + Ok(ModuleInner { + func_resolver: Box::new(backend), + protected_caller, + cache_gen, + + info, + }) } unsafe fn from_cache(&self, _artifact: Artifact, _: Token) -> Result { - unimplemented!() + unimplemented!("the llvm backend doesn't support caching yet") } } @@ -55,14 +103,9 @@ fn test_read_module() { get_local 0 i32.const 0 call_indirect (type $t0) - memory.grow ) (func $foobar (type $t0) get_local 0 - ) - (func $bar (type $t0) (param i32) (result i32) - get_local 0 - call $foo )) "#; let wasm = wat2wasm(wat).unwrap(); @@ -71,86 +114,50 @@ fn test_read_module() { let (module, intrinsics) = code::parse_function_bodies(&info, code_reader).unwrap(); - { - Target::initialize_x86(&InitializationConfig { - asm_parser: true, - asm_printer: true, - base: true, - disassembler: true, - info: true, - machine_code: true, - }); - let triple = TargetMachine::get_default_triple().to_string(); - let target = Target::from_triple(&triple).unwrap(); - let target_machine = target - .create_target_machine( - &triple, - &TargetMachine::get_host_cpu_name().to_string(), - &TargetMachine::get_host_cpu_features().to_string(), - OptimizationLevel::Default, - RelocMode::PIC, - CodeModel::Default, - ) - .unwrap(); + // let backend = backend::LLVMBackend::new(module, intrinsics); - let memory_buffer = target_machine - .write_to_memory_buffer(&module, FileType::Object) - .unwrap(); - // std::fs::write("memory_buffer", memory_buffer.as_slice()).unwrap(); - let mem_buf_slice = memory_buffer.as_slice(); - - let macho = goblin::mach::MachO::parse(mem_buf_slice, 0).unwrap(); - let symbols = macho.symbols.as_ref().unwrap(); - let relocations = macho.relocations().unwrap(); - for (_, reloc_iter, section) in relocations.into_iter() { - println!("section: {:#?}", section); - for reloc_info in reloc_iter { - let reloc_info = reloc_info.unwrap(); - println!("\treloc_info: {:#?}", reloc_info); - println!( - "\tsymbol: {:#?}", - symbols.get(reloc_info.r_symbolnum()).unwrap() - ); - } - } + extern "C" { + fn test_cpp(); } - let exec_engine = module - .create_jit_execution_engine(OptimizationLevel::Default) - .unwrap(); + unsafe { test_cpp() }; - exec_engine.add_global_mapping( - &intrinsics.memory_grow_dynamic_local, - vmcalls::local_dynamic_memory_grow as usize, - ); - exec_engine.add_global_mapping( - &intrinsics.memory_grow_static_local, - vmcalls::local_static_memory_grow as usize, - ); - exec_engine.add_global_mapping( - &intrinsics.memory_grow_dynamic_import, - vmcalls::imported_dynamic_memory_grow as usize, - ); - exec_engine.add_global_mapping( - &intrinsics.memory_grow_static_import, - vmcalls::imported_static_memory_grow as usize, - ); - exec_engine.add_global_mapping( - &intrinsics.memory_size_dynamic_local, - vmcalls::local_dynamic_memory_size as usize, - ); - exec_engine.add_global_mapping( - &intrinsics.memory_size_static_local, - vmcalls::local_static_memory_size as usize, - ); - exec_engine.add_global_mapping( - &intrinsics.memory_size_dynamic_import, - vmcalls::imported_dynamic_memory_size as usize, - ); - exec_engine.add_global_mapping( - &intrinsics.memory_size_static_import, - vmcalls::imported_static_memory_size as usize, - ); + // let exec_engine = module + // .create_jit_execution_engine(OptimizationLevel::Default) + // .unwrap(); + + // exec_engine.add_global_mapping( + // &intrinsics.memory_grow_dynamic_local, + // vmcalls::local_dynamic_memory_grow as usize, + // ); + // exec_engine.add_global_mapping( + // &intrinsics.memory_grow_static_local, + // vmcalls::local_static_memory_grow as usize, + // ); + // exec_engine.add_global_mapping( + // &intrinsics.memory_grow_dynamic_import, + // vmcalls::imported_dynamic_memory_grow as usize, + // ); + // exec_engine.add_global_mapping( + // &intrinsics.memory_grow_static_import, + // vmcalls::imported_static_memory_grow as usize, + // ); + // exec_engine.add_global_mapping( + // &intrinsics.memory_size_dynamic_local, + // vmcalls::local_dynamic_memory_size as usize, + // ); + // exec_engine.add_global_mapping( + // &intrinsics.memory_size_static_local, + // vmcalls::local_static_memory_size as usize, + // ); + // exec_engine.add_global_mapping( + // &intrinsics.memory_size_dynamic_import, + // vmcalls::imported_dynamic_memory_size as usize, + // ); + // exec_engine.add_global_mapping( + // &intrinsics.memory_size_static_import, + // vmcalls::imported_static_memory_size as usize, + // ); // unsafe { // let func: JitFunction i32> = exec_engine.get_function("fn0").unwrap(); From e6d0f91832662dada7a36cbf06e112843a5167a1 Mon Sep 17 00:00:00 2001 From: Syrus Date: Tue, 26 Feb 2019 01:12:34 -0800 Subject: [PATCH 129/262] Use blake2b SIMD version for increased performance --- lib/runtime-core/src/cache.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/runtime-core/src/cache.rs b/lib/runtime-core/src/cache.rs index ec2b0b01f..339b78fcc 100644 --- a/lib/runtime-core/src/cache.rs +++ b/lib/runtime-core/src/cache.rs @@ -2,7 +2,7 @@ use crate::{ module::{Module, ModuleInfo}, sys::Memory, }; -use blake2b_simd::blake2b; +use blake2b_simd::blake2bp; use std::{fmt, io, mem, slice}; #[derive(Debug)] @@ -45,7 +45,10 @@ impl WasmHash { let mut first_part = [0u8; 32]; let mut second_part = [0u8; 32]; - let mut hasher = blake2b(wasm); + let mut state = blake2bp::State::new(); + state.update(wasm); + + let mut hasher = state.finalize(); let generic_array = hasher.as_bytes(); first_part.copy_from_slice(&generic_array[0..32]); From 204d7a8d17a45ac22c4e19eb8ca4eff0cfa84532 Mon Sep 17 00:00:00 2001 From: Mark Roberts Date: Tue, 26 Feb 2019 20:17:48 +0800 Subject: [PATCH 130/262] Add nginx LICENSE --- examples/nginx/LICENSE | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 examples/nginx/LICENSE diff --git a/examples/nginx/LICENSE b/examples/nginx/LICENSE new file mode 100644 index 000000000..c63e0ba4e --- /dev/null +++ b/examples/nginx/LICENSE @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2002-2019 Igor Sysoev + * Copyright (C) 2011-2019 Nginx, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ From d5aed446711bb6436f8a1c47d02527a2af0e6d15 Mon Sep 17 00:00:00 2001 From: Ryan Jacobs Date: Tue, 26 Feb 2019 13:16:06 -0800 Subject: [PATCH 131/262] bugfix: Replace echo with printf so "\n" renders. notes: I could have used the -e flag in echo, however other lines nearby use printf so I figured it would be smart to stay consistent. Also, I see the usage of `command printf`. Not 100% if this is necessary. I don't see why printf would be redefined in the shell. If we're doing this, then we might as well prefix every call to a builtin or binary with `command` _just to be safe_. --- install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install.sh b/install.sh index 04b5f364a..0b7da4ca2 100755 --- a/install.sh +++ b/install.sh @@ -133,7 +133,7 @@ wasmer_link() { SOURCE_STR="# Wasmer config\nexport WASMER_DIR=\"\$HOME/.wasmer\"\nexport WASMER_CACHE_DIR=\"\$WASMER_DIR/cache\"\nexport PATH=\"\$HOME/.wasmer/bin:\$PATH\"\n" # We create the wasmer.sh file - echo "$SOURCE_STR" > "$HOME/.wasmer/wasmer.sh" + printf "$SOURCE_STR" > "$HOME/.wasmer/wasmer.sh" if [ -z "${WASMER_PROFILE-}" ] ; then printf "${red}Profile not found. Tried:\n* ${WASMER_PROFILE} (as defined in \$PROFILE)\n* ~/.bashrc\n* ~/.bash_profile\n* ~/.zshrc\n* ~/.profile.\n" From f7197bf456299ffb70f3d755d59f513091b9a2da Mon Sep 17 00:00:00 2001 From: Syrus Date: Tue, 26 Feb 2019 15:39:54 -0800 Subject: [PATCH 132/262] Added debug build --- Cargo.toml | 2 +- Makefile | 5 ++++- lib/runtime/README.md | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 15b09e542..21bbfa60c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,6 +36,6 @@ glob = "0.2.11" [features] default = ["fast-tests"] -debug = [] +debug = ["wasmer-clif-backend/debug", "wasmer-runtime-core/debug"] # This feature will allow cargo test to run much faster fast-tests = [] diff --git a/Makefile b/Makefile index 2506f196c..74e3428fc 100644 --- a/Makefile +++ b/Makefile @@ -19,7 +19,7 @@ capi: # rm -rf artifacts build: - cargo build + cargo build --features debug install: cargo install --path . @@ -47,6 +47,9 @@ release: # brew install mingw-w64 cargo build --release +debug-release: + cargo build --release --features debug + debug-release: cargo build --release --features "debug" diff --git a/lib/runtime/README.md b/lib/runtime/README.md index bd9bb0f0c..5e5542c8d 100644 --- a/lib/runtime/README.md +++ b/lib/runtime/README.md @@ -51,7 +51,7 @@ fn main() -> error::Result<()> { // We're not importing anything, so make an empty import object. let import_object = imports! {}; - let mut instance = instantiate(WASM, import_object)?; + let mut instance = instantiate(WASM, &import_object)?; let values = instance .func("add_one")? From 2a7a8c0069917d1ce5a8738f8ff99f989418167a Mon Sep 17 00:00:00 2001 From: Mackenzie Clark Date: Wed, 27 Feb 2019 10:41:22 -0800 Subject: [PATCH 133/262] newline in test-module-imports.c --- lib/runtime-c-api/tests/test-module-imports.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/runtime-c-api/tests/test-module-imports.c b/lib/runtime-c-api/tests/test-module-imports.c index 47757c58c..b63d308f2 100644 --- a/lib/runtime-c-api/tests/test-module-imports.c +++ b/lib/runtime-c-api/tests/test-module-imports.c @@ -53,4 +53,4 @@ int main() printf("Destroy imports\n"); wasmer_import_descriptors_destroy(imports); return 0; -} \ No newline at end of file +} From ff5e1320daf3b52902f2fb2f69f4d800f495d8f3 Mon Sep 17 00:00:00 2001 From: Mackenzie Clark Date: Wed, 27 Feb 2019 13:54:28 -0800 Subject: [PATCH 134/262] Fix casting errors cause io issues (#222) --- lib/emscripten/src/syscalls/mod.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/emscripten/src/syscalls/mod.rs b/lib/emscripten/src/syscalls/mod.rs index 2143599f7..7c5ee578b 100644 --- a/lib/emscripten/src/syscalls/mod.rs +++ b/lib/emscripten/src/syscalls/mod.rs @@ -71,10 +71,10 @@ pub fn ___syscall3(ctx: &mut Ctx, which: i32, mut varargs: VarArgs) -> i32 { debug!("emscripten::___syscall3 (read) {}", which); let fd: i32 = varargs.get(ctx); let buf: u32 = varargs.get(ctx); - let count = varargs.get(ctx); + let count: i32 = varargs.get(ctx); debug!("=> fd: {}, buf_offset: {}, count: {}", fd, buf, count); let buf_addr = emscripten_memory_pointer!(ctx.memory(0), buf) as *mut c_void; - let ret = unsafe { read(fd, buf_addr, count) }; + let ret = unsafe { read(fd, buf_addr, count as _) }; debug!("=> ret: {}", ret); ret as _ } @@ -84,10 +84,10 @@ pub fn ___syscall4(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall4 (write) {}", which); let fd: i32 = varargs.get(ctx); let buf: u32 = varargs.get(ctx); - let count = varargs.get(ctx); + let count: i32 = varargs.get(ctx); debug!("=> fd: {}, buf: {}, count: {}", fd, buf, count); let buf_addr = emscripten_memory_pointer!(ctx.memory(0), buf) as *const c_void; - unsafe { write(fd, buf_addr, count) as i32 } + unsafe { write(fd, buf_addr, count as _) as i32 } } /// close @@ -241,10 +241,10 @@ pub fn ___syscall140(ctx: &mut Ctx, which: i32, mut varargs: VarArgs) -> i32 { // -> c_int debug!("emscripten::___syscall140 (lseek) {}", which); let fd: i32 = varargs.get(ctx); - let offset = varargs.get(ctx); + let offset: i32 = varargs.get(ctx); let whence: i32 = varargs.get(ctx); debug!("=> fd: {}, offset: {}, whence = {}", fd, offset, whence); - unsafe { lseek(fd, offset, whence) as _ } + unsafe { lseek(fd, offset as _, whence) as _ } } /// readv From 95062d524ac56ce3229c2dc28248489c12954a63 Mon Sep 17 00:00:00 2001 From: Mackenzie Clark Date: Wed, 27 Feb 2019 14:20:53 -0800 Subject: [PATCH 135/262] commit virtual memory before copying (#212) --- lib/runtime-core/src/sys/windows/memory.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/lib/runtime-core/src/sys/windows/memory.rs b/lib/runtime-core/src/sys/windows/memory.rs index d47388170..3ca86bec9 100644 --- a/lib/runtime-core/src/sys/windows/memory.rs +++ b/lib/runtime-core/src/sys/windows/memory.rs @@ -33,7 +33,7 @@ impl Memory { let protect = protection.to_protect_const(); - let ptr = unsafe { VirtualAlloc(ptr::null_mut(), size, MEM_RESERVE, protect) }; + let ptr = unsafe { VirtualAlloc(ptr::null_mut(), size, MEM_RESERVE | MEM_COMMIT, protect) }; if ptr.is_null() { Err("unable to allocate memory".to_string()) @@ -57,7 +57,14 @@ impl Memory { let size = round_up_to_page_size(size, page_size::get()); - let ptr = unsafe { VirtualAlloc(ptr::null_mut(), size, MEM_RESERVE, PAGE_NOACCESS) }; + let ptr = unsafe { + VirtualAlloc( + ptr::null_mut(), + size, + MEM_RESERVE | MEM_COMMIT, + PAGE_NOACCESS, + ) + }; if ptr.is_null() { Err(MemoryCreationError::VirtualMemoryAllocationFailed( From 60f8f15db37b004e005a368c23b343f0095aac97 Mon Sep 17 00:00:00 2001 From: Syrus Date: Wed, 27 Feb 2019 17:20:49 -0800 Subject: [PATCH 136/262] Updated version to 0.2.1 --- Cargo.lock | 30 +++++++++++++++--------------- Cargo.toml | 2 +- lib/emscripten/Cargo.toml | 4 ++-- lib/runtime-c-api/Cargo.toml | 6 +++--- lib/runtime-core/Cargo.toml | 2 +- lib/runtime/Cargo.toml | 4 ++-- 6 files changed, 24 insertions(+), 24 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b2222ed55..6940f529c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1205,15 +1205,15 @@ dependencies = [ [[package]] name = "wasmer" -version = "0.2.0" +version = "0.2.1" dependencies = [ "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "structopt 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-clif-backend 0.2.0", - "wasmer-emscripten 0.2.0", - "wasmer-runtime 0.2.0", - "wasmer-runtime-core 0.2.0", + "wasmer-emscripten 0.2.1", + "wasmer-runtime 0.2.1", + "wasmer-runtime-core 0.2.1", ] [[package]] @@ -1234,7 +1234,7 @@ dependencies = [ "serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", "target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "wasmer-runtime-core 0.2.0", + "wasmer-runtime-core 0.2.1", "wasmer-win-exception-handler 0.2.0", "wasmparser 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1242,7 +1242,7 @@ dependencies = [ [[package]] name = "wasmer-emscripten" -version = "0.2.0" +version = "0.2.1" dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1252,34 +1252,34 @@ dependencies = [ "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-clif-backend 0.2.0", - "wasmer-runtime-core 0.2.0", + "wasmer-runtime-core 0.2.1", ] [[package]] name = "wasmer-runtime" -version = "0.2.0" +version = "0.2.1" dependencies = [ "criterion 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-clif-backend 0.2.0", - "wasmer-runtime-core 0.2.0", + "wasmer-runtime-core 0.2.1", ] [[package]] name = "wasmer-runtime-c-api" -version = "0.2.0" +version = "0.2.1" dependencies = [ "cbindgen 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", - "wasmer-runtime 0.2.0", - "wasmer-runtime-core 0.2.0", + "wasmer-runtime 0.2.1", + "wasmer-runtime-core 0.2.1", ] [[package]] name = "wasmer-runtime-core" -version = "0.2.0" +version = "0.2.1" dependencies = [ "blake2b_simd 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1307,7 +1307,7 @@ version = "0.2.0" dependencies = [ "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-clif-backend 0.2.0", - "wasmer-runtime-core 0.2.0", + "wasmer-runtime-core 0.2.1", ] [[package]] @@ -1318,7 +1318,7 @@ dependencies = [ "cmake 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "wasmer-runtime-core 0.2.0", + "wasmer-runtime-core 0.2.1", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/Cargo.toml b/Cargo.toml index 21bbfa60c..85dddd1ee 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer" -version = "0.2.0" +version = "0.2.1" authors = ["The Wasmer Engineering Team "] edition = "2018" repository = "https://github.com/wasmerio/wasmer" diff --git a/lib/emscripten/Cargo.toml b/lib/emscripten/Cargo.toml index 1300eb124..62fb40c5a 100644 --- a/lib/emscripten/Cargo.toml +++ b/lib/emscripten/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-emscripten" -version = "0.2.0" +version = "0.2.1" description = "Wasmer runtime emscripten implementation library" license = "MIT" authors = ["The Wasmer Engineering Team "] @@ -9,7 +9,7 @@ edition = "2018" build = "build/mod.rs" [dependencies] -wasmer-runtime-core = { path = "../runtime-core", version = "0.2.0" } +wasmer-runtime-core = { path = "../runtime-core", version = "0.2.1" } lazy_static = "1.2.0" libc = "0.2.49" byteorder = "1" diff --git a/lib/runtime-c-api/Cargo.toml b/lib/runtime-c-api/Cargo.toml index d2b327c22..3a88431f7 100644 --- a/lib/runtime-c-api/Cargo.toml +++ b/lib/runtime-c-api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-runtime-c-api" -version = "0.2.0" +version = "0.2.1" description = "Wasmer c-api library" license = "MIT" authors = ["The Wasmer Engineering Team "] @@ -9,8 +9,8 @@ edition = "2018" readme = "README.md" [dependencies] -wasmer-runtime = { path = "../runtime", version = "0.2.0" } -wasmer-runtime-core = { path = "../runtime-core", version = "0.2.0" } +wasmer-runtime = { path = "../runtime", version = "0.2.1" } +wasmer-runtime-core = { path = "../runtime-core", version = "0.2.1" } libc = "0.2" [lib] diff --git a/lib/runtime-core/Cargo.toml b/lib/runtime-core/Cargo.toml index 00ac57189..c6ac22f40 100644 --- a/lib/runtime-core/Cargo.toml +++ b/lib/runtime-core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-runtime-core" -version = "0.2.0" +version = "0.2.1" description = "Wasmer runtime core library" license = "MIT" authors = ["The Wasmer Engineering Team "] diff --git a/lib/runtime/Cargo.toml b/lib/runtime/Cargo.toml index f7aa32cb5..3ad8cbadc 100644 --- a/lib/runtime/Cargo.toml +++ b/lib/runtime/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-runtime" -version = "0.2.0" +version = "0.2.1" description = "Wasmer runtime library" license = "MIT" authors = ["The Wasmer Engineering Team "] @@ -14,7 +14,7 @@ memmap = "0.7.0" [dependencies.wasmer-runtime-core] path = "../runtime-core" -version = "0.2.0" +version = "0.2.1" [dependencies.wasmer-clif-backend] path = "../clif-backend" From 5d777693816b92c92ba24ab6f297eb267ccc521e Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Wed, 27 Feb 2019 17:21:20 -0800 Subject: [PATCH 137/262] Hopefully finish the memory manager implementation for llvm RuntimeDyLd --- Cargo.lock | 50 ++++----- lib/llvm-backend/build.rs | 1 + lib/llvm-backend/cpp/object_loader.cpp | 122 ++++++++++++++++++---- lib/llvm-backend/src/code.rs | 2 +- lib/llvm-backend/src/platform/mod.rs | 8 ++ lib/llvm-backend/src/platform/unix/mod.rs | 40 +++++++ 6 files changed, 176 insertions(+), 47 deletions(-) create mode 100644 lib/llvm-backend/src/platform/mod.rs create mode 100644 lib/llvm-backend/src/platform/unix/mod.rs diff --git a/Cargo.lock b/Cargo.lock index 9d743e96c..566a1514b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -63,7 +63,7 @@ dependencies = [ "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", @@ -136,7 +136,7 @@ name = "cexpr" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "nom 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "nom 4.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -269,7 +269,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dlopen_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -431,7 +431,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "inkwell" version = "0.1.0" -source = "git+https://github.com/TheDan64/inkwell?branch=llvm7-0#e66f8941061a45299ef73533c747c32bcd5d696a" +source = "git+https://github.com/TheDan64/inkwell?branch=llvm7-0#b8699b0ee594e4162ce850fbedb37892e9cdb7e4" dependencies = [ "either 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "enum-methods 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -443,7 +443,7 @@ dependencies = [ [[package]] name = "inkwell_internal_macros" version = "0.1.0" -source = "git+https://github.com/TheDan64/inkwell?branch=llvm7-0#e66f8941061a45299ef73533c747c32bcd5d696a" +source = "git+https://github.com/TheDan64/inkwell?branch=llvm7-0#b8699b0ee594e4162ce850fbedb37892e9cdb7e4" dependencies = [ "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", @@ -465,13 +465,13 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" version = "0.2.49" -source = "git+https://github.com/rust-lang/libc#68701e7e673da580de8ba6197c544316bd38e84a" +source = "git+https://github.com/rust-lang/libc#b905aef34008c962ef8a4410216eae65bbb7f68f" [[package]] name = "libc" @@ -496,7 +496,7 @@ dependencies = [ "goblin 0.0.20 (registry+https://github.com/rust-lang/crates.io-index)", "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "inkwell 0.1.0 (git+https://github.com/TheDan64/inkwell?branch=llvm7-0)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -512,7 +512,7 @@ version = "70.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -575,7 +575,7 @@ dependencies = [ [[package]] name = "nom" -version = "4.2.0" +version = "4.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -691,7 +691,7 @@ dependencies = [ "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "rand_os 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -759,11 +759,11 @@ dependencies = [ [[package]] name = "rand_pcg" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -907,7 +907,7 @@ dependencies = [ [[package]] name = "serde_bytes" -version = "0.10.4" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1082,7 +1082,7 @@ name = "thread_local" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1201,7 +1201,7 @@ dependencies = [ "nix 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", "serde-bench 0.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_bytes 0.10.5 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", "target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-runtime-core 0.1.2", @@ -1216,7 +1216,7 @@ version = "0.1.0" dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.49 (git+https://github.com/rust-lang/libc)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1229,7 +1229,7 @@ dependencies = [ name = "wasmer-runtime" version = "0.1.4" dependencies = [ - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-clif-backend 0.1.2", "wasmer-runtime-core 0.1.2", @@ -1254,14 +1254,14 @@ dependencies = [ "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "nix 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "page_size 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", "serde-bench 0.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_bytes 0.10.5 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-clif-backend 0.1.2", @@ -1415,7 +1415,7 @@ dependencies = [ "checksum inkwell_internal_macros 0.1.0 (git+https://github.com/TheDan64/inkwell?branch=llvm7-0)" = "" "checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -"checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1" +"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" "checksum libc 0.2.49 (git+https://github.com/rust-lang/libc)" = "" "checksum libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)" = "413f3dfc802c5dc91dc570b05125b6cda9855edfaa9825c9849807876376e70e" "checksum libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3ad660d7cb8c5822cd83d10897b0f1f1526792737a179e73896152f85b88c2" @@ -1426,7 +1426,7 @@ dependencies = [ "checksum memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" "checksum nix 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "921f61dc817b379d0834e45d5ec45beaacfae97082090a49c2cf30dcbc30206f" "checksum nix 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46f0f3210768d796e8fa79ec70ee6af172dacbe7147f5e69be5240a47778302b" -"checksum nom 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b30adc557058ce00c9d0d7cb3c6e0b5bc6f36e2e2eabe74b0ba726d194abd588" +"checksum nom 4.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4836e9d6036552017e107edc598c97b2dee245161ff1b1ad4af215004774b354" "checksum opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "93f5bb2e8e8dec81642920ccff6b61f1eb94fa3020c5a325c9851ff604152409" "checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" "checksum page_size 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f89ef58b3d32420dbd1a43d2f38ae92f6239ef12bb556ab09ca55445f5a67242" @@ -1448,7 +1448,7 @@ dependencies = [ "checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" "checksum rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b9ea758282efe12823e0d952ddb269d2e1897227e464919a554f2a03ef1b832" "checksum rand_os 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b7c690732391ae0abafced5015ffb53656abfaec61b342290e5eb56b286a679d" -"checksum rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "086bd09a33c7044e56bb44d5bdde5a60e7f119a9e95b0775f545de759a32fe05" +"checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" "checksum raw-cpuid 6.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "30a9d219c32c9132f7be513c18be77c9881c7107d2ab5569d205a6a0f0e6dc7d" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" @@ -1467,7 +1467,7 @@ dependencies = [ "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" "checksum serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)" = "9f301d728f2b94c9a7691c90f07b0b4e8a4517181d9461be94c04bddeb4bd850" "checksum serde-bench 0.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "d733da87e79faaac25616e33d26299a41143fd4cd42746cbb0e91d8feea243fd" -"checksum serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)" = "adb6e51a6b3696b301bc221d785f898b4457c619b51d7ce195a6d20baecb37b3" +"checksum serde_bytes 0.10.5 (registry+https://github.com/rust-lang/crates.io-index)" = "defbb8a83d7f34cc8380751eeb892b825944222888aff18996ea7901f24aec88" "checksum serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)" = "ac38f51a52a556cd17545798e29536885fb1a3fa63d6399f5ef650f4a7d35901" "checksum serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)" = "27dce848e7467aa0e2fcaf0a413641499c0b745452aaca1194d24dedde9e13c9" "checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d" diff --git a/lib/llvm-backend/build.rs b/lib/llvm-backend/build.rs index 0f4d1f195..33ce4525d 100644 --- a/lib/llvm-backend/build.rs +++ b/lib/llvm-backend/build.rs @@ -49,6 +49,7 @@ lazy_static! { use std::io::Read; let mut s = String::new(); file.read_to_string(&mut s).unwrap(); + s.truncate(s.len() - 4); Some(s) } else { None diff --git a/lib/llvm-backend/cpp/object_loader.cpp b/lib/llvm-backend/cpp/object_loader.cpp index 9ab36f4c3..52625b64b 100644 --- a/lib/llvm-backend/cpp/object_loader.cpp +++ b/lib/llvm-backend/cpp/object_loader.cpp @@ -1,19 +1,35 @@ #include "object_loader.hh" #include #include +#include -class MemoryManager : llvm::RuntimeDyld::MemoryManager { +struct MemoryManager : llvm::RuntimeDyld::MemoryManager { public: - MemoryManager() {} + MemoryManager(callbacks_t *callbacks) : callbacks(callbacks) {} - virtual ~MemoryManager() {} - - virtual uint8_t* allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID, llvm::StringRef SectionName) override { - return nullptr; + virtual ~MemoryManager() { + // Deallocate all of the allocated memory. + callbacks->dealloc_memory(code_section.base, code_section.size); + callbacks->dealloc_memory(read_section.base, read_section.size); + callbacks->dealloc_memory(readwrite_section.base, readwrite_section.size); } - virtual uint8_t* allocateDataSection(uintptr_t Size, unsigned Alignment, unsigned SectionID, llvm::StringRef SectionName, bool isReadOnly) override { - return nullptr; + virtual uint8_t* allocateCodeSection(uintptr_t size, unsigned alignment, unsigned section_id, llvm::StringRef section_name) override { + std::cout << "code section name: " << (std::string)section_name << std::endl; + + return allocate_bump(code_section, code_bump_ptr, size, alignment); + } + + virtual uint8_t* allocateDataSection(uintptr_t size, unsigned alignment, unsigned section_id, llvm::StringRef section_name, bool read_only) override { + std::cout << "data section name: " << (std::string)section_name << std::endl; + + // Allocate from the read-only section or the read-write section, depending on if this allocation + // should be read-only or not. + if (read_only) { + return allocate_bump(read_section, read_bump_ptr, size, alignment); + } else { + return allocate_bump(readwrite_section, readwrite_bump_ptr, size, alignment); + } } virtual void reserveAllocationSpace( @@ -24,7 +40,20 @@ public: uintptr_t read_write_data_size, uint32_t read_write_data_align ) override { - + uint8_t *ptr_out = nullptr; + size_t size_out = 0; + + auto code_result = callbacks->alloc_memory(code_size, PROTECT_READ_WRITE, &ptr_out, &size_out); + code_section = Section { ptr_out, size_out }; + code_bump_ptr = (uintptr_t)ptr_out; + + auto read_result = callbacks->alloc_memory(read_data_size, PROTECT_READ_WRITE, &ptr_out, &size_out); + read_section = Section { ptr_out, size_out }; + read_bump_ptr = (uintptr_t)ptr_out; + + auto readwrite_result = callbacks->alloc_memory(read_write_data_size, PROTECT_READ_WRITE, &ptr_out, &size_out); + readwrite_section = Section { ptr_out, size_out }; + readwrite_bump_ptr = (uintptr_t)ptr_out; } /* Turn on the `reserveAllocationSpace` callback. */ @@ -33,38 +62,59 @@ public: } virtual void registerEHFrames(uint8_t* Addr, uint64_t LoadAddr, size_t Size) override { - + std::cout << "should register eh frames" << std::endl; } virtual void deregisterEHFrames() override { - + std::cout << "should deregister eh frames" << std::endl; } virtual bool finalizeMemory(std::string *ErrMsg = nullptr) override { - + auto code_result = callbacks->protect_memory(code_section.base, code_section.size, mem_protect_t::PROTECT_READ_EXECUTE); + if (code_result != RESULT_OK) { + return false; + } + + auto read_result = callbacks->protect_memory(read_section.base, read_section.size, mem_protect_t::PROTECT_READ); + if (read_result != RESULT_OK) { + return false; + } + + // The readwrite section is already mapped as read-write. return false; } - virtual void notifyObjectLoaded(llvm::RuntimeDyld &RTDyld, const llvm::object::ObjectFile &Obj) override { - - } + virtual void notifyObjectLoaded(llvm::RuntimeDyld &RTDyld, const llvm::object::ObjectFile &Obj) override {} private: struct Section { uint8_t* base; - size_t num_pages; - size_t num_commited_bytes; + size_t size; }; - uint8_t *image_base; - size_t num_allocated_pages; + uint8_t* allocate_bump(Section& section, uintptr_t& bump_ptr, size_t size, size_t align) { + auto aligner = [](uintptr_t& ptr, size_t align) { + ptr = (ptr + align - 1) & ~(align - 1); + }; + + // Align the bump pointer to the requires alignment. + aligner(bump_ptr, align); + + auto ret_ptr = bump_ptr; + bump_ptr += size; + + assert(bump_ptr <= (uintptr_t)section.base + section.size); + + return (uint8_t*)ret_ptr; + } Section code_section, read_section, readwrite_section; + uintptr_t code_bump_ptr, read_bump_ptr, readwrite_bump_ptr; - + callbacks_t *callbacks; }; -class SymbolLookup : llvm::JITSymbolResolver { +struct SymbolLookup : llvm::JITSymbolResolver { public: virtual llvm::Expected lookup(const LookupSet& symbols) override { LookupResult result; @@ -93,4 +143,34 @@ private: return llvm::JITEvaluatedSymbol(addr, llvm::JITSymbolFlags::None); } +}; + +class WasmModule { +public: + WasmModule( + const uint8_t *object_start, + size_t object_size, + callbacks_t *callbacks + + ) : memory_manager(std::unique_ptr(new MemoryManager(callbacks))) { + object_file = llvm::cantFail(llvm::object::ObjectFile::createObjectFile(llvm::MemoryBufferRef( + llvm::StringRef((const char *)object_start, object_size), "object" + ))); + + SymbolLookup symbol_resolver; + llvm::RuntimeDyld loader(*memory_manager, symbol_resolver); + + loader.setProcessAllSections(true); + + auto loaded_object_info = loader.loadObject(*object_file); + loader.finalizeWithMemoryManagerLocking(); + + assert(!loader.hasError()); + + + + } +private: + std::unique_ptr memory_manager; + std::unique_ptr object_file; }; \ No newline at end of file diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index e0f4d984f..b0e8f2912 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -616,7 +616,7 @@ fn parse_function( let struct_value = basic_value.into_struct_value(); for i in 0..(count as u32) { let value = - builder.build_extract_value(struct_value, i, &state.var_name()); + builder.build_extract_value(struct_value, i, &state.var_name()).unwrap(); state.push1(value); } } diff --git a/lib/llvm-backend/src/platform/mod.rs b/lib/llvm-backend/src/platform/mod.rs new file mode 100644 index 000000000..bcc0378c2 --- /dev/null +++ b/lib/llvm-backend/src/platform/mod.rs @@ -0,0 +1,8 @@ + +#[cfg(target_family = "unix")] +mod unix; +#[cfg(target_family = "unix")] +pub use self::unix::*; + +#[cfg(target_family = "windows")] +compile_error!("windows not yet supported for the llvm-based compiler backend"); \ No newline at end of file diff --git a/lib/llvm-backend/src/platform/unix/mod.rs b/lib/llvm-backend/src/platform/unix/mod.rs new file mode 100644 index 000000000..c0e86f7ef --- /dev/null +++ b/lib/llvm-backend/src/platform/unix/mod.rs @@ -0,0 +1,40 @@ + +extern "C" { + fn __register_frame(frame: *const u8); + fn __deregister_frame(frame: *const u8); +} + +pub unsafe fn register_eh_frames(eh_frames: *const u8, num_bytes: usize) { + visit_frame_desc_entries(eh_frames, num_bytes, |frame| __register_frame(frame)); +} + +unsafe fn visit_frame_desc_entries(eh_frames: *const u8, num_bytes: usize, visitor: F) +where + F: Fn(*const u8), +{ + let mut next = eh_frames; + let mut end = eh_frames.add(num_bytes); + + loop { + if next >= end { + break; + } + + let cfi = next; + let mut cfi_num_bytes = (next as *const u32).read_unaligned() as u64; + assert!(cfi_num_bytes != 0); + + next = next.add(4); + if num_bytes == 0xffffffff { + let cfi_num_bytes64 = (next as *const u64).read_unaligned(); + cfi_num_bytes = cfi_num_bytes64; + next = next.add(8); + } + + let cie_offset = (next as *const u32).read_unaligned(); + if cie_offset != 0 { + visitor(cfi); + } + next = next.add(cfi_num_bytes as usize); + } +} From d4ae5cdd409fefdb4cf8a684389c3ae31f4a9d31 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Thu, 28 Feb 2019 12:31:39 -0800 Subject: [PATCH 138/262] Get function addresses from llvm-compiled code --- Cargo.lock | 46 +++-- lib/llvm-backend/Cargo.toml | 4 +- lib/llvm-backend/cpp/object_loader.cpp | 74 ++++---- lib/llvm-backend/cpp/object_loader.hh | 27 ++- lib/llvm-backend/src/backend.rs | 235 ++++++++++++++++++++++--- lib/llvm-backend/src/code.rs | 5 +- lib/llvm-backend/src/lib.rs | 67 ++----- 7 files changed, 313 insertions(+), 145 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 566a1514b..5e7852448 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -106,6 +106,22 @@ name = "byteorder" version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "capstone" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "capstone-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "capstone-sys" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "cast" version = "0.2.2" @@ -262,28 +278,6 @@ dependencies = [ "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "dlopen" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "dlopen_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "dlopen_derive" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "either" version = "1.5.1" @@ -491,16 +485,16 @@ dependencies = [ name = "llvm-backend" version = "0.1.0" dependencies = [ + "capstone 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", - "dlopen 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "goblin 0.0.20 (registry+https://github.com/rust-lang/crates.io-index)", "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "inkwell 0.1.0 (git+https://github.com/TheDan64/inkwell?branch=llvm7-0)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", - "tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-runtime-core 0.1.2", "wasmparser 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1373,6 +1367,8 @@ dependencies = [ "checksum block-padding 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d75255892aeb580d3c566f213a2b6fdc1c66667839f45719ee1d30ebf2aea591" "checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" "checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" +"checksum capstone 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "00be9d203fa0e078b93b24603633fb081851dfe0c1086364431f52587a47157e" +"checksum capstone-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2dc8d32bc5c1e6d0fcde10af411c98b07d93498d51654f678757f08fa2acd6a6" "checksum cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "926013f2860c46252efceabb19f4a6b308197505082c609025aa6706c011d427" "checksum cbindgen 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "32e01024aaf5390d6a8145047371a4f5b0063a14c1e411bc731353bd2278ca44" "checksum cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)" = "4390a3b5f4f6bce9c1d0c00128379df433e53777fdd30e92f16a529332baec4e" @@ -1390,8 +1386,6 @@ dependencies = [ "checksum cranelift-native 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "474bee81d620a473bf43411a3d6f10ffbf7965141dc5e5b76d8d2151dde3285d" "checksum cranelift-wasm 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49723365dab9a48b354bdc24cb6d9d5719bc1d3b858ffd2ea179d0d7d885804a" "checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c" -"checksum dlopen 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f8c301a18a3404a48d5d078e86b011ac834a6c4c742217e9aa8ceadd8a7e09e0" -"checksum dlopen_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6e16e4e343d6090ba47113c55bf6aa94e9b1eb5ab0c5abc9510d4c15074f30e9" "checksum either 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c67353c641dc847124ea1902d69bd753dee9bb3beff9aa3662ecf86c971d1fac" "checksum enum-methods 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7798e7da2d4cb0d6d6fc467e8d6b5bf247e9e989f786dde1732d79899c32bb10" "checksum env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "afb070faf94c85d17d50ca44f6ad076bce18ae92f0037d350947240a36e9d42e" diff --git a/lib/llvm-backend/Cargo.toml b/lib/llvm-backend/Cargo.toml index 3ec83d77c..eadc2c12f 100644 --- a/lib/llvm-backend/Cargo.toml +++ b/lib/llvm-backend/Cargo.toml @@ -11,8 +11,8 @@ inkwell = { git = "https://github.com/TheDan64/inkwell", branch = "llvm7-0" } hashbrown = "0.1.8" smallvec = "0.6.8" goblin = "0.0.20" -dlopen = "0.1.6" -tempfile = "3.0.7" +libc = "0.2.49" +capstone = "0.5.0" [build-dependencies] cc = "1.0" diff --git a/lib/llvm-backend/cpp/object_loader.cpp b/lib/llvm-backend/cpp/object_loader.cpp index 52625b64b..9265f8739 100644 --- a/lib/llvm-backend/cpp/object_loader.cpp +++ b/lib/llvm-backend/cpp/object_loader.cpp @@ -1,5 +1,4 @@ #include "object_loader.hh" -#include #include #include @@ -40,20 +39,26 @@ public: uintptr_t read_write_data_size, uint32_t read_write_data_align ) override { - uint8_t *ptr_out = nullptr; - size_t size_out = 0; + uint8_t *code_ptr_out = nullptr; + size_t code_size_out = 0; + auto code_result = callbacks->alloc_memory(code_size, PROTECT_READ_WRITE, &code_ptr_out, &code_size_out); + assert(code_result == RESULT_OK); + code_section = Section { code_ptr_out, code_size_out }; + code_bump_ptr = (uintptr_t)code_ptr_out; - auto code_result = callbacks->alloc_memory(code_size, PROTECT_READ_WRITE, &ptr_out, &size_out); - code_section = Section { ptr_out, size_out }; - code_bump_ptr = (uintptr_t)ptr_out; + uint8_t *read_ptr_out = nullptr; + size_t read_size_out = 0; + auto read_result = callbacks->alloc_memory(read_data_size, PROTECT_READ_WRITE, &read_ptr_out, &read_size_out); + assert(read_result == RESULT_OK); + read_section = Section { read_ptr_out, read_size_out }; + read_bump_ptr = (uintptr_t)read_ptr_out; - auto read_result = callbacks->alloc_memory(read_data_size, PROTECT_READ_WRITE, &ptr_out, &size_out); - read_section = Section { ptr_out, size_out }; - read_bump_ptr = (uintptr_t)ptr_out; - - auto readwrite_result = callbacks->alloc_memory(read_write_data_size, PROTECT_READ_WRITE, &ptr_out, &size_out); - readwrite_section = Section { ptr_out, size_out }; - readwrite_bump_ptr = (uintptr_t)ptr_out; + uint8_t *readwrite_ptr_out = nullptr; + size_t readwrite_size_out = 0; + auto readwrite_result = callbacks->alloc_memory(read_write_data_size, PROTECT_READ_WRITE, &readwrite_ptr_out, &readwrite_size_out); + assert(readwrite_result == RESULT_OK); + readwrite_section = Section { readwrite_ptr_out, readwrite_size_out }; + readwrite_bump_ptr = (uintptr_t)readwrite_ptr_out; } /* Turn on the `reserveAllocationSpace` callback. */ @@ -145,32 +150,37 @@ private: } }; -class WasmModule { -public: - WasmModule( +WasmModule::WasmModule( const uint8_t *object_start, size_t object_size, callbacks_t *callbacks +) : memory_manager(std::unique_ptr(new MemoryManager(callbacks))) +{ + object_file = llvm::cantFail(llvm::object::ObjectFile::createObjectFile(llvm::MemoryBufferRef( + llvm::StringRef((const char *)object_start, object_size), "object" + ))); - ) : memory_manager(std::unique_ptr(new MemoryManager(callbacks))) { - object_file = llvm::cantFail(llvm::object::ObjectFile::createObjectFile(llvm::MemoryBufferRef( - llvm::StringRef((const char *)object_start, object_size), "object" - ))); + SymbolLookup symbol_resolver; + llvm::RuntimeDyld loader(*memory_manager, symbol_resolver); - SymbolLookup symbol_resolver; - llvm::RuntimeDyld loader(*memory_manager, symbol_resolver); + loader.setProcessAllSections(true); - loader.setProcessAllSections(true); + auto loaded_object_info = loader.loadObject(*object_file); + loader.finalizeWithMemoryManagerLocking(); - auto loaded_object_info = loader.loadObject(*object_file); - loader.finalizeWithMemoryManagerLocking(); + assert(!loader.hasError()); - assert(!loader.hasError()); - - + symbol_table = loader.getSymbolTable(); + for (auto const& pair : symbol_table) { + std::cout << "symbol: (" << (std::string)pair.first << ") => " << (void*)pair.second.getAddress() << std::endl; } -private: - std::unique_ptr memory_manager; - std::unique_ptr object_file; -}; \ No newline at end of file +} + +void* WasmModule::get_func(llvm::StringRef name) const { + try { + return (void*)symbol_table.at(name).getAddress(); + } catch (const std::out_of_range& e) { + return nullptr; + } +} \ No newline at end of file diff --git a/lib/llvm-backend/cpp/object_loader.hh b/lib/llvm-backend/cpp/object_loader.hh index 50b618b38..9db12ce96 100644 --- a/lib/llvm-backend/cpp/object_loader.hh +++ b/lib/llvm-backend/cpp/object_loader.hh @@ -1,5 +1,6 @@ #include #include +#include typedef enum { PROTECT_NONE, @@ -19,7 +20,7 @@ typedef enum { typedef result_t (*alloc_memory_t)(size_t size, mem_protect_t protect, uint8_t** ptr_out, size_t* size_out); typedef result_t (*protect_memory_t)(uint8_t* ptr, size_t size, mem_protect_t protect); typedef result_t (*dealloc_memory_t)(uint8_t* ptr, size_t size); -typedef uintptr_t (*lookup_vm_symbol_t)(char* name_ptr, size_t name_size); +typedef uintptr_t (*lookup_vm_symbol_t)(char* name_ptr); typedef struct { /* Memory management. */ @@ -30,11 +31,31 @@ typedef struct { lookup_vm_symbol_t lookup_vm_symbol; } callbacks_t; + + +class WasmModule { +public: + WasmModule( + const uint8_t *object_start, + size_t object_size, + callbacks_t *callbacks + ); + + void *get_func(llvm::StringRef name) const; +private: + std::unique_ptr memory_manager; + std::unique_ptr object_file; + std::map symbol_table; +}; + extern "C" { - result_t object_load(uint8_t* mem_ptr, size_t mem_size, callbacks_t* callbacks) { + result_t object_load(const uint8_t* mem_ptr, size_t mem_size, callbacks_t* callbacks, WasmModule** module_out) { + *module_out = new WasmModule(mem_ptr, mem_size, callbacks); + return RESULT_OK; } - void test_cpp() { + void* get_func_symbol(WasmModule* module, const char* name) { + return module->get_func(llvm::StringRef(name)); } } \ No newline at end of file diff --git a/lib/llvm-backend/src/backend.rs b/lib/llvm-backend/src/backend.rs index 2b4bb7023..94310fd79 100644 --- a/lib/llvm-backend/src/backend.rs +++ b/lib/llvm-backend/src/backend.rs @@ -1,19 +1,153 @@ use crate::intrinsics::Intrinsics; -use dlopen::symbor::Library; use inkwell::{ module::Module, targets::{CodeModel, FileType, InitializationConfig, RelocMode, Target, TargetMachine}, OptimizationLevel, }; -use std::{io::Write, ptr::NonNull}; -use tempfile::NamedTempFile; +use libc::{ + c_char, mmap, mprotect, munmap, MAP_ANON, MAP_PRIVATE, PROT_EXEC, PROT_NONE, PROT_READ, + PROT_WRITE, +}; +use std::{ + ffi::CString, + ptr::{self, NonNull}, +}; use wasmer_runtime_core::{ - backend::FuncResolver, module::ModuleInner, structures::TypedIndex, types::LocalFuncIndex, vm, + backend::FuncResolver, + module::{ModuleInfo, ModuleInner}, + structures::TypedIndex, + types::LocalFuncIndex, + vm, }; +#[repr(C)] +struct LLVMModule { + _private: [u8; 0], +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[repr(C)] +enum MemProtect { + NONE, + READ, + READ_WRITE, + READ_EXECUTE, +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[repr(C)] +enum LLVMResult { + OK, + ALLOCATE_FAILURE, + PROTECT_FAILURE, + DEALLOC_FAILURE, + OBJECT_LOAD_FAILURE, +} + +#[repr(C)] +struct Callbacks { + alloc_memory: extern "C" fn(usize, MemProtect, &mut *mut u8, &mut usize) -> LLVMResult, + protect_memory: extern "C" fn(*mut u8, usize, MemProtect) -> LLVMResult, + dealloc_memory: extern "C" fn(*mut u8, usize) -> LLVMResult, + + lookup_vm_symbol: extern "C" fn(*const c_char) -> *const vm::Func, +} + +extern "C" { + fn object_load( + mem_ptr: *const u8, + mem_size: usize, + callbacks: *const Callbacks, + module_out: &mut *mut LLVMModule, + ) -> LLVMResult; + fn get_func_symbol(module: *mut LLVMModule, name: *const c_char) -> *const vm::Func; +} + +fn get_callbacks() -> Callbacks { + fn round_up_to_page_size(size: usize) -> usize { + (size + (4096 - 1)) & !(4096 - 1) + } + + extern "C" fn alloc_memory( + size: usize, + protect: MemProtect, + ptr_out: &mut *mut u8, + size_out: &mut usize, + ) -> LLVMResult { + println!("size: {}", size); + let ptr = unsafe { + mmap( + ptr::null_mut(), + round_up_to_page_size(size), + match protect { + MemProtect::NONE => PROT_NONE, + MemProtect::READ => PROT_READ, + MemProtect::READ_WRITE => PROT_READ | PROT_WRITE, + MemProtect::READ_EXECUTE => PROT_READ | PROT_EXEC, + }, + MAP_PRIVATE | MAP_ANON, + -1, + 0, + ) + }; + if ptr as isize == -1 { + return LLVMResult::ALLOCATE_FAILURE; + } + *ptr_out = ptr as _; + *size_out = size; + LLVMResult::OK + } + + extern "C" fn protect_memory(ptr: *mut u8, size: usize, protect: MemProtect) -> LLVMResult { + println!("protect memory: {:p}:{} -> {:?}", ptr, size, protect); + let res = unsafe { + mprotect( + ptr as _, + round_up_to_page_size(size), + match protect { + MemProtect::NONE => PROT_NONE, + MemProtect::READ => PROT_READ, + MemProtect::READ_WRITE => PROT_READ | PROT_WRITE, + MemProtect::READ_EXECUTE => PROT_READ | PROT_EXEC, + }, + ) + }; + + if res == 0 { + LLVMResult::OK + } else { + LLVMResult::PROTECT_FAILURE + } + } + + extern "C" fn dealloc_memory(ptr: *mut u8, size: usize) -> LLVMResult { + println!("dealloc_memory"); + let res = unsafe { munmap(ptr as _, round_up_to_page_size(size)) }; + + if res == 0 { + LLVMResult::OK + } else { + LLVMResult::DEALLOC_FAILURE + } + } + + extern "C" fn lookup_vm_symbol(_name_ptr: *const c_char) -> *const vm::Func { + ptr::null() + } + + Callbacks { + alloc_memory, + protect_memory, + dealloc_memory, + lookup_vm_symbol, + } +} + +unsafe impl Send for LLVMBackend {} +unsafe impl Sync for LLVMBackend {} + pub struct LLVMBackend { - tempfile: NamedTempFile, - library: Library, + module: *mut LLVMModule, } impl LLVMBackend { @@ -42,14 +176,50 @@ impl LLVMBackend { let memory_buffer = target_machine .write_to_memory_buffer(&module, FileType::Object) .unwrap(); + let mem_buf_slice = memory_buffer.as_slice(); - let mut tempfile = NamedTempFile::new().unwrap(); - tempfile.write_all(memory_buffer.as_slice()).unwrap(); - tempfile.flush().unwrap(); + let callbacks = get_callbacks(); + let mut module: *mut LLVMModule = ptr::null_mut(); - let library = Library::open(tempfile.path()).unwrap(); + let res = unsafe { + object_load( + mem_buf_slice.as_ptr(), + mem_buf_slice.len(), + &callbacks, + &mut module, + ) + }; - Self { tempfile, library } + if res != LLVMResult::OK { + panic!("failed to load object") + } + + Self { module } + } + + pub fn get_func( + &self, + info: &ModuleInfo, + local_func_index: LocalFuncIndex, + ) -> Option> { + let index = local_func_index.index(); + let name = if cfg!(target_os = "macos") { + format!("_fn{}", index) + } else { + format!("fn{}", index) + }; + + println!("name: {}", name); + + let c_str = CString::new(name).ok()?; + + let ptr = unsafe { get_func_symbol(self.module, c_str.as_ptr()) }; + + unsafe { + disass_ptr(ptr as _, 0x20, 4); + } + + NonNull::new(ptr as _) } } @@ -59,18 +229,35 @@ impl FuncResolver for LLVMBackend { module: &ModuleInner, local_func_index: LocalFuncIndex, ) -> Option> { - let index = module.info.imported_functions.len() + local_func_index.index(); - let name = if cfg!(macos) { - format!("_fn{}", index) - } else { - format!("fn{}", index) - }; - - unsafe { - self.library - .symbol::>(&name) - .ok() - .map(|symbol| *symbol) - } + self.get_func(&module.info, local_func_index) + } +} + +unsafe fn disass_ptr(ptr: *const u8, size: usize, inst_count: usize) { + use capstone::arch::BuildsCapstone; + let mut cs = capstone::Capstone::new() // Call builder-pattern + .x86() // X86 architecture + .mode(capstone::arch::x86::ArchMode::Mode64) // 64-bit mode + .detail(true) // Generate extra instruction details + .build() + .expect("Failed to create Capstone object"); + + // Get disassembled instructions + let insns = cs + .disasm_count( + std::slice::from_raw_parts(ptr, size), + ptr as u64, + inst_count, + ) + .expect("Failed to disassemble"); + + println!("count = {}", insns.len()); + for insn in insns.iter() { + println!( + "0x{:x}: {:6} {}", + insn.address(), + insn.mnemonic().unwrap_or(""), + insn.op_str().unwrap_or("") + ); } } diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index b0e8f2912..70382bd0b 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -615,8 +615,9 @@ fn parse_function( // This is a multi-value return. let struct_value = basic_value.into_struct_value(); for i in 0..(count as u32) { - let value = - builder.build_extract_value(struct_value, i, &state.var_name()).unwrap(); + let value = builder + .build_extract_value(struct_value, i, &state.var_name()) + .unwrap(); state.push1(value); } } diff --git a/lib/llvm-backend/src/lib.rs b/lib/llvm-backend/src/lib.rs index e06b081af..692ba091f 100644 --- a/lib/llvm-backend/src/lib.rs +++ b/lib/llvm-backend/src/lib.rs @@ -88,24 +88,18 @@ impl Compiler for LLVMCompiler { #[test] fn test_read_module() { + use std::mem::transmute; use wabt::wat2wasm; - use wasmer_runtime_core::vmcalls; + use wasmer_runtime_core::{structures::TypedIndex, types::LocalFuncIndex, vm, vmcalls}; // let wasm = include_bytes!("../../spectests/examples/simple/simple.wasm") as &[u8]; let wat = r#" (module (type $t0 (func (param i32) (result i32))) (type $t1 (func (result i32))) (memory 1) - (table 10 anyfunc) - (elem (i32.const 0) $foobar) (global $g0 (mut i32) (i32.const 0)) (func $foo (type $t0) (param i32) (result i32) get_local 0 - i32.const 0 - call_indirect (type $t0) - ) - (func $foobar (type $t0) - get_local 0 )) "#; let wasm = wat2wasm(wat).unwrap(); @@ -114,54 +108,15 @@ fn test_read_module() { let (module, intrinsics) = code::parse_function_bodies(&info, code_reader).unwrap(); - // let backend = backend::LLVMBackend::new(module, intrinsics); + let backend = backend::LLVMBackend::new(module, intrinsics); - extern "C" { - fn test_cpp(); + let func_ptr = backend.get_func(&info, LocalFuncIndex::new(0)).unwrap(); + + println!("func_ptr: {:p}", func_ptr.as_ptr()); + + unsafe { + let func: unsafe extern "C" fn(*mut vm::Ctx, i32) -> i32 = transmute(func_ptr); + let result = func(0 as _, 42); + println!("result: {}", result); } - - unsafe { test_cpp() }; - - // let exec_engine = module - // .create_jit_execution_engine(OptimizationLevel::Default) - // .unwrap(); - - // exec_engine.add_global_mapping( - // &intrinsics.memory_grow_dynamic_local, - // vmcalls::local_dynamic_memory_grow as usize, - // ); - // exec_engine.add_global_mapping( - // &intrinsics.memory_grow_static_local, - // vmcalls::local_static_memory_grow as usize, - // ); - // exec_engine.add_global_mapping( - // &intrinsics.memory_grow_dynamic_import, - // vmcalls::imported_dynamic_memory_grow as usize, - // ); - // exec_engine.add_global_mapping( - // &intrinsics.memory_grow_static_import, - // vmcalls::imported_static_memory_grow as usize, - // ); - // exec_engine.add_global_mapping( - // &intrinsics.memory_size_dynamic_local, - // vmcalls::local_dynamic_memory_size as usize, - // ); - // exec_engine.add_global_mapping( - // &intrinsics.memory_size_static_local, - // vmcalls::local_static_memory_size as usize, - // ); - // exec_engine.add_global_mapping( - // &intrinsics.memory_size_dynamic_import, - // vmcalls::imported_dynamic_memory_size as usize, - // ); - // exec_engine.add_global_mapping( - // &intrinsics.memory_size_static_import, - // vmcalls::imported_static_memory_size as usize, - // ); - - // unsafe { - // let func: JitFunction i32> = exec_engine.get_function("fn0").unwrap(); - // let result = func.call(0 as _, 0); - // println!("result: {}", result); - // } } From 359ac5abec85f85a7c7d078db63858250681bf74 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Thu, 28 Feb 2019 13:18:00 -0800 Subject: [PATCH 139/262] Connect part of the llvm backend to the runtime --- .gitignore | 1 + Cargo.lock | 40 +++++++++++++++++++----------------- lib/llvm-backend/Cargo.toml | 2 +- lib/llvm-backend/src/lib.rs | 9 ++++++-- lib/runtime/Cargo.toml | 6 ++++++ lib/runtime/examples/call.rs | 38 ++++++++++++++++++++++++++++++++++ lib/runtime/src/lib.rs | 5 +++-- 7 files changed, 77 insertions(+), 24 deletions(-) create mode 100644 lib/runtime/examples/call.rs diff --git a/.gitignore b/.gitignore index dd8330f3e..f0538a823 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ /artifacts .DS_Store .idea +**/.vscode \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 5e7852448..977f7280b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -481,25 +481,6 @@ dependencies = [ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "llvm-backend" -version = "0.1.0" -dependencies = [ - "capstone 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", - "goblin 0.0.20 (registry+https://github.com/rust-lang/crates.io-index)", - "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "inkwell 0.1.0 (git+https://github.com/TheDan64/inkwell?branch=llvm7-0)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", - "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", - "wasmer-runtime-core 0.1.2", - "wasmparser 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "llvm-sys" version = "70.1.0" @@ -1219,13 +1200,34 @@ dependencies = [ "wasmer-runtime-core 0.1.2", ] +[[package]] +name = "wasmer-llvm-backend" +version = "0.1.0" +dependencies = [ + "capstone 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "goblin 0.0.20 (registry+https://github.com/rust-lang/crates.io-index)", + "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "inkwell 0.1.0 (git+https://github.com/TheDan64/inkwell?branch=llvm7-0)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmer-runtime-core 0.1.2", + "wasmparser 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "wasmer-runtime" version = "0.1.4" dependencies = [ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-clif-backend 0.1.2", + "wasmer-llvm-backend 0.1.0", "wasmer-runtime-core 0.1.2", ] diff --git a/lib/llvm-backend/Cargo.toml b/lib/llvm-backend/Cargo.toml index eadc2c12f..81301872b 100644 --- a/lib/llvm-backend/Cargo.toml +++ b/lib/llvm-backend/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "llvm-backend" +name = "wasmer-llvm-backend" version = "0.1.0" authors = ["Lachlan Sneff "] edition = "2018" diff --git a/lib/llvm-backend/src/lib.rs b/lib/llvm-backend/src/lib.rs index 692ba091f..66d8e5753 100644 --- a/lib/llvm-backend/src/lib.rs +++ b/lib/llvm-backend/src/lib.rs @@ -54,10 +54,10 @@ impl Compiler for LLVMCompiler { _vmctx: *mut vm::Ctx, _: Token, ) -> RuntimeResult> { - Ok(vec![]) + unimplemented!("the llvm-based backend does not yet implement ProtectedCaller") } fn get_early_trapper(&self) -> Box { - unimplemented!() + Box::new(Placeholder) } } impl CacheGen for Placeholder { @@ -68,6 +68,11 @@ impl Compiler for LLVMCompiler { unimplemented!() } } + impl UserTrapper for Placeholder { + unsafe fn do_early_trap(&self, msg: String) -> ! { + unimplemented!("do early trap: {}", msg) + } + } (Box::new(Placeholder), Box::new(Placeholder)) }; diff --git a/lib/runtime/Cargo.toml b/lib/runtime/Cargo.toml index e4169a652..e0c23af11 100644 --- a/lib/runtime/Cargo.toml +++ b/lib/runtime/Cargo.toml @@ -20,5 +20,11 @@ version = "0.1.2" path = "../clif-backend" version = "0.1.2" +[dependencies.wasmer-llvm-backend] +path = "../llvm-backend" + [features] debug = ["wasmer-clif-backend/debug", "wasmer-runtime-core/debug"] + +[dev-dependencies] +wabt = "0.7.4" \ No newline at end of file diff --git a/lib/runtime/examples/call.rs b/lib/runtime/examples/call.rs new file mode 100644 index 000000000..a209c12dc --- /dev/null +++ b/lib/runtime/examples/call.rs @@ -0,0 +1,38 @@ +use wasmer_runtime::{compile, error, imports, Func}; + +use wabt::wat2wasm; + +static WAT: &'static str = r#" + (module + (type $t0 (func (param i32) (result i32))) + (type $t1 (func (result i32))) + (memory 1) + (global $g0 (mut i32) (i32.const 0)) + (export "foo" (func $foo)) + (func $foo (type $t0) (param i32) (result i32) + get_local 0 + ) + ) +"#; + +fn get_wasm() -> Vec { + wat2wasm(WAT).unwrap() +} + +fn main() -> Result<(), error::Error> { + let wasm = get_wasm(); + + let module = compile(&wasm)?; + + let imports = imports! {}; + + let instance = module.instantiate(&imports)?; + + let foo: Func = instance.func("foo")?; + + let result = foo.call(42); + + println!("result: {:?}", result); + + Ok(()) +} diff --git a/lib/runtime/src/lib.rs b/lib/runtime/src/lib.rs index c7e3b3826..4c5ce88cd 100644 --- a/lib/runtime/src/lib.rs +++ b/lib/runtime/src/lib.rs @@ -154,10 +154,11 @@ pub fn instantiate(wasm: &[u8], import_object: &ImportObject) -> error::Result &'static dyn Compiler { use lazy_static::lazy_static; - use wasmer_clif_backend::CraneliftCompiler; + // use wasmer_clif_backend::CraneliftCompiler; + use wasmer_llvm_backend::LLVMCompiler; lazy_static! { - static ref DEFAULT_COMPILER: CraneliftCompiler = { CraneliftCompiler::new() }; + static ref DEFAULT_COMPILER: LLVMCompiler = { LLVMCompiler::new() }; } &*DEFAULT_COMPILER as &dyn Compiler From 6a20676fa975c91f240e95cbb4d6f1a9e957d597 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Thu, 28 Feb 2019 17:20:18 -0800 Subject: [PATCH 140/262] Actually unmap the code after it's done being used --- Cargo.lock | 2 + lib/llvm-backend/cpp/object_loader.cpp | 54 +++++++++++--------------- lib/llvm-backend/cpp/object_loader.hh | 14 ++++--- lib/llvm-backend/src/backend.rs | 38 ++++++++++-------- lib/llvm-backend/src/code.rs | 14 +++---- lib/runtime/examples/call.rs | 6 +++ 6 files changed, 66 insertions(+), 62 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 977f7280b..c3cf75ae4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,3 +1,5 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. [[package]] name = "aho-corasick" version = "0.6.10" diff --git a/lib/llvm-backend/cpp/object_loader.cpp b/lib/llvm-backend/cpp/object_loader.cpp index 9265f8739..9d1d8c731 100644 --- a/lib/llvm-backend/cpp/object_loader.cpp +++ b/lib/llvm-backend/cpp/object_loader.cpp @@ -4,24 +4,20 @@ struct MemoryManager : llvm::RuntimeDyld::MemoryManager { public: - MemoryManager(callbacks_t *callbacks) : callbacks(callbacks) {} + MemoryManager(callbacks_t callbacks) : callbacks(callbacks) {} - virtual ~MemoryManager() { + virtual ~MemoryManager() override { // Deallocate all of the allocated memory. - callbacks->dealloc_memory(code_section.base, code_section.size); - callbacks->dealloc_memory(read_section.base, read_section.size); - callbacks->dealloc_memory(readwrite_section.base, readwrite_section.size); + callbacks.dealloc_memory(code_section.base, code_section.size); + callbacks.dealloc_memory(read_section.base, read_section.size); + callbacks.dealloc_memory(readwrite_section.base, readwrite_section.size); } virtual uint8_t* allocateCodeSection(uintptr_t size, unsigned alignment, unsigned section_id, llvm::StringRef section_name) override { - std::cout << "code section name: " << (std::string)section_name << std::endl; - return allocate_bump(code_section, code_bump_ptr, size, alignment); } virtual uint8_t* allocateDataSection(uintptr_t size, unsigned alignment, unsigned section_id, llvm::StringRef section_name, bool read_only) override { - std::cout << "data section name: " << (std::string)section_name << std::endl; - // Allocate from the read-only section or the read-write section, depending on if this allocation // should be read-only or not. if (read_only) { @@ -41,21 +37,21 @@ public: ) override { uint8_t *code_ptr_out = nullptr; size_t code_size_out = 0; - auto code_result = callbacks->alloc_memory(code_size, PROTECT_READ_WRITE, &code_ptr_out, &code_size_out); + auto code_result = callbacks.alloc_memory(code_size, PROTECT_READ_WRITE, &code_ptr_out, &code_size_out); assert(code_result == RESULT_OK); code_section = Section { code_ptr_out, code_size_out }; code_bump_ptr = (uintptr_t)code_ptr_out; uint8_t *read_ptr_out = nullptr; size_t read_size_out = 0; - auto read_result = callbacks->alloc_memory(read_data_size, PROTECT_READ_WRITE, &read_ptr_out, &read_size_out); + auto read_result = callbacks.alloc_memory(read_data_size, PROTECT_READ_WRITE, &read_ptr_out, &read_size_out); assert(read_result == RESULT_OK); read_section = Section { read_ptr_out, read_size_out }; read_bump_ptr = (uintptr_t)read_ptr_out; uint8_t *readwrite_ptr_out = nullptr; size_t readwrite_size_out = 0; - auto readwrite_result = callbacks->alloc_memory(read_write_data_size, PROTECT_READ_WRITE, &readwrite_ptr_out, &readwrite_size_out); + auto readwrite_result = callbacks.alloc_memory(read_write_data_size, PROTECT_READ_WRITE, &readwrite_ptr_out, &readwrite_size_out); assert(readwrite_result == RESULT_OK); readwrite_section = Section { readwrite_ptr_out, readwrite_size_out }; readwrite_bump_ptr = (uintptr_t)readwrite_ptr_out; @@ -75,12 +71,12 @@ public: } virtual bool finalizeMemory(std::string *ErrMsg = nullptr) override { - auto code_result = callbacks->protect_memory(code_section.base, code_section.size, mem_protect_t::PROTECT_READ_EXECUTE); + auto code_result = callbacks.protect_memory(code_section.base, code_section.size, mem_protect_t::PROTECT_READ_EXECUTE); if (code_result != RESULT_OK) { return false; } - auto read_result = callbacks->protect_memory(read_section.base, read_section.size, mem_protect_t::PROTECT_READ); + auto read_result = callbacks.protect_memory(read_section.base, read_section.size, mem_protect_t::PROTECT_READ); if (read_result != RESULT_OK) { return false; } @@ -116,7 +112,7 @@ private: Section code_section, read_section, readwrite_section; uintptr_t code_bump_ptr, read_bump_ptr, readwrite_bump_ptr; - callbacks_t *callbacks; + callbacks_t callbacks; }; struct SymbolLookup : llvm::JITSymbolResolver { @@ -153,34 +149,28 @@ private: WasmModule::WasmModule( const uint8_t *object_start, size_t object_size, - callbacks_t *callbacks -) : memory_manager(std::unique_ptr(new MemoryManager(callbacks))) + callbacks_t callbacks +) : memory_manager(new MemoryManager(callbacks)) { object_file = llvm::cantFail(llvm::object::ObjectFile::createObjectFile(llvm::MemoryBufferRef( llvm::StringRef((const char *)object_start, object_size), "object" ))); SymbolLookup symbol_resolver; - llvm::RuntimeDyld loader(*memory_manager, symbol_resolver); + runtime_dyld = std::unique_ptr(new llvm::RuntimeDyld(*memory_manager, symbol_resolver)); - loader.setProcessAllSections(true); + runtime_dyld->setProcessAllSections(true); - auto loaded_object_info = loader.loadObject(*object_file); - loader.finalizeWithMemoryManagerLocking(); + runtime_dyld->loadObject(*object_file); + runtime_dyld->finalizeWithMemoryManagerLocking(); - assert(!loader.hasError()); - - symbol_table = loader.getSymbolTable(); - - for (auto const& pair : symbol_table) { - std::cout << "symbol: (" << (std::string)pair.first << ") => " << (void*)pair.second.getAddress() << std::endl; + if (runtime_dyld->hasError()) { + std::cout << "RuntimeDyld error: " << (std::string)runtime_dyld->getErrorString() << std::endl; + abort(); } } void* WasmModule::get_func(llvm::StringRef name) const { - try { - return (void*)symbol_table.at(name).getAddress(); - } catch (const std::out_of_range& e) { - return nullptr; - } + auto symbol = runtime_dyld->getSymbol(name); + return (void*)symbol.getAddress(); } \ No newline at end of file diff --git a/lib/llvm-backend/cpp/object_loader.hh b/lib/llvm-backend/cpp/object_loader.hh index 9db12ce96..969f16150 100644 --- a/lib/llvm-backend/cpp/object_loader.hh +++ b/lib/llvm-backend/cpp/object_loader.hh @@ -31,30 +31,32 @@ typedef struct { lookup_vm_symbol_t lookup_vm_symbol; } callbacks_t; - - class WasmModule { public: WasmModule( const uint8_t *object_start, size_t object_size, - callbacks_t *callbacks + callbacks_t callbacks ); void *get_func(llvm::StringRef name) const; private: - std::unique_ptr memory_manager; + llvm::RuntimeDyld::MemoryManager* memory_manager; std::unique_ptr object_file; - std::map symbol_table; + std::unique_ptr runtime_dyld; }; extern "C" { - result_t object_load(const uint8_t* mem_ptr, size_t mem_size, callbacks_t* callbacks, WasmModule** module_out) { + result_t module_load(const uint8_t* mem_ptr, size_t mem_size, callbacks_t callbacks, WasmModule** module_out) { *module_out = new WasmModule(mem_ptr, mem_size, callbacks); return RESULT_OK; } + void module_delete(WasmModule* module) { + delete module; + } + void* get_func_symbol(WasmModule* module, const char* name) { return module->get_func(llvm::StringRef(name)); } diff --git a/lib/llvm-backend/src/backend.rs b/lib/llvm-backend/src/backend.rs index 94310fd79..6e55d55fe 100644 --- a/lib/llvm-backend/src/backend.rs +++ b/lib/llvm-backend/src/backend.rs @@ -1,5 +1,6 @@ use crate::intrinsics::Intrinsics; use inkwell::{ + memory_buffer::MemoryBuffer, module::Module, targets::{CodeModel, FileType, InitializationConfig, RelocMode, Target, TargetMachine}, OptimizationLevel, @@ -25,6 +26,7 @@ struct LLVMModule { _private: [u8; 0], } +#[allow(non_camel_case_types, dead_code)] #[derive(Debug, Copy, Clone, PartialEq, Eq)] #[repr(C)] enum MemProtect { @@ -34,6 +36,7 @@ enum MemProtect { READ_EXECUTE, } +#[allow(non_camel_case_types, dead_code)] #[derive(Debug, Copy, Clone, PartialEq, Eq)] #[repr(C)] enum LLVMResult { @@ -54,12 +57,13 @@ struct Callbacks { } extern "C" { - fn object_load( + fn module_load( mem_ptr: *const u8, mem_size: usize, - callbacks: *const Callbacks, + callbacks: Callbacks, module_out: &mut *mut LLVMModule, ) -> LLVMResult; + fn module_delete(module: *mut LLVMModule); fn get_func_symbol(module: *mut LLVMModule, name: *const c_char) -> *const vm::Func; } @@ -74,11 +78,11 @@ fn get_callbacks() -> Callbacks { ptr_out: &mut *mut u8, size_out: &mut usize, ) -> LLVMResult { - println!("size: {}", size); + let size = round_up_to_page_size(size); let ptr = unsafe { mmap( ptr::null_mut(), - round_up_to_page_size(size), + size, match protect { MemProtect::NONE => PROT_NONE, MemProtect::READ => PROT_READ, @@ -99,7 +103,6 @@ fn get_callbacks() -> Callbacks { } extern "C" fn protect_memory(ptr: *mut u8, size: usize, protect: MemProtect) -> LLVMResult { - println!("protect memory: {:p}:{} -> {:?}", ptr, size, protect); let res = unsafe { mprotect( ptr as _, @@ -121,7 +124,6 @@ fn get_callbacks() -> Callbacks { } extern "C" fn dealloc_memory(ptr: *mut u8, size: usize) -> LLVMResult { - println!("dealloc_memory"); let res = unsafe { munmap(ptr as _, round_up_to_page_size(size)) }; if res == 0 { @@ -148,6 +150,8 @@ unsafe impl Sync for LLVMBackend {} pub struct LLVMBackend { module: *mut LLVMModule, + #[allow(dead_code)] + memory_buffer: MemoryBuffer, } impl LLVMBackend { @@ -182,10 +186,10 @@ impl LLVMBackend { let mut module: *mut LLVMModule = ptr::null_mut(); let res = unsafe { - object_load( + module_load( mem_buf_slice.as_ptr(), mem_buf_slice.len(), - &callbacks, + callbacks, &mut module, ) }; @@ -194,7 +198,10 @@ impl LLVMBackend { panic!("failed to load object") } - Self { module } + Self { + module, + memory_buffer, + } } pub fn get_func( @@ -209,20 +216,19 @@ impl LLVMBackend { format!("fn{}", index) }; - println!("name: {}", name); - let c_str = CString::new(name).ok()?; - let ptr = unsafe { get_func_symbol(self.module, c_str.as_ptr()) }; - unsafe { - disass_ptr(ptr as _, 0x20, 4); - } - NonNull::new(ptr as _) } } +impl Drop for LLVMBackend { + fn drop(&mut self) { + unsafe { module_delete(self.module) } + } +} + impl FuncResolver for LLVMBackend { fn get( &self, diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index 70382bd0b..3b72dd309 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -1,7 +1,7 @@ use inkwell::{ builder::Builder, context::Context, - module::Module, + module::{Linkage, Module}, passes::PassManager, types::{BasicType, BasicTypeEnum, FunctionType, PointerType}, values::{BasicValue, FunctionValue, PhiValue, PointerValue}, @@ -10,7 +10,7 @@ use inkwell::{ use smallvec::SmallVec; use wasmer_runtime_core::{ memory::MemoryType, - module::ModuleInfo, + module::{ExportIndex, ModuleInfo}, structures::{Map, SliceMap, TypedIndex}, types::{ FuncIndex, FuncSig, GlobalIndex, LocalFuncIndex, LocalOrImport, MemoryIndex, SigIndex, @@ -80,7 +80,7 @@ pub fn parse_function_bodies( module.add_function( &format!("fn{}", func_index.index()), signatures[sig_index], - None, + Some(Linkage::External), ) }) .collect(); @@ -106,6 +106,7 @@ pub fn parse_function_bodies( } let pass_manager = PassManager::create_for_module(); + pass_manager.add_function_inlining_pass(); pass_manager.add_promote_memory_to_register_pass(); pass_manager.add_cfg_simplification_pass(); pass_manager.add_instruction_combining_pass(); @@ -113,13 +114,11 @@ pub fn parse_function_bodies( // pass_manager.add_merged_load_store_motion_pass(); // pass_manager.add_sccp_pass(); pass_manager.add_gvn_pass(); - pass_manager.add_new_gvn_pass(); + // pass_manager.add_new_gvn_pass(); pass_manager.add_aggressive_dce_pass(); - pass_manager.add_verifier_pass(); + // pass_manager.add_verifier_pass(); pass_manager.run_on_module(&module); - println!("{}", module.print_to_string().to_string()); - Ok((module, intrinsics)) } @@ -1791,7 +1790,6 @@ fn parse_function( state.push1(result.try_as_basic_value().left().unwrap()); } op @ _ => { - println!("{}", module.print_to_string().to_string()); unimplemented!("{:?}", op); } } diff --git a/lib/runtime/examples/call.rs b/lib/runtime/examples/call.rs index a209c12dc..6015a4bb1 100644 --- a/lib/runtime/examples/call.rs +++ b/lib/runtime/examples/call.rs @@ -11,6 +11,12 @@ static WAT: &'static str = r#" (export "foo" (func $foo)) (func $foo (type $t0) (param i32) (result i32) get_local 0 + call $bar + ) + (func $bar (type $t0) (param i32) (result i32) + get_local 0 + i32.const 10 + i32.add ) ) "#; From 51c9091fc5a452f38727ebffb9d2f3faa46ea477 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Thu, 28 Feb 2019 18:26:47 -0800 Subject: [PATCH 141/262] Start work on generating trampolines --- lib/llvm-backend/src/trampolines.rs | 38 +++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 lib/llvm-backend/src/trampolines.rs diff --git a/lib/llvm-backend/src/trampolines.rs b/lib/llvm-backend/src/trampolines.rs new file mode 100644 index 000000000..34ce9eb15 --- /dev/null +++ b/lib/llvm-backend/src/trampolines.rs @@ -0,0 +1,38 @@ +use inkwell::{ + builder::Builder, + context::Context, + module::{Linkage, Module}, + passes::PassManager, + types::{BasicType, BasicTypeEnum, FunctionType, PointerType}, + values::{BasicValue, FunctionValue, PhiValue, PointerValue}, + AddressSpace, FloatPredicate, IntPredicate, +}; +use wasmer_runtime_core::{ + module::ModuleInfo, + types::{SigIndex, FuncSig}, + structures::{TypedIndex, SliceMap}, +}; +use crate::intrinsics::Intrinsics; + +pub fn generate_trampolines(info: &ModuleInfo, signatures: &SliceMap, module: &Module, builder: &Builder, intrinsics: &Intrinsics) -> Result<(), String> { + let trampoline_sig = intrinsics.void_ty.fn_type(&[ + intrinsics.ctx_ptr_ty, // vmctx ptr + intrinsics.i64_ptr_ty, // func ptr + intrinsics.i64_ptr_ty, + intrinsics.i64_ptr_ty, + ], false); + + for (sig_index, sig) in info.signatures.iter() { + + } +} + +pub fn generate_trampoline(sig_index: usize, trampoline_sig: FunctionType, sig: &FuncSig, builder: &Builder, intrinsics: &Intrinsics) { + let function = module.add_function( + &format!("tramp{}", sig_index.index()), + signatures[sig_index], + Some(Linkage::External), + ); + + +} \ No newline at end of file From ea3d5b04d41b93aca2dd7b83f58246f098890764 Mon Sep 17 00:00:00 2001 From: David Calavera Date: Thu, 28 Feb 2019 19:16:22 -0800 Subject: [PATCH 142/262] Remove debug option from run command. I was looking into the code and I noticed that this option is not used. The `debug!` macro is used across the codebase, which looks more ideal. Signed-off-by: David Calavera --- src/bin/wasmer.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/bin/wasmer.rs b/src/bin/wasmer.rs index d5364504b..e36e99cb6 100644 --- a/src/bin/wasmer.rs +++ b/src/bin/wasmer.rs @@ -33,9 +33,6 @@ enum CLIOptions { #[derive(Debug, StructOpt)] struct Run { - #[structopt(short = "d", long = "debug")] - debug: bool, - // Disable the cache #[structopt(long = "disable-cache")] disable_cache: bool, From b80252e1654904b4ca61043084ca1b34b95b52c7 Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Thu, 28 Feb 2019 23:02:03 -0600 Subject: [PATCH 143/262] Setup the spectests lib to use llvm-backend --- Cargo.lock | 1 + lib/runtime-core/src/types.rs | 7 +------ lib/spectests/Cargo.toml | 1 + lib/spectests/build/spectests.rs | 9 +++++---- 4 files changed, 8 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c3cf75ae4..f06c9e940 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1273,6 +1273,7 @@ version = "0.1.2" dependencies = [ "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-clif-backend 0.1.2", + "wasmer-llvm-backend 0.1.0", "wasmer-runtime-core 0.1.2", ] diff --git a/lib/runtime-core/src/types.rs b/lib/runtime-core/src/types.rs index 618f24004..9ee5270dd 100644 --- a/lib/runtime-core/src/types.rs +++ b/lib/runtime-core/src/types.rs @@ -1,9 +1,4 @@ -use crate::{ - memory::MemoryType, - module::ModuleInfo, - structures::TypedIndex, - units::Pages, -}; +use crate::{memory::MemoryType, module::ModuleInfo, structures::TypedIndex, units::Pages}; use std::{borrow::Cow, mem}; /// Represents a WebAssembly type. diff --git a/lib/spectests/Cargo.toml b/lib/spectests/Cargo.toml index f69782b40..49f052d77 100644 --- a/lib/spectests/Cargo.toml +++ b/lib/spectests/Cargo.toml @@ -16,6 +16,7 @@ wabt = "0.7.2" [dev-dependencies] wasmer-clif-backend = { path = "../clif-backend", version = "0.1.2" } +wasmer-llvm-backend = { path = "../llvm-backend", version = "0.1.0" } wabt = "0.7.2" [features] diff --git a/lib/spectests/build/spectests.rs b/lib/spectests/build/spectests.rs index 54d9404d6..25b3b63b8 100644 --- a/lib/spectests/build/spectests.rs +++ b/lib/spectests/build/spectests.rs @@ -78,6 +78,7 @@ static COMMON: &'static str = r##" use std::{{f32, f64}}; use wabt::wat2wasm; use wasmer_clif_backend::CraneliftCompiler; +use wasmer_llvm_backend::LLVMCompiler; use wasmer_runtime_core::import::ImportObject; use wasmer_runtime_core::types::Value; use wasmer_runtime_core::{{Instance, module::Module}}; @@ -97,7 +98,7 @@ static IMPORT_MODULE: &str = r#" pub fn generate_imports() -> ImportObject { let wasm_binary = wat2wasm(IMPORT_MODULE.as_bytes()).expect("WAST not valid or malformed"); - let module = wasmer_runtime_core::compile_with(&wasm_binary[..], &CraneliftCompiler::new()) + let module = wasmer_runtime_core::compile_with(&wasm_binary[..], &LLVMCompiler::new()) .expect("WASM can't be compiled"); let instance = module .instantiate(&ImportObject::new()) @@ -358,7 +359,7 @@ fn test_module_{}() {{ let module_str = \"{}\"; println!(\"{{}}\", module_str); let wasm_binary = wat2wasm(module_str.as_bytes()).expect(\"WAST not valid or malformed\"); - let module = wasmer_runtime_core::compile_with(&wasm_binary[..], &CraneliftCompiler::new()).expect(\"WASM can't be compiled\"); + let module = wasmer_runtime_core::compile_with(&wasm_binary[..], &LLVMCompiler::new()).expect(\"WASM can't be compiled\"); module.instantiate(&generate_imports()).expect(\"WASM can't be instantiated\") }}\n", self.last_module, @@ -381,7 +382,7 @@ fn test_module_{}() {{ "#[test] fn {}_assert_invalid() {{ let wasm_binary = {:?}; - let module = wasmer_runtime_core::compile_with(&wasm_binary, &CraneliftCompiler::new()); + let module = wasmer_runtime_core::compile_with(&wasm_binary, &LLVMCompiler::new()); assert!(module.is_err(), \"WASM should not compile as is invalid\"); }}\n", command_name, @@ -512,7 +513,7 @@ fn {}_assert_invalid() {{ "#[test] fn {}_assert_malformed() {{ let wasm_binary = {:?}; - let compilation = wasmer_runtime_core::compile_with(&wasm_binary, &CraneliftCompiler::new()); + let compilation = wasmer_runtime_core::compile_with(&wasm_binary, &LLVMCompiler::new()); assert!(compilation.is_err(), \"WASM should not compile as is malformed\"); }}\n", command_name, From bde2022b581b80e35590c7b748932c8dccf6cf85 Mon Sep 17 00:00:00 2001 From: Mackenzie Clark Date: Fri, 1 Mar 2019 13:16:32 -0800 Subject: [PATCH 144/262] fix appveyor installer and build (#224) * remove exception handler when function returns or throws * revert to only reserving and not committing memory due to issues * appveyor builds for release, caches more, only publish artifact once --- .appveyor.yml | 24 ++++++++++--------- lib/runtime-core/src/sys/windows/memory.rs | 11 ++------- .../exception_handling/exception_handling.c | 14 ++++++++++- 3 files changed, 28 insertions(+), 21 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 4ec05f8c7..2a67567e4 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -14,34 +14,36 @@ environment: cache: - 'C:\Users\appveyor\.cargo' + - target install: - - appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe - - rustup-init.exe -yv --default-host %target% + # uncomment these lines if the cache is cleared, or if we must re-install rust for some reason + # - appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe + # - rustup-init.exe -yv --default-host %target% - set PATH=%PATH%;%USERPROFILE%\.cargo\bin + - rustup default stable-%target% + - rustup update - rustc -vV - cargo -vV # Install InnoSetup - appveyor-retry appveyor DownloadFile https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/2017-08-22-is.exe - 2017-08-22-is.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /SP- - set PATH="C:\Program Files (x86)\Inno Setup 5";%PATH% +# uncomment to RDP to appveyor +# - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) build_script: - - cargo build --verbose + - cargo build --release --verbose test_script: - - set RUST_BACKTRACE=1 - - cd ./lib/spectests && cargo test -- --test-threads 1 && cd ../.. + - cargo test --package wasmer-spectests -before_deploy: +after_build: - cd ./src/installer - iscc wasmer.iss - copy /y .\WasmerInstaller.exe ..\..\WasmerInstaller-%APPVEYOR_REPO_TAG_NAME%.exe - - appveyor PushArtifact WasmerInstaller-%APPVEYOR_REPO_TAG_NAME%.exe - -artifacts: - - path: WasmerInstaller-%APPVEYOR_REPO_TAG_NAME%.exe - name: WasmerInstaller.exe + - appveyor PushArtifact ..\..\WasmerInstaller-%APPVEYOR_REPO_TAG_NAME%.exe + - cd ..\..\ deploy: description: 'WasmerInstaller' diff --git a/lib/runtime-core/src/sys/windows/memory.rs b/lib/runtime-core/src/sys/windows/memory.rs index 3ca86bec9..d47388170 100644 --- a/lib/runtime-core/src/sys/windows/memory.rs +++ b/lib/runtime-core/src/sys/windows/memory.rs @@ -33,7 +33,7 @@ impl Memory { let protect = protection.to_protect_const(); - let ptr = unsafe { VirtualAlloc(ptr::null_mut(), size, MEM_RESERVE | MEM_COMMIT, protect) }; + let ptr = unsafe { VirtualAlloc(ptr::null_mut(), size, MEM_RESERVE, protect) }; if ptr.is_null() { Err("unable to allocate memory".to_string()) @@ -57,14 +57,7 @@ impl Memory { let size = round_up_to_page_size(size, page_size::get()); - let ptr = unsafe { - VirtualAlloc( - ptr::null_mut(), - size, - MEM_RESERVE | MEM_COMMIT, - PAGE_NOACCESS, - ) - }; + let ptr = unsafe { VirtualAlloc(ptr::null_mut(), size, MEM_RESERVE, PAGE_NOACCESS) }; if ptr.is_null() { Err(MemoryCreationError::VirtualMemoryAllocationFailed( diff --git a/lib/win-exception-handler/exception_handling/exception_handling.c b/lib/win-exception-handler/exception_handling/exception_handling.c index 3284034cc..eb45b204d 100644 --- a/lib/win-exception-handler/exception_handling/exception_handling.c +++ b/lib/win-exception-handler/exception_handling/exception_handling.c @@ -10,6 +10,7 @@ __declspec(thread) DWORD64 caughtInstructionPointer; __declspec(thread) PVOID savedStackPointer; __declspec(thread) BOOL exceptionHandlerInstalled = FALSE; __declspec(thread) BOOL alreadyHandlingException = FALSE; +__declspec(thread) PVOID handle; void longjmpOutOfHere() { longjmp(jmpBuf, 1); @@ -38,6 +39,14 @@ exceptionHandler(struct _EXCEPTION_POINTERS *ExceptionInfo) { return EXCEPTION_CONTINUE_EXECUTION; } +static void removeExceptionHandler() { + if (exceptionHandlerInstalled == FALSE) { + return; + } + RemoveVectoredExceptionHandler(handle); + exceptionHandlerInstalled = FALSE; +} + uint8_t callProtected(trampoline_t trampoline, const struct wasmer_instance_context_t* ctx, const struct func_t* func, @@ -48,7 +57,7 @@ uint8_t callProtected(trampoline_t trampoline, // install exception handler if (exceptionHandlerInstalled == FALSE) { exceptionHandlerInstalled = TRUE; - AddVectoredExceptionHandler(CALL_FIRST, exceptionHandler); + handle = AddVectoredExceptionHandler(CALL_FIRST, exceptionHandler); } // jmp jmp jmp! @@ -60,6 +69,8 @@ uint8_t callProtected(trampoline_t trampoline, out_result->code = 0; out_result->exceptionAddress = 0; out_result->instructionPointer = 0; + + removeExceptionHandler(); return TRUE; } @@ -70,5 +81,6 @@ uint8_t callProtected(trampoline_t trampoline, caughtExceptionAddress = 0; caughtInstructionPointer = 0; + removeExceptionHandler(); return FALSE; } From 3717c5720d9a5357498b8b7a6c356bb9cbfe03ab Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Fri, 1 Mar 2019 15:48:43 -0800 Subject: [PATCH 145/262] Get control flow (at least according to the llvm verifier) working. Next up: - Importing vm intrinsics. --- lib/llvm-backend/src/backend.rs | 153 ++++++++++++++++++++++++-- lib/llvm-backend/src/code.rs | 164 ++++++++++++++++++++++------ lib/llvm-backend/src/intrinsics.rs | 1 - lib/llvm-backend/src/lib.rs | 47 ++++---- lib/llvm-backend/src/trampolines.rs | 118 +++++++++++++++++--- lib/runtime-core/src/instance.rs | 2 +- lib/runtime/examples/call.rs | 28 ++--- 7 files changed, 408 insertions(+), 105 deletions(-) diff --git a/lib/llvm-backend/src/backend.rs b/lib/llvm-backend/src/backend.rs index 6e55d55fe..98b0bc6e0 100644 --- a/lib/llvm-backend/src/backend.rs +++ b/lib/llvm-backend/src/backend.rs @@ -11,14 +11,17 @@ use libc::{ }; use std::{ ffi::CString, + mem, ptr::{self, NonNull}, }; use wasmer_runtime_core::{ - backend::FuncResolver, + backend::{FuncResolver, ProtectedCaller, Token, UserTrapper}, + error::RuntimeResult, + export::Context, module::{ModuleInfo, ModuleInner}, structures::TypedIndex, - types::LocalFuncIndex, - vm, + types::{FuncIndex, FuncSig, LocalFuncIndex, LocalOrImport, SigIndex, Type, Value}, + vm::{self, ImportBacking}, }; #[repr(C)] @@ -155,7 +158,7 @@ pub struct LLVMBackend { } impl LLVMBackend { - pub fn new(module: Module, intrinsics: Intrinsics) -> Self { + pub fn new(module: Module, intrinsics: Intrinsics) -> (Self, LLVMProtectedCaller) { Target::initialize_x86(&InitializationConfig { asm_parser: true, asm_printer: true, @@ -198,10 +201,13 @@ impl LLVMBackend { panic!("failed to load object") } - Self { - module, - memory_buffer, - } + ( + Self { + module, + memory_buffer, + }, + LLVMProtectedCaller { module }, + ) } pub fn get_func( @@ -239,6 +245,137 @@ impl FuncResolver for LLVMBackend { } } +struct Placeholder; + +unsafe impl Send for LLVMProtectedCaller {} +unsafe impl Sync for LLVMProtectedCaller {} + +pub struct LLVMProtectedCaller { + module: *mut LLVMModule, +} + +impl ProtectedCaller for LLVMProtectedCaller { + fn call( + &self, + module: &ModuleInner, + func_index: FuncIndex, + params: &[Value], + import_backing: &ImportBacking, + vmctx: *mut vm::Ctx, + _: Token, + ) -> RuntimeResult> { + let (func_ptr, ctx, signature, sig_index) = + get_func_from_index(&module, import_backing, func_index); + + let vmctx_ptr = match ctx { + Context::External(external_vmctx) => external_vmctx, + Context::Internal => vmctx, + }; + + assert!( + signature.returns().len() <= 1, + "multi-value returns not yet supported" + ); + + assert!( + signature.check_param_value_types(params), + "incorrect signature" + ); + + let param_vec: Vec = params + .iter() + .map(|val| match val { + Value::I32(x) => *x as u64, + Value::I64(x) => *x as u64, + Value::F32(x) => x.to_bits() as u64, + Value::F64(x) => x.to_bits(), + }) + .collect(); + + let mut return_vec = vec![0; signature.returns().len()]; + + let trampoline: unsafe extern "C" fn(*mut vm::Ctx, *const vm::Func, *const u64, *mut u64) = unsafe { + let name = if cfg!(target_os = "macos") { + format!("_trmp{}", sig_index.index()) + } else { + format!("trmp{}", sig_index.index()) + }; + + let c_str = CString::new(name).unwrap(); + let symbol = get_func_symbol(self.module, c_str.as_ptr()); + assert!(!symbol.is_null()); + + mem::transmute(symbol) + }; + + // Here we go. + unsafe { + trampoline( + vmctx_ptr, + func_ptr, + param_vec.as_ptr(), + return_vec.as_mut_ptr(), + ); + } + + Ok(return_vec + .iter() + .zip(signature.returns().iter()) + .map(|(&x, ty)| match ty { + Type::I32 => Value::I32(x as i32), + Type::I64 => Value::I64(x as i64), + Type::F32 => Value::F32(f32::from_bits(x as u32)), + Type::F64 => Value::F64(f64::from_bits(x as u64)), + }) + .collect()) + } + + fn get_early_trapper(&self) -> Box { + Box::new(Placeholder) + } +} + +impl UserTrapper for Placeholder { + unsafe fn do_early_trap(&self, msg: String) -> ! { + unimplemented!("do early trap: {}", msg) + } +} + +fn get_func_from_index<'a>( + module: &'a ModuleInner, + import_backing: &ImportBacking, + func_index: FuncIndex, +) -> (*const vm::Func, Context, &'a FuncSig, SigIndex) { + let sig_index = *module + .info + .func_assoc + .get(func_index) + .expect("broken invariant, incorrect func index"); + + let (func_ptr, ctx) = match func_index.local_or_import(&module.info) { + LocalOrImport::Local(local_func_index) => ( + module + .func_resolver + .get(&module, local_func_index) + .expect("broken invariant, func resolver not synced with module.exports") + .cast() + .as_ptr() as *const _, + Context::Internal, + ), + LocalOrImport::Import(imported_func_index) => { + let imported_func = import_backing.imported_func(imported_func_index); + ( + imported_func.func as *const _, + Context::External(imported_func.vmctx), + ) + } + }; + + let signature = &module.info.signatures[sig_index]; + + (func_ptr, ctx, signature, sig_index) +} + unsafe fn disass_ptr(ptr: *const u8, size: usize, inst_count: usize) { use capstone::arch::BuildsCapstone; let mut cs = capstone::Capstone::new() // Call builder-pattern diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index 3b72dd309..dd7ec30c7 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -24,6 +24,7 @@ use wasmparser::{ use crate::intrinsics::{CtxType, GlobalCache, Intrinsics}; use crate::read_info::type_to_type; use crate::state::{ControlFrame, IfElseState, State}; +use crate::trampolines::generate_trampolines; fn func_sig_to_llvm(context: &Context, intrinsics: &Intrinsics, sig: &FuncSig) -> FunctionType { let user_param_types = sig.params().iter().map(|&ty| type_to_llvm(intrinsics, ty)); @@ -102,10 +103,19 @@ pub fn parse_function_bodies( LocalFuncIndex::new(local_func_index), locals_reader, op_reader, - )?; + ) + .map_err(|e| BinaryReaderError { + message: e.message, + offset: local_func_index, + })?; } + // module.print_to_stderr(); + + generate_trampolines(info, &signatures, &module, &context, &builder, &intrinsics); + let pass_manager = PassManager::create_for_module(); + pass_manager.add_verifier_pass(); pass_manager.add_function_inlining_pass(); pass_manager.add_promote_memory_to_register_pass(); pass_manager.add_cfg_simplification_pass(); @@ -116,7 +126,6 @@ pub fn parse_function_bodies( pass_manager.add_gvn_pass(); // pass_manager.add_new_gvn_pass(); pass_manager.add_aggressive_dce_pass(); - // pass_manager.add_verifier_pass(); pass_manager.run_on_module(&module); Ok((module, intrinsics)) @@ -209,8 +218,34 @@ fn parse_function( locals.push(alloca); } + let mut unreachable_depth = 0; + for op in op_reader { - match op? { + let op = op?; + if !state.reachable { + match op { + Operator::Block { ty: _ } | Operator::Loop { ty: _ } | Operator::If { ty: _ } => { + unreachable_depth += 1; + continue; + } + Operator::Else => { + if unreachable_depth != 0 { + continue; + } + } + Operator::End => { + if unreachable_depth != 0 { + unreachable_depth -= 1; + continue; + } + } + _ => { + continue; + } + } + } + + match op { /*************************** * Control Flow instructions. * https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#control-flow-instructions @@ -356,7 +391,7 @@ fn parse_function( builder.build_switch(index.into_int_value(), default_frame.br_dest(), &cases[..]); state.popn(res_len)?; - builder.build_unreachable(); + state.reachable = false; } Operator::If { ty } => { let current_block = builder.get_insert_block().ok_or(BinaryReaderError { @@ -440,8 +475,22 @@ fn parse_function( builder.build_unconditional_branch(frame.code_after()); for phi in frame.phis().iter().rev() { - let value = state.pop1()?; - phi.add_incoming(&[(&value, ¤t_block)]) + if phi.count_incoming() != 0 { + let value = state.pop1()?; + phi.add_incoming(&[(&value, ¤t_block)]) + } else { + let basic_ty = phi.as_basic_value().get_type(); + let placeholder_value = match basic_ty { + BasicTypeEnum::IntType(int_ty) => { + int_ty.const_int(0, false).as_basic_value_enum() + } + BasicTypeEnum::FloatType(float_ty) => { + float_ty.const_float(0.0).as_basic_value_enum() + } + _ => unimplemented!(), + }; + phi.add_incoming(&[(&placeholder_value, ¤t_block)]); + } } } @@ -466,13 +515,40 @@ fn parse_function( // Push each phi value to the value stack. for phi in frame.phis() { - state.push1(phi.as_basic_value()); + if phi.count_incoming() != 0 { + state.push1(phi.as_basic_value()); + } else { + let basic_ty = phi.as_basic_value().get_type(); + let placeholder_value = match basic_ty { + BasicTypeEnum::IntType(int_ty) => { + int_ty.const_int(0, false).as_basic_value_enum() + } + BasicTypeEnum::FloatType(float_ty) => { + float_ty.const_float(0.0).as_basic_value_enum() + } + _ => unimplemented!(), + }; + state.push1(placeholder_value); + phi.as_instruction().erase_from_basic_block(); + } } } Operator::Return => { let frame = state.outermost_frame()?; + let current_block = builder.get_insert_block().ok_or(BinaryReaderError { + message: "not currently in a block", + offset: -1isize as usize, + })?; builder.build_unconditional_branch(frame.br_dest()); + + let phis = frame.phis().to_vec(); + + for phi in phis.iter() { + let arg = state.pop1()?; + phi.add_incoming(&[(&arg, ¤t_block)]); + } + state.reachable = false; } @@ -508,7 +584,7 @@ fn parse_function( Operator::F32Const { value } => { let f = intrinsics .f32_ty - .const_float(f64::from_bits(value.bits() as u64)); + .const_float(f32::from_bits(value.bits()) as f64); state.push1(f); } Operator::F64Const { value } => { @@ -562,15 +638,20 @@ fn parse_function( Operator::Select => { let (v1, v2, cond) = state.pop3()?; - let cond = cond.into_int_value(); - let res = builder.build_select(cond, v1, v2, &state.var_name()); + let cond_value = builder.build_int_compare( + IntPredicate::NE, + cond.into_int_value(), + intrinsics.i32_zero, + &state.var_name(), + ); + let res = builder.build_select(cond_value, v1, v2, &state.var_name()); state.push1(res); } Operator::Call { function_index } => { let func_index = FuncIndex::new(function_index as usize); let sigindex = info.func_assoc[func_index]; let llvm_sig = signatures[sigindex]; - let func_sig = &info.signatures[sig_index]; + let func_sig = &info.signatures[sigindex]; let call_site = match func_index.local_or_import(info) { LocalOrImport::Local(local_func_index) => { @@ -710,7 +791,6 @@ fn parse_function( let args: Vec<_> = std::iter::once(ctx_ptr) .chain(pushed_args.into_iter()) .collect(); - println!("args: {:?}", args); let typed_func_ptr = builder.build_pointer_cast( func_ptr, @@ -948,22 +1028,24 @@ fn parse_function( } Operator::I32Eqz => { let input = state.pop1()?.into_int_value(); - let res = builder.build_int_compare( + let cond = builder.build_int_compare( IntPredicate::EQ, input, intrinsics.i32_zero, &state.var_name(), ); + let res = builder.build_int_z_extend(cond, intrinsics.i32_ty, &state.var_name()); state.push1(res); } Operator::I64Eqz => { let input = state.pop1()?.into_int_value(); - let res = builder.build_int_compare( + let cond = builder.build_int_compare( IntPredicate::EQ, input, intrinsics.i64_zero, &state.var_name(), ); + let res = builder.build_int_z_extend(cond, intrinsics.i32_ty, &state.var_name()); state.push1(res); } @@ -1170,61 +1252,71 @@ fn parse_function( Operator::I32Eq | Operator::I64Eq => { let (v1, v2) = state.pop2()?; let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); - let res = builder.build_int_compare(IntPredicate::EQ, v1, v2, &state.var_name()); + let cond = builder.build_int_compare(IntPredicate::EQ, v1, v2, &state.var_name()); + let res = builder.build_int_z_extend(cond, intrinsics.i32_ty, &state.var_name()); state.push1(res); } Operator::I32Ne | Operator::I64Ne => { let (v1, v2) = state.pop2()?; let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); - let res = builder.build_int_compare(IntPredicate::NE, v1, v2, &state.var_name()); + let cond = builder.build_int_compare(IntPredicate::NE, v1, v2, &state.var_name()); + let res = builder.build_int_z_extend(cond, intrinsics.i32_ty, &state.var_name()); state.push1(res); } Operator::I32LtS | Operator::I64LtS => { let (v1, v2) = state.pop2()?; let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); - let res = builder.build_int_compare(IntPredicate::SLT, v1, v2, &state.var_name()); + let cond = builder.build_int_compare(IntPredicate::SLT, v1, v2, &state.var_name()); + let res = builder.build_int_z_extend(cond, intrinsics.i32_ty, &state.var_name()); state.push1(res); } Operator::I32LtU | Operator::I64LtU => { let (v1, v2) = state.pop2()?; let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); - let res = builder.build_int_compare(IntPredicate::ULT, v1, v2, &state.var_name()); + let cond = builder.build_int_compare(IntPredicate::ULT, v1, v2, &state.var_name()); + let res = builder.build_int_z_extend(cond, intrinsics.i32_ty, &state.var_name()); state.push1(res); } Operator::I32LeS | Operator::I64LeS => { let (v1, v2) = state.pop2()?; let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); - let res = builder.build_int_compare(IntPredicate::SLE, v1, v2, &state.var_name()); + let cond = builder.build_int_compare(IntPredicate::SLE, v1, v2, &state.var_name()); + let res = builder.build_int_z_extend(cond, intrinsics.i32_ty, &state.var_name()); state.push1(res); } Operator::I32LeU | Operator::I64LeU => { let (v1, v2) = state.pop2()?; let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); - let res = builder.build_int_compare(IntPredicate::ULE, v1, v2, &state.var_name()); + let cond = builder.build_int_compare(IntPredicate::ULE, v1, v2, &state.var_name()); + let res = builder.build_int_z_extend(cond, intrinsics.i32_ty, &state.var_name()); state.push1(res); } Operator::I32GtS | Operator::I64GtS => { let (v1, v2) = state.pop2()?; let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); - let res = builder.build_int_compare(IntPredicate::SGT, v1, v2, &state.var_name()); + let cond = builder.build_int_compare(IntPredicate::SGT, v1, v2, &state.var_name()); + let res = builder.build_int_z_extend(cond, intrinsics.i32_ty, &state.var_name()); state.push1(res); } Operator::I32GtU | Operator::I64GtU => { let (v1, v2) = state.pop2()?; let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); - let res = builder.build_int_compare(IntPredicate::UGT, v1, v2, &state.var_name()); + let cond = builder.build_int_compare(IntPredicate::UGT, v1, v2, &state.var_name()); + let res = builder.build_int_z_extend(cond, intrinsics.i32_ty, &state.var_name()); state.push1(res); } Operator::I32GeS | Operator::I64GeS => { let (v1, v2) = state.pop2()?; let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); - let res = builder.build_int_compare(IntPredicate::SGE, v1, v2, &state.var_name()); + let cond = builder.build_int_compare(IntPredicate::SGE, v1, v2, &state.var_name()); + let res = builder.build_int_z_extend(cond, intrinsics.i32_ty, &state.var_name()); state.push1(res); } Operator::I32GeU | Operator::I64GeU => { let (v1, v2) = state.pop2()?; let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); - let res = builder.build_int_compare(IntPredicate::UGE, v1, v2, &state.var_name()); + let cond = builder.build_int_compare(IntPredicate::UGE, v1, v2, &state.var_name()); + let res = builder.build_int_z_extend(cond, intrinsics.i32_ty, &state.var_name()); state.push1(res); } @@ -1235,43 +1327,49 @@ fn parse_function( Operator::F32Eq | Operator::F64Eq => { let (v1, v2) = state.pop2()?; let (v1, v2) = (v1.into_float_value(), v2.into_float_value()); - let res = + let cond = builder.build_float_compare(FloatPredicate::OEQ, v1, v2, &state.var_name()); + let res = builder.build_int_z_extend(cond, intrinsics.i32_ty, &state.var_name()); state.push1(res); } Operator::F32Ne | Operator::F64Ne => { let (v1, v2) = state.pop2()?; let (v1, v2) = (v1.into_float_value(), v2.into_float_value()); - let res = + let cond = builder.build_float_compare(FloatPredicate::UNE, v1, v2, &state.var_name()); + let res = builder.build_int_z_extend(cond, intrinsics.i32_ty, &state.var_name()); state.push1(res); } Operator::F32Lt | Operator::F64Lt => { let (v1, v2) = state.pop2()?; let (v1, v2) = (v1.into_float_value(), v2.into_float_value()); - let res = + let cond = builder.build_float_compare(FloatPredicate::OLT, v1, v2, &state.var_name()); + let res = builder.build_int_z_extend(cond, intrinsics.i32_ty, &state.var_name()); state.push1(res); } Operator::F32Le | Operator::F64Le => { let (v1, v2) = state.pop2()?; let (v1, v2) = (v1.into_float_value(), v2.into_float_value()); - let res = + let cond = builder.build_float_compare(FloatPredicate::OLE, v1, v2, &state.var_name()); + let res = builder.build_int_z_extend(cond, intrinsics.i32_ty, &state.var_name()); state.push1(res); } Operator::F32Gt | Operator::F64Gt => { let (v1, v2) = state.pop2()?; let (v1, v2) = (v1.into_float_value(), v2.into_float_value()); - let res = + let cond = builder.build_float_compare(FloatPredicate::OGT, v1, v2, &state.var_name()); + let res = builder.build_int_z_extend(cond, intrinsics.i32_ty, &state.var_name()); state.push1(res); } Operator::F32Ge | Operator::F64Ge => { let (v1, v2) = state.pop2()?; let (v1, v2) = (v1.into_float_value(), v2.into_float_value()); - let res = + let cond = builder.build_float_compare(FloatPredicate::OGE, v1, v2, &state.var_name()); + let res = builder.build_int_z_extend(cond, intrinsics.i32_ty, &state.var_name()); state.push1(res); } @@ -1816,9 +1914,5 @@ fn resolve_memory_ptr( let mem_base_int = builder.build_ptr_to_int(mem_base, intrinsics.i64_ty, &state.var_name()); let effective_address_int = builder.build_int_add(mem_base_int, effective_offset, &state.var_name()); - Ok(builder.build_int_to_ptr( - effective_address_int, - intrinsics.i32_ptr_ty, - &state.var_name(), - )) + Ok(builder.build_int_to_ptr(effective_address_int, ptr_ty, &state.var_name())) } diff --git a/lib/llvm-backend/src/intrinsics.rs b/lib/llvm-backend/src/intrinsics.rs index f2ec8fd05..97af89a5b 100644 --- a/lib/llvm-backend/src/intrinsics.rs +++ b/lib/llvm-backend/src/intrinsics.rs @@ -639,7 +639,6 @@ impl<'a> CtxType<'a> { let int = builder.build_ptr_to_int(global_ptr, intrinsics.i64_ty, "global_ptr_int"); builder.build_int_to_ptr(int, llvm_ptr_ty, "global_ptr_typed") }; - println!("global_ptr: {:?}", global_ptr_typed); if mutable { GlobalCache::Mut { diff --git a/lib/llvm-backend/src/lib.rs b/lib/llvm-backend/src/lib.rs index 66d8e5753..f46520383 100644 --- a/lib/llvm-backend/src/lib.rs +++ b/lib/llvm-backend/src/lib.rs @@ -9,12 +9,14 @@ use wasmer_runtime_core::{ error::CompileError, module::ModuleInner, }; +use wasmparser::{self, WasmDecoder}; mod backend; mod code; mod intrinsics; mod read_info; mod state; +mod trampolines; pub struct LLVMCompiler { _private: (), @@ -28,13 +30,15 @@ impl LLVMCompiler { impl Compiler for LLVMCompiler { fn compile(&self, wasm: &[u8], _: Token) -> Result { + validate(wasm)?; + let (info, code_reader) = read_info::read_module(wasm).unwrap(); let (module, intrinsics) = code::parse_function_bodies(&info, code_reader).unwrap(); - let backend = backend::LLVMBackend::new(module, intrinsics); + let (backend, protected_caller) = backend::LLVMBackend::new(module, intrinsics); // Create placeholder values here. - let (protected_caller, cache_gen) = { + let cache_gen = { use wasmer_runtime_core::backend::{ sys::Memory, CacheGen, ProtectedCaller, UserTrapper, }; @@ -44,22 +48,6 @@ impl Compiler for LLVMCompiler { use wasmer_runtime_core::types::{FuncIndex, Value}; use wasmer_runtime_core::vm; struct Placeholder; - impl ProtectedCaller for Placeholder { - fn call( - &self, - _module: &ModuleInner, - _func_index: FuncIndex, - _params: &[Value], - _import_backing: &vm::ImportBacking, - _vmctx: *mut vm::Ctx, - _: Token, - ) -> RuntimeResult> { - unimplemented!("the llvm-based backend does not yet implement ProtectedCaller") - } - fn get_early_trapper(&self) -> Box { - Box::new(Placeholder) - } - } impl CacheGen for Placeholder { fn generate_cache( &self, @@ -68,18 +56,13 @@ impl Compiler for LLVMCompiler { unimplemented!() } } - impl UserTrapper for Placeholder { - unsafe fn do_early_trap(&self, msg: String) -> ! { - unimplemented!("do early trap: {}", msg) - } - } - (Box::new(Placeholder), Box::new(Placeholder)) + Box::new(Placeholder) }; Ok(ModuleInner { func_resolver: Box::new(backend), - protected_caller, + protected_caller: Box::new(protected_caller), cache_gen, info, @@ -91,6 +74,20 @@ impl Compiler for LLVMCompiler { } } +fn validate(bytes: &[u8]) -> Result<(), CompileError> { + let mut parser = wasmparser::ValidatingParser::new(bytes, None); + loop { + let state = parser.read(); + match *state { + wasmparser::ParserState::EndWasm => break Ok(()), + wasmparser::ParserState::Error(err) => Err(CompileError::ValidationError { + msg: err.message.to_string(), + })?, + _ => {} + } + } +} + #[test] fn test_read_module() { use std::mem::transmute; diff --git a/lib/llvm-backend/src/trampolines.rs b/lib/llvm-backend/src/trampolines.rs index 34ce9eb15..4619cb990 100644 --- a/lib/llvm-backend/src/trampolines.rs +++ b/lib/llvm-backend/src/trampolines.rs @@ -1,3 +1,4 @@ +use crate::intrinsics::Intrinsics; use inkwell::{ builder::Builder, context::Context, @@ -9,30 +10,111 @@ use inkwell::{ }; use wasmer_runtime_core::{ module::ModuleInfo, - types::{SigIndex, FuncSig}, - structures::{TypedIndex, SliceMap}, + structures::{SliceMap, TypedIndex}, + types::{FuncSig, SigIndex, Type}, }; -use crate::intrinsics::Intrinsics; - -pub fn generate_trampolines(info: &ModuleInfo, signatures: &SliceMap, module: &Module, builder: &Builder, intrinsics: &Intrinsics) -> Result<(), String> { - let trampoline_sig = intrinsics.void_ty.fn_type(&[ - intrinsics.ctx_ptr_ty, // vmctx ptr - intrinsics.i64_ptr_ty, // func ptr - intrinsics.i64_ptr_ty, - intrinsics.i64_ptr_ty, - ], false); +pub fn generate_trampolines( + info: &ModuleInfo, + signatures: &SliceMap, + module: &Module, + context: &Context, + builder: &Builder, + intrinsics: &Intrinsics, +) { for (sig_index, sig) in info.signatures.iter() { + let func_type = signatures[sig_index]; + let trampoline_sig = intrinsics.void_ty.fn_type( + &[ + intrinsics.ctx_ptr_ty.as_basic_type_enum(), // vmctx ptr + func_type + .ptr_type(AddressSpace::Generic) + .as_basic_type_enum(), // func ptr + intrinsics.i64_ptr_ty.as_basic_type_enum(), // args ptr + intrinsics.i64_ptr_ty.as_basic_type_enum(), // returns ptr + ], + false, + ); + + let trampoline_func = module.add_function( + &format!("trmp{}", sig_index.index()), + trampoline_sig, + Some(Linkage::External), + ); + + generate_trampoline( + trampoline_func, + func_type, + sig, + context, + builder, + intrinsics, + ); } } -pub fn generate_trampoline(sig_index: usize, trampoline_sig: FunctionType, sig: &FuncSig, builder: &Builder, intrinsics: &Intrinsics) { - let function = module.add_function( - &format!("tramp{}", sig_index.index()), - signatures[sig_index], - Some(Linkage::External), - ); +fn generate_trampoline( + trampoline_func: FunctionValue, + sig_type: FunctionType, + func_sig: &FuncSig, + context: &Context, + builder: &Builder, + intrinsics: &Intrinsics, +) { + let entry_block = context.append_basic_block(&trampoline_func, "entry"); + builder.position_at_end(&entry_block); + let (vmctx_ptr, func_ptr, args_ptr, returns_ptr) = match trampoline_func.get_params().as_slice() + { + &[vmctx_ptr, func_ptr, args_ptr, returns_ptr] => ( + vmctx_ptr, + func_ptr.into_pointer_value(), + args_ptr.into_pointer_value(), + returns_ptr.into_pointer_value(), + ), + _ => unimplemented!(), + }; -} \ No newline at end of file + let cast_ptr_ty = |wasmer_ty| match wasmer_ty { + Type::I32 => intrinsics.i32_ptr_ty, + Type::I64 => intrinsics.i64_ptr_ty, + Type::F32 => intrinsics.f32_ptr_ty, + Type::F64 => intrinsics.f64_ptr_ty, + }; + + let mut args_vec = Vec::with_capacity(func_sig.params().len() + 1); + args_vec.push(vmctx_ptr); + + for (i, param_ty) in func_sig.params().iter().enumerate() { + let index = intrinsics.i32_ty.const_int(i as _, false); + let item_pointer = unsafe { builder.build_in_bounds_gep(args_ptr, &[index], "arg_ptr") }; + + let casted_pointer_type = cast_ptr_ty(*param_ty); + + let typed_item_pointer = + builder.build_pointer_cast(item_pointer, casted_pointer_type, "typed_arg_pointer"); + + let arg = builder.build_load(typed_item_pointer, "arg"); + args_vec.push(arg); + } + + let call_site = builder.build_call(func_ptr, &args_vec, "call"); + + match func_sig.returns() { + &[] => {} + &[one_ret] => { + let ret_ptr_type = cast_ptr_ty(one_ret); + + let typed_ret_ptr = + builder.build_pointer_cast(returns_ptr, ret_ptr_type, "typed_ret_ptr"); + builder.build_store( + typed_ret_ptr, + call_site.try_as_basic_value().left().unwrap(), + ); + } + _ => unimplemented!("multi-value returns"), + } + + builder.build_return(None); +} diff --git a/lib/runtime-core/src/instance.rs b/lib/runtime-core/src/instance.rs index 6a4d5d438..61e8f556d 100644 --- a/lib/runtime-core/src/instance.rs +++ b/lib/runtime-core/src/instance.rs @@ -454,7 +454,7 @@ impl<'a> DynFunc<'a> { /// # Ok(()) /// # } /// ``` - pub fn call(&mut self, params: &[Value]) -> CallResult> { + pub fn call(&self, params: &[Value]) -> CallResult> { if !self.signature.check_param_value_types(params) { Err(ResolveError::Signature { expected: (*self.signature).clone(), diff --git a/lib/runtime/examples/call.rs b/lib/runtime/examples/call.rs index 6015a4bb1..d583f8a2f 100644 --- a/lib/runtime/examples/call.rs +++ b/lib/runtime/examples/call.rs @@ -1,23 +1,16 @@ -use wasmer_runtime::{compile, error, imports, Func}; +use wasmer_runtime::{compile, error, imports, Func, Value}; use wabt::wat2wasm; static WAT: &'static str = r#" (module - (type $t0 (func (param i32) (result i32))) - (type $t1 (func (result i32))) - (memory 1) - (global $g0 (mut i32) (i32.const 0)) - (export "foo" (func $foo)) - (func $foo (type $t0) (param i32) (result i32) - get_local 0 - call $bar - ) - (func $bar (type $t0) (param i32) (result i32) - get_local 0 - i32.const 10 - i32.add - ) + (type (;0;) (func (result i32))) + (func (;0;) (type 0) (result i32) + block (result i32) ;; label = @1 + i32.const 1 + end + return) + (export "as-return-value" (func 0)) ) "#; @@ -32,11 +25,12 @@ fn main() -> Result<(), error::Error> { let imports = imports! {}; + println!("instantiating"); let instance = module.instantiate(&imports)?; - let foo: Func = instance.func("foo")?; + let foo = instance.dyn_func("as-call-value")?; - let result = foo.call(42); + let result = foo.call(&[]); println!("result: {:?}", result); From f0ac76517a9a39c5b016db3315eb5a4f98707f34 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Fri, 1 Mar 2019 17:11:20 -0800 Subject: [PATCH 146/262] Start running spectests Additional info: - Execution is turned off, this is just to make sure the backend can compile the entire specsuite. - That being said, trampolines are implemented and protected call works (just doesn't protect). --- lib/llvm-backend/cpp/object_loader.cpp | 8 +++-- lib/llvm-backend/cpp/object_loader.hh | 2 +- lib/llvm-backend/src/backend.rs | 33 +++++++++++++++++-- lib/llvm-backend/src/code.rs | 44 ++++++++++---------------- lib/llvm-backend/src/intrinsics.rs | 8 ++--- 5 files changed, 57 insertions(+), 38 deletions(-) diff --git a/lib/llvm-backend/cpp/object_loader.cpp b/lib/llvm-backend/cpp/object_loader.cpp index 9d1d8c731..3c36707c5 100644 --- a/lib/llvm-backend/cpp/object_loader.cpp +++ b/lib/llvm-backend/cpp/object_loader.cpp @@ -117,6 +117,8 @@ private: struct SymbolLookup : llvm::JITSymbolResolver { public: + SymbolLookup(callbacks_t callbacks) : callbacks(callbacks) {} + virtual llvm::Expected lookup(const LookupSet& symbols) override { LookupResult result; @@ -140,10 +142,12 @@ public: private: llvm::JITEvaluatedSymbol symbol_lookup(llvm::StringRef name) { std::cout << "symbol name: " << (std::string)name << std::endl; - uint64_t addr = 0; + uint64_t addr = callbacks.lookup_vm_symbol(name.data(), name.size()); return llvm::JITEvaluatedSymbol(addr, llvm::JITSymbolFlags::None); } + + callbacks_t callbacks; }; WasmModule::WasmModule( @@ -156,7 +160,7 @@ WasmModule::WasmModule( llvm::StringRef((const char *)object_start, object_size), "object" ))); - SymbolLookup symbol_resolver; + SymbolLookup symbol_resolver(callbacks); runtime_dyld = std::unique_ptr(new llvm::RuntimeDyld(*memory_manager, symbol_resolver)); runtime_dyld->setProcessAllSections(true); diff --git a/lib/llvm-backend/cpp/object_loader.hh b/lib/llvm-backend/cpp/object_loader.hh index 969f16150..8134385fd 100644 --- a/lib/llvm-backend/cpp/object_loader.hh +++ b/lib/llvm-backend/cpp/object_loader.hh @@ -20,7 +20,7 @@ typedef enum { typedef result_t (*alloc_memory_t)(size_t size, mem_protect_t protect, uint8_t** ptr_out, size_t* size_out); typedef result_t (*protect_memory_t)(uint8_t* ptr, size_t size, mem_protect_t protect); typedef result_t (*dealloc_memory_t)(uint8_t* ptr, size_t size); -typedef uintptr_t (*lookup_vm_symbol_t)(char* name_ptr); +typedef uintptr_t (*lookup_vm_symbol_t)(const char* name_ptr, size_t length); typedef struct { /* Memory management. */ diff --git a/lib/llvm-backend/src/backend.rs b/lib/llvm-backend/src/backend.rs index 98b0bc6e0..5b9299ce9 100644 --- a/lib/llvm-backend/src/backend.rs +++ b/lib/llvm-backend/src/backend.rs @@ -13,6 +13,7 @@ use std::{ ffi::CString, mem, ptr::{self, NonNull}, + slice, str, }; use wasmer_runtime_core::{ backend::{FuncResolver, ProtectedCaller, Token, UserTrapper}, @@ -22,6 +23,7 @@ use wasmer_runtime_core::{ structures::TypedIndex, types::{FuncIndex, FuncSig, LocalFuncIndex, LocalOrImport, SigIndex, Type, Value}, vm::{self, ImportBacking}, + vmcalls, }; #[repr(C)] @@ -56,7 +58,7 @@ struct Callbacks { protect_memory: extern "C" fn(*mut u8, usize, MemProtect) -> LLVMResult, dealloc_memory: extern "C" fn(*mut u8, usize) -> LLVMResult, - lookup_vm_symbol: extern "C" fn(*const c_char) -> *const vm::Func, + lookup_vm_symbol: extern "C" fn(*const c_char, usize) -> *const vm::Func, } extern "C" { @@ -136,8 +138,31 @@ fn get_callbacks() -> Callbacks { } } - extern "C" fn lookup_vm_symbol(_name_ptr: *const c_char) -> *const vm::Func { - ptr::null() + extern "C" fn lookup_vm_symbol(name_ptr: *const c_char, length: usize) -> *const vm::Func { + #[cfg(target_os = "macos")] + macro_rules! fn_name { + ($s:literal) => { + concat!("_", $s) + }; + } + + #[cfg(not(target_os = "macos"))] + macro_rules! fn_name { + ($s:literal) => { + $s + }; + } + + let name_slice = unsafe { slice::from_raw_parts(name_ptr as *const u8, length) }; + let name = str::from_utf8(name_slice).unwrap(); + + match name { + fn_name!("vm.memory.grow.dynamic.local") => vmcalls::local_dynamic_memory_grow as _, + fn_name!("vm.memory.size.dynamic.local") => vmcalls::local_dynamic_memory_size as _, + fn_name!("vm.memory.grow.static.local") => vmcalls::local_static_memory_grow as _, + fn_name!("vm.memory.size.static.local") => vmcalls::local_static_memory_size as _, + _ => ptr::null(), + } } Callbacks { @@ -241,6 +266,7 @@ impl FuncResolver for LLVMBackend { module: &ModuleInner, local_func_index: LocalFuncIndex, ) -> Option> { + unimplemented!(); self.get_func(&module.info, local_func_index) } } @@ -264,6 +290,7 @@ impl ProtectedCaller for LLVMProtectedCaller { vmctx: *mut vm::Ctx, _: Token, ) -> RuntimeResult> { + unimplemented!(); let (func_ptr, ctx, signature, sig_index) = get_func_from_index(&module, import_backing, func_index); diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index dd7ec30c7..aeb050cd5 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -110,7 +110,7 @@ pub fn parse_function_bodies( })?; } - // module.print_to_stderr(); + module.print_to_stderr(); generate_trampolines(info, &signatures, &module, &context, &builder, &intrinsics); @@ -475,22 +475,8 @@ fn parse_function( builder.build_unconditional_branch(frame.code_after()); for phi in frame.phis().iter().rev() { - if phi.count_incoming() != 0 { - let value = state.pop1()?; - phi.add_incoming(&[(&value, ¤t_block)]) - } else { - let basic_ty = phi.as_basic_value().get_type(); - let placeholder_value = match basic_ty { - BasicTypeEnum::IntType(int_ty) => { - int_ty.const_int(0, false).as_basic_value_enum() - } - BasicTypeEnum::FloatType(float_ty) => { - float_ty.const_float(0.0).as_basic_value_enum() - } - _ => unimplemented!(), - }; - phi.add_incoming(&[(&placeholder_value, ¤t_block)]); - } + let value = state.pop1()?; + phi.add_incoming(&[(&value, ¤t_block)]); } } @@ -558,6 +544,7 @@ fn parse_function( // it will emit a `ud2` instruction on x86_64 arches. ctx.build_trap(); builder.build_unreachable(); + state.reachable = false; } @@ -747,12 +734,13 @@ fn parse_function( ) }; - let sigindices_equal = builder.build_int_compare( - IntPredicate::EQ, - expected_dynamic_sigindex, - found_dynamic_sigindex, - "sigindices_equal", - ); + // let sigindices_equal = builder.build_int_compare( + // IntPredicate::EQ, + // expected_dynamic_sigindex, + // found_dynamic_sigindex, + // "sigindices_equal", + // ); + let sigindices_equal = intrinsics.i1_ty.const_int(1, false); // Tell llvm that `expected_dynamic_sigindex` should equal `found_dynamic_sigindex`. let sigindices_equal = builder @@ -1227,18 +1215,18 @@ fn parse_function( state.push1(res); } Operator::F32Copysign => { - let input = state.pop1()?; + let (mag, sgn) = state.pop2()?; let res = builder - .build_call(intrinsics.copysign_f32, &[input], &state.var_name()) + .build_call(intrinsics.copysign_f32, &[mag, sgn], &state.var_name()) .try_as_basic_value() .left() .unwrap(); state.push1(res); } Operator::F64Copysign => { - let input = state.pop1()?; + let (msg, sgn) = state.pop2()?; let res = builder - .build_call(intrinsics.copysign_f64, &[input], &state.var_name()) + .build_call(intrinsics.copysign_f64, &[msg, sgn], &state.var_name()) .try_as_basic_value() .left() .unwrap(); @@ -1549,7 +1537,7 @@ fn parse_function( &mut state, &mut ctx, memarg, - intrinsics.i32_ptr_ty, + intrinsics.f32_ptr_ty, )?; let result = builder.build_load(effective_address, &state.var_name()); state.push1(result); diff --git a/lib/llvm-backend/src/intrinsics.rs b/lib/llvm-backend/src/intrinsics.rs index 97af89a5b..c3f2191f3 100644 --- a/lib/llvm-backend/src/intrinsics.rs +++ b/lib/llvm-backend/src/intrinsics.rs @@ -231,11 +231,11 @@ impl Intrinsics { sqrt_f32: module.add_function("llvm.sqrt.f32", ret_f32_take_f32, None), sqrt_f64: module.add_function("llvm.sqrt.f64", ret_f64_take_f64, None), - minimum_f32: module.add_function("llvm.minimum.f32", ret_f32_take_f32_f32, None), - minimum_f64: module.add_function("llvm.minimum.f64", ret_f64_take_f64_f64, None), + minimum_f32: module.add_function("llvm.minnum.f32", ret_f32_take_f32_f32, None), + minimum_f64: module.add_function("llvm.minnum.f64", ret_f64_take_f64_f64, None), - maximum_f32: module.add_function("llvm.maximum.f32", ret_f32_take_f32_f32, None), - maximum_f64: module.add_function("llvm.maximum.f64", ret_f64_take_f64_f64, None), + maximum_f32: module.add_function("llvm.maxnum.f32", ret_f32_take_f32_f32, None), + maximum_f64: module.add_function("llvm.maxnum.f64", ret_f64_take_f64_f64, None), ceil_f32: module.add_function("llvm.ceil.f32", ret_f32_take_f32, None), ceil_f64: module.add_function("llvm.ceil.f64", ret_f64_take_f64, None), From 362e5aa160137c0e9226dab111521aef7dd9a480 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Fri, 1 Mar 2019 20:23:21 -0800 Subject: [PATCH 147/262] Fix issue caused by dangling instruction. - Come on inkwell, I thought you were better than this. --- lib/llvm-backend/src/code.rs | 35 +++++++++++++++++------------------ lib/runtime/examples/call.rs | 15 ++++++--------- 2 files changed, 23 insertions(+), 27 deletions(-) diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index aeb050cd5..7a0587a15 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -110,8 +110,6 @@ pub fn parse_function_bodies( })?; } - module.print_to_stderr(); - generate_trampolines(info, &signatures, &module, &context, &builder, &intrinsics); let pass_manager = PassManager::create_for_module(); @@ -161,22 +159,6 @@ fn parse_function( .map(|ty| builder.build_phi(ty, &state.var_name())) .collect(); - match phis.as_slice() { - // No returns. - &[] => { - builder.build_return(None); - } - &[one_value] => { - let value = one_value.as_basic_value(); - builder.build_return(Some(&value)); - } - returns @ _ => { - // let struct_ty = llvm_sig.get_return_type().as_struct_type(); - // let ret_struct = struct_ty.const_zero(); - unimplemented!("multi-value returns not yet implemented") - } - } - state.push_block(return_block, phis); builder.position_at_end(&entry_block); @@ -504,6 +486,7 @@ fn parse_function( if phi.count_incoming() != 0 { state.push1(phi.as_basic_value()); } else { + println!("replacing"); let basic_ty = phi.as_basic_value().get_type(); let placeholder_value = match basic_ty { BasicTypeEnum::IntType(int_ty) => { @@ -1881,6 +1864,22 @@ fn parse_function( } } + let results = state.popn_save(func_sig.returns().len())?; + + match results.as_slice() { + [] => { + builder.build_return(None); + } + [one_value] => { + builder.build_return(Some(one_value)); + } + returns @ _ => { + // let struct_ty = llvm_sig.get_return_type().as_struct_type(); + // let ret_struct = struct_ty.const_zero(); + unimplemented!("multi-value returns not yet implemented") + } + } + Ok(()) } diff --git a/lib/runtime/examples/call.rs b/lib/runtime/examples/call.rs index d583f8a2f..0684c1bb7 100644 --- a/lib/runtime/examples/call.rs +++ b/lib/runtime/examples/call.rs @@ -4,13 +4,10 @@ use wabt::wat2wasm; static WAT: &'static str = r#" (module - (type (;0;) (func (result i32))) - (func (;0;) (type 0) (result i32) - block (result i32) ;; label = @1 - i32.const 1 - end - return) - (export "as-return-value" (func 0)) + (type (;0;) (func (param i32) (result i32))) + (func (;0;) (type 0) (param i32) (result i32) + unreachable) + (export "select_trap_l" (func 0)) ) "#; @@ -28,9 +25,9 @@ fn main() -> Result<(), error::Error> { println!("instantiating"); let instance = module.instantiate(&imports)?; - let foo = instance.dyn_func("as-call-value")?; + let foo = instance.dyn_func("select_trap_l")?; - let result = foo.call(&[]); + let result = foo.call(&[Value::I32(0)]); println!("result: {:?}", result); From a6fc06c9081f69ee8d7f78e59fdd978a46fa52a4 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Sat, 2 Mar 2019 10:04:44 -0800 Subject: [PATCH 148/262] Fix more compiling issues Specifically: - Don't truncate the list of local parameters. - If the default destination in a br_table instruction is a loop, don't pop any results. --- lib/llvm-backend/src/backend.rs | 2 -- lib/llvm-backend/src/code.rs | 18 +++++++++++------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/lib/llvm-backend/src/backend.rs b/lib/llvm-backend/src/backend.rs index 5b9299ce9..a7d700e90 100644 --- a/lib/llvm-backend/src/backend.rs +++ b/lib/llvm-backend/src/backend.rs @@ -266,7 +266,6 @@ impl FuncResolver for LLVMBackend { module: &ModuleInner, local_func_index: LocalFuncIndex, ) -> Option> { - unimplemented!(); self.get_func(&module.info, local_func_index) } } @@ -290,7 +289,6 @@ impl ProtectedCaller for LLVMProtectedCaller { vmctx: *mut vm::Ctx, _: Token, ) -> RuntimeResult> { - unimplemented!(); let (func_ptr, ctx, signature, sig_index) = get_func_from_index(&module, import_backing, func_index); diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index 7a0587a15..2504d3977 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -179,14 +179,16 @@ fn parse_function( }), ); - for (index, local) in locals_reader.into_iter().enumerate().skip(locals.len()) { + let param_len = locals.len(); + + for (index, local) in locals_reader.into_iter().enumerate() { let (_, ty) = local?; let wasmer_ty = type_to_type(ty)?; let ty = type_to_llvm(intrinsics, wasmer_ty); - let alloca = builder.build_alloca(ty, &format!("local{}", index)); + let alloca = builder.build_alloca(ty, &format!("local{}", param_len + index)); let default_value = match wasmer_ty { Type::I32 => intrinsics.i32_zero.as_basic_value_enum(), @@ -346,9 +348,12 @@ fn parse_function( let default_frame = state.frame_at_depth(default_depth)?; - let res_len = default_frame.phis().len(); - - let args = state.peekn(res_len)?; + let args = if default_frame.is_loop() { + &[] + } else { + let res_len = default_frame.phis().len(); + state.peekn(res_len)? + }; for (phi, value) in default_frame.phis().iter().zip(args.iter()) { phi.add_incoming(&[(value, ¤t_block)]); @@ -372,7 +377,7 @@ fn parse_function( builder.build_switch(index.into_int_value(), default_frame.br_dest(), &cases[..]); - state.popn(res_len)?; + state.popn(args.len())?; state.reachable = false; } Operator::If { ty } => { @@ -486,7 +491,6 @@ fn parse_function( if phi.count_incoming() != 0 { state.push1(phi.as_basic_value()); } else { - println!("replacing"); let basic_ty = phi.as_basic_value().get_type(); let placeholder_value = match basic_ty { BasicTypeEnum::IntType(int_ty) => { From 87ddf4f8550225a68a04dc20b7ada85cc7d82baf Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Sat, 2 Mar 2019 10:20:18 -0800 Subject: [PATCH 149/262] Add personality function. - This is part of supporting exceptions in the future. --- lib/llvm-backend/src/code.rs | 14 ++++++++++++-- lib/runtime/examples/call.rs | 2 +- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index 2504d3977..a9170082b 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -68,6 +68,12 @@ pub fn parse_function_bodies( let intrinsics = Intrinsics::declare(&module, &context); + let personality_func = module.add_function( + "__gxx_personality_v0", + intrinsics.i32_ty.fn_type(&[], false), + Some(Linkage::External), + ); + let signatures: Map = info .signatures .iter() @@ -78,11 +84,13 @@ pub fn parse_function_bodies( .iter() .skip(info.imported_functions.len()) .map(|(func_index, &sig_index)| { - module.add_function( + let func = module.add_function( &format!("fn{}", func_index.index()), signatures[sig_index], Some(Linkage::External), - ) + ); + func.set_personality_function(personality_func); + func }) .collect(); @@ -110,6 +118,8 @@ pub fn parse_function_bodies( })?; } + module.print_to_stderr(); + generate_trampolines(info, &signatures, &module, &context, &builder, &intrinsics); let pass_manager = PassManager::create_for_module(); diff --git a/lib/runtime/examples/call.rs b/lib/runtime/examples/call.rs index 0684c1bb7..ac38b8d46 100644 --- a/lib/runtime/examples/call.rs +++ b/lib/runtime/examples/call.rs @@ -6,7 +6,7 @@ static WAT: &'static str = r#" (module (type (;0;) (func (param i32) (result i32))) (func (;0;) (type 0) (param i32) (result i32) - unreachable) + i32.const 42) (export "select_trap_l" (func 0)) ) "#; From 5760f6006ab38b3f0c7426e9e72b5e5a3b529f43 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Sat, 2 Mar 2019 10:56:02 -0800 Subject: [PATCH 150/262] Start implementing exception handling by adding frame descriptor entry processing. - Soon, we should be able basic exceptions. --- lib/llvm-backend/cpp/object_loader.cpp | 20 +++++++++--- lib/llvm-backend/cpp/object_loader.hh | 6 +++- lib/llvm-backend/src/backend.rs | 8 +++++ lib/llvm-backend/src/lib.rs | 1 + lib/llvm-backend/src/platform/mod.rs | 7 ++-- lib/llvm-backend/src/platform/unix.rs | 35 ++++++++++++++++++++ lib/llvm-backend/src/platform/unix/mod.rs | 40 ----------------------- 7 files changed, 68 insertions(+), 49 deletions(-) create mode 100644 lib/llvm-backend/src/platform/unix.rs delete mode 100644 lib/llvm-backend/src/platform/unix/mod.rs diff --git a/lib/llvm-backend/cpp/object_loader.cpp b/lib/llvm-backend/cpp/object_loader.cpp index 3c36707c5..ff6dbe2d1 100644 --- a/lib/llvm-backend/cpp/object_loader.cpp +++ b/lib/llvm-backend/cpp/object_loader.cpp @@ -2,11 +2,15 @@ #include #include +extern "C" void __register_frame(uint8_t *); +extern "C" void __deregister_frame(uint8_t *); + struct MemoryManager : llvm::RuntimeDyld::MemoryManager { public: MemoryManager(callbacks_t callbacks) : callbacks(callbacks) {} virtual ~MemoryManager() override { + deregisterEHFrames(); // Deallocate all of the allocated memory. callbacks.dealloc_memory(code_section.base, code_section.size); callbacks.dealloc_memory(read_section.base, read_section.size); @@ -62,12 +66,17 @@ public: return true; } - virtual void registerEHFrames(uint8_t* Addr, uint64_t LoadAddr, size_t Size) override { - std::cout << "should register eh frames" << std::endl; + virtual void registerEHFrames(uint8_t* addr, uint64_t LoadAddr, size_t size) override { + eh_frame_ptr = addr; + eh_frame_size = size; + eh_frames_registered = true; + callbacks.visit_fde(addr, size, __register_frame); } virtual void deregisterEHFrames() override { - std::cout << "should deregister eh frames" << std::endl; + if (eh_frames_registered) { + callbacks.visit_fde(eh_frame_ptr, eh_frame_size, __deregister_frame); + } } virtual bool finalizeMemory(std::string *ErrMsg = nullptr) override { @@ -111,6 +120,9 @@ private: Section code_section, read_section, readwrite_section; uintptr_t code_bump_ptr, read_bump_ptr, readwrite_bump_ptr; + uint8_t* eh_frame_ptr; + size_t eh_frame_size; + bool eh_frames_registered = false; callbacks_t callbacks; }; @@ -154,7 +166,7 @@ WasmModule::WasmModule( const uint8_t *object_start, size_t object_size, callbacks_t callbacks -) : memory_manager(new MemoryManager(callbacks)) +) : memory_manager(std::unique_ptr(new MemoryManager(callbacks))) { object_file = llvm::cantFail(llvm::object::ObjectFile::createObjectFile(llvm::MemoryBufferRef( llvm::StringRef((const char *)object_start, object_size), "object" diff --git a/lib/llvm-backend/cpp/object_loader.hh b/lib/llvm-backend/cpp/object_loader.hh index 8134385fd..d31d33266 100644 --- a/lib/llvm-backend/cpp/object_loader.hh +++ b/lib/llvm-backend/cpp/object_loader.hh @@ -21,6 +21,8 @@ typedef result_t (*alloc_memory_t)(size_t size, mem_protect_t protect, uint8_t** typedef result_t (*protect_memory_t)(uint8_t* ptr, size_t size, mem_protect_t protect); typedef result_t (*dealloc_memory_t)(uint8_t* ptr, size_t size); typedef uintptr_t (*lookup_vm_symbol_t)(const char* name_ptr, size_t length); +typedef void (*fde_visitor_t)(uint8_t *fde); +typedef result_t (*visit_fde_t)(uint8_t *fde, size_t size, fde_visitor_t visitor); typedef struct { /* Memory management. */ @@ -29,6 +31,8 @@ typedef struct { dealloc_memory_t dealloc_memory; lookup_vm_symbol_t lookup_vm_symbol; + + visit_fde_t visit_fde; } callbacks_t; class WasmModule { @@ -41,7 +45,7 @@ public: void *get_func(llvm::StringRef name) const; private: - llvm::RuntimeDyld::MemoryManager* memory_manager; + std::unique_ptr memory_manager; std::unique_ptr object_file; std::unique_ptr runtime_dyld; }; diff --git a/lib/llvm-backend/src/backend.rs b/lib/llvm-backend/src/backend.rs index a7d700e90..66f29cbbb 100644 --- a/lib/llvm-backend/src/backend.rs +++ b/lib/llvm-backend/src/backend.rs @@ -59,6 +59,7 @@ struct Callbacks { dealloc_memory: extern "C" fn(*mut u8, usize) -> LLVMResult, lookup_vm_symbol: extern "C" fn(*const c_char, usize) -> *const vm::Func, + visit_fde: extern "C" fn(*mut u8, usize, extern "C" fn(*mut u8)), } extern "C" { @@ -165,11 +166,18 @@ fn get_callbacks() -> Callbacks { } } + extern "C" fn visit_fde(fde: *mut u8, size: usize, visitor: extern "C" fn(*mut u8)) { + unsafe { + crate::platform::visit_fde(fde, size, visitor); + } + } + Callbacks { alloc_memory, protect_memory, dealloc_memory, lookup_vm_symbol, + visit_fde, } } diff --git a/lib/llvm-backend/src/lib.rs b/lib/llvm-backend/src/lib.rs index f46520383..3a18d7d48 100644 --- a/lib/llvm-backend/src/lib.rs +++ b/lib/llvm-backend/src/lib.rs @@ -14,6 +14,7 @@ use wasmparser::{self, WasmDecoder}; mod backend; mod code; mod intrinsics; +mod platform; mod read_info; mod state; mod trampolines; diff --git a/lib/llvm-backend/src/platform/mod.rs b/lib/llvm-backend/src/platform/mod.rs index bcc0378c2..01b81b022 100644 --- a/lib/llvm-backend/src/platform/mod.rs +++ b/lib/llvm-backend/src/platform/mod.rs @@ -1,8 +1,7 @@ - -#[cfg(target_family = "unix")] +#[cfg(unix)] mod unix; -#[cfg(target_family = "unix")] +#[cfg(unix)] pub use self::unix::*; #[cfg(target_family = "windows")] -compile_error!("windows not yet supported for the llvm-based compiler backend"); \ No newline at end of file +compile_error!("windows not yet supported for the llvm-based compiler backend"); diff --git a/lib/llvm-backend/src/platform/unix.rs b/lib/llvm-backend/src/platform/unix.rs new file mode 100644 index 000000000..ee03ea08f --- /dev/null +++ b/lib/llvm-backend/src/platform/unix.rs @@ -0,0 +1,35 @@ +/// `__register_frame` and `__deregister_frame` on macos take a single fde as an +/// argument, so we need to parse the fde table here. +/// +/// This is a pretty direct port of llvm's fde handling code: +/// https://llvm.org/doxygen/RTDyldMemoryManager_8cpp_source.html. +#[cfg(target_os = "macos")] +pub unsafe fn visit_fde(addr: *mut u8, size: usize, visitor: extern "C" fn(*mut u8)) { + unsafe fn process_fde(entry: *mut u8, visitor: extern "C" fn(*mut u8)) -> *mut u8 { + let mut p = entry; + let length = (p as *const u32).read_unaligned(); + p = p.add(4); + let offset = (p as *const u32).read_unaligned(); + + if offset != 0 { + visitor(entry); + } + p.add(length as usize) + } + + let mut p = addr; + let end = p.add(size); + + loop { + if p >= end { + break; + } + + p = process_fde(p, visitor); + } +} + +#[cfg(not(target_os = "macos"))] +pub unsafe fn visit_fde(addr: *mut u8, size: usize, visitor: extern "C" fn(*mut u8)) { + visitor(addr); +} diff --git a/lib/llvm-backend/src/platform/unix/mod.rs b/lib/llvm-backend/src/platform/unix/mod.rs deleted file mode 100644 index c0e86f7ef..000000000 --- a/lib/llvm-backend/src/platform/unix/mod.rs +++ /dev/null @@ -1,40 +0,0 @@ - -extern "C" { - fn __register_frame(frame: *const u8); - fn __deregister_frame(frame: *const u8); -} - -pub unsafe fn register_eh_frames(eh_frames: *const u8, num_bytes: usize) { - visit_frame_desc_entries(eh_frames, num_bytes, |frame| __register_frame(frame)); -} - -unsafe fn visit_frame_desc_entries(eh_frames: *const u8, num_bytes: usize, visitor: F) -where - F: Fn(*const u8), -{ - let mut next = eh_frames; - let mut end = eh_frames.add(num_bytes); - - loop { - if next >= end { - break; - } - - let cfi = next; - let mut cfi_num_bytes = (next as *const u32).read_unaligned() as u64; - assert!(cfi_num_bytes != 0); - - next = next.add(4); - if num_bytes == 0xffffffff { - let cfi_num_bytes64 = (next as *const u64).read_unaligned(); - cfi_num_bytes = cfi_num_bytes64; - next = next.add(8); - } - - let cie_offset = (next as *const u32).read_unaligned(); - if cie_offset != 0 { - visitor(cfi); - } - next = next.add(cfi_num_bytes as usize); - } -} From 9a90689b931db780cb7d57eae90ed92c1050eae2 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Sat, 2 Mar 2019 12:57:35 -0800 Subject: [PATCH 151/262] Add preliminary support for throwing and catching uncatchable exceptions. Additional info: - WebAssembly "traps" are uncatchable, but are still caught by the trampoline caller. --- lib/llvm-backend/cpp/object_loader.hh | 75 +++++++++++++++++++++++++++ lib/llvm-backend/src/backend.rs | 18 ++++++- lib/llvm-backend/src/code.rs | 22 +++++--- lib/llvm-backend/src/intrinsics.rs | 14 ++++- lib/runtime/examples/call.rs | 2 +- 5 files changed, 120 insertions(+), 11 deletions(-) diff --git a/lib/llvm-backend/cpp/object_loader.hh b/lib/llvm-backend/cpp/object_loader.hh index d31d33266..9a6fe5681 100644 --- a/lib/llvm-backend/cpp/object_loader.hh +++ b/lib/llvm-backend/cpp/object_loader.hh @@ -1,6 +1,9 @@ #include #include #include +#include +#include +#include typedef enum { PROTECT_NONE, @@ -24,6 +27,8 @@ typedef uintptr_t (*lookup_vm_symbol_t)(const char* name_ptr, size_t length); typedef void (*fde_visitor_t)(uint8_t *fde); typedef result_t (*visit_fde_t)(uint8_t *fde, size_t size, fde_visitor_t visitor); +typedef void (*trampoline_t)(void*, void*, void*, void*); + typedef struct { /* Memory management. */ alloc_memory_t alloc_memory; @@ -35,6 +40,59 @@ typedef struct { visit_fde_t visit_fde; } callbacks_t; +class WasmException { +public: + virtual std::string description() const noexcept = 0; +}; + +struct UncatchableException : WasmException { +public: + enum class Type { + Unreachable, + IncorrectCallIndirectSignature, + Unknown, + } type; + + UncatchableException(Type type) : type(type) {} + + virtual std::string description() const noexcept override { + std::ostringstream ss; + ss + << "Uncatchable exception:" << '\n' + << " - type: " << type << '\n'; + + return ss.str(); + } + +private: + friend std::ostream& operator<<(std::ostream& out, const Type& ty) { + switch (ty) { + case Type::Unreachable: + out << "unreachable"; + break; + case Type::IncorrectCallIndirectSignature: + out << "incorrect call_indirect signature"; + break; + case Type::Unknown: + out << "unknown"; + break; + } + return out; + } +}; + +struct CatchableException : WasmException { +public: + CatchableException(uint32_t type_id, uint32_t value_num) : type_id(type_id), value_num(value_num) {} + + virtual std::string description() const noexcept override { + return "catchable exception"; + } + + uint32_t type_id, value_num; + uint64_t values[]; +}; + class WasmModule { public: WasmModule( @@ -57,10 +115,27 @@ extern "C" { return RESULT_OK; } + void throw_unreachable_exception() { + throw UncatchableException(UncatchableException::Type::Unreachable); + } + void throw_incorrect_call_indirect_signature() { + throw UncatchableException(UncatchableException::Type::IncorrectCallIndirectSignature); + } + void module_delete(WasmModule* module) { delete module; } + void invoke_trampoline(trampoline_t trampoline, void* ctx, void* func, void* params, void* results) { + try { + trampoline(ctx, func, params, results); + } catch(const WasmException& e) { + std::cout << e.description() << std::endl; + } catch (...) { + std::cout << "unknown exception" << std::endl; + } + } + void* get_func_symbol(WasmModule* module, const char* name) { return module->get_func(llvm::StringRef(name)); } diff --git a/lib/llvm-backend/src/backend.rs b/lib/llvm-backend/src/backend.rs index 66f29cbbb..ebffd914e 100644 --- a/lib/llvm-backend/src/backend.rs +++ b/lib/llvm-backend/src/backend.rs @@ -71,6 +71,16 @@ extern "C" { ) -> LLVMResult; fn module_delete(module: *mut LLVMModule); fn get_func_symbol(module: *mut LLVMModule, name: *const c_char) -> *const vm::Func; + fn throw_unreachable_exception(); + fn throw_incorrect_call_indirect_signature(); + // invoke_trampoline(trampoline_t trampoline, void* ctx, void* func, void* params, void* results) + fn invoke_trampoline( + trampoline: unsafe extern "C" fn(*mut vm::Ctx, *const vm::Func, *const u64, *mut u64), + vmctx_ptr: *mut vm::Ctx, + func_ptr: *const vm::Func, + params: *const u64, + results: *mut u64, + ); } fn get_callbacks() -> Callbacks { @@ -162,6 +172,11 @@ fn get_callbacks() -> Callbacks { fn_name!("vm.memory.size.dynamic.local") => vmcalls::local_dynamic_memory_size as _, fn_name!("vm.memory.grow.static.local") => vmcalls::local_static_memory_grow as _, fn_name!("vm.memory.size.static.local") => vmcalls::local_static_memory_size as _, + + fn_name!("vm.exception.throw.unreachable") => throw_unreachable_exception as _, + fn_name!("vm.exception.throw.incorrect-call_indirect_signature") => { + throw_incorrect_call_indirect_signature as _ + } _ => ptr::null(), } } @@ -343,7 +358,8 @@ impl ProtectedCaller for LLVMProtectedCaller { // Here we go. unsafe { - trampoline( + invoke_trampoline( + trampoline, vmctx_ptr, func_ptr, param_vec.as_ptr(), diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index a9170082b..00ad353c3 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -539,6 +539,9 @@ fn parse_function( // Emit an unreachable instruction. // If llvm cannot prove that this is never touched, // it will emit a `ud2` instruction on x86_64 arches. + + builder.build_call(intrinsics.throw_unreachable, &[], "throw"); + ctx.build_trap(); builder.build_unreachable(); @@ -731,13 +734,12 @@ fn parse_function( ) }; - // let sigindices_equal = builder.build_int_compare( - // IntPredicate::EQ, - // expected_dynamic_sigindex, - // found_dynamic_sigindex, - // "sigindices_equal", - // ); - let sigindices_equal = intrinsics.i1_ty.const_int(1, false); + let sigindices_equal = builder.build_int_compare( + IntPredicate::EQ, + expected_dynamic_sigindex, + found_dynamic_sigindex, + "sigindices_equal", + ); // Tell llvm that `expected_dynamic_sigindex` should equal `found_dynamic_sigindex`. let sigindices_equal = builder @@ -764,7 +766,11 @@ fn parse_function( ); builder.position_at_end(&sigindices_notequal_block); - ctx.build_trap(); + builder.build_call( + intrinsics.throw_incorrect_call_indirect_signature, + &[], + "throw", + ); builder.build_unreachable(); builder.position_at_end(&continue_block); diff --git a/lib/llvm-backend/src/intrinsics.rs b/lib/llvm-backend/src/intrinsics.rs index c3f2191f3..a6f7cb02e 100644 --- a/lib/llvm-backend/src/intrinsics.rs +++ b/lib/llvm-backend/src/intrinsics.rs @@ -105,6 +105,9 @@ pub struct Intrinsics { pub memory_size_static_import: FunctionValue, pub memory_size_shared_import: FunctionValue, + pub throw_unreachable: FunctionValue, + pub throw_incorrect_call_indirect_signature: FunctionValue, + ctx_ty: StructType, pub ctx_ptr_ty: PointerType, } @@ -344,7 +347,16 @@ impl Intrinsics { ret_i32_take_ctx_i32, None, ), - + throw_unreachable: module.add_function( + "vm.exception.throw.unreachable", + void_ty.fn_type(&[], false), + None, + ), + throw_incorrect_call_indirect_signature: module.add_function( + "vm.exception.throw.incorrect-call_indirect_signature", + void_ty.fn_type(&[], false), + None, + ), ctx_ty, ctx_ptr_ty, } diff --git a/lib/runtime/examples/call.rs b/lib/runtime/examples/call.rs index ac38b8d46..0684c1bb7 100644 --- a/lib/runtime/examples/call.rs +++ b/lib/runtime/examples/call.rs @@ -6,7 +6,7 @@ static WAT: &'static str = r#" (module (type (;0;) (func (param i32) (result i32))) (func (;0;) (type 0) (param i32) (result i32) - i32.const 42) + unreachable) (export "select_trap_l" (func 0)) ) "#; From 57bfa9b0a4c4b680a7c87e5632f7f640ea5c3e14 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Sat, 2 Mar 2019 14:16:02 -0800 Subject: [PATCH 152/262] Remove multiple throwing functions, just use one. --- lib/llvm-backend/cpp/object_loader.hh | 50 +++++++++++++++++++-------- lib/llvm-backend/src/backend.rs | 12 +++---- lib/llvm-backend/src/code.rs | 12 ++++--- lib/llvm-backend/src/intrinsics.rs | 22 ++++++------ 4 files changed, 60 insertions(+), 36 deletions(-) diff --git a/lib/llvm-backend/cpp/object_loader.hh b/lib/llvm-backend/cpp/object_loader.hh index 9a6fe5681..33724a868 100644 --- a/lib/llvm-backend/cpp/object_loader.hh +++ b/lib/llvm-backend/cpp/object_loader.hh @@ -40,30 +40,51 @@ typedef struct { visit_fde_t visit_fde; } callbacks_t; -class WasmException { +struct WasmException { public: virtual std::string description() const noexcept = 0; }; struct UncatchableException : WasmException { public: - enum class Type { - Unreachable, - IncorrectCallIndirectSignature, - Unknown, - } type; + virtual std::string description() const noexcept override { + return "Uncatchable exception"; + } +}; - UncatchableException(Type type) : type(type) {} +struct UserException : UncatchableException { +public: + UserException(std::string msg) : msg(msg) {} + + virtual std::string description() const noexcept override { + return std::string("user exception: ") + msg; + } +private: + std::string msg; +}; + +struct WasmTrap : UncatchableException { +public: + enum Type { + Unreachable = 0, + IncorrectCallIndirectSignature = 1, + MemoryOutOfBounds = 2, + Unknown, + }; + + WasmTrap(Type type) : type(type) {} virtual std::string description() const noexcept override { std::ostringstream ss; ss - << "Uncatchable exception:" << '\n' + << "WebAssembly trap:" << '\n' << " - type: " << type << '\n'; return ss.str(); } + Type type; + private: friend std::ostream& operator<<(std::ostream& out, const Type& ty) { switch (ty) { @@ -73,7 +94,11 @@ private: case Type::IncorrectCallIndirectSignature: out << "incorrect call_indirect signature"; break; + case Type::MemoryOutOfBounds: + out << "memory access out-of-bounds"; + break; case Type::Unknown: + default: out << "unknown"; break; } @@ -93,7 +118,7 @@ public: uint64_t values[]; }; -class WasmModule { +struct WasmModule { public: WasmModule( const uint8_t *object_start, @@ -115,11 +140,8 @@ extern "C" { return RESULT_OK; } - void throw_unreachable_exception() { - throw UncatchableException(UncatchableException::Type::Unreachable); - } - void throw_incorrect_call_indirect_signature() { - throw UncatchableException(UncatchableException::Type::IncorrectCallIndirectSignature); + void throw_trap(WasmTrap::Type ty) { + throw WasmTrap(ty); } void module_delete(WasmModule* module) { diff --git a/lib/llvm-backend/src/backend.rs b/lib/llvm-backend/src/backend.rs index ebffd914e..e7e641aa9 100644 --- a/lib/llvm-backend/src/backend.rs +++ b/lib/llvm-backend/src/backend.rs @@ -71,9 +71,9 @@ extern "C" { ) -> LLVMResult; fn module_delete(module: *mut LLVMModule); fn get_func_symbol(module: *mut LLVMModule, name: *const c_char) -> *const vm::Func; - fn throw_unreachable_exception(); - fn throw_incorrect_call_indirect_signature(); - // invoke_trampoline(trampoline_t trampoline, void* ctx, void* func, void* params, void* results) + + fn throw_trap(ty: i32); + fn invoke_trampoline( trampoline: unsafe extern "C" fn(*mut vm::Ctx, *const vm::Func, *const u64, *mut u64), vmctx_ptr: *mut vm::Ctx, @@ -173,10 +173,8 @@ fn get_callbacks() -> Callbacks { fn_name!("vm.memory.grow.static.local") => vmcalls::local_static_memory_grow as _, fn_name!("vm.memory.size.static.local") => vmcalls::local_static_memory_size as _, - fn_name!("vm.exception.throw.unreachable") => throw_unreachable_exception as _, - fn_name!("vm.exception.throw.incorrect-call_indirect_signature") => { - throw_incorrect_call_indirect_signature as _ - } + fn_name!("vm.exception.trap") => throw_trap as _, + _ => ptr::null(), } } diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index 00ad353c3..eba8fdd7d 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -540,9 +540,11 @@ fn parse_function( // If llvm cannot prove that this is never touched, // it will emit a `ud2` instruction on x86_64 arches. - builder.build_call(intrinsics.throw_unreachable, &[], "throw"); - - ctx.build_trap(); + builder.build_call( + intrinsics.throw_trap, + &[intrinsics.trap_unreachable], + "throw", + ); builder.build_unreachable(); state.reachable = false; @@ -767,8 +769,8 @@ fn parse_function( builder.position_at_end(&sigindices_notequal_block); builder.build_call( - intrinsics.throw_incorrect_call_indirect_signature, - &[], + intrinsics.throw_trap, + &[intrinsics.trap_call_indirect_sig], "throw", ); builder.build_unreachable(); diff --git a/lib/llvm-backend/src/intrinsics.rs b/lib/llvm-backend/src/intrinsics.rs index a6f7cb02e..152047b84 100644 --- a/lib/llvm-backend/src/intrinsics.rs +++ b/lib/llvm-backend/src/intrinsics.rs @@ -90,6 +90,10 @@ pub struct Intrinsics { pub f32_zero: FloatValue, pub f64_zero: FloatValue, + pub trap_unreachable: BasicValueEnum, + pub trap_call_indirect_sig: BasicValueEnum, + pub trap_memory_oob: BasicValueEnum, + // VM intrinsics. pub memory_grow_dynamic_local: FunctionValue, pub memory_grow_static_local: FunctionValue, @@ -105,8 +109,7 @@ pub struct Intrinsics { pub memory_size_static_import: FunctionValue, pub memory_size_shared_import: FunctionValue, - pub throw_unreachable: FunctionValue, - pub throw_incorrect_call_indirect_signature: FunctionValue, + pub throw_trap: FunctionValue, ctx_ty: StructType, pub ctx_ptr_ty: PointerType, @@ -285,6 +288,10 @@ impl Intrinsics { f32_zero, f64_zero, + trap_unreachable: i32_zero.as_basic_value_enum(), + trap_call_indirect_sig: i32_ty.const_int(1, false).as_basic_value_enum(), + trap_memory_oob: i32_ty.const_int(2, false).as_basic_value_enum(), + // VM intrinsics. memory_grow_dynamic_local: module.add_function( "vm.memory.grow.dynamic.local", @@ -347,14 +354,9 @@ impl Intrinsics { ret_i32_take_ctx_i32, None, ), - throw_unreachable: module.add_function( - "vm.exception.throw.unreachable", - void_ty.fn_type(&[], false), - None, - ), - throw_incorrect_call_indirect_signature: module.add_function( - "vm.exception.throw.incorrect-call_indirect_signature", - void_ty.fn_type(&[], false), + throw_trap: module.add_function( + "vm.exception.trap", + void_ty.fn_type(&[i32_ty_basic], false), None, ), ctx_ty, From caf2205936f677bca62be83fcf62ed069fecc2c0 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Sat, 2 Mar 2019 17:00:05 -0800 Subject: [PATCH 153/262] Add a signal handler for macos and linux. Implementation Notes: - To avoid setjmp, longjmp, and the mess that those create, we instead set the interrupting context of the signal handler to return into the `throw_trap` routine. To my surprise, this actually works. The stack ends up getting unwound normally and the memory-oob error is caught by the trampoline. --- Cargo.lock | 1 + lib/llvm-backend/Cargo.toml | 1 + lib/llvm-backend/cpp/object_loader.hh | 4 +- lib/llvm-backend/src/backend.rs | 4 + lib/llvm-backend/src/platform/unix.rs | 106 ++++++++++++++++++++++++++ lib/runtime/examples/call.rs | 5 +- 6 files changed, 118 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f06c9e940..a31fa0a7d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1213,6 +1213,7 @@ dependencies = [ "inkwell 0.1.0 (git+https://github.com/TheDan64/inkwell?branch=llvm7-0)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "nix 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/lib/llvm-backend/Cargo.toml b/lib/llvm-backend/Cargo.toml index 81301872b..f350b263e 100644 --- a/lib/llvm-backend/Cargo.toml +++ b/lib/llvm-backend/Cargo.toml @@ -12,6 +12,7 @@ hashbrown = "0.1.8" smallvec = "0.6.8" goblin = "0.0.20" libc = "0.2.49" +nix = "0.13.0" capstone = "0.5.0" [build-dependencies] diff --git a/lib/llvm-backend/cpp/object_loader.hh b/lib/llvm-backend/cpp/object_loader.hh index 33724a868..9d51d686c 100644 --- a/lib/llvm-backend/cpp/object_loader.hh +++ b/lib/llvm-backend/cpp/object_loader.hh @@ -115,7 +115,7 @@ public: } uint32_t type_id, value_num; - uint64_t values[]; + uint64_t values[1]; }; struct WasmModule { @@ -140,7 +140,7 @@ extern "C" { return RESULT_OK; } - void throw_trap(WasmTrap::Type ty) { + [[noreturn]] void throw_trap(WasmTrap::Type ty) { throw WasmTrap(ty); } diff --git a/lib/llvm-backend/src/backend.rs b/lib/llvm-backend/src/backend.rs index e7e641aa9..792a10422 100644 --- a/lib/llvm-backend/src/backend.rs +++ b/lib/llvm-backend/src/backend.rs @@ -243,6 +243,10 @@ impl LLVMBackend { ) }; + unsafe { + crate::platform::install_signal_handler(); + } + if res != LLVMResult::OK { panic!("failed to load object") } diff --git a/lib/llvm-backend/src/platform/unix.rs b/lib/llvm-backend/src/platform/unix.rs index ee03ea08f..7db0d0110 100644 --- a/lib/llvm-backend/src/platform/unix.rs +++ b/lib/llvm-backend/src/platform/unix.rs @@ -1,3 +1,8 @@ +use libc::{c_void, siginfo_t}; +use nix::sys::signal::{ + sigaction, SaFlags, SigAction, SigHandler, SigSet, Signal, SIGBUS, SIGFPE, SIGILL, SIGSEGV, +}; + /// `__register_frame` and `__deregister_frame` on macos take a single fde as an /// argument, so we need to parse the fde table here. /// @@ -33,3 +38,104 @@ pub unsafe fn visit_fde(addr: *mut u8, size: usize, visitor: extern "C" fn(*mut pub unsafe fn visit_fde(addr: *mut u8, size: usize, visitor: extern "C" fn(*mut u8)) { visitor(addr); } + +extern "C" { + fn throw_trap(ty: i32) -> !; +} + +pub unsafe fn install_signal_handler() { + let sa = SigAction::new( + SigHandler::SigAction(signal_trap_handler), + SaFlags::SA_ONSTACK, + SigSet::empty(), + ); + sigaction(SIGFPE, &sa).unwrap(); + sigaction(SIGILL, &sa).unwrap(); + sigaction(SIGSEGV, &sa).unwrap(); + sigaction(SIGBUS, &sa).unwrap(); +} + +extern "C" fn signal_trap_handler( + signum: ::nix::libc::c_int, + siginfo: *mut siginfo_t, + ucontext: *mut c_void, +) { + unsafe { + /// By setting the instruction pointer of the interrupted context + /// to `throw_trap` and the register of the first argument + /// to the trap ID, we can approximate throwing an exception + /// from a signal handler. + set_context_to_throw(ucontext); + } +} + +#[cfg(all(target_os = "linux", target_arch = "x86_64"))] +unsafe fn set_context_to_throw(ucontext: *mut c_void) { + use libc::{ucontext_t, RDI, RIP}; + + let ucontext = ucontext as *mut ucontext_t; + (*ucontext).uc_mcontext.gregs[RIP as usize] = throw_trap as u64; + (*ucontext).uc_mcontext.gregs[RDI as usize] = 2; // `MemoryOutOfBounds` variant. +} + +#[cfg(all(target_os = "macos", target_arch = "x86_64"))] +unsafe fn set_context_to_throw(ucontext: *mut c_void) { + #[allow(dead_code)] + #[repr(C)] + struct ucontext_t { + uc_onstack: u32, + uc_sigmask: u32, + uc_stack: libc::stack_t, + uc_link: *const ucontext_t, + uc_mcsize: u64, + uc_mcontext: *mut mcontext_t, + } + #[repr(C)] + struct exception_state { + trapno: u16, + cpu: u16, + err: u32, + faultvaddr: u64, + } + #[repr(C)] + struct regs { + rax: u64, + rbx: u64, + rcx: u64, + rdx: u64, + rdi: u64, + rsi: u64, + rbp: u64, + rsp: u64, + r8: u64, + r9: u64, + r10: u64, + r11: u64, + r12: u64, + r13: u64, + r14: u64, + r15: u64, + rip: u64, + rflags: u64, + cs: u64, + fs: u64, + gs: u64, + } + #[allow(dead_code)] + #[repr(C)] + struct mcontext_t { + es: exception_state, + ss: regs, + // ... + } + + let ucontext = ucontext as *mut ucontext_t; + (*(*ucontext).uc_mcontext).ss.rip = throw_trap as u64; + (*(*ucontext).uc_mcontext).ss.rdi = 2; // `MemoryOutOfBounds` variant. +} + +#[cfg(not(any( + all(target_os = "macos", target_arch = "x86_64"), + all(target_os = "linux", target_arch = "x86_64"), +)))] +compile_error!("This crate doesn't yet support compiling on operating systems other than linux and macos and architectures other than x86_64"); diff --git a/lib/runtime/examples/call.rs b/lib/runtime/examples/call.rs index 0684c1bb7..2a11db9e8 100644 --- a/lib/runtime/examples/call.rs +++ b/lib/runtime/examples/call.rs @@ -4,9 +4,12 @@ use wabt::wat2wasm; static WAT: &'static str = r#" (module + (memory 1) (type (;0;) (func (param i32) (result i32))) (func (;0;) (type 0) (param i32) (result i32) - unreachable) + i32.const 0x20000 + i32.load + ) (export "select_trap_l" (func 0)) ) "#; From 9cfda6800ff3493bd267e4a822fb949915b83325 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Sat, 2 Mar 2019 19:08:15 -0800 Subject: [PATCH 154/262] Try to return an error from call_protected when an exception occurs. Something breaks pretty drastically sometimes, not sure why. --- lib/llvm-backend/cpp/object_loader.hh | 22 ++++++++- lib/llvm-backend/src/backend.rs | 65 ++++++++++++++++++++------- lib/llvm-backend/src/code.rs | 2 - lib/llvm-backend/src/platform/unix.rs | 2 +- lib/runtime/examples/call.rs | 37 ++++++++++----- 5 files changed, 98 insertions(+), 30 deletions(-) diff --git a/lib/llvm-backend/cpp/object_loader.hh b/lib/llvm-backend/cpp/object_loader.hh index 9d51d686c..cb1b48554 100644 --- a/lib/llvm-backend/cpp/object_loader.hh +++ b/lib/llvm-backend/cpp/object_loader.hh @@ -141,6 +141,7 @@ extern "C" { } [[noreturn]] void throw_trap(WasmTrap::Type ty) { + std::cout << "throwing trap: " << ty << std::endl; throw WasmTrap(ty); } @@ -148,13 +149,30 @@ extern "C" { delete module; } - void invoke_trampoline(trampoline_t trampoline, void* ctx, void* func, void* params, void* results) { + bool invoke_trampoline( + trampoline_t trampoline, + void* ctx, + void* func, + void* params, + void* results, + WasmTrap::Type* trap_out + ) throw() { try { trampoline(ctx, func, params, results); + std::cout << "Success" << std::endl; + return true; + } catch(const WasmTrap& e) { + std::cout << e.description() << std::endl; + *trap_out = e.type; + return false; } catch(const WasmException& e) { std::cout << e.description() << std::endl; + *trap_out = WasmTrap::Type::Unknown; + return false; } catch (...) { - std::cout << "unknown exception" << std::endl; + std::cout << "unknown" << std::endl; + *trap_out = WasmTrap::Type::Unknown; + return false; } } diff --git a/lib/llvm-backend/src/backend.rs b/lib/llvm-backend/src/backend.rs index 792a10422..2d67d7a9b 100644 --- a/lib/llvm-backend/src/backend.rs +++ b/lib/llvm-backend/src/backend.rs @@ -17,11 +17,14 @@ use std::{ }; use wasmer_runtime_core::{ backend::{FuncResolver, ProtectedCaller, Token, UserTrapper}, - error::RuntimeResult, + error::{RuntimeError, RuntimeResult}, export::Context, module::{ModuleInfo, ModuleInner}, structures::TypedIndex, - types::{FuncIndex, FuncSig, LocalFuncIndex, LocalOrImport, SigIndex, Type, Value}, + types::{ + FuncIndex, FuncSig, LocalFuncIndex, LocalOrImport, MemoryIndex, SigIndex, TableIndex, Type, + Value, + }, vm::{self, ImportBacking}, vmcalls, }; @@ -52,6 +55,14 @@ enum LLVMResult { OBJECT_LOAD_FAILURE, } +#[repr(C)] +enum WasmTrapType { + Unreachable = 0, + IncorrectCallIndirectSignature = 1, + MemoryOutOfBounds = 2, + Unknown, +} + #[repr(C)] struct Callbacks { alloc_memory: extern "C" fn(usize, MemProtect, &mut *mut u8, &mut usize) -> LLVMResult, @@ -80,7 +91,8 @@ extern "C" { func_ptr: *const vm::Func, params: *const u64, results: *mut u64, - ); + trap_out: *mut WasmTrapType, + ) -> bool; } fn get_callbacks() -> Callbacks { @@ -358,27 +370,50 @@ impl ProtectedCaller for LLVMProtectedCaller { mem::transmute(symbol) }; + let mut trap_out = WasmTrapType::Unknown; + // Here we go. - unsafe { + let success = unsafe { invoke_trampoline( trampoline, vmctx_ptr, func_ptr, param_vec.as_ptr(), return_vec.as_mut_ptr(), - ); - } + &mut trap_out, + ) + }; - Ok(return_vec - .iter() - .zip(signature.returns().iter()) - .map(|(&x, ty)| match ty { - Type::I32 => Value::I32(x as i32), - Type::I64 => Value::I64(x as i64), - Type::F32 => Value::F32(f32::from_bits(x as u32)), - Type::F64 => Value::F64(f64::from_bits(x as u64)), + if success { + Ok(return_vec + .iter() + .zip(signature.returns().iter()) + .map(|(&x, ty)| match ty { + Type::I32 => Value::I32(x as i32), + Type::I64 => Value::I64(x as i64), + Type::F32 => Value::F32(f32::from_bits(x as u32)), + Type::F64 => Value::F64(f64::from_bits(x as u64)), + }) + .collect()) + } else { + Err(match trap_out { + WasmTrapType::Unreachable => RuntimeError::User { + msg: "unreachable".into(), + }, + WasmTrapType::IncorrectCallIndirectSignature => { + RuntimeError::IndirectCallSignature { + table: TableIndex::new(0), + } + } + WasmTrapType::MemoryOutOfBounds => RuntimeError::OutOfBoundsAccess { + memory: MemoryIndex::new(0), + addr: None, + }, + WasmTrapType::Unknown => RuntimeError::Unknown { + msg: "unknown error".into(), + }, }) - .collect()) + } } fn get_early_trapper(&self) -> Box { diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index eba8fdd7d..01fb09a20 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -118,8 +118,6 @@ pub fn parse_function_bodies( })?; } - module.print_to_stderr(); - generate_trampolines(info, &signatures, &module, &context, &builder, &intrinsics); let pass_manager = PassManager::create_for_module(); diff --git a/lib/llvm-backend/src/platform/unix.rs b/lib/llvm-backend/src/platform/unix.rs index 7db0d0110..6b6f8356e 100644 --- a/lib/llvm-backend/src/platform/unix.rs +++ b/lib/llvm-backend/src/platform/unix.rs @@ -46,7 +46,7 @@ extern "C" { pub unsafe fn install_signal_handler() { let sa = SigAction::new( SigHandler::SigAction(signal_trap_handler), - SaFlags::SA_ONSTACK, + SaFlags::SA_ONSTACK | SaFlags::SA_SIGINFO, SigSet::empty(), ); sigaction(SIGFPE, &sa).unwrap(); diff --git a/lib/runtime/examples/call.rs b/lib/runtime/examples/call.rs index 2a11db9e8..e9ac58acc 100644 --- a/lib/runtime/examples/call.rs +++ b/lib/runtime/examples/call.rs @@ -4,14 +4,31 @@ use wabt::wat2wasm; static WAT: &'static str = r#" (module - (memory 1) - (type (;0;) (func (param i32) (result i32))) - (func (;0;) (type 0) (param i32) (result i32) - i32.const 0x20000 - i32.load - ) - (export "select_trap_l" (func 0)) - ) + (type (;0;) (func (result i32))) + (type (;1;) (func (param i32 i32))) + (type (;2;) (func (param i32) (result i32))) + (func (;0;) (type 0) (result i32) + memory.size + i32.const 65536 + i32.mul) + (func (;1;) (type 1) (param i32 i32) + call 0 + local.get 0 + i32.sub + local.get 1 + i32.store) + (func (;2;) (type 2) (param i32) (result i32) + call 0 + local.get 0 + i32.add + i32.load) + (func (;3;) (type 2) (param i32) (result i32) + local.get 0 + memory.grow) + (memory (;0;) 1 2) + (export "store" (func 1)) + (export "load" (func 2)) + (export "memory.grow" (func 3))) "#; fn get_wasm() -> Vec { @@ -28,9 +45,9 @@ fn main() -> Result<(), error::Error> { println!("instantiating"); let instance = module.instantiate(&imports)?; - let foo = instance.dyn_func("select_trap_l")?; + let foo = instance.dyn_func("store")?; - let result = foo.call(&[Value::I32(0)]); + let result = foo.call(&[Value::I32(0), Value::I32(1)]); println!("result: {:?}", result); From 2077fb448a84eddac39d38c5270d420a696c21c8 Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Sat, 2 Mar 2019 22:28:00 -0600 Subject: [PATCH 155/262] Fix C API table/global/memory imports --- lib/runtime-c-api/src/lib.rs | 44 +++++-- lib/runtime-c-api/tests/.gitignore | 1 + lib/runtime-c-api/tests/CMakeLists.txt | 4 + lib/runtime-c-api/tests/hello_wasm.wasm | Bin 0 -> 206 bytes lib/runtime-c-api/tests/test-imports.c | 154 ++++++++++++++++++++++++ 5 files changed, 193 insertions(+), 10 deletions(-) create mode 100644 lib/runtime-c-api/tests/hello_wasm.wasm create mode 100644 lib/runtime-c-api/tests/test-imports.c diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index 2fbf36cf8..5512c0287 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -454,12 +454,24 @@ pub unsafe extern "C" fn wasmer_module_instantiate( .or_insert_with(|| Namespace::new()); let export = match import.tag { - wasmer_import_export_kind::WASM_MEMORY => import.value.memory as *mut Export, - wasmer_import_export_kind::WASM_FUNCTION => import.value.func as *mut Export, - wasmer_import_export_kind::WASM_GLOBAL => import.value.global as *mut Export, - wasmer_import_export_kind::WASM_TABLE => import.value.table as *mut Export, + wasmer_import_export_kind::WASM_MEMORY => { + let mem = import.value.memory as *mut Memory; + Export::Memory((&*mem).clone()) + } + wasmer_import_export_kind::WASM_FUNCTION => { + let func_export = import.value.func as *mut Export; + (&*func_export).clone() + } + wasmer_import_export_kind::WASM_GLOBAL => { + let global = import.value.global as *mut Global; + Export::Global((&*global).clone()) + } + wasmer_import_export_kind::WASM_TABLE => { + let table = import.value.table as *mut Table; + Export::Table((&*table).clone()) + } }; - namespace.insert(import_name, unsafe { (&*export).clone() }); + namespace.insert(import_name, export); } for (module_name, namespace) in namespaces.into_iter() { import_object.register(module_name, namespace); @@ -806,12 +818,24 @@ pub unsafe extern "C" fn wasmer_instantiate( .or_insert_with(|| Namespace::new()); let export = match import.tag { - wasmer_import_export_kind::WASM_MEMORY => import.value.memory as *mut Export, - wasmer_import_export_kind::WASM_FUNCTION => import.value.func as *mut Export, - wasmer_import_export_kind::WASM_GLOBAL => import.value.global as *mut Export, - wasmer_import_export_kind::WASM_TABLE => import.value.table as *mut Export, + wasmer_import_export_kind::WASM_MEMORY => { + let mem = import.value.memory as *mut Memory; + Export::Memory((&*mem).clone()) + } + wasmer_import_export_kind::WASM_FUNCTION => { + let func_export = import.value.func as *mut Export; + (&*func_export).clone() + } + wasmer_import_export_kind::WASM_GLOBAL => { + let global = import.value.global as *mut Global; + Export::Global((&*global).clone()) + } + wasmer_import_export_kind::WASM_TABLE => { + let table = import.value.table as *mut Table; + Export::Table((&*table).clone()) + } }; - namespace.insert(import_name, unsafe { (&*export).clone() }); + namespace.insert(import_name, unsafe { export }); } for (module_name, namespace) in namespaces.into_iter() { import_object.register(module_name, namespace); diff --git a/lib/runtime-c-api/tests/.gitignore b/lib/runtime-c-api/tests/.gitignore index a39c13250..15e33d2cf 100644 --- a/lib/runtime-c-api/tests/.gitignore +++ b/lib/runtime-c-api/tests/.gitignore @@ -12,6 +12,7 @@ _deps test-globals test-exports test-instantiate +test-imports test-import-function test-memory test-module-imports diff --git a/lib/runtime-c-api/tests/CMakeLists.txt b/lib/runtime-c-api/tests/CMakeLists.txt index 697729580..6f899b5b5 100644 --- a/lib/runtime-c-api/tests/CMakeLists.txt +++ b/lib/runtime-c-api/tests/CMakeLists.txt @@ -1,6 +1,7 @@ cmake_minimum_required (VERSION 2.6) project (WasmerCApiTests) +add_executable(test-imports test-imports.c) add_executable(test-exports test-exports.c) add_executable(test-globals test-globals.c) add_executable(test-instantiate test-instantiate.c) @@ -21,6 +22,8 @@ if(NOT WASMER_LIB) message(FATAL_ERROR "wasmer library not found") endif() +target_link_libraries(test-imports + general ${WASMER_LIB}) target_link_libraries(test-exports general ${WASMER_LIB}) target_link_libraries(test-globals @@ -43,6 +46,7 @@ target_link_libraries(test-tables general ${WASMER_LIB}) enable_testing() +add_test(test-imports test-imports) add_test(test-exports test-exports) add_test(test-globals test-globals) add_test(test-instantiate test-instantiate) diff --git a/lib/runtime-c-api/tests/hello_wasm.wasm b/lib/runtime-c-api/tests/hello_wasm.wasm new file mode 100644 index 0000000000000000000000000000000000000000..b2287be036ed768bfd608c1a1583fdeb72cf160d GIT binary patch literal 206 zcmXAjK?=e!6h!C$NQH)q=miwJbnU)7Z{YH`V!+lml_n^z(j#~zk7lZ~7={NA29@gw zF^lB#YHNFYj~|`^l&O+KKnV&Zzz3y_eWY?9YU{=M0hmB0(wVLwUUIISQQ-%ZKVpom z6cZIuPblBTCS#TdwIq~pmf72b||tXqPU*svdL*j#TfrJ UIcvS9NOg9cto`QH5A9|91+J +#include "../wasmer.h" +#include +#include + +static print_str_called = false; + +// Host function that will be imported into the Web Assembly Instance +void print_str(wasmer_instance_context_t *ctx, int32_t ptr, int32_t len) +{ + print_str_called = true; + wasmer_memory_t *memory = wasmer_instance_context_memory(ctx, 0); + uint32_t mem_len = wasmer_memory_length(memory); + uint8_t *mem_bytes = wasmer_memory_data(memory); + printf("%.*s", len, mem_bytes + ptr); +} + +// Use the last_error API to retrieve error messages +void print_wasmer_error() +{ + int error_len = wasmer_last_error_length(); + printf("Error len: `%d`\n", error_len); + char *error_str = malloc(error_len); + wasmer_last_error_message(error_str, error_len); + printf("Error str: `%s`\n", error_str); +} + +int main() +{ + // Create a new func to hold the parameter and signature + // of our `print_str` host function + wasmer_value_tag params_sig[] = {WASM_I32, WASM_I32}; + wasmer_value_tag returns_sig[] = {}; + wasmer_import_func_t *func = wasmer_import_func_new(print_str, params_sig, 2, returns_sig, 0); + + // Create module name for our imports + // represented in bytes for UTF-8 compatability + char *module_name = "env"; + wasmer_byte_array module_name_bytes; + module_name_bytes.bytes = module_name; + module_name_bytes.bytes_len = strlen(module_name); + + // Define a function import + char *import_name = "_print_str"; + wasmer_byte_array import_name_bytes; + import_name_bytes.bytes = import_name; + import_name_bytes.bytes_len = strlen(import_name); + wasmer_import_t func_import; + func_import.module_name = module_name_bytes; + func_import.import_name = import_name_bytes; + func_import.tag = WASM_FUNCTION; + func_import.value.func = func; + + // Define a memory import + char *import_memory_name = "memory"; + wasmer_byte_array import_memory_name_bytes; + import_memory_name_bytes.bytes = import_memory_name; + import_memory_name_bytes.bytes_len = strlen(import_memory_name); + wasmer_import_t memory_import; + memory_import.module_name = module_name_bytes; + memory_import.import_name = import_memory_name_bytes; + memory_import.tag = WASM_MEMORY; + wasmer_memory_t *memory = NULL; + wasmer_limits_t descriptor; + descriptor.min = 256; + wasmer_limit_option_t max; + max.has_some = true; + max.some = 256; + descriptor.max = max; + wasmer_result_t memory_result = wasmer_memory_new(&memory, descriptor); + if (memory_result != WASMER_OK) + { + print_wasmer_error(); + } + memory_import.value.memory = memory; + + // Define a global import + char *import_global_name = "__memory_base"; + wasmer_byte_array import_global_name_bytes; + import_global_name_bytes.bytes = import_global_name; + import_global_name_bytes.bytes_len = strlen(import_global_name); + wasmer_import_t global_import; + global_import.module_name = module_name_bytes; + global_import.import_name = import_global_name_bytes; + global_import.tag = WASM_GLOBAL; + wasmer_value_t val; + val.tag = WASM_I32; + val.value.I32 = 1024; + wasmer_global_t *global = wasmer_global_new(val, false); + global_import.value.global = global; + + // Define a table import + char *import_table_name = "table"; + wasmer_byte_array import_table_name_bytes; + import_table_name_bytes.bytes = import_table_name; + import_table_name_bytes.bytes_len = strlen(import_table_name); + wasmer_import_t table_import; + table_import.module_name = module_name_bytes; + table_import.import_name = import_table_name_bytes; + table_import.tag = WASM_TABLE; + wasmer_table_t *table = NULL; + wasmer_limits_t table_descriptor; + table_descriptor.min = 256; + wasmer_limit_option_t table_max; + table_max.has_some = true; + table_max.some = 256; + table_descriptor.max = table_max; + wasmer_result_t table_result = wasmer_table_new(&table, table_descriptor); + if (table_result != WASMER_OK) + { + print_wasmer_error(); + } + table_import.value.table = table; + + // Define an array containing our imports + wasmer_import_t imports[] = {func_import, global_import, memory_import, table_import}; + + // Read the wasm file bytes + FILE *file = fopen("hello_wasm.wasm", "r"); + fseek(file, 0, SEEK_END); + long len = ftell(file); + uint8_t *bytes = malloc(len); + fseek(file, 0, SEEK_SET); + fread(bytes, 1, len, file); + fclose(file); + + // Creates a WebAssembly Instance from wasm bytes and imports + wasmer_instance_t *instance = NULL; + wasmer_result_t compile_result = wasmer_instantiate(&instance, bytes, len, imports, 3); + printf("Compile result: %d\n", compile_result); + if (compile_result != WASMER_OK) + { + print_wasmer_error(); + } + assert(compile_result == WASMER_OK); + + // Call the exported "hello_wasm" function of our instance + wasmer_value_t params[] = {}; + wasmer_value_t result_one; + wasmer_value_t results[] = {result_one}; + wasmer_result_t call_result = wasmer_instance_call(instance, "_hello_wasm", params, 0, results, 1); + printf("Call result: %d\n", call_result); + assert(call_result == WASMER_OK); + assert(print_str_called); + + // Use *_destroy methods to cleanup as specified in the header documentation + wasmer_import_func_destroy(func); + wasmer_global_destroy(global); + wasmer_memory_destroy(memory); + wasmer_table_destroy(table); + wasmer_instance_destroy(instance); + + return 0; +} From e362b56b07a336bc726d17da5d87f61341cc1bb2 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Sun, 3 Mar 2019 02:15:53 -0800 Subject: [PATCH 156/262] Turns out we can just throw an exception from the signal handler without any fancy tricks. This has been tested on macos, hopefully it works on linux too. --- lib/llvm-backend/src/platform/unix.rs | 82 ++------------------------- 1 file changed, 6 insertions(+), 76 deletions(-) diff --git a/lib/llvm-backend/src/platform/unix.rs b/lib/llvm-backend/src/platform/unix.rs index 6b6f8356e..585797b0a 100644 --- a/lib/llvm-backend/src/platform/unix.rs +++ b/lib/llvm-backend/src/platform/unix.rs @@ -61,81 +61,11 @@ extern "C" fn signal_trap_handler( ucontext: *mut c_void, ) { unsafe { - /// By setting the instruction pointer of the interrupted context - /// to `throw_trap` and the register of the first argument - /// to the trap ID, we can approximate throwing an exception - /// from a signal handler. - set_context_to_throw(ucontext); + /// Apparently, we can unwind from arbitary instructions, as long + /// as we don't need to catch the exception inside the function that + /// was interrupted. + /// + /// This works on macos, not sure about linux. + throw_trap(2); } } - -#[cfg(all(target_os = "linux", target_arch = "x86_64"))] -unsafe fn set_context_to_throw(ucontext: *mut c_void) { - use libc::{ucontext_t, RDI, RIP}; - - let ucontext = ucontext as *mut ucontext_t; - (*ucontext).uc_mcontext.gregs[RIP as usize] = throw_trap as u64; - (*ucontext).uc_mcontext.gregs[RDI as usize] = 2; // `MemoryOutOfBounds` variant. -} - -#[cfg(all(target_os = "macos", target_arch = "x86_64"))] -unsafe fn set_context_to_throw(ucontext: *mut c_void) { - #[allow(dead_code)] - #[repr(C)] - struct ucontext_t { - uc_onstack: u32, - uc_sigmask: u32, - uc_stack: libc::stack_t, - uc_link: *const ucontext_t, - uc_mcsize: u64, - uc_mcontext: *mut mcontext_t, - } - #[repr(C)] - struct exception_state { - trapno: u16, - cpu: u16, - err: u32, - faultvaddr: u64, - } - #[repr(C)] - struct regs { - rax: u64, - rbx: u64, - rcx: u64, - rdx: u64, - rdi: u64, - rsi: u64, - rbp: u64, - rsp: u64, - r8: u64, - r9: u64, - r10: u64, - r11: u64, - r12: u64, - r13: u64, - r14: u64, - r15: u64, - rip: u64, - rflags: u64, - cs: u64, - fs: u64, - gs: u64, - } - #[allow(dead_code)] - #[repr(C)] - struct mcontext_t { - es: exception_state, - ss: regs, - // ... - } - - let ucontext = ucontext as *mut ucontext_t; - (*(*ucontext).uc_mcontext).ss.rip = throw_trap as u64; - (*(*ucontext).uc_mcontext).ss.rdi = 2; // `MemoryOutOfBounds` variant. -} - -#[cfg(not(any( - all(target_os = "macos", target_arch = "x86_64"), - all(target_os = "linux", target_arch = "x86_64"), -)))] -compile_error!("This crate doesn't yet support compiling on operating systems other than linux and macos and architectures other than x86_64"); From 2c765c87c5b62fba3d28c842515a0b7b54b15aef Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Sun, 3 Mar 2019 12:55:29 -0600 Subject: [PATCH 157/262] Update locals reading to use count --- lib/llvm-backend/src/code.rs | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index 01fb09a20..355a6d830 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -172,7 +172,8 @@ fn parse_function( let mut ctx = intrinsics.ctx(info, builder, &function); - let mut locals = Vec::with_capacity(locals_reader.get_count() as usize); + let mut locals = Vec::with_capacity(locals_reader.get_count() as usize); // TODO fix capacity + locals.extend( function .get_param_iter() @@ -189,15 +190,12 @@ fn parse_function( let param_len = locals.len(); + let mut local_idx = 0; for (index, local) in locals_reader.into_iter().enumerate() { - let (_, ty) = local?; - + let (count, ty) = local?; let wasmer_ty = type_to_type(ty)?; - let ty = type_to_llvm(intrinsics, wasmer_ty); - let alloca = builder.build_alloca(ty, &format!("local{}", param_len + index)); - let default_value = match wasmer_ty { Type::I32 => intrinsics.i32_zero.as_basic_value_enum(), Type::I64 => intrinsics.i64_zero.as_basic_value_enum(), @@ -205,9 +203,14 @@ fn parse_function( Type::F64 => intrinsics.f64_zero.as_basic_value_enum(), }; - builder.build_store(alloca, default_value); + for _ in 0..count { + let alloca = builder.build_alloca(ty, &format!("local{}", param_len + local_idx)); - locals.push(alloca); + builder.build_store(alloca, default_value); + + locals.push(alloca); + local_idx += 1; + } } let mut unreachable_depth = 0; From 97a70327d063f171034e3aa99c58aae9612ffb45 Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Sun, 3 Mar 2019 15:13:20 -0600 Subject: [PATCH 158/262] Fix compilation of test example --- lib/llvm-backend/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/llvm-backend/src/lib.rs b/lib/llvm-backend/src/lib.rs index 3a18d7d48..b1ddc1f18 100644 --- a/lib/llvm-backend/src/lib.rs +++ b/lib/llvm-backend/src/lib.rs @@ -111,7 +111,7 @@ fn test_read_module() { let (module, intrinsics) = code::parse_function_bodies(&info, code_reader).unwrap(); - let backend = backend::LLVMBackend::new(module, intrinsics); + let (backend, _caller) = backend::LLVMBackend::new(module, intrinsics); let func_ptr = backend.get_func(&info, LocalFuncIndex::new(0)).unwrap(); From 3f345b41c2c29825f7055b304d3ac41f89a78df4 Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Sun, 3 Mar 2019 15:18:16 -0600 Subject: [PATCH 159/262] Fix emscripten lib compilation --- lib/emscripten/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/emscripten/src/lib.rs b/lib/emscripten/src/lib.rs index 5a7f008f1..4f3fa0d3d 100644 --- a/lib/emscripten/src/lib.rs +++ b/lib/emscripten/src/lib.rs @@ -341,7 +341,7 @@ impl EmscriptenGlobals { if name == "abortOnCannotGrowMemory" && namespace == "env" { let sig_index = module.info().func_assoc[index.convert_up(module.info())]; let expected_sig = &module.info().signatures[sig_index]; - if **expected_sig == *OLD_ABORT_ON_CANNOT_GROW_MEMORY_SIG { + if *expected_sig == *OLD_ABORT_ON_CANNOT_GROW_MEMORY_SIG { use_old_abort_on_cannot_grow_memory = true; } break; From aae256b4074cc147b8559653612acf0ce2f96b0c Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Sun, 3 Mar 2019 15:34:20 -0600 Subject: [PATCH 160/262] Add tag to fix cast ptr lint error --- lib/llvm-backend/src/platform/unix.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/llvm-backend/src/platform/unix.rs b/lib/llvm-backend/src/platform/unix.rs index 585797b0a..c17f56359 100644 --- a/lib/llvm-backend/src/platform/unix.rs +++ b/lib/llvm-backend/src/platform/unix.rs @@ -8,6 +8,7 @@ use nix::sys::signal::{ /// /// This is a pretty direct port of llvm's fde handling code: /// https://llvm.org/doxygen/RTDyldMemoryManager_8cpp_source.html. +#[allow(clippy::cast_ptr_alignment)] #[cfg(target_os = "macos")] pub unsafe fn visit_fde(addr: *mut u8, size: usize, visitor: extern "C" fn(*mut u8)) { unsafe fn process_fde(entry: *mut u8, visitor: extern "C" fn(*mut u8)) -> *mut u8 { From c07298e58eb8804bfe7b412a6dfd7ea732a54e9a Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Sun, 3 Mar 2019 16:02:20 -0600 Subject: [PATCH 161/262] Make capstone optional with a feature --- lib/llvm-backend/Cargo.toml | 5 +++-- lib/llvm-backend/src/backend.rs | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/llvm-backend/Cargo.toml b/lib/llvm-backend/Cargo.toml index f350b263e..cdbfe63bf 100644 --- a/lib/llvm-backend/Cargo.toml +++ b/lib/llvm-backend/Cargo.toml @@ -13,7 +13,7 @@ smallvec = "0.6.8" goblin = "0.0.20" libc = "0.2.49" nix = "0.13.0" -capstone = "0.5.0" +capstone = { version = "0.5.0", optional = true } [build-dependencies] cc = "1.0" @@ -25,4 +25,5 @@ semver = "0.9" wabt = "0.7.4" [features] -debug = ["wasmer-runtime-core/debug"] \ No newline at end of file +debug = ["wasmer-runtime-core/debug"] +disasm = ["capstone"] \ No newline at end of file diff --git a/lib/llvm-backend/src/backend.rs b/lib/llvm-backend/src/backend.rs index 2d67d7a9b..f08f0fd84 100644 --- a/lib/llvm-backend/src/backend.rs +++ b/lib/llvm-backend/src/backend.rs @@ -462,6 +462,7 @@ fn get_func_from_index<'a>( (func_ptr, ctx, signature, sig_index) } +#[cfg(feature = "disasm")] unsafe fn disass_ptr(ptr: *const u8, size: usize, inst_count: usize) { use capstone::arch::BuildsCapstone; let mut cs = capstone::Capstone::new() // Call builder-pattern From 51cf9dde058778fa748f2d966f91f2f8261a6b63 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Sun, 3 Mar 2019 21:13:37 -0800 Subject: [PATCH 162/262] Move SSA value caches to the entry block. The supporting framework around LLVM will make sure to only compute values once if they are known to never change. Previously, these values were attempted to be reused from places where the users may not dominate the creation of the value. To avoid that, they are always created in the entry block now. --- lib/llvm-backend/cpp/object_loader.hh | 4 - lib/llvm-backend/src/code.rs | 11 ++- lib/llvm-backend/src/intrinsics.rs | 133 +++++++++++++++++--------- 3 files changed, 99 insertions(+), 49 deletions(-) diff --git a/lib/llvm-backend/cpp/object_loader.hh b/lib/llvm-backend/cpp/object_loader.hh index cb1b48554..67a2f5740 100644 --- a/lib/llvm-backend/cpp/object_loader.hh +++ b/lib/llvm-backend/cpp/object_loader.hh @@ -159,18 +159,14 @@ extern "C" { ) throw() { try { trampoline(ctx, func, params, results); - std::cout << "Success" << std::endl; return true; } catch(const WasmTrap& e) { - std::cout << e.description() << std::endl; *trap_out = e.type; return false; } catch(const WasmException& e) { - std::cout << e.description() << std::endl; *trap_out = WasmTrap::Type::Unknown; return false; } catch (...) { - std::cout << "unknown" << std::endl; *trap_out = WasmTrap::Type::Unknown; return false; } diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index 355a6d830..46ddffa41 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -118,6 +118,8 @@ pub fn parse_function_bodies( })?; } + // module.print_to_stderr(); + generate_trampolines(info, &signatures, &module, &context, &builder, &intrinsics); let pass_manager = PassManager::create_for_module(); @@ -170,8 +172,6 @@ fn parse_function( state.push_block(return_block, phis); builder.position_at_end(&entry_block); - let mut ctx = intrinsics.ctx(info, builder, &function); - let mut locals = Vec::with_capacity(locals_reader.get_count() as usize); // TODO fix capacity locals.extend( @@ -213,6 +213,13 @@ fn parse_function( } } + let start_of_code_block = context.append_basic_block(&function, "start_of_code"); + let entry_end_inst = builder.build_unconditional_branch(&start_of_code_block); + builder.position_at_end(&start_of_code_block); + + let cache_builder = context.create_builder(); + cache_builder.position_before(&entry_end_inst); + let mut ctx = intrinsics.ctx(info, builder, &function, cache_builder); let mut unreachable_depth = 0; for op in op_reader { diff --git a/lib/llvm-backend/src/intrinsics.rs b/lib/llvm-backend/src/intrinsics.rs index 152047b84..908448a51 100644 --- a/lib/llvm-backend/src/intrinsics.rs +++ b/lib/llvm-backend/src/intrinsics.rs @@ -4,7 +4,10 @@ use inkwell::{ context::Context, module::Module, types::{BasicType, FloatType, IntType, PointerType, StructType, VoidType}, - values::{BasicValue, BasicValueEnum, FloatValue, FunctionValue, IntValue, PointerValue}, + values::{ + BasicValue, BasicValueEnum, FloatValue, FunctionValue, InstructionValue, IntValue, + PointerValue, + }, AddressSpace, }; use std::marker::PhantomData; @@ -369,6 +372,7 @@ impl Intrinsics { info: &'a ModuleInfo, builder: &'a Builder, func_value: &'a FunctionValue, + cache_builder: Builder, ) -> CtxType<'a> { CtxType { ctx_ty: self.ctx_ty, @@ -379,6 +383,7 @@ impl Intrinsics { builder, intrinsics: self, info, + cache_builder, cached_memories: HashMap::new(), cached_tables: HashMap::new(), @@ -429,6 +434,7 @@ pub struct CtxType<'a> { builder: &'a Builder, intrinsics: &'a Intrinsics, info: &'a ModuleInfo, + cache_builder: Builder, cached_memories: HashMap, cached_tables: HashMap, @@ -445,43 +451,52 @@ impl<'a> CtxType<'a> { } pub fn memory(&mut self, index: MemoryIndex) -> (PointerValue, IntValue) { - let (cached_memories, builder, info, ctx_ptr_value, intrinsics) = ( + let (cached_memories, builder, info, ctx_ptr_value, intrinsics, cache_builder) = ( &mut self.cached_memories, self.builder, self.info, self.ctx_ptr_value, self.intrinsics, + &self.cache_builder, ); let memory_cache = cached_memories.entry(index).or_insert_with(|| { let (memory_array_ptr_ptr, index, memory_type) = match index.local_or_import(info) { LocalOrImport::Local(local_mem_index) => ( - unsafe { builder.build_struct_gep(ctx_ptr_value, 0, "memory_array_ptr_ptr") }, + unsafe { + cache_builder.build_struct_gep(ctx_ptr_value, 0, "memory_array_ptr_ptr") + }, local_mem_index.index() as u64, info.memories[local_mem_index].memory_type(), ), LocalOrImport::Import(import_mem_index) => ( - unsafe { builder.build_struct_gep(ctx_ptr_value, 3, "memory_array_ptr_ptr") }, + unsafe { + cache_builder.build_struct_gep(ctx_ptr_value, 3, "memory_array_ptr_ptr") + }, import_mem_index.index() as u64, info.imported_memories[import_mem_index].1.memory_type(), ), }; - let memory_array_ptr = builder + let memory_array_ptr = cache_builder .build_load(memory_array_ptr_ptr, "memory_array_ptr") .into_pointer_value(); let const_index = intrinsics.i32_ty.const_int(index, false); let memory_ptr_ptr = unsafe { - builder.build_in_bounds_gep(memory_array_ptr, &[const_index], "memory_ptr_ptr") + cache_builder.build_in_bounds_gep( + memory_array_ptr, + &[const_index], + "memory_ptr_ptr", + ) }; - let memory_ptr = builder + let memory_ptr = cache_builder .build_load(memory_ptr_ptr, "memory_ptr") .into_pointer_value(); let (ptr_to_base_ptr, ptr_to_bounds) = unsafe { ( - builder.build_struct_gep(memory_ptr, 0, "base_ptr"), - builder.build_struct_gep(memory_ptr, 1, "bounds_ptr"), + cache_builder.build_struct_gep(memory_ptr, 0, "base_ptr"), + cache_builder.build_struct_gep(memory_ptr, 1, "bounds_ptr"), ) }; @@ -491,10 +506,12 @@ impl<'a> CtxType<'a> { ptr_to_bounds, }, MemoryType::Static | MemoryType::SharedStatic => MemoryCache::Static { - base_ptr: builder + base_ptr: cache_builder .build_load(ptr_to_base_ptr, "base") .into_pointer_value(), - bounds: builder.build_load(ptr_to_bounds, "bounds").into_int_value(), + bounds: cache_builder + .build_load(ptr_to_bounds, "bounds") + .into_int_value(), }, } }); @@ -518,12 +535,13 @@ impl<'a> CtxType<'a> { } pub fn table(&mut self, index: TableIndex) -> (PointerValue, IntValue) { - let (cached_tables, builder, info, ctx_ptr_value, intrinsics) = ( + let (cached_tables, builder, info, ctx_ptr_value, intrinsics, cache_builder) = ( &mut self.cached_tables, self.builder, self.info, self.ctx_ptr_value, self.intrinsics, + &self.cache_builder, ); let TableCache { @@ -532,30 +550,34 @@ impl<'a> CtxType<'a> { } = *cached_tables.entry(index).or_insert_with(|| { let (table_array_ptr_ptr, index) = match index.local_or_import(info) { LocalOrImport::Local(local_table_index) => ( - unsafe { builder.build_struct_gep(ctx_ptr_value, 1, "table_array_ptr_ptr") }, + unsafe { + cache_builder.build_struct_gep(ctx_ptr_value, 1, "table_array_ptr_ptr") + }, local_table_index.index() as u64, ), LocalOrImport::Import(import_table_index) => ( - unsafe { builder.build_struct_gep(ctx_ptr_value, 4, "table_array_ptr_ptr") }, + unsafe { + cache_builder.build_struct_gep(ctx_ptr_value, 4, "table_array_ptr_ptr") + }, import_table_index.index() as u64, ), }; - let table_array_ptr = builder + let table_array_ptr = cache_builder .build_load(table_array_ptr_ptr, "table_array_ptr") .into_pointer_value(); let const_index = intrinsics.i32_ty.const_int(index, false); let table_ptr_ptr = unsafe { - builder.build_in_bounds_gep(table_array_ptr, &[const_index], "table_ptr_ptr") + cache_builder.build_in_bounds_gep(table_array_ptr, &[const_index], "table_ptr_ptr") }; - let table_ptr = builder + let table_ptr = cache_builder .build_load(table_ptr_ptr, "table_ptr") .into_pointer_value(); let (ptr_to_base_ptr, ptr_to_bounds) = unsafe { ( - builder.build_struct_gep(table_ptr, 0, "base_ptr"), - builder.build_struct_gep(table_ptr, 1, "bounds_ptr"), + cache_builder.build_struct_gep(table_ptr, 0, "base_ptr"), + cache_builder.build_struct_gep(table_ptr, 1, "bounds_ptr"), ) }; @@ -574,39 +596,46 @@ impl<'a> CtxType<'a> { } pub fn dynamic_sigindex(&mut self, index: SigIndex) -> IntValue { - let (cached_sigindices, builder, info, ctx_ptr_value, intrinsics) = ( + let (cached_sigindices, builder, info, ctx_ptr_value, intrinsics, cache_builder) = ( &mut self.cached_sigindices, self.builder, self.info, self.ctx_ptr_value, self.intrinsics, + &self.cache_builder, ); *cached_sigindices.entry(index).or_insert_with(|| { - let sigindex_array_ptr_ptr = - unsafe { builder.build_struct_gep(ctx_ptr_value, 7, "sigindex_array_ptr_ptr") }; - let sigindex_array_ptr = builder + let sigindex_array_ptr_ptr = unsafe { + cache_builder.build_struct_gep(ctx_ptr_value, 7, "sigindex_array_ptr_ptr") + }; + let sigindex_array_ptr = cache_builder .build_load(sigindex_array_ptr_ptr, "sigindex_array_ptr") .into_pointer_value(); let const_index = intrinsics.i32_ty.const_int(index.index() as u64, false); let sigindex_ptr = unsafe { - builder.build_in_bounds_gep(sigindex_array_ptr, &[const_index], "sigindex_ptr") + cache_builder.build_in_bounds_gep( + sigindex_array_ptr, + &[const_index], + "sigindex_ptr", + ) }; - builder + cache_builder .build_load(sigindex_ptr, "sigindex") .into_int_value() }) } pub fn global_cache(&mut self, index: GlobalIndex) -> GlobalCache { - let (cached_globals, builder, ctx_ptr_value, info, intrinsics) = ( + let (cached_globals, builder, ctx_ptr_value, info, intrinsics, cache_builder) = ( &mut self.cached_globals, self.builder, self.ctx_ptr_value, self.info, self.intrinsics, + &self.cache_builder, ); *cached_globals.entry(index).or_insert_with(|| { @@ -616,7 +645,11 @@ impl<'a> CtxType<'a> { let desc = info.globals[local_global_index].desc; ( unsafe { - builder.build_struct_gep(ctx_ptr_value, 2, "globals_array_ptr_ptr") + cache_builder.build_struct_gep( + ctx_ptr_value, + 2, + "globals_array_ptr_ptr", + ) }, local_global_index.index() as u64, desc.mutable, @@ -627,7 +660,11 @@ impl<'a> CtxType<'a> { let desc = info.imported_globals[import_global_index].1; ( unsafe { - builder.build_struct_gep(ctx_ptr_value, 5, "globals_array_ptr_ptr") + cache_builder.build_struct_gep( + ctx_ptr_value, + 5, + "globals_array_ptr_ptr", + ) }, import_global_index.index() as u64, desc.mutable, @@ -638,20 +675,25 @@ impl<'a> CtxType<'a> { let llvm_ptr_ty = type_to_llvm_ptr(intrinsics, wasmer_ty); - let global_array_ptr = builder + let global_array_ptr = cache_builder .build_load(globals_array_ptr_ptr, "global_array_ptr") .into_pointer_value(); let const_index = intrinsics.i32_ty.const_int(index, false); let global_ptr_ptr = unsafe { - builder.build_in_bounds_gep(global_array_ptr, &[const_index], "global_ptr_ptr") + cache_builder.build_in_bounds_gep( + global_array_ptr, + &[const_index], + "global_ptr_ptr", + ) }; - let global_ptr = builder + let global_ptr = cache_builder .build_load(global_ptr_ptr, "global_ptr") .into_pointer_value(); let global_ptr_typed = { - let int = builder.build_ptr_to_int(global_ptr, intrinsics.i64_ty, "global_ptr_int"); - builder.build_int_to_ptr(int, llvm_ptr_ty, "global_ptr_typed") + let int = + cache_builder.build_ptr_to_int(global_ptr, intrinsics.i64_ty, "global_ptr_int"); + cache_builder.build_int_to_ptr(int, llvm_ptr_ty, "global_ptr_typed") }; if mutable { @@ -660,7 +702,7 @@ impl<'a> CtxType<'a> { } } else { GlobalCache::Const { - value: builder + value: cache_builder .build_load(global_ptr_typed, "global_value") .into_int_value(), } @@ -669,38 +711,43 @@ impl<'a> CtxType<'a> { } pub fn imported_func(&mut self, index: ImportedFuncIndex) -> (PointerValue, PointerValue) { - let (cached_imported_functions, builder, ctx_ptr_value, intrinsics) = ( + let (cached_imported_functions, builder, ctx_ptr_value, intrinsics, cache_builder) = ( &mut self.cached_imported_functions, self.builder, self.ctx_ptr_value, self.intrinsics, + &self.cache_builder, ); let imported_func_cache = cached_imported_functions.entry(index).or_insert_with(|| { let func_array_ptr_ptr = unsafe { - builder.build_struct_gep(ctx_ptr_value, 6, "imported_func_array_ptr_ptr") + cache_builder.build_struct_gep(ctx_ptr_value, 6, "imported_func_array_ptr_ptr") }; - let func_array_ptr = builder + let func_array_ptr = cache_builder .build_load(func_array_ptr_ptr, "func_array_ptr") .into_pointer_value(); let const_index = intrinsics.i32_ty.const_int(index.index() as u64, false); let imported_func_ptr_ptr = unsafe { - builder.build_in_bounds_gep(func_array_ptr, &[const_index], "imported_func_ptr_ptr") + cache_builder.build_in_bounds_gep( + func_array_ptr, + &[const_index], + "imported_func_ptr_ptr", + ) }; - let imported_func_ptr = builder + let imported_func_ptr = cache_builder .build_load(imported_func_ptr_ptr, "imported_func_ptr") .into_pointer_value(); let (func_ptr_ptr, ctx_ptr_ptr) = unsafe { ( - builder.build_struct_gep(imported_func_ptr, 0, "func_ptr_ptr"), - builder.build_struct_gep(imported_func_ptr, 1, "ctx_ptr_ptr"), + cache_builder.build_struct_gep(imported_func_ptr, 0, "func_ptr_ptr"), + cache_builder.build_struct_gep(imported_func_ptr, 1, "ctx_ptr_ptr"), ) }; - let func_ptr = builder + let func_ptr = cache_builder .build_load(func_ptr_ptr, "func_ptr") .into_pointer_value(); - let ctx_ptr = builder + let ctx_ptr = cache_builder .build_load(ctx_ptr_ptr, "ctx_ptr") .into_pointer_value(); From 801979c40d36c70869e06b35667e94f41356fde4 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Sun, 3 Mar 2019 21:26:34 -0800 Subject: [PATCH 163/262] Add dynamic sigindices to the vm context. --- lib/runtime-core/src/backing.rs | 23 +++++++++++++++++++++-- lib/runtime-core/src/vm.rs | 12 ++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/lib/runtime-core/src/backing.rs b/lib/runtime-core/src/backing.rs index 9734f0c02..33cd80182 100644 --- a/lib/runtime-core/src/backing.rs +++ b/lib/runtime-core/src/backing.rs @@ -4,13 +4,14 @@ use crate::{ global::Global, import::ImportObject, memory::Memory, - module::{ImportName, ModuleInner}, + module::{ImportName, ModuleInfo, ModuleInner}, sig_registry::SigRegistry, structures::{BoxedMap, Map, SliceMap, TypedIndex}, table::Table, types::{ ImportedFuncIndex, ImportedGlobalIndex, ImportedMemoryIndex, ImportedTableIndex, - Initializer, LocalGlobalIndex, LocalMemoryIndex, LocalOrImport, LocalTableIndex, Value, + Initializer, LocalGlobalIndex, LocalMemoryIndex, LocalOrImport, LocalTableIndex, SigIndex, + Value, }, vm, }; @@ -25,6 +26,8 @@ pub struct LocalBacking { pub(crate) vm_memories: BoxedMap, pub(crate) vm_tables: BoxedMap, pub(crate) vm_globals: BoxedMap, + + pub(crate) dynamic_sigindices: BoxedMap, } // impl LocalBacking { @@ -47,6 +50,8 @@ impl LocalBacking { let vm_tables = Self::finalize_tables(module, imports, &mut tables, vmctx); let vm_globals = Self::finalize_globals(&mut globals); + let dynamic_sigindices = Self::generate_sigindices(&module.info); + Self { memories, tables, @@ -55,9 +60,23 @@ impl LocalBacking { vm_memories, vm_tables, vm_globals, + + dynamic_sigindices, } } + fn generate_sigindices(info: &ModuleInfo) -> BoxedMap { + info.signatures + .iter() + .map(|(_, signature)| { + let signature = SigRegistry.lookup_signature_ref(signature); + let sig_index = SigRegistry.lookup_sig_index(signature); + vm::SigId(sig_index.index() as u32) + }) + .collect::>() + .into_boxed_map() + } + fn generate_memories(module: &ModuleInner) -> BoxedMap { let mut memories = Map::with_capacity(module.info.memories.len()); for (_, &desc) in &module.info.memories { diff --git a/lib/runtime-core/src/vm.rs b/lib/runtime-core/src/vm.rs index 71400af70..c016c76e7 100644 --- a/lib/runtime-core/src/vm.rs +++ b/lib/runtime-core/src/vm.rs @@ -34,6 +34,12 @@ pub struct Ctx { /// A pointer to an array of imported functions, indexed by `FuncIndex`. pub(crate) imported_funcs: *mut ImportedFunc, + /// A pointer to an array of signature ids. Conceptually, this maps + /// from a static, module-local signature id to a runtime-global + /// signature id. This is used to allow call-indirect to other + /// modules safely. + pub(crate) dynamic_sigindices: *const SigId, + local_backing: *mut LocalBacking, import_backing: *mut ImportBacking, module: *const ModuleInner, @@ -59,6 +65,8 @@ impl Ctx { imported_globals: import_backing.vm_globals.as_mut_ptr(), imported_funcs: import_backing.vm_functions.as_mut_ptr(), + dynamic_sigindices: local_backing.dynamic_sigindices.as_ptr(), + local_backing, import_backing, module, @@ -86,6 +94,8 @@ impl Ctx { imported_globals: import_backing.vm_globals.as_mut_ptr(), imported_funcs: import_backing.vm_functions.as_mut_ptr(), + dynamic_sigindices: local_backing.dynamic_sigindices.as_ptr(), + local_backing, import_backing, module, @@ -468,6 +478,8 @@ mod vm_ctx_tests { vm_memories: Map::new().into_boxed_map(), vm_tables: Map::new().into_boxed_map(), vm_globals: Map::new().into_boxed_map(), + + dynamic_sigindices: Map::new().into_boxed_map(), }; let module = generate_module(); let data = &mut data as *mut _ as *mut c_void; From 87c453a0ec77bd024529aa05fa4f437c6891c13e Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Sun, 3 Mar 2019 21:38:35 -0800 Subject: [PATCH 164/262] Add check for table bounds on call_indirect. --- lib/llvm-backend/cpp/object_loader.hh | 1 + lib/llvm-backend/src/code.rs | 48 +++++++++++++++++++++++++++ lib/llvm-backend/src/intrinsics.rs | 2 ++ 3 files changed, 51 insertions(+) diff --git a/lib/llvm-backend/cpp/object_loader.hh b/lib/llvm-backend/cpp/object_loader.hh index 67a2f5740..880d97b3f 100644 --- a/lib/llvm-backend/cpp/object_loader.hh +++ b/lib/llvm-backend/cpp/object_loader.hh @@ -69,6 +69,7 @@ public: Unreachable = 0, IncorrectCallIndirectSignature = 1, MemoryOutOfBounds = 2, + CallIndirectOOB = 3, Unknown, }; diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index 46ddffa41..341848d27 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -744,6 +744,54 @@ fn parse_function( ) }; + let truncated_table_bounds = builder.build_int_truncate( + table_bound, + intrinsics.i32_ty, + "truncated_table_bounds", + ); + + // First, check if the index is outside of the table bounds. + let index_in_bounds = builder.build_int_compare( + IntPredicate::ULT, + func_index, + truncated_table_bounds, + "index_in_bounds", + ); + + let index_in_bounds = builder + .build_call( + intrinsics.expect_i1, + &[ + index_in_bounds.as_basic_value_enum(), + intrinsics.i1_ty.const_int(1, false).as_basic_value_enum(), + ], + "index_in_bounds_expect", + ) + .try_as_basic_value() + .left() + .unwrap() + .into_int_value(); + + let in_bounds_continue_block = + context.append_basic_block(&function, "in_bounds_continue_block"); + let not_in_bounds_block = + context.append_basic_block(&function, "not_in_bounds_block"); + builder.build_conditional_branch( + index_in_bounds, + &in_bounds_continue_block, + ¬_in_bounds_block, + ); + builder.position_at_end(¬_in_bounds_block); + builder.build_call( + intrinsics.throw_trap, + &[intrinsics.trap_call_indirect_oob], + "throw", + ); + builder.build_unreachable(); + builder.position_at_end(&in_bounds_continue_block); + + // Next, check if the signature id is correct. + let sigindices_equal = builder.build_int_compare( IntPredicate::EQ, expected_dynamic_sigindex, diff --git a/lib/llvm-backend/src/intrinsics.rs b/lib/llvm-backend/src/intrinsics.rs index 908448a51..f19561417 100644 --- a/lib/llvm-backend/src/intrinsics.rs +++ b/lib/llvm-backend/src/intrinsics.rs @@ -95,6 +95,7 @@ pub struct Intrinsics { pub trap_unreachable: BasicValueEnum, pub trap_call_indirect_sig: BasicValueEnum, + pub trap_call_indirect_oob: BasicValueEnum, pub trap_memory_oob: BasicValueEnum, // VM intrinsics. @@ -293,6 +294,7 @@ impl Intrinsics { trap_unreachable: i32_zero.as_basic_value_enum(), trap_call_indirect_sig: i32_ty.const_int(1, false).as_basic_value_enum(), + trap_call_indirect_oob: i32_ty.const_int(3, false).as_basic_value_enum(), trap_memory_oob: i32_ty.const_int(2, false).as_basic_value_enum(), // VM intrinsics. From ae3b2b2a42f9008ad4002bce6d37b2f79da6b991 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Sun, 3 Mar 2019 21:56:30 -0800 Subject: [PATCH 165/262] Add bounds checking for memory accesses on dynamic memories --- lib/llvm-backend/src/code.rs | 104 ++++++++++++++++++++++++++++- lib/llvm-backend/src/intrinsics.rs | 26 ++------ 2 files changed, 106 insertions(+), 24 deletions(-) diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index 341848d27..471cb78db 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -21,7 +21,7 @@ use wasmparser::{ BinaryReaderError, CodeSectionReader, LocalsReader, MemoryImmediate, Operator, OperatorsReader, }; -use crate::intrinsics::{CtxType, GlobalCache, Intrinsics}; +use crate::intrinsics::{CtxType, GlobalCache, Intrinsics, MemoryCache}; use crate::read_info::type_to_type; use crate::state::{ControlFrame, IfElseState, State}; use crate::trampolines::generate_trampolines; @@ -1571,6 +1571,8 @@ fn parse_function( let effective_address = resolve_memory_ptr( builder, intrinsics, + context, + &function, &mut state, &mut ctx, memarg, @@ -1583,6 +1585,8 @@ fn parse_function( let effective_address = resolve_memory_ptr( builder, intrinsics, + context, + &function, &mut state, &mut ctx, memarg, @@ -1595,6 +1599,8 @@ fn parse_function( let effective_address = resolve_memory_ptr( builder, intrinsics, + context, + &function, &mut state, &mut ctx, memarg, @@ -1607,6 +1613,8 @@ fn parse_function( let effective_address = resolve_memory_ptr( builder, intrinsics, + context, + &function, &mut state, &mut ctx, memarg, @@ -1621,6 +1629,8 @@ fn parse_function( let effective_address = resolve_memory_ptr( builder, intrinsics, + context, + &function, &mut state, &mut ctx, memarg, @@ -1633,6 +1643,8 @@ fn parse_function( let effective_address = resolve_memory_ptr( builder, intrinsics, + context, + &function, &mut state, &mut ctx, memarg, @@ -1645,6 +1657,8 @@ fn parse_function( let effective_address = resolve_memory_ptr( builder, intrinsics, + context, + &function, &mut state, &mut ctx, memarg, @@ -1657,6 +1671,8 @@ fn parse_function( let effective_address = resolve_memory_ptr( builder, intrinsics, + context, + &function, &mut state, &mut ctx, memarg, @@ -1669,6 +1685,8 @@ fn parse_function( let effective_address = resolve_memory_ptr( builder, intrinsics, + context, + &function, &mut state, &mut ctx, memarg, @@ -1685,6 +1703,8 @@ fn parse_function( let effective_address = resolve_memory_ptr( builder, intrinsics, + context, + &function, &mut state, &mut ctx, memarg, @@ -1701,6 +1721,8 @@ fn parse_function( let effective_address = resolve_memory_ptr( builder, intrinsics, + context, + &function, &mut state, &mut ctx, memarg, @@ -1717,6 +1739,8 @@ fn parse_function( let effective_address = resolve_memory_ptr( builder, intrinsics, + context, + &function, &mut state, &mut ctx, memarg, @@ -1733,6 +1757,8 @@ fn parse_function( let effective_address = resolve_memory_ptr( builder, intrinsics, + context, + &function, &mut state, &mut ctx, memarg, @@ -1750,6 +1776,8 @@ fn parse_function( let effective_address = resolve_memory_ptr( builder, intrinsics, + context, + &function, &mut state, &mut ctx, memarg, @@ -1766,6 +1794,8 @@ fn parse_function( let effective_address = resolve_memory_ptr( builder, intrinsics, + context, + &function, &mut state, &mut ctx, memarg, @@ -1782,6 +1812,8 @@ fn parse_function( let effective_address = resolve_memory_ptr( builder, intrinsics, + context, + &function, &mut state, &mut ctx, memarg, @@ -1798,6 +1830,8 @@ fn parse_function( let effective_address = resolve_memory_ptr( builder, intrinsics, + context, + &function, &mut state, &mut ctx, memarg, @@ -1814,6 +1848,8 @@ fn parse_function( let effective_address = resolve_memory_ptr( builder, intrinsics, + context, + &function, &mut state, &mut ctx, memarg, @@ -1832,6 +1868,8 @@ fn parse_function( let effective_address = resolve_memory_ptr( builder, intrinsics, + context, + &function, &mut state, &mut ctx, memarg, @@ -1846,6 +1884,8 @@ fn parse_function( let effective_address = resolve_memory_ptr( builder, intrinsics, + context, + &function, &mut state, &mut ctx, memarg, @@ -1860,6 +1900,8 @@ fn parse_function( let effective_address = resolve_memory_ptr( builder, intrinsics, + context, + &function, &mut state, &mut ctx, memarg, @@ -1964,6 +2006,8 @@ fn parse_function( fn resolve_memory_ptr( builder: &Builder, intrinsics: &Intrinsics, + context: &Context, + function: &FunctionValue, state: &mut State, ctx: &mut CtxType, memarg: MemoryImmediate, @@ -1975,8 +2019,62 @@ fn resolve_memory_ptr( let var_offset = builder.build_int_z_extend(var_offset_i32, intrinsics.i64_ty, &state.var_name()); let effective_offset = builder.build_int_add(var_offset, imm_offset, &state.var_name()); - let (mem_base, mem_bound) = ctx.memory(MemoryIndex::new(0)); - let mem_base_int = builder.build_ptr_to_int(mem_base, intrinsics.i64_ty, &state.var_name()); + let memory_cache = ctx.memory(MemoryIndex::new(0)); + + let mem_base_int = match memory_cache { + MemoryCache::Dynamic { + ptr_to_base_ptr, + ptr_to_bounds, + } => { + let base = builder + .build_load(ptr_to_base_ptr, "base") + .into_pointer_value(); + let bounds = builder.build_load(ptr_to_bounds, "bounds").into_int_value(); + + let base_as_int = builder.build_ptr_to_int(base, intrinsics.i64_ty, "base_as_int"); + + let base_in_bounds = + builder.build_int_compare(IntPredicate::ULT, base_as_int, bounds, "base_in_bounds"); + + let base_in_bounds = builder + .build_call( + intrinsics.expect_i1, + &[ + base_in_bounds.as_basic_value_enum(), + intrinsics.i1_ty.const_int(1, false).as_basic_value_enum(), + ], + "base_in_bounds_expect", + ) + .try_as_basic_value() + .left() + .unwrap() + .into_int_value(); + + let in_bounds_continue_block = + context.append_basic_block(function, "in_bounds_continue_block"); + let not_in_bounds_block = context.append_basic_block(function, "not_in_bounds_block"); + builder.build_conditional_branch( + base_in_bounds, + &in_bounds_continue_block, + ¬_in_bounds_block, + ); + builder.position_at_end(¬_in_bounds_block); + builder.build_call( + intrinsics.throw_trap, + &[intrinsics.trap_memory_oob], + "throw", + ); + builder.build_unreachable(); + builder.position_at_end(&in_bounds_continue_block); + + base_as_int + } + MemoryCache::Static { + base_ptr, + bounds: _, + } => builder.build_ptr_to_int(base_ptr, intrinsics.i64_ty, "base_as_int"), + }; + let effective_address_int = builder.build_int_add(mem_base_int, effective_offset, &state.var_name()); Ok(builder.build_int_to_ptr(effective_address_int, ptr_ty, &state.var_name())) diff --git a/lib/llvm-backend/src/intrinsics.rs b/lib/llvm-backend/src/intrinsics.rs index f19561417..9e91c5911 100644 --- a/lib/llvm-backend/src/intrinsics.rs +++ b/lib/llvm-backend/src/intrinsics.rs @@ -398,7 +398,8 @@ impl Intrinsics { } } -enum MemoryCache { +#[derive(Clone, Copy)] +pub enum MemoryCache { /// The memory moves around. Dynamic { ptr_to_base_ptr: PointerValue, @@ -452,7 +453,7 @@ impl<'a> CtxType<'a> { self.ctx_ptr_value.as_basic_value_enum() } - pub fn memory(&mut self, index: MemoryIndex) -> (PointerValue, IntValue) { + pub fn memory(&mut self, index: MemoryIndex) -> MemoryCache { let (cached_memories, builder, info, ctx_ptr_value, intrinsics, cache_builder) = ( &mut self.cached_memories, self.builder, @@ -462,7 +463,7 @@ impl<'a> CtxType<'a> { &self.cache_builder, ); - let memory_cache = cached_memories.entry(index).or_insert_with(|| { + *cached_memories.entry(index).or_insert_with(|| { let (memory_array_ptr_ptr, index, memory_type) = match index.local_or_import(info) { LocalOrImport::Local(local_mem_index) => ( unsafe { @@ -516,24 +517,7 @@ impl<'a> CtxType<'a> { .into_int_value(), }, } - }); - - match memory_cache { - MemoryCache::Dynamic { - ptr_to_base_ptr, - ptr_to_bounds, - } => { - let base = builder - .build_load(*ptr_to_base_ptr, "base") - .into_pointer_value(); - let bounds = builder - .build_load(*ptr_to_bounds, "bounds") - .into_int_value(); - - (base, bounds) - } - MemoryCache::Static { base_ptr, bounds } => (*base_ptr, *bounds), - } + }) } pub fn table(&mut self, index: TableIndex) -> (PointerValue, IntValue) { From ab550f46fcb6763eb088aa6b7416426a565be56c Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Sun, 3 Mar 2019 22:11:40 -0800 Subject: [PATCH 166/262] Fix bug resulting from comparing the memory base instead of the memory offset to the memory bounds. --- lib/llvm-backend/src/code.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index 471cb78db..51815f3f6 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -2033,8 +2033,12 @@ fn resolve_memory_ptr( let base_as_int = builder.build_ptr_to_int(base, intrinsics.i64_ty, "base_as_int"); - let base_in_bounds = - builder.build_int_compare(IntPredicate::ULT, base_as_int, bounds, "base_in_bounds"); + let base_in_bounds = builder.build_int_compare( + IntPredicate::ULT, + effective_offset, + bounds, + "base_in_bounds", + ); let base_in_bounds = builder .build_call( From 3f9dbca17f987a411be00e52b753505ad66804fd Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Sun, 3 Mar 2019 22:47:34 -0800 Subject: [PATCH 167/262] List specific supported features for validator. --- lib/llvm-backend/src/lib.rs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/lib/llvm-backend/src/lib.rs b/lib/llvm-backend/src/lib.rs index b1ddc1f18..d70f0f363 100644 --- a/lib/llvm-backend/src/lib.rs +++ b/lib/llvm-backend/src/lib.rs @@ -76,7 +76,19 @@ impl Compiler for LLVMCompiler { } fn validate(bytes: &[u8]) -> Result<(), CompileError> { - let mut parser = wasmparser::ValidatingParser::new(bytes, None); + let mut parser = wasmparser::ValidatingParser::new( + bytes, + Some(wasmparser::ValidatingParserConfig { + operator_config: wasmparser::OperatorValidatorConfig { + enable_threads: false, + enable_reference_types: false, + enable_simd: false, + enable_bulk_memory: false, + }, + mutable_global_imports: false, + }), + ); + loop { let state = parser.read(); match *state { From ec4e476cc6aefe8a01544e0c216f5e0b8583e71d Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 4 Mar 2019 13:51:13 +0100 Subject: [PATCH 168/262] fix(runtime-core) Remove an unused import. This patch removes an unused import, namely `crate::sys::Memory`. --- lib/runtime-core/src/error.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/runtime-core/src/error.rs b/lib/runtime-core/src/error.rs index abc69cc5e..0e2ab6eb7 100644 --- a/lib/runtime-core/src/error.rs +++ b/lib/runtime-core/src/error.rs @@ -1,4 +1,3 @@ -use crate::sys::Memory; use crate::types::{ FuncSig, GlobalDescriptor, MemoryDescriptor, MemoryIndex, TableDescriptor, TableIndex, Type, }; From d9073c03c65a899647dee667ebcdd336a53288b9 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 4 Mar 2019 13:53:41 +0100 Subject: [PATCH 169/262] fix(runtime-core) `hasher` does not need to be mutable. This patch updates the `hasher` variable. It is declared as mutable, but it's never mutated. --- lib/runtime-core/src/cache.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/runtime-core/src/cache.rs b/lib/runtime-core/src/cache.rs index 339b78fcc..1cb804655 100644 --- a/lib/runtime-core/src/cache.rs +++ b/lib/runtime-core/src/cache.rs @@ -48,7 +48,7 @@ impl WasmHash { let mut state = blake2bp::State::new(); state.update(wasm); - let mut hasher = state.finalize(); + let hasher = state.finalize(); let generic_array = hasher.as_bytes(); first_part.copy_from_slice(&generic_array[0..32]); From 42c9bdf8c233a87ff5434d313fe917f142401e4f Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 4 Mar 2019 13:59:37 +0100 Subject: [PATCH 170/262] fix(clif-backend) Remove an unused variable declaration. The `compiled_functions` variable is declared twice. The first declaration is never used. This patch removes it. --- lib/clif-backend/src/resolver.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/clif-backend/src/resolver.rs b/lib/clif-backend/src/resolver.rs index 53b3a789a..dce331b58 100644 --- a/lib/clif-backend/src/resolver.rs +++ b/lib/clif-backend/src/resolver.rs @@ -94,7 +94,6 @@ impl FuncResolverBuilder { info: &ModuleInfo, ) -> CompileResult<(Self, HandlerData)> { let num_func_bodies = function_bodies.len(); - let mut compiled_functions: Vec<(Vec, RelocSink)> = Vec::with_capacity(num_func_bodies); let mut local_relocs = Map::with_capacity(num_func_bodies); let mut external_relocs = Map::with_capacity(num_func_bodies); From 5744f6896ff44c3c7c57630d3fff040714ac3c47 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 4 Mar 2019 14:03:07 +0100 Subject: [PATCH 171/262] fix(clif-backend) `Module::new` does not use its argument. The `Module::new` method requires an argument (`wasm: &[u8]`) that is never used. This patch removes the argument, and updates the code accordingly. --- lib/clif-backend/src/lib.rs | 2 +- lib/clif-backend/src/module.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/clif-backend/src/lib.rs b/lib/clif-backend/src/lib.rs index c4abf644f..88de51e12 100644 --- a/lib/clif-backend/src/lib.rs +++ b/lib/clif-backend/src/lib.rs @@ -44,7 +44,7 @@ impl Compiler for CraneliftCompiler { let isa = get_isa(); - let mut module = module::Module::new(wasm); + let mut module = module::Module::new(); let module_env = module_env::ModuleEnv::new(&mut module, &*isa); let func_bodies = module_env.translate(wasm)?; diff --git a/lib/clif-backend/src/module.rs b/lib/clif-backend/src/module.rs index 07efe9bd3..9e934ee0a 100644 --- a/lib/clif-backend/src/module.rs +++ b/lib/clif-backend/src/module.rs @@ -25,7 +25,7 @@ pub struct Module { } impl Module { - pub fn new(wasm: &[u8]) -> Self { + pub fn new() -> Self { Self { info: ModuleInfo { memories: Map::new(), From ddc385a4aca2eca161bfb0f9b47742243835b69b Mon Sep 17 00:00:00 2001 From: Mackenzie Clark Date: Fri, 1 Mar 2019 10:52:31 -0800 Subject: [PATCH 172/262] git ignore vscode directory --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index dd8330f3e..22c3f7454 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,5 @@ /artifacts .DS_Store .idea + +\.vscode From cf2909f5f3546e56ed436ec5fdde6f3c7f73c8ed Mon Sep 17 00:00:00 2001 From: Mackenzie Clark Date: Fri, 1 Mar 2019 10:53:40 -0800 Subject: [PATCH 173/262] add alternative assert function for emscripten --- lib/emscripten/tests/emtests/_common.rs | 41 +++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/lib/emscripten/tests/emtests/_common.rs b/lib/emscripten/tests/emtests/_common.rs index 8d3e00296..f3cc9af7f 100644 --- a/lib/emscripten/tests/emtests/_common.rs +++ b/lib/emscripten/tests/emtests/_common.rs @@ -41,3 +41,44 @@ macro_rules! assert_emscripten_output { ); }}; } + +pub fn assert_emscripten_output(wasm_bytes: &[u8], raw_expected_str: &str) { + use wasmer_clif_backend::CraneliftCompiler; + use wasmer_emscripten::{ + EmscriptenGlobals, + generate_emscripten_env, + stdio::StdioCapturer + }; + + let module = wasmer_runtime_core::compile_with(&wasm_bytes[..], &CraneliftCompiler::new()) + .expect("WASM can't be compiled"); + + let mut emscripten_globals = EmscriptenGlobals::new(&module); + let import_object = generate_emscripten_env(&mut emscripten_globals); + let mut instance = module.instantiate(&import_object) + .map_err(|err| format!("Can't instantiate the WebAssembly module: {:?}", err)).unwrap(); + + let capturer = StdioCapturer::new(); + + wasmer_emscripten::run_emscripten_instance( + &module, + &mut instance, + "test", + vec![], + ).expect("run_emscripten_instance finishes"); + + let raw_output_string = capturer.end().unwrap().0; + + // trim the strings to avoid cross-platform line ending and white space issues + let output = raw_output_string.trim(); + let expected_output = raw_expected_str.trim(); + + let contains_output = output.contains(expected_output); + + assert!( + contains_output, + "Output: `{}` does not contain expected output: `{}`", + output, + expected_output + ); +} From 2ea9d0b09b91d19935047c4609e9217e37cba0b4 Mon Sep 17 00:00:00 2001 From: Mackenzie Clark Date: Fri, 1 Mar 2019 10:54:39 -0800 Subject: [PATCH 174/262] add __syscall42 (pipe) --- lib/emscripten/emtests/test_pipe.c | 13 ++++++++++ lib/emscripten/emtests/test_pipe.out | 1 + lib/emscripten/emtests/test_pipe.wasm | Bin 0 -> 45365 bytes lib/emscripten/src/lib.rs | 1 + lib/emscripten/src/syscalls/mod.rs | 28 ++++++++++++++++++++++ lib/emscripten/tests/emtests/mod.rs | 1 + lib/emscripten/tests/emtests/test_pipe.rs | 8 +++++++ 7 files changed, 52 insertions(+) create mode 100644 lib/emscripten/emtests/test_pipe.c create mode 100644 lib/emscripten/emtests/test_pipe.out create mode 100644 lib/emscripten/emtests/test_pipe.wasm create mode 100644 lib/emscripten/tests/emtests/test_pipe.rs diff --git a/lib/emscripten/emtests/test_pipe.c b/lib/emscripten/emtests/test_pipe.c new file mode 100644 index 000000000..c8f650310 --- /dev/null +++ b/lib/emscripten/emtests/test_pipe.c @@ -0,0 +1,13 @@ +#include +#include +#include +#include + +int main() { + int mypipe[2]; + printf("pipe\n"); + if (pipe(mypipe)) { + printf("error\n"); + } + return 0; +} diff --git a/lib/emscripten/emtests/test_pipe.out b/lib/emscripten/emtests/test_pipe.out new file mode 100644 index 000000000..6b14dd0e0 --- /dev/null +++ b/lib/emscripten/emtests/test_pipe.out @@ -0,0 +1 @@ +pipe diff --git a/lib/emscripten/emtests/test_pipe.wasm b/lib/emscripten/emtests/test_pipe.wasm new file mode 100644 index 0000000000000000000000000000000000000000..1aa68a5c4b7df6bdb0bd1d99891c867a163292b6 GIT binary patch literal 45365 zcmeFacbt{gwf}#fcFut_Faro;Wo-*!M`JIM2X&;xlHyIgH;FAIamJDvkR&%o1}UPV zVi#;!K?Oy`iUk#W!`>Bpudz42@6US93?%n{U%&6)zgKWOXFt2Fz4qE`x3$+^yL7;q zL!(lu6#cGg|7865@zMDGqvB6#|JXlE1mP>~pAqdLN>|!HIm$ocqm;aeEA3w%e`GyT zbYyhY{_&CHqa*h(mG)1I(D;_5Z!-F@alH>X@bLDrKOcL*L9Kg@8{PihaGnK*xlO?|MMQB4?Vp7uSG1C0vwmaNr@MR}Skj zcJ!ft+V$`w2;O^adp%*#UH9EH-($oszu0T<{r3LF&+4J&0%9C>#2wxynL~^I6m{>O z?6^ae##tK0@Jy6Or6ekqqqq`Ps@=LprS3_sp+}EWnx;vTl#)^ur9GpFG+^6E%3t*y zAFUhL_>=G_Fa3Y~IWpQ6&h&puxok`SyKr$_`+KyDg1dezw?~b=Xq3_I?S~yM);M77 z!G|AKTD`L0?|*;D5o7*X+Bw_r_wA!cm-;sDcgP{*4&Cp-F@L6o4*t;=rD55AhaPb7 zVWmD5eh(pQX%&3lMx|Zc2XB>j&Gs8}V0&w6x9-3DD{XPeA>z;Gh7})t?%rqg7?JAW zF@JQ<{`sE{IB0aKcXt90YRw&VV}pPEjD&}`k1qA<=AS=5VBF|ZQ@5t5v~E=EKD^(E z5o`8eb;O7f-8=4zcNiQ+-NkWTk=1($+vFfp6O64HI-@>HP*7y zx;-0f<&u@w>sjmWKNhXmSUWJP3P6RN<^VifZpv24t1Th3N=WfGwFKHEl=6Gmva~5* z-J+%)Lu_$g+C3ze>_%CY^?K%|##;XHT9zqA{rlC!qIKK0FExih+8>1?VNqKcV`K7YOgPGpB5g}JHnL-* zJQ^ELi}HI18h_)lE#dsg&W}Wa%Okry67*{$yVgS%N4D5Q9*hike$*VEj_hd=&jo61 zcr~(DqkR0B@IfSmKA_C6B5<^?qOIdnMy9->B}|MBcfNusfj~Spp^}UZC&qSSoG0yJ zMyx{9mT+-wxEZlhgUN|;OSmewt7641ifvIW6z`7h?l_Oy!=nnZM?Ll8C`6EXy`Ex( ze2!D&wKxO!8`5I65`lD?mRXC614AVMb~*(mWm)E>7*@G*8>YRjCnuRoWhIQXIZ<;jYx~ zO7m!3Sen{WlDCEDVVBgNC)JyZ!#6H`lG-Pp>bumw!_yX~W=8bXtUa8X5r=PFI4?6k z&Vx5D%j~jDysdM{R+Lp7a#7iEw`Gc;sQ29ShEmjo7JPDL z*>J~Xt>H%fh+~$Ng$i8pNZD{p94z=9Lv@}j+l^)M$D3t)uB=3#lnwW0XQC_1E#bSe z;coPx7wF*4;h2gYQ-Le;h0Z*uRNx$SymKpdEtv2vSPPZ z+QNMmyRRZh%PO|40=Id1dw8#+n!i_31<3|Q_vANpw>`tJvU|PGF){;I4-i|qI5i8nN@3HakcoI%x9$*?x+F_JnyK2=;CUqHbgb%C}->ABg0ij zg=vvZ6PA^{e@i$avJ9WSyCS>Gi@!UvyIIJz zhkF!a_b73(MrsfD*5TY28SY+(Q&rmg)pu0FLy_U`_ZWH;Z1ZqrxT+ejm=9L~ zJ`XI7>hr*(kv-}wsKSbjQTS!eerZcRTdW@bd}O#HV5#SN0URUq zbr1n0c`-8F@~0O>yf>#3cnH+Q^+e(Yk0$xSI31nBYV?Ry%pJ80$B=c zWhBj)FJI26_I6}%D|CQDN!anj&Mo1c$ljrEj0^8Z_AXUz3-1Yvy$8YHkL-PtEgR4h zK8)-`Pxet{AJNWj;p50~@6q(1C>bAP!>5sbN`{Wcmhg|r{^1!ui|jKRvMqcb87V&} z!xvHB)4l-nFO{C4vEl2;zK-(7ap9ZD2>k}e{5G<0og2P$Po*V%A5j_mo@wic$bKNM zEi8`=_Z>hxV(W;*TD6)+leL_4Cd4+u*Rw~*cC@cRCdCXwlUS!hnjQH6$M!}PhUPnk zd#V|k1~iAsF~5{BCC*o~DRFB!Cbr4iEvO5`wJ*f^|B zkof?;ruxEhu^s0K93R{9vF593vEkHeC&Y$ZV?;P9wv)7SKEW}Z9@}(%tr>O&)^L7D z<+qo>uOZ9$*o?OQ@(DG?Z&(IiD;SDB3OnRPsAc-q2su@QY8sjgQXzH#A(*!Z}Co!O1Cn3=z7!<%Ef+1v0INDy|mTjDSxvmfKz zA&jWm2od$x*lrbFb`HaAXlTyx?22c&jp$^fqB(9asXcZLyV&rsyNwDXoo7diXK#z` zHZNvzY>S;|Z;uTpp1mVB-0ma7ow40Xr{F8I-D~0YYVkQTvt4T8&Z>>nl(!_dB@XGX z*zWRXyC=4Lgx*N;?7gww>(Tecc3&Ls2h?5qsoDLW_<`6SP~tnQROa?-XcnLGv5P)- zCs7z#FqjQf)gO%Q!A_RQ>f6(YV#5jZhhuBDhvO09k=PzlvS9?bgr%|JhK&l3#rBv7 zYg&Cgw#OZ_Cy3Kv|72`Wdcae$;fAqM*Ff@gk%PLt7~6}U;HB7Ja_nD@?d2jGN-T?Q znMc0@HXi+IY_AecL*`oXy%L8lNfNf9XTK!>i}Kr+VGG+PY~_u!g=qE~{lEde9^2~< z=#ALkP&r$O;%~SEpZJ|pnQ zv3*Q09}_;&@L-?N>;4gI-S-bi<{vSo`sxpSpw4Hpedc9+9vhBU{2~^r(Dh5C6XNI3 zpwpKOegA3yxl*ZL#r9QKHGB=2i%q_c4flkXHB1G36Wcdlz_+n|>m>Ltw(ndHk}Lj) z*l^!^2I2v+JT{!_SA#kr(vet4q8WceViOWo`DmmU$qE|gN;NSt+=N7QAr*ioC5CfC zIk7eDHfudNIiV3I3qZ4T{FKC|Bw7(3lTaf4{n*5C$2hEE#4&3nc3h&U;}bjHk(rj* zv_z}C6BJ@6D6uarfOBFU&Pj>kPINfUN;^HFZwbuFiQ%Su485(HjYML&W})9K0l;Z| zU%|ESCCB0vAK!O^dx3F+y*E zD{f5eMsJmy+{1Eg5v^v6Xug{hyP2rAa7$vin}B(1Vz(w?K(QJd;0<`2^8+Km?TO(A z)M-b*xFfMUoZ;?F>`n-#7y|T5Qx9O}k=WgdEup3FO6)Et={{k`7O zUQiu6UE{vQaJSXjPi=L7Vz`x?^TEV$9-`K}%^BjM#2#|A9!~6G4|yc9M_h!wl*H7& zIXtTF^{5beC<&`&Hb860$Ecmw0*@!GAs>gZPbBtOQmi4LNNV9p5$;LI{B&YZC!xRc zuI__;f34kKN^Et83wxq)#@8)shyPO&s_fG<=L1pJ*5nr?se+0 za9WxHTxI^ue#TeLy5&Qdlc;3A88cC8r=@lZxSt9>_*=v2shyhI>5Qpoq=tiPXQp;$ zDuG35<*Gd6RhgOEOs~q>sh#bKmU{R(so~B5^0}$u&Pn$O=eciYIx3u>8XxC#sBmr7 zuGNxeWzeaZ*Ow&F0HC2$_#5 zevEKwYPgFid3I{Eg{HZ1e@<$1Qc>qJPjDINUY;6GNv}xl3Lr8f)<{ij&P{Eur=FME zJTLaj)UNC*RO8CLG-Sn)0uehP=e?=nM9%wCyD!z`x4beU+@IS0WGt|FKrv0bg$Gk} zY#&PP0Was_)bKwHR*$4c>?0{dZfcJz=YwfJp0PHy$Mkhy8n(^!_a{VzJ@S)91-6Eq zlBHogMQoo>Ragzld)St70(!AA?TFY3hFd_Lu1)P)C&YF2pq6kw-=u2|H>7rbYB!MT#?){N2wRleb!jmZEaL3(=G1Uv zlDn#T!8f;X$W*mk2)fmMu-|R+bP{fHYJ4vS>NT80h;s@)ygjws9g{m!yTcop{I|e# zcczB#cG`1EYJ4n#>29dn4F%I}+mO+^cU2+4-KpW`L*jcbPQb0|@ z|CO3`a!xJCY1_Ak$5Y!bAHREeBDL*1k$*BZ+!G*wOV#Lu+m8xQrG~qO-S^E^ySXaP zBwKTMCAC-Tt)Ly!_F%GI7a~~=saw&lpH}x(dC#PVdm6$$s}^_~YCo6Sv#C8taWACy zLKpA7nA(d@p??O-*zkh5@TJsVaz=PLwUm)bJ%+6t6XQ0nZr zucr1Y{kA>4meP~$H6IYS4ZGzh6@9bR>4o(0;7KAHT+m6S*He34<(?sI-k>u4ypwlz%`w5e03a8s=K0rU={p$0SPx~BfzDVs0HTo0v1hx7w_ho8dLWkz? zm4>;mlw`ioS6`?0wMTrD+8%gEgl|*B|1HG7zG~Nt$>$HWJ(x*q42kZ^U*EufqN(Nm zVk)W6N#CdWl7aTUh#PVgkK?ZIz0;q;aAA~PS4GQ@GInoPS27-_!Y9a)AQgU{0h0Z)APh2{0dpx>3Lxg zeuX^K>3Mw+euXUS^t?X^ze3*b^n5l5zd}Cl^n5o6ze2w1^h_FzUm+cxo@s;eD`aY? z=d{826*9fkbIxG=3OTFObMavO3YpdEnL8N2LgsXO77oU*koldSn+M}p$PJyIC4=!R zWO1kG!NK?ya&O&ZKgoZ^wjb8?wOMM*)6kJwN0xJ#Jt4CR%th?*`AZnfvCJlV)Fh5S zvtpK*l-0uI4Bnp1x%-sN05+MV$7WidP0>ldmT<@Vkv@T}(~ips*J|we%y7qf)E;Ey zd^@vg9(6)yCuF(fI@K3PCuaH01MNhm^`%3TFCCgR>z$NYlfX^SY`V|RCuc_3$>4K} z5IZGn4yR>yT1Hpn(2`k~eMyrle0pZ5dyX?QJHxAbCcAFZNs@O)7MhBM0t3ZN9|66X zvs4@#hZ&j8@XRwao5|{?!@X1H^+wy>ybi|G0w zsS#%u$EcajsuN3fx*#(gQ5On?aJ`5|$?$OESB}%eqvJb1@X3o!M-Unv>b3 z^~RY)<6JHXb~)6zf>YHDUu&4_t#d`aK%47LKp?F%FS9GW39ifxH_xL0a3KJ$%IqqS zo6oxApPJ`tZ=S1_xFOXZrx^VfsOAf@5#buN97O-lp^jiGcda+&U~kI7s`ho6;jX2@ zuFvdxWw@}j!3K*6H)M8$)BMKFZuIKkl-W)72D>o}gS#5+LT|9aYN$n-E%Hn^XLhqU z)Ge9a;<<0l>{d0@U>|pFu-IsEW{W-f?U~^~^A3gB9Zm`FD0d>~&BBt*mN>!hLNM&$ z?p9kYfxh=-c8^Eh%Yvld7WdK?_lX|&LCFVHOV#K>)_+-eD6@w={ll3(?4TYIsD}Wx zG_$21^=M{~)ImK8sK*4s9s}0noE&E1iOe3z!c&>yd5U~b>suS8XEMXjX6jk~YBTqo zVpP-TGs8XC*}{)Q_7^gyuNOr4Vqf-RX1Hf5<)uvh_$4J)&wj>p5eUn?%x>KQzQQ&) zvzHZ>)i<%PW`+~!*D`xefD6T}*OBoSfZx!j)825vY-|g_1OoWYPQY(vhI`Y?q&{ze z&)W!$|L~k+QR#py$`JB@IhuDsHq9&nCrtLeq8v-JreDG ztg3&kB*3C&K0!^&VSOt6#Yq3i>>nQTS!TFTsnqA0eXdGz=!nkKSDAg4N#6T)R+j~S zlNs)7di=KvvTqA~m01wK%MACK*XuJc_4~|lpVq5Y@}iM<{J_BKMKA9}rlV{fW%Zc} zWy6WW6U)?KV!5aRVymfTo9fC>$Cm9_PkUV1jw@?OKfY|oE8$cRo>sPL9(-ciP9&J6 zn`_0)3Mkm#@pWlWd8Pa%Ge}q>{9=Yiw*S#VJELVZ8NEC zlN{pYvP~|Fl2gitn^1-w_^b9i21PN&79n9LR(#97Yn@)U)4g!#8svRvlw%HDSPTA&o16)?N%gUfk4&pB_8*Yx1ig;jL zQ8t{aSR<oDe(ZJxups%%%)>9~{doL@HFJcmLGpj=%xoI??7E%frPE!(x_{3wnh6=K&p{9YO!t}oZeog2!A zyWV3M9(tjwQZ`&KHBm1K@E7sn0{olHcC#9AQCWh?TgnpP^H&XiYndLZwz`ct5{wOt zQA#Y^VjAuCvfb{Lz5~rH<@fORaHsOvonA8eVY{E&t>w_yej4^+Zt;-2%66C60&VV|1qQy=R3ihb`X8?G4p7)yb3Z`p8tRRaP@a$nhSx2h-&c)cXRzrSqvJ6aEj zGampkx^6!xpq*M}RCus#4=Qj#=%+lSbs_#kWqSzSw{hX&vONrrZDFYZ*;4BKXxSbm znS}U{mF+Q4_Bb2~6SRdV%7$B7ZVyi?86RWAQ)PRK3=-l$UACt^!!y(cqPB%+QPM2i zvt)R_j1d3%a%*@&=?NMeUM$;-WeM?LDjT6Mp_BP?*_&u_^;4%_DXqNc(rV= z64e%7D;sVZFkdg*>*dg|5aRdqMtsY8f=>N**>L^p^n=OYDcd{F$?ul!U5KU_0$hk+ z^wIa!?)^|JDcgHxd!J_i0HtQ9?}u=$n%%?O!$;nSKk{bx66?jl^BeI#{Tu5$TUrC6X*NEbbz*|8PFtx_ilV`&aC7=Z3$;r>}*$VJf~vkRKj@`JFlYM+4&Va-{8Ma&g4Sk*%h1Z#a-qe8t3v# zu}i$7QtT4vR%~u1%&XWuFYL;SUFmpSB|PSV$NY-T_o%BYc2ymZs{y?L0JZ=$7FG;k z3rKoxMQh20Y7?z4ul2?ukiq@B3gM#U^%cWi=TUo*kzGK=Zt$oZD|TaL0uBIN%ndwF{UGAjG!m2gYN8~zrDd~?Na zrkaW(09LuJVz@IQ>f(wm7Wdz*EE$dI?FnhWOq;{)6}#Q}WOgOop`dVQ#qit-J(dVt zO+j~6?5>I?y}K1+cY85QoG|xzBT}_{D~7wLURhhxnTF}^{tBNy-#t*V2ZYM~%Hxv zO6X~OhhMOV@sP(W_PAH#sfs?BQr67PL z&sGfgkcvX3LG@w6d#+;7IbP3K?0N8Fx@%+`R;kZ-FQBon&;bf1q0e?NR_sMoV3}qr z_7YIq!pnkUFH_@JD)tJ=G~2yeu~$9WYZZHq7H$i#R}A-Zr9Hf%WPFSbZ&vJ0GHAAY zt730?hPNyBHY9Be?^KMG?~vi$3bWn2wCMXvPte%#LB&3(Xtw*XVuXGOBY#w}kGx$z zb`K$+sNw9B%DC`p#XcntjggAsJ_hJ#75l6b8jIDH9Xf-; z4;90G?omZ^Ew31ELP>ez66)sC-* znlktB4qMYacWTvoXr4Q@>XbXJYNvVmCspkvzx{A})lR2O&2y~d$A%L;0#r||+KHZY zdex>oswZclg+H!Ovm8ts-0a`?>MJwxB@n@U4@YN+^XTuuC6HMysF_ERy5!FRXd+L z6ChblvDLqzYB)}FE~?r^s*=81!^KsN%oht9W3?LWlB(g5EL>XE=zXadL^1~L*;PK( zx^t?Ao9$69bhu2J6mxmiaF=-uA>eyO)voxbDYj|#Fc&R(>Zw9YE6u)NtP#zLb&(H^ zNMf49TDDd?w6Vs=Usw)Ab+OYk5dlY{6d-OMW+!kJGX?9wzfmt$41&STaM4_F4o9UwS7W28;R)TeuXW{5Ll$xrrC;{yB)R|+E0>FyzyVxZ94+6GOC_?583?~H)d zNHu`p0ufFZMFhZHS9V@QK>r_i5#p02(!ytC)r}Y?3Mt4-(1DhFv1f8cca+}S!qW<} zrz0Ws&ox1U>8k0^O2Zw%N^zrWue+){vHvpz zJt^aT`QMY@YLwA4^zd~9#+k$813ci_X7AzWGK(mV6W;TCc6Bh-%C!>*QJL~ zY!MPxWh8mQRqtH|UL;zH$pn`<#8u)27kzl-AkvCwnSfgS=U%%nB6Q+KXY}8{RPBga zRq$6;om_v}8RRn<Kv-4r=+@&VdsiYJ5L08rsoFKNszV+dqgXE(u1qf&$4i<1Uywi{Uf37v z^~X8D;~d}#u4eCaT)9bf3u9VD8-0!XkbGxqvw$l6Bzi9j?`H`~n6VgDxIH_=aX@MP zY}eaHHC>wO%~Df87i36E1Z$M@q^z!p^QDYVgB63iE35;pIb0wOb;65T;X)~@Yp_R4 zoq6CQVXjf%$8W+IiMX!oBl`dwz|~#F7o(qX$H$scSPYITq0Y#RR{qOSTBKXY*71VZ zwRI`B5D%|s>#5N7HMFf?fTZ$xY<(3;`6B%w8)O3&2wm2134?90CobyBXuqLtC@34L z>WqFH>sO=SCX5rC&_EE6?zE|Gs^;5FpY)|6HbkGB+vc`eGrGrHI8$#t7KP*=iKDlw zk9b?#*0xn!*hZt>HXxziyqN%OYuno9!fJCt-_EwP%{;osLWLq=qU~*a6|qCT#2sx% zeePsC5zrid40b;*u!9A6wOv)!-E23dX+}Gfw%gryC&8`?8E(TBGQviHXDRg8z%`uB z_O78XEYyr|H+1xlO4)zH=8o)p*d73E63_2xdn#ft+e;C9+up@M zwO8oHZPitP`4fDj@L4ZluEPFa7Zm#xgH%)K@0FzDLv5(wGC_%E$z|4WUbp=Jlw_Sg1nf#v$VgZ(X`5NAL8 zEkn$&GuyAmb&)k!Dus)$&_g3if3@U+cA)Jb6hIqjT!a<0-`Vek5f@=qqyCEdz5U*P zr-Z*#HZH|F%$gmf#^u(&vgwX2*;=fn$Oaj1$XP+srYHA2vo1x(V#q0_+jS zP1`zH`Vp6Gt(&JICo(6x)L-~fkK)EHHT{d0&Ht?}=6`#e{jJ_rj-*lkGM1aRN7~=p zWRF1AB_oX85JxJL5)whzz%ESSI z0|J4h^R47@y1J{aV1-K-4AG^NWG6@5y46FTmClz!CFx{naxdr*c-fI^rIzdd~vgeHC+DqdTwK zNiNh~SL@dtt`!2;3W2Mm!0xQ9jpTKptBvIK5gWNn}cHM&o&09fJ+sK<$E+2JOMG9F#tGjjm)%#+|0A-^x{q8o3jhjm-l83FcL>^s7x zx{E5kLvF_|9>`r-H6wnA@mOS!=_)O={o5Oa*vaTCmB>8)as7hy6S}J^qH%y7h1hq` zz;Z38#@b$m`Ii6Huu3(Q+3oF!-4^p2VyvZU4X9T(=^f`~D>rouDaKq@3z^9}NY+?8 zJBx;D8#xS1Ekjna)G|btT83dFChW)$+`oejHIiRhomD0k;$?8ZtnMHLTLEW3jE% z8d#`?il*S4Z9AQ|lyBS;`dA+&S%t45EgbUo)mJ}T#rm~y_0-YmZ~cp{$|_878x+?F zwk>{Q0NOB^v(i|bA4N@K&ffo!oT22lq#a+b^yX*4u(1KhenVc1p-1HV#3lp53o<28n6Di2dg0d>^g zV4ODAeiW63u=-)g{-XjtP}H*$T!AcyzE^a`@gV~15V@tMhR6ju>@+t-qFH>z#^k&x zih2oJpZ~4;eZakskgihJdM&~=_o2z#QaCRzwFzmBJq_02t;5*R)x)Zw-dOaoMv;li z=cmqb(lmcj`p|5@Kz0;;m&>2s*t}=(RNFt zsIQRkXQhoxB@l`9(*QpG$L9Tyfc*ZuI|$W-1YWJvqaEH^g+dxAv=*|=7zUwMQlEL4 z;~Oo``DwC70qtc?`svMKZvne^Cv5tB;T7zPRg9xj*b~^jf!!-`B7qJY&>I7`%5(*q z242p@U8T1A?Z$!;(I4bwtrTUdkl1Z+A7k_GBh4sFXiQF>C+_!>u%5K7OPcPL0?UM3k^DqgPm$HdKl#%Meq= zOZoleqvl2Pbv9Boyv|M4e7`mtkHL!$L1uM!nolt3RU$YX<*dS((A#<|qL1~qLF#-y zkI>4UUvy&zisGv$bWs|#Qb7Rz5tpxOs}@JtD_6F^He1bMbz7Zs`m0NNS72yYVQccm ze~fsQwmfd>RVuAsj71vg$hNkv%~EH4X8kpE_b!ev1)p$p0TBl|k!+o|H{RSp_ zdBf!Mczn;Jq9fs?uVYwgabf7Ku+z4qxEp4OxhCiHfHZ*k3El{*~fdJT&hvxM@RD zLa<83UWmdf4M_v6T&giHBVwbIKFY2FqiRmUM;%K97DD4up`ihToL|LxcP2mR#_eOk z^wpnF97%+m0`pdc)KqoEJ_a&BAEfg2n+sW+xS%g(!$*CU7`Yp{SP~&`qwr%~)^kj( z>@IR!k=^BO9CG>7yiQ2(v0YJ+WW8o&_z3Pna7Pu!9{x;E~ zC_7dc{HazK#fEV3A}l~WDJuisGtG8EWU-VwO#}0d8zdSRBjJg&TRh+2P(EWAUP%;||%p zP>wre<9afZPI4@XF>SFyQqnE@W0Kk7ZbyxU`8~3n7*>OQhG6ODd@5CU{(;2n%4OMktq!NbHt@I9n#VQmNM_di6Kpo=u|n7oYu=^;6YAGk^2ZB zGEzmOU0Mf-XjE+V8~E@y&W69W-xf^h31twl7zp>b{gv6~&5vUN%3(W6#C*M+}0rNw_M>s_4;bEkfvVG1ueHBuwhgTa&t)RHg}meyET> zR7g*X!TQkfV-2|dZDjZ{(vK4Bv>%5yUn{hUcrsd8&;(&C#EPlPqS=M}H+qJ}LM;|GyPvRzug&eQDd!;~oB zrfc}wx@-8+NOMGIq&j`C&Nat2U1`V)1zgN4${gd;+=BR1k*R6rcdP`vd1G5R&gHh8 zu^%s~t{uRT61v`F)s-SY$AOUv*Z3arrZfD zms=|}u-)_hNl}AuV(MJS@Eg_voftO$Q>w`cc7$eo-?%ffgX~VRlN}Tg`h^WuJxGK|sEKcNEsjA96zU=qg5O?v;35RliR%b*ldI zS{Wg=LbTqMsi7;A7-EX78qJn8oNel3zO!QMsZo?RSfn|K(Rr)y?O&d|69{KZ1%Qn6tpJ>mtf>=P_hNK0tkP!ijCE}ej%trZa`iiz$9-B!5z_}CNJvm-#8mP0UIvwvs5nYg0gc-Dtj zWJOwH{hKxn59pvo?fsxUG9S8@EQa#?Fx~eNK8*t`jzAt1<8%D|2&ivfd@W^8d4NyU z8A49Jm8iRUCoAS*2QT{36-5_=B1a+|g;XJSPhVlU0^pPXYFV@=dWTHvcd<8%nl?uJ z3e_tuQ=f@!E9=RvKLwy~H7Yz8p`wOK(f06GVGBKf(%FsNu1$f46)AhV>Cmk(9y+Sf ztb+HR2Mq#3Pi_OE2UXu`i_}l9K>8WD)R!3DGE|ouSlcv&z)R!@5+l6n)_UX^+icr;FN z%6u;Eeqetx^Oz=u^w!aq~gX{p(XnU zQg7P<1-Dk|Rc?cpjVo3C&;)6 zb;Rhjsh|ncV-sFS$3y|^2Q(nM_TuH5tjhv;xva|q_=hNLSpcqcY(~vF-j~c20c&~1 z2}{n~2;J(ZEseE}3*mmnT$YPCUnBX7GY=qB9VF)4uU>1cT@^*ENYKAZSL%&fck8UB zSaq`yWCQBwPJX1})Qq%xkG+yeFb+Y+=0zbSS7s#1^~}8yp0kJ4SrKwmU9qRqWf;RX z5z0!8(7v7+X+0(B><0=Vs|U|4AecnXA3Ehb)N@AnWO_8da#Sp#GV5CO2SdE=fU=wSjXgkr zW?S3OAW#v(_TBgMM6kP8Y5Q1a`?Nv1vgoDKs*sJ+hEv*bl~$cA9h4GlcvgN54aKUV zvx=O(ve5D>A_$O7KsDKy)7*VI6)7Uv`12~jZxx|eM=12y*4=*X$8I_$QK3B;?}T4#kiJa;BmPLMk_+v zRTO#2n~4j;Bet^7$;hXwFHjp6@k#8c*CVtx?94bjkET)Hl5<@ zOj|gt#qdSaUBF=%;jmVL1N~^8bcoOh^U|?2wKBye&&L$Baw2Y!g1SmS0@VhdRj?ug zQG>srKm^)dD*Z2JhSEx~5Z1AERQkHMj$rIc>AR}*b$#{CYNzO^b9FGnTOW=>rEBx& z1VHIAtY4Ib_`)R_lys!6Z%1-GSVSBxwJ#~HPhg5{m9(P6m5P~_Yu)n(osOWf<1w=mx~c}vNOp`niw%5O=JY(>bW=y znZdD9p(iFp3RwdbnG)H?sFk&`oZN(Ic~h;lXGXTE@-%}>vv5I_7i|XzWL>*fFCA@; zuvr0qnr1RiX z)F^#-O5eRG{cJBiEmrxubI4deJ&JpdkB?$pY_gIT>I|tG?R9h-F$yy@`tX3s9fPU}#v_X0#& z!?0wkCL+OMmH{TP>%>rU;j z)rNKN(5dUN?nluBSF<(#u1;9sqlpYedV?0#=dj&+3z5|vi^@pciAX3Wamc$=FFOlESV41=Jushe^rY$` z@J}^QMuoK?68D&h?+$zRaN=|q={c;oHOH`N9gr{o{@Xt@Hsk9cZ!ruP-Z6pE*jTus zm!u*Yep%m`c)fdQ679NcY+N6OAcj^3O%=(wNt*Q~?F>CKJPDp!UR#Mg8DZRJQ<#&c zrm7?KZm#QD)GJk^oCH%z*i?ey8bYI^-%}(){o-Fqvyp8Cl%5a*yn3olH)iEWn=*n5 zG=pfJUNGs#0NjKtH$F(Hb(%nd^(3zf3~8)A6-B+piv7?Q=!jQRJn4v~Ezl2!Pubw4 zzD5x2UW|#!NU@jo@`)Tw2x*0_>c`VCLmyy`@Xj~h`eb}a{jJfE9W?E_Iy7Z*!T z&x+=ID0_`d)Ps`Og;P6@l4_p@$Wa=GD5imK+}Y`C&NlQ-1_E+t40sff=~TMkdc0n@ zVX-J@@hha6!@SNK2SKycw7EKBK(x;AwQ!5%^<;dnqk>kr?<5dne!3DN=BFaWJBbt; zFO})q{45w@zI-x{yeJ8GdgwWX?k`i!E|KDarxq4HQPZZy!(|d3a^65KqM3zlRbnu6 zdrTTI{L0CH{^nZrL#*Du3y(u`#C<+t3Vl|6sib{Kgw6;1=0Z6bq0UK7s{iZq9N4ZMn5Ukwc9u_G zyQX_TKM3<!XPEwhRc=jT-h|oD!E?Di-+=19+0P{So+QCSlZBl8Q^o0u#R_>b=2L@ zmucX7{19q&0>)+?+N=aq=7mbe390g7^L!m20Wb-zLFIx3%jU(fl5c{U9N9JZ5@!|$ zcX=}J0$JPz;z{YOFg?ZA?o8R!Jy|$OHD{V4XUViKPN`3oMO}|%aIV!Uc~M~;eR#MS zyfAUz8ZL1w>Ep4A&P_%rGg~Im=Z3;2aw}rSISB^Nt(7;S^pqn=?XPzoFV|y%`4G*+ zmnX8?F^9i3AV{GWOXyc5dE8dFn9k*md2TUXb1U}J`-oPULC0O02tvlomvv+5N`kfY zJ~^We#?o;MJPCbrI5yK^F9fgG>X|~d(skb7SC#eUj?~+sBfT6u>RQ%a58vJ(E9#acw$oed4<<&<;r0Y8>(J_QVe) z;WwFshNs@f)Vk)+R<^i+ILHq4!r05&L9KzEtxD7;w?8}JU)w?9H{3Ad(E!~QDn^k% zpu(;(g#I|QK6*%2_D7a<27lIAf9+kneoEfZ-A@_SVf=ugdy!rWsVIszP zeGt+y`0rZStug|&X%jLr4HHs^-hHtf=qdh7BLqSJ751&!zJlJacLioa)iGRC8qY^& zV`|#jhhP)ZaCE`5N2gb?Ee^%4q@ZODH_8a}sL*O(;hQRCW zSYos+?qVMS&?y4i#S*>P2!qE+Jt0WFda>p@f)(w);ji9T{+h2fT)SZ~`)ignSNx5| zE~_c6um_CL?v+df!lv9;nisI+-cxdmP#CFf9L!3NJ?^~1(mN*Ar(opWn&yR%Wsn`i z=tmYN-iLLZ_TCFg2NvEj<6e9mC7bS_$dvov3#0C{Im>S}X=9USwzkBL!b96I@R$&> zRW1h49xQ)4qD~W*9X|ISt^IT-q63tVjV`Xk52PkW7!pPk=yJKzUqLA(5eipCopFq@ z4jqY3*OQSBeWpJhIUXU0Lw`Oo!FyitYI<{WykXr9zYe%}*WvcuNC(?^u7t){>7G{} zA5ok!Bj*^YmkvofolvCe3v|m17z=>DdrhxI6a&aL{=VTEwB$nPorR9>Lh3cVIAVrA zFC?_^OXKY-&hnT@!EA|h@LRO=T?*5J z_HMr!b{C9wkM4xk@9gZu;kGPDaBw}eIJCAuGnM&8Fe>(dpKnsJ2X%y*v&nqOFOWUN zD&k=sa)M|tu?0t+9DH}&Tk_M+rSuH%Qjhwhh#lxCJtnIVoNjx=J?_DPeL|PRILSma zP>&(z)#1es(fyOa&{Ru#2zR|)SazI z)(x;L=qEGJ>15M3aM8%~{yO3Yhsaa}fiF<>i+T-Fec~k@r>izE>nPHOHiuUt!@UI2 z9!-juQh1SZXLiKH;DbFek?OmTSN*AL0KBH-#`MTtOa5=@F4?Y8-B;5y3>)ZX;p_hP z;_I~Z8+BiEc+-n{lVW&%g~wJpA$+`Z=Q8=Loojmf`;8UQm+f4<06rsS2~OE>NuwHa z%t!-oY@C^fALz3EHfGWGHi{XYD%LED-(h58(K}VIM$go%7w-U+cQ3GRoYun3`uDMX z&*0l1h7iP=f>;yHUW8`viB$HUcPw7=_&%9cyq3X(9tVc^r91#CB-()2u{`Mqp7aC6 zBBwHsjne7hhe`uIhd|5SyqSk+9{C8#WwF`Bw;Q%s^*kdfcT?mivW`*2eiDUI85h_` z$wr38wom;5M;PTZJ@bf(3Jp>is;HOPd8CIyjUhHF?3R%T5zMHtYbVbLnax0E*BUqE zzfdo)zw`K|_wuj&fDf+yIx4Q$f1^`9NzeQ+4-_|pH@-%ro9r+LzAa(Ht-Weni*>(? ziUT{&{K)$qJg~feNT;0N*K?}Z?kZ764gJdEO&Eym-| zY-mky@C@Tj=cR;Wrai;nlHd%dd+$Zn_C`iy!&`N9xR>oc3WZtb@`+ll?G=9Ji2h7u zo+MimqUjWwybyaGBfWdg7#AJVCQkV0?&vd_^crNF6(R8ok+eKt| zsU7d8&x{HFERnYEQ_zzqXl1UxnP9o0j>7l3R#&M{U8`lBo&-wqSs`V){vZGp~ ztbeN4+EwwH#k+;Autpo_-T$P8f@|c9C}&C=pXgE;OhfPJ^xIJljdnh&{TOT#Anb8? zHgq~?I#gHFr_dQOqPDYQJyDETuh^-vHNtPD9}3k0D!X%Z_RlE>{BvXbY5h$}#_3tH z%|Z+Oh;V`H=EIs7`rDC=(-#${J>Ti*VxB+%yglaoNZOzQdMno~e~MbKUW+7;5! zFQB~wG@ecpv^N}@ZoBAf6Mru-!}l!Vu=F;XrRJj9F53ZxMnCNF3$*yzSJ#Xpt#Dh0UZNJ#S-xTYf5!n`z z%@z2S?G`EUla1K*uty$q#C?b z`~l0`oa;O67WwGk41FAcD0e0!9%rD7N;i9K~(g|xk85yIUD0yedBtC101K&%F9;T~5h2^t7f|4qZAl<%aT!PBQvdPM3G;ba}_= zLR4|;;wLEYx`K{K`ktPU^j-a~Y97LPy6d_OSxGjSQdY1x&95fM{Hpd$S` zO!UVv3;z6CgAH=9Z}jw~8s%HRHTWHVClcDj1?Qr?xDA>Edxt%ozZ9SMrH^TOA9 z@eEBGn0JD7Y4J99J$t#l&aNmSqJlLc(M9e(Y;UZwCo$8mX0(c?iKz)R!w1Q@0Ww_A zT7t^4$hV$I>3UyNt#NX~bDBJ=*%nSs>{M0m#027= zl!QHa>OKj(tkmqga7iFX=jSvEpc1DgIl37PJv?-lpu2U3Ufkr3%~l@R1cM*(gr)jV zU3Pw!GFdTTot2R5eq`s=Xg_0Eo}tG#sR2^~c6>%~>VYoQh{js)I36GA%oj$xB_Pae zto2op4pCG_)HEdcVdrPPk{YMOnIamLmLt?*TTYeE3CF%tb=N8Ea-EKMsuOY6=DHs_ zTK*kPrT>R}ng34mZwmaI0{^DKzbWu<3jCV_|G%O@B$EqPs>=#>{KT??#ZYI+$Gco8 z#V}uR^fec7Nw_go3Uqx@C@6<&W~IP-NDJ|(u-SvwTtiY<=G4WuxbAP79i$!Hmq8t+Qz?QI>t}bVbQQcVWQ*XohRuG>o%#Z6-x7swb#>V2kF)9#L|id zbAPJPU#A?d8<=+>(Q-?jhSZJy>8320bP%g}RhhG$jKLTxkADe zVZ~}qi|!r(YtW84%6D#4MM1w^t2j^8#GzS}ibB6m3vZy#XBFE^o}q2h6UsXlgI*u& zWqsPQ1-1iihw-#=YP5VAkfemB;`$ZEtx9qIisHa&H59`r6^%hJ6{RpwyC!K_y069g z`I=p*q3Gp_T+<7H#;qa~YDpJr9Z0W&1vcu7OC!QMwvHpydz|#W@{d7geOuoP7+4@P z2xJBp1%RzbL@R;ilg21ZmGT11<2XJ@(G%>UrocuI*3Gz(Q zt{Yfv;aAO5ozJIYQks=yiyHzv2lOtLmOaI)t{kY~giTi2H(5#DGN5Y&N*B>J00pB8 zb5k;=lnP-%Hx#|J-9kN#eVO=`M6m1ssqS2w<2H^sj$N)ukt>QzJt;+xpcmfwN;4L?+uI#MaF=ZVJG2 z^`l;JHPl;a+>))&)jz7tNIZftz4An3FDx0o`IH*f2n%ylXOnEPm~=towhYVS$oz0g zrSEue$HO&tHCO-rfy%1-eAjQ-Pztp_{_S6Xoz$x&i-{)OQ{5>=-3yJ^7gwm|^W}a2 z+MIN?R*N+&j}bkpEnHiz##!CLNLRE2Yqm?kgaE1nBX~gX%!2+=q_(Bk|=^F zbw)77J|EhhQ@$&V(J~YZud>1sP%y=@)`7e56sshSYvU}Tk;I=rP-vtuWLSQ%cu$oN z7n|;0d5@6;7GI)0)dD)Bcy~nyz;$0esL>j(%Y;P>Xl3qxGSl&L{ z)B2w$D%XYBmze#)9IjNHU2#_=L*9QfxN74K6FwD)oeFCLIu~a#@*5h%0p2!Vk-PL& zn!s=PsNkwBlK55iT4(C0Z-HPU(^mm)9mF2i4V07)cceB7H^oNzcsf;N;u37hzQ$Bj zwM=rjB?(5eNg+&(62%OL{0Uc_tN)`? zSul@}15rjc+?;r0>Ed}Se7;ZE*YFNO6WURPepIuQZ8MW(dHJVl8kOUp8MQet0MoQ! zS0*a+j6>?WZC=m_r)YUbi3ZtJpb=W4PoUzdDV!Ovt871nS`%xn=#9fvf<0CkmSYe+ zF~=O!_YA#Qvc!U9LB#*f)$bMo_XO=W#$t9G3faY2Q8%Hpmb9@+*3Aa48u*@)CHs_V z^L`g!rTLc^8xzgHlST3HSPhx`{#mWOAQ8%6!~MbPJeBm2Ll8Vu)ZD! z8+YZX7thukZ-Vo>xKqFzt${lNJgd0n2}XFfm;`Hs_bT~vz%fKpj)p&Ysw&3 zQ$D!Dacj-XX`sv5DWBu8${?Ak{fydp3qOc9d}csQPq)>&i_zjM)M>zdf%am>Uc)l> zMb=w%dfCogaF=Ow!TM<6|Is5@MU%fSRwtOD_+upMdKL=)5QHdOYrZSqbsu>Ne1T3J zh2kF;C_^JV?XMShxwl`70Gb1=1xeU#M;01I=26g#a?}xs(HEHUSsu4)dv0WelUj=S ztd4=Q;T4)?q0CZ*$fNT1ShO%KMVg5a$tL_GUj3j+{eTC4(CQG(mL+m>e=s8v59H5J zYorXAyH*?L8MDC5wvy`sH^qK2Zm}`2awAVQ6i*y9Vqqr**fm82Rhz&1ELf8?aXr<> zA*OP&Rr>8JtgrExtPpUf6WgpBChk=w_K9uOj5ma+B3v$JCFA2no^E!H3z!Gk3W;m8gs|KSB+_gyH=i#=&D9hE$Io-6D3Xe(&Xqa z^`iU9J%bu`H>P;MP6rwPt_o;@15P|j+arch@h8E~_XeW)q&?1M38SJL51b0u3&JSc zjthCJm3Z?j;bi-s4NFA{6cr`#Q6USL*L8hcy8BV31+2A12@6u`9GYf1f=7t|L(+mFcZwr&j;w>b*Ss0 zzxiNphVv6MQ$gkEbe;O?Ne=a3Qr8q$TFc@vcIAw&r2n8AOsiU(q|2ViFS7EXu^KDe zVcJ)7^o6lTqvGLFDF|jM*K`P`eKp7N^J7gZHpa*~mF+O?t2y%T5o(Vd(Q*I3J?Bk$ z`?nj_jwD14!YK|WArsH|`O!sI7?*&R?XX8eOD})(l~-T8dF%G;&E=K*Z$Egnc;VD6 zd9&uemvN4O*LSqtlIClDc*$jaqqA=MY1E>wxi+buGHj+U~ ztMx&)8?44T+ztAS$z{7)9`#%+>~_mm)bx`yOgr6OH;BWXu+ufBSL2e|YJaTvGus;%VWkwb|*m-4K#$G!&1)bA-t9-a+Q=e!;vOHSNuIQlZlQlkv>2f`_)JxEc?--LD5XmL6YQdQ8=grRUd{o;%K< SxnOneK@f*=u-04)UiuHx9ovrp literal 0 HcmV?d00001 diff --git a/lib/emscripten/src/lib.rs b/lib/emscripten/src/lib.rs index 5a2f24211..373ad51ab 100644 --- a/lib/emscripten/src/lib.rs +++ b/lib/emscripten/src/lib.rs @@ -481,6 +481,7 @@ pub fn generate_emscripten_env(globals: &mut EmscriptenGlobals) -> ImportObject "___syscall39" => func!(crate::syscalls::___syscall39), "___syscall38" => func!(crate::syscalls::___syscall38), "___syscall40" => func!(crate::syscalls::___syscall40), + "___syscall42" => func!(crate::syscalls::___syscall42), "___syscall54" => func!(crate::syscalls::___syscall54), "___syscall57" => func!(crate::syscalls::___syscall57), "___syscall60" => func!(crate::syscalls::___syscall60), diff --git a/lib/emscripten/src/syscalls/mod.rs b/lib/emscripten/src/syscalls/mod.rs index 7c5ee578b..39bd2750d 100644 --- a/lib/emscripten/src/syscalls/mod.rs +++ b/lib/emscripten/src/syscalls/mod.rs @@ -40,6 +40,7 @@ use libc::{ use wasmer_runtime_core::vm::Ctx; use super::env; +use std::cell::Cell; use std::slice; // use std::sys::fd::FileDesc; @@ -140,6 +141,33 @@ pub fn ___syscall40(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int unsafe { rmdir(pathname_addr) } } +// pipe +pub fn ___syscall42(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { + debug!("emscripten::___syscall42 (pipe)"); + // offset to a file descriptor, which contains a read end and write end, 2 integers + let fd_offset: u32 = varargs.get(ctx); + + use std::cell::Cell; + let emscripten_memory = ctx.memory(0); + + // convert the file descriptor into a vec with two slots + let mut fd_vec: Vec = emscripten_memory.view()[((fd_offset / 4) as usize)..] + .iter() + .map(|pipe_end: &Cell| pipe_end.get()) + .take(2) + .collect(); + + // get it as a mutable pointer + let fd_ptr = fd_vec.as_mut_ptr(); + + // call pipe and store the pointers in this array + #[cfg(target_os = "windows")] + let result: c_int = unsafe { libc::pipe(fd_ptr, 2048, 0) }; + #[cfg(not(target_os = "windows"))] + let result: c_int = unsafe { libc::pipe(fd_ptr) }; + result +} + pub fn ___syscall60(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall60"); -1 diff --git a/lib/emscripten/tests/emtests/mod.rs b/lib/emscripten/tests/emtests/mod.rs index a280fc48a..efedf0d6b 100644 --- a/lib/emscripten/tests/emtests/mod.rs +++ b/lib/emscripten/tests/emtests/mod.rs @@ -118,6 +118,7 @@ mod test_nested_struct_varargs; mod test_nl_types; mod test_perrar; mod test_phiundef; +mod test_pipe; mod test_poll; mod test_posixtime; mod test_printf_2; diff --git a/lib/emscripten/tests/emtests/test_pipe.rs b/lib/emscripten/tests/emtests/test_pipe.rs new file mode 100644 index 000000000..9ffe0c828 --- /dev/null +++ b/lib/emscripten/tests/emtests/test_pipe.rs @@ -0,0 +1,8 @@ +use crate::emtests::_common::assert_emscripten_output; + +#[test] +fn test_pipe() { + let wasm_bytes = include_bytes!("../../emtests/test_pipe.wasm"); + let expected_str = include_str!("../../emtests/test_pipe.out"); + assert_emscripten_output(wasm_bytes, expected_str); +} From 00e3ec14466d372e2c6399a959714fee93adb13b Mon Sep 17 00:00:00 2001 From: Mackenzie Clark Date: Fri, 1 Mar 2019 10:59:52 -0800 Subject: [PATCH 175/262] add execvp --- lib/emscripten/emtests/test_execvp.c | 17 ++++++++ lib/emscripten/emtests/test_execvp.out | 1 + lib/emscripten/emtests/test_execvp.wasm | Bin 0 -> 45386 bytes lib/emscripten/emtests/test_execvp_windows.c | 18 ++++++++ .../emtests/test_execvp_windows.wasm | Bin 0 -> 45500 bytes lib/emscripten/src/exec.rs | 40 ++++++++++++++++++ lib/emscripten/src/lib.rs | 4 ++ lib/emscripten/tests/emtests/mod.rs | 1 + lib/emscripten/tests/emtests/test_execvp.rs | 17 ++++++++ 9 files changed, 98 insertions(+) create mode 100644 lib/emscripten/emtests/test_execvp.c create mode 100644 lib/emscripten/emtests/test_execvp.out create mode 100644 lib/emscripten/emtests/test_execvp.wasm create mode 100644 lib/emscripten/emtests/test_execvp_windows.c create mode 100644 lib/emscripten/emtests/test_execvp_windows.wasm create mode 100644 lib/emscripten/src/exec.rs create mode 100644 lib/emscripten/tests/emtests/test_execvp.rs diff --git a/lib/emscripten/emtests/test_execvp.c b/lib/emscripten/emtests/test_execvp.c new file mode 100644 index 000000000..402654721 --- /dev/null +++ b/lib/emscripten/emtests/test_execvp.c @@ -0,0 +1,17 @@ +#include +#include + +int main() { + char command[] = "touch"; + char arg1[] = "foo.txt"; + char* argv[3]; + argv[0] = command; + argv[1] = arg1; + argv[2] = 0; + + printf("_execvp\n"); + int result = execvp(command, argv); + // should not return, and not print this message + printf("error"); + return 0; +} diff --git a/lib/emscripten/emtests/test_execvp.out b/lib/emscripten/emtests/test_execvp.out new file mode 100644 index 000000000..5048f1e2c --- /dev/null +++ b/lib/emscripten/emtests/test_execvp.out @@ -0,0 +1 @@ +_execvp diff --git a/lib/emscripten/emtests/test_execvp.wasm b/lib/emscripten/emtests/test_execvp.wasm new file mode 100644 index 0000000000000000000000000000000000000000..a0959cc56fbd6670bce2a3b64c462e56c32f84b4 GIT binary patch literal 45386 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 W*Kr0-25am0f;fzW_2zo;!hZn2x$Q3i literal 0 HcmV?d00001 diff --git a/lib/emscripten/emtests/test_execvp_windows.c b/lib/emscripten/emtests/test_execvp_windows.c new file mode 100644 index 000000000..c3920a4fa --- /dev/null +++ b/lib/emscripten/emtests/test_execvp_windows.c @@ -0,0 +1,18 @@ +#include +#include + +int main() { + char command[] = "C:\\Windows\\System32\\cmd.exe"; + char arg1[] = "echo"; + char arg2[] = "foo"; + char* argv[4]; + argv[0] = command; + argv[1] = arg1; + argv[2] = arg2; + argv[3] = 0; + printf("_execvp\n"); + int result = execvp(command, argv); + // should not return, and not print this message + printf("error"); + return 0; +} diff --git a/lib/emscripten/emtests/test_execvp_windows.wasm b/lib/emscripten/emtests/test_execvp_windows.wasm new file mode 100644 index 0000000000000000000000000000000000000000..ec3a210c5cf578243cff0bc20afc2ced0256d3e7 GIT binary patch literal 45500 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 i32 { + // a single reference to re-use + let emscripten_memory = ctx.memory(0); + + // read command name as string + let command_name_string_vec: Vec = emscripten_memory.view() + [(command_name_offset as usize)..] + .iter() + .map(|cell| cell.get()) + .take_while(|&byte| byte != 0) + .collect(); + let command_name_string = CString::new(command_name_string_vec).unwrap(); + + // get the array of args + let mut argv: Vec<*const i8> = emscripten_memory.view()[((argv_offset / 4) as usize)..] + .iter() + .map(|cell: &Cell| cell.get()) + .take_while(|&byte| byte != 0) + .map(|offset| { + let p: *const i8 = (emscripten_memory.view::()[(offset as usize)..]) + .iter() + .map(|cell| cell.as_ptr() as *const i8) + .collect::>()[0]; + p + }) + .collect(); + + // push a nullptr on to the end of the args array + argv.push(std::ptr::null()); + + // construct raw pointers and hand them to `execvp` + let command_pointer = command_name_string.as_ptr() as *const i8; + let args_pointer = argv.as_ptr(); + unsafe { execvp(command_pointer, args_pointer) } +} diff --git a/lib/emscripten/src/lib.rs b/lib/emscripten/src/lib.rs index 373ad51ab..cbcb5c1fc 100644 --- a/lib/emscripten/src/lib.rs +++ b/lib/emscripten/src/lib.rs @@ -31,6 +31,7 @@ mod emscripten_target; mod env; mod errno; mod exception; +mod exec; mod io; mod jmp; mod linking; @@ -439,6 +440,9 @@ pub fn generate_emscripten_env(globals: &mut EmscriptenGlobals) -> ImportObject "___unlock" => func!(crate::lock::___unlock), "___wait" => func!(crate::lock::___wait), + // exec + "_execvp" => func!(crate::exec::_execvp), + // Env "___assert_fail" => func!(crate::env::___assert_fail), "_getenv" => func!(crate::env::_getenv), diff --git a/lib/emscripten/tests/emtests/mod.rs b/lib/emscripten/tests/emtests/mod.rs index efedf0d6b..89a66bf2b 100644 --- a/lib/emscripten/tests/emtests/mod.rs +++ b/lib/emscripten/tests/emtests/mod.rs @@ -43,6 +43,7 @@ mod test_exceptions_2; mod test_exceptions_multi; mod test_exceptions_std; mod test_exceptions_white_list; +mod test_execvp; mod test_fast_math; mod test_flexarray_struct; mod test_float32_precise; diff --git a/lib/emscripten/tests/emtests/test_execvp.rs b/lib/emscripten/tests/emtests/test_execvp.rs new file mode 100644 index 000000000..c9b4b5113 --- /dev/null +++ b/lib/emscripten/tests/emtests/test_execvp.rs @@ -0,0 +1,17 @@ +#[test] +fn test_execvp() { + #[cfg(not(target_os = "windows"))] + assert_emscripten_output!( + "../../emtests/test_execvp.wasm", + "test_execvp", + vec![], + "../../emtests/test_execvp.out" + ); + #[cfg(target_os = "windows")] + assert_emscripten_output!( + "../../emtests/test_execvp_windows.wasm", + "test_execvp", + vec![], + "../../emtests/test_execvp.out" + ); +} From 65100d19fc5b0fbb901c03f6e5334e14e48cefc8 Mon Sep 17 00:00:00 2001 From: Mackenzie Clark Date: Fri, 1 Mar 2019 11:24:14 -0800 Subject: [PATCH 176/262] add __exit --- lib/emscripten/src/exit.rs | 7 +++++++ lib/emscripten/src/lib.rs | 4 ++++ 2 files changed, 11 insertions(+) create mode 100644 lib/emscripten/src/exit.rs diff --git a/lib/emscripten/src/exit.rs b/lib/emscripten/src/exit.rs new file mode 100644 index 000000000..c53fd2bd2 --- /dev/null +++ b/lib/emscripten/src/exit.rs @@ -0,0 +1,7 @@ +use wasmer_runtime_core::vm::Ctx; + +// __exit +pub fn __exit(_ctx: &mut Ctx, value: i32) { + debug!("emscripten::__exit {}", value); + ::std::process::exit(value); +} diff --git a/lib/emscripten/src/lib.rs b/lib/emscripten/src/lib.rs index cbcb5c1fc..822fbdc0e 100644 --- a/lib/emscripten/src/lib.rs +++ b/lib/emscripten/src/lib.rs @@ -32,6 +32,7 @@ mod env; mod errno; mod exception; mod exec; +mod exit; mod io; mod jmp; mod linking; @@ -443,6 +444,9 @@ pub fn generate_emscripten_env(globals: &mut EmscriptenGlobals) -> ImportObject // exec "_execvp" => func!(crate::exec::_execvp), + // exit + "__exit" => func!(crate::exit::__exit), + // Env "___assert_fail" => func!(crate::env::___assert_fail), "_getenv" => func!(crate::env::_getenv), From 4eb6ad238e76bbc0a64471c6614accf015eaf177 Mon Sep 17 00:00:00 2001 From: Mackenzie Clark Date: Mon, 4 Mar 2019 08:11:36 -0800 Subject: [PATCH 177/262] lint --- lib/emscripten/tests/emtests/_common.rs | 31 ++++++++++--------------- 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/lib/emscripten/tests/emtests/_common.rs b/lib/emscripten/tests/emtests/_common.rs index f3cc9af7f..309d4de41 100644 --- a/lib/emscripten/tests/emtests/_common.rs +++ b/lib/emscripten/tests/emtests/_common.rs @@ -44,28 +44,22 @@ macro_rules! assert_emscripten_output { pub fn assert_emscripten_output(wasm_bytes: &[u8], raw_expected_str: &str) { use wasmer_clif_backend::CraneliftCompiler; - use wasmer_emscripten::{ - EmscriptenGlobals, - generate_emscripten_env, - stdio::StdioCapturer - }; + use wasmer_emscripten::{generate_emscripten_env, stdio::StdioCapturer, EmscriptenGlobals}; let module = wasmer_runtime_core::compile_with(&wasm_bytes[..], &CraneliftCompiler::new()) .expect("WASM can't be compiled"); let mut emscripten_globals = EmscriptenGlobals::new(&module); let import_object = generate_emscripten_env(&mut emscripten_globals); - let mut instance = module.instantiate(&import_object) - .map_err(|err| format!("Can't instantiate the WebAssembly module: {:?}", err)).unwrap(); + let mut instance = module + .instantiate(&import_object) + .map_err(|err| format!("Can't instantiate the WebAssembly module: {:?}", err)) + .unwrap(); let capturer = StdioCapturer::new(); - wasmer_emscripten::run_emscripten_instance( - &module, - &mut instance, - "test", - vec![], - ).expect("run_emscripten_instance finishes"); + wasmer_emscripten::run_emscripten_instance(&module, &mut instance, "test", vec![]) + .expect("run_emscripten_instance finishes"); let raw_output_string = capturer.end().unwrap().0; @@ -75,10 +69,9 @@ pub fn assert_emscripten_output(wasm_bytes: &[u8], raw_expected_str: &str) { let contains_output = output.contains(expected_output); - assert!( - contains_output, - "Output: `{}` does not contain expected output: `{}`", - output, - expected_output - ); + assert!( + contains_output, + "Output: `{}` does not contain expected output: `{}`", + output, expected_output + ); } From deea9e98a4a449f9236151752a7819d598dbbf08 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Mon, 4 Mar 2019 10:19:38 -0800 Subject: [PATCH 178/262] Add import names, whoops. --- lib/llvm-backend/src/read_info.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/llvm-backend/src/read_info.rs b/lib/llvm-backend/src/read_info.rs index bed91aa90..a974beb59 100644 --- a/lib/llvm-backend/src/read_info.rs +++ b/lib/llvm-backend/src/read_info.rs @@ -111,6 +111,9 @@ pub fn read_module(wasm: &[u8]) -> Result<(ModuleInfo, CodeSectionReader), Binar } } } + + info.namespace_table = namespace_builder.finish(); + info.name_table = name_builder.finish(); } SectionCode::Function => { let func_decl_reader = section.get_function_section_reader()?; From 65ec10961b611468a042712d1cfc7a5871dbbfbf Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Mon, 4 Mar 2019 12:57:26 -0800 Subject: [PATCH 179/262] Change RuntimeError type (#234) * Change RuntimeError type and fix codebase to use it * Fix spectests to work with new runtime error type * Fix windows signal handler in the clif-backend * Add missing conversion * final windows fix --- lib/clif-backend/src/signal/mod.rs | 8 ++-- lib/clif-backend/src/signal/unix.rs | 38 ++++++++--------- lib/clif-backend/src/signal/windows.rs | 43 +++++++++---------- lib/runtime-core/src/backend.rs | 4 +- lib/runtime-core/src/error.rs | 59 ++++++-------------------- lib/runtime-core/src/typed_func.rs | 26 ++++-------- lib/spectests/build/spectests.rs | 2 +- lib/spectests/tests/semantics.rs | 2 +- 8 files changed, 70 insertions(+), 112 deletions(-) diff --git a/lib/clif-backend/src/signal/mod.rs b/lib/clif-backend/src/signal/mod.rs index 9ccbf1822..7ec33d0e1 100644 --- a/lib/clif-backend/src/signal/mod.rs +++ b/lib/clif-backend/src/signal/mod.rs @@ -2,7 +2,7 @@ use crate::relocation::{TrapData, TrapSink}; use crate::trampoline::Trampolines; use hashbrown::HashSet; use libc::c_void; -use std::{cell::Cell, sync::Arc}; +use std::{any::Any, cell::Cell, sync::Arc}; use wasmer_runtime_core::{ backend::{ProtectedCaller, Token, UserTrapper}, error::RuntimeResult, @@ -25,14 +25,14 @@ pub use self::unix::*; pub use self::windows::*; thread_local! { - pub static TRAP_EARLY_DATA: Cell> = Cell::new(None); + pub static TRAP_EARLY_DATA: Cell>> = Cell::new(None); } pub struct Trapper; impl UserTrapper for Trapper { - unsafe fn do_early_trap(&self, msg: String) -> ! { - TRAP_EARLY_DATA.with(|cell| cell.set(Some(msg))); + unsafe fn do_early_trap(&self, data: Box) -> ! { + TRAP_EARLY_DATA.with(|cell| cell.set(Some(data))); trigger_trap() } } diff --git a/lib/clif-backend/src/signal/unix.rs b/lib/clif-backend/src/signal/unix.rs index 9d2f80eca..86cc53638 100644 --- a/lib/clif-backend/src/signal/unix.rs +++ b/lib/clif-backend/src/signal/unix.rs @@ -79,8 +79,8 @@ pub fn call_protected(handler_data: &HandlerData, f: impl FnOnce() -> T) -> R if signum != 0 { *jmp_buf = prev_jmp_buf; - if let Some(msg) = super::TRAP_EARLY_DATA.with(|cell| cell.replace(None)) { - Err(RuntimeError::User { msg }) + if let Some(data) = super::TRAP_EARLY_DATA.with(|cell| cell.replace(None)) { + Err(RuntimeError::Panic { data }) } else { let (faulting_addr, inst_ptr) = CAUGHT_ADDRESSES.with(|cell| cell.get()); @@ -91,28 +91,28 @@ pub fn call_protected(handler_data: &HandlerData, f: impl FnOnce() -> T) -> R { Err(match Signal::from_c_int(signum) { Ok(SIGILL) => match trapcode { - TrapCode::BadSignature => RuntimeError::IndirectCallSignature { - table: TableIndex::new(0), + TrapCode::BadSignature => RuntimeError::Trap { + msg: "incorrect call_indirect signature".into(), }, - TrapCode::IndirectCallToNull => RuntimeError::IndirectCallToNull { - table: TableIndex::new(0), + TrapCode::IndirectCallToNull => RuntimeError::Trap { + msg: "indirect call to null".into(), }, - TrapCode::HeapOutOfBounds => RuntimeError::OutOfBoundsAccess { - memory: MemoryIndex::new(0), - addr: None, + TrapCode::HeapOutOfBounds => RuntimeError::Trap { + msg: "memory out-of-bounds access".into(), }, - TrapCode::TableOutOfBounds => RuntimeError::TableOutOfBounds { - table: TableIndex::new(0), + TrapCode::TableOutOfBounds => RuntimeError::Trap { + msg: "table out-of-bounds access".into(), }, - _ => RuntimeError::Unknown { - msg: "unknown trap".to_string(), + _ => RuntimeError::Trap { + msg: "unknown trap".into(), }, }, - Ok(SIGSEGV) | Ok(SIGBUS) => RuntimeError::OutOfBoundsAccess { - memory: MemoryIndex::new(0), - addr: None, + Ok(SIGSEGV) | Ok(SIGBUS) => RuntimeError::Trap { + msg: "memory out-of-bounds access".into(), + }, + Ok(SIGFPE) => RuntimeError::Trap { + msg: "illegal arithmetic operation".into(), }, - Ok(SIGFPE) => RuntimeError::IllegalArithmeticOperation, _ => unimplemented!(), } .into()) @@ -126,8 +126,8 @@ pub fn call_protected(handler_data: &HandlerData, f: impl FnOnce() -> T) -> R _ => "unkown trapped signal", }; // When the trap-handler is fully implemented, this will return more information. - Err(RuntimeError::Unknown { - msg: format!("trap at {:p} - {}", faulting_addr, signal), + Err(RuntimeError::Trap { + msg: format!("unknown trap at {:p} - {}", faulting_addr, signal).into(), } .into()) } diff --git a/lib/clif-backend/src/signal/windows.rs b/lib/clif-backend/src/signal/windows.rs index 191085d91..e5bd41994 100644 --- a/lib/clif-backend/src/signal/windows.rs +++ b/lib/clif-backend/src/signal/windows.rs @@ -57,35 +57,34 @@ pub fn call_protected( }) = handler_data.lookup(instruction_pointer as _) { Err(match signum as DWORD { - EXCEPTION_ACCESS_VIOLATION => RuntimeError::OutOfBoundsAccess { - memory: MemoryIndex::new(0), - addr: None, + EXCEPTION_ACCESS_VIOLATION => RuntimeError::Trap { + msg: "memory out-of-bounds access".into(), }, EXCEPTION_ILLEGAL_INSTRUCTION => match trapcode { - TrapCode::BadSignature => RuntimeError::IndirectCallSignature { - table: TableIndex::new(0), + TrapCode::BadSignature => RuntimeError::Trap { + msg: "incorrect call_indirect signature".into(), }, - TrapCode::IndirectCallToNull => RuntimeError::IndirectCallToNull { - table: TableIndex::new(0), + TrapCode::IndirectCallToNull => RuntimeError::Trap { + msg: "indirect call to null".into(), }, - TrapCode::HeapOutOfBounds => RuntimeError::OutOfBoundsAccess { - memory: MemoryIndex::new(0), - addr: None, + TrapCode::HeapOutOfBounds => RuntimeError::Trap { + msg: "memory out-of-bounds access".into(), }, - TrapCode::TableOutOfBounds => RuntimeError::TableOutOfBounds { - table: TableIndex::new(0), + TrapCode::TableOutOfBounds => RuntimeError::Trap { + msg: "table out-of-bounds access".into(), }, - _ => RuntimeError::Unknown { - msg: "unknown trap".to_string(), + _ => RuntimeError::Trap { + msg: "unknown trap".into(), }, }, - EXCEPTION_STACK_OVERFLOW => RuntimeError::Unknown { - msg: "unknown trap".to_string(), + EXCEPTION_STACK_OVERFLOW => RuntimeError::Trap { + msg: "stack overflow trap".into(), }, - EXCEPTION_INT_DIVIDE_BY_ZERO => RuntimeError::IllegalArithmeticOperation, - EXCEPTION_INT_OVERFLOW => RuntimeError::IllegalArithmeticOperation, - _ => RuntimeError::Unknown { - msg: "unknown trap".to_string(), + EXCEPTION_INT_DIVIDE_BY_ZERO | EXCEPTION_INT_OVERFLOW => RuntimeError::Trap { + msg: "illegal arithmetic operation".into(), + }, + _ => RuntimeError::Trap { + msg: "unknown trap".into(), }, } .into()) @@ -103,8 +102,8 @@ pub fn call_protected( _ => "unkown trapped signal", }; - Err(RuntimeError::Unknown { - msg: format!("trap at {} - {}", exception_address, signal), + Err(RuntimeError::Trap { + msg: format!("unknown trap at {} - {}", exception_address, signal).into(), } .into()) } diff --git a/lib/runtime-core/src/backend.rs b/lib/runtime-core/src/backend.rs index e88383800..17266f2a5 100644 --- a/lib/runtime-core/src/backend.rs +++ b/lib/runtime-core/src/backend.rs @@ -12,7 +12,7 @@ use crate::{ module::ModuleInfo, sys::Memory, }; -use std::ptr::NonNull; +use std::{any::Any, ptr::NonNull}; pub mod sys { pub use crate::sys::*; @@ -78,7 +78,7 @@ pub trait ProtectedCaller: Send + Sync { } pub trait UserTrapper { - unsafe fn do_early_trap(&self, msg: String) -> !; + unsafe fn do_early_trap(&self, data: Box) -> !; } pub trait FuncResolver: Send + Sync { diff --git a/lib/runtime-core/src/error.rs b/lib/runtime-core/src/error.rs index 0e2ab6eb7..f1291448f 100644 --- a/lib/runtime-core/src/error.rs +++ b/lib/runtime-core/src/error.rs @@ -1,8 +1,9 @@ use crate::types::{ FuncSig, GlobalDescriptor, MemoryDescriptor, MemoryIndex, TableDescriptor, TableIndex, Type, + Value, }; use core::borrow::Borrow; -use std::sync::Arc; +use std::{any::Any, sync::Arc}; pub type Result = std::result::Result; pub type CompileResult = std::result::Result; @@ -120,28 +121,11 @@ impl std::error::Error for LinkError {} /// The main way to do this is `Instance.call`. /// /// Comparing two `RuntimeError`s always evaluates to false. -#[derive(Debug, Clone)] +#[derive(Debug)] pub enum RuntimeError { - OutOfBoundsAccess { - memory: MemoryIndex, - addr: Option, - }, - TableOutOfBounds { - table: TableIndex, - }, - IndirectCallSignature { - table: TableIndex, - }, - IndirectCallToNull { - table: TableIndex, - }, - IllegalArithmeticOperation, - User { - msg: String, - }, - Unknown { - msg: String, - }, + Trap { msg: Box }, + Exception { data: Box<[Value]> }, + Panic { data: Box }, } impl PartialEq for RuntimeError { @@ -153,30 +137,13 @@ impl PartialEq for RuntimeError { impl std::fmt::Display for RuntimeError { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { match self { - RuntimeError::IndirectCallSignature { table } => write!( - f, - "Indirect call signature error with Table Index \"{:?}\"", - table - ), - RuntimeError::IndirectCallToNull { table } => { - write!(f, "Indirect call to null with table index \"{:?}\"", table) + RuntimeError::Trap { ref msg } => { + write!(f, "WebAssembly trap occured during runtime: {}", msg) } - RuntimeError::IllegalArithmeticOperation => write!(f, "Illegal arithmetic operation"), - RuntimeError::OutOfBoundsAccess { memory, addr } => match addr { - Some(addr) => write!( - f, - "Out-of-bounds access with memory index {:?} and address {}", - memory, addr - ), - None => write!(f, "Out-of-bounds access with memory index {:?}", memory), - }, - RuntimeError::TableOutOfBounds { table } => { - write!(f, "Table out of bounds with table index \"{:?}\"", table) + RuntimeError::Exception { ref data } => { + write!(f, "Uncaught WebAssembly exception: {:?}", data) } - RuntimeError::Unknown { msg } => { - write!(f, "Unknown runtime error with message: \"{}\"", msg) - } - RuntimeError::User { msg } => write!(f, "User runtime error with message: \"{}\"", msg), + RuntimeError::Panic { data: _ } => write!(f, "User-defined \"panic\""), } } } @@ -239,7 +206,7 @@ impl std::error::Error for ResolveError {} /// be the `CallError::Runtime(RuntimeError)` variant. /// /// Comparing two `CallError`s always evaluates to false. -#[derive(Debug, Clone)] +#[derive(Debug)] pub enum CallError { Resolve(ResolveError), Runtime(RuntimeError), @@ -298,7 +265,7 @@ impl std::error::Error for CreationError {} /// of a webassembly module. /// /// Comparing two `Error`s always evaluates to false. -#[derive(Debug, Clone)] +#[derive(Debug)] pub enum Error { CompileError(CompileError), LinkError(Vec), diff --git a/lib/runtime-core/src/typed_func.rs b/lib/runtime-core/src/typed_func.rs index 6e59d0d4a..6e2a4d26c 100644 --- a/lib/runtime-core/src/typed_func.rs +++ b/lib/runtime-core/src/typed_func.rs @@ -6,7 +6,7 @@ use crate::{ types::{FuncSig, Type, WasmExternType}, vm::Ctx, }; -use std::{cell::UnsafeCell, fmt, marker::PhantomData, mem, panic, ptr, sync::Arc}; +use std::{any::Any, cell::UnsafeCell, fmt, marker::PhantomData, mem, panic, ptr, sync::Arc}; thread_local! { pub static EARLY_TRAPPER: UnsafeCell>> = UnsafeCell::new(None); @@ -40,14 +40,14 @@ pub trait TrapEarly where Rets: WasmTypeList, { - fn report(self) -> Result; + fn report(self) -> Result>; } impl TrapEarly for Rets where Rets: WasmTypeList, { - fn report(self) -> Result { + fn report(self) -> Result> { Ok(self) } } @@ -55,10 +55,10 @@ where impl TrapEarly for Result where Rets: WasmTypeList, - E: fmt::Debug, + E: Any, { - fn report(self) -> Result { - self.map_err(|err| format!("Error: {:?}", err)) + fn report(self) -> Result> { + self.map_err(|err| Box::new(err) as Box) } } @@ -191,25 +191,17 @@ macro_rules! impl_traits { extern fn wrap<$( $x: WasmExternType, )* Rets: WasmTypeList, Trap: TrapEarly, FN: Fn( &mut Ctx $( ,$x )* ) -> Trap>( ctx: &mut Ctx $( ,$x: $x )* ) -> Rets::CStruct { let f: FN = unsafe { mem::transmute_copy(&()) }; - let msg = match panic::catch_unwind(panic::AssertUnwindSafe(|| { + let err = match panic::catch_unwind(panic::AssertUnwindSafe(|| { f( ctx $( ,$x )* ).report() })) { Ok(Ok(returns)) => return returns.into_c_struct(), Ok(Err(err)) => err, - Err(err) => { - if let Some(s) = err.downcast_ref::<&str>() { - s.to_string() - } else if let Some(s) = err.downcast_ref::() { - s.clone() - } else { - "a panic occurred, but no additional information is available".to_string() - } - }, + Err(err) => err, }; unsafe { if let Some(early_trapper) = &*EARLY_TRAPPER.with(|ucell| ucell.get()) { - early_trapper.do_early_trap(msg) + early_trapper.do_early_trap(err) } else { eprintln!("panic handling not setup"); std::process::exit(1) diff --git a/lib/spectests/build/spectests.rs b/lib/spectests/build/spectests.rs index 54d9404d6..01e9c52dc 100644 --- a/lib/spectests/build/spectests.rs +++ b/lib/spectests/build/spectests.rs @@ -568,7 +568,7 @@ fn {}_assert_malformed() {{ let assertion = if expected.len() > 0 && is_nan(&expected[0]) { format!( "let expected = {expected_result}; - if let {return_type_destructure} = result.clone().unwrap().first().unwrap() {{ + if let {return_type_destructure} = result.as_ref().unwrap().first().unwrap() {{ assert!((*result as {return_type}).is_nan()); assert_eq!((*result as {return_type}).is_sign_positive(), (expected as {return_type}).is_sign_positive()); }} else {{ diff --git a/lib/spectests/tests/semantics.rs b/lib/spectests/tests/semantics.rs index c364dca29..0bffa9dca 100644 --- a/lib/spectests/tests/semantics.rs +++ b/lib/spectests/tests/semantics.rs @@ -31,7 +31,7 @@ mod tests { match result { Err(err) => match err { - CallError::Runtime(RuntimeError::Unknown { msg }) => { + CallError::Runtime(RuntimeError::Trap { msg }) => { assert!(!msg.contains("segmentation violation")); assert!(!msg.contains("bus error")); } From 039ebdcf7591e1ff0aea16c9ecc8a2e061fbf1c0 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Mon, 4 Mar 2019 13:10:28 -0800 Subject: [PATCH 180/262] Fix merge errors and update llvm to use the new runtime error type. --- Cargo.lock | 1682 +++++++++++++++++++++++++++++++ lib/llvm-backend/Cargo.toml | 2 +- lib/llvm-backend/src/backend.rs | 24 +- 3 files changed, 1694 insertions(+), 14 deletions(-) create mode 100644 Cargo.lock diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 000000000..2845dc155 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,1682 @@ +[[package]] +name = "aho-corasick" +version = "0.6.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ansi_term" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "arrayref" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "arrayvec" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "atty" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "autocfg" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "backtrace" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "backtrace-sys" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "bindgen" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cexpr 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "clang-sys 0.26.4 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "which 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "bitflags" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "blake2b_simd" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "byteorder" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "capstone" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "capstone-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "capstone-sys" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cast" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "cbindgen" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.27 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cc" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "cexpr" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "nom 4.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cfg-if" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "clang-sys" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "clap" +version = "2.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cloudabi" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cmake" +version = "0.1.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "constant_time_eq" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "cranelift-bforest" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cranelift-entity 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cranelift-codegen" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cranelift-bforest 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-codegen-meta 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-entity 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cranelift-codegen-meta" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cranelift-entity 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cranelift-entity" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "cranelift-frontend" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cranelift-codegen 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cranelift-native" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cranelift-codegen 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "raw-cpuid 6.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cranelift-wasm" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-codegen 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-entity 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-frontend 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmparser 0.22.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "criterion" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", + "criterion-plot 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "csv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_xoshiro 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", + "tinytemplate 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "criterion-plot" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-deque" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-utils" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "csv" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "csv-core 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "csv-core" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "digest" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "either" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "enum-methods" +version = "0.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "env_logger" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "errno" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "errno-dragonfly 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "failure" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "failure_derive" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.27 (registry+https://github.com/rust-lang/crates.io-index)", + "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "field-offset" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "fuchsia-cprng" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "gcc" +version = "0.3.55" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "generic-array" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "glob" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "goblin" +version = "0.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "plain 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "scroll 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "hashbrown" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "heck" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "hex" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "humantime" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "indexmap" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "inkwell" +version = "0.1.0" +source = "git+https://github.com/TheDan64/inkwell?branch=llvm7-0#b8699b0ee594e4162ce850fbedb37892e9cdb7e4" +dependencies = [ + "either 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "enum-methods 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "inkwell_internal_macros 0.1.0 (git+https://github.com/TheDan64/inkwell?branch=llvm7-0)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "llvm-sys 70.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "inkwell_internal_macros" +version = "0.1.0" +source = "git+https://github.com/TheDan64/inkwell?branch=llvm7-0#b8699b0ee594e4162ce850fbedb37892e9cdb7e4" +dependencies = [ + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.27 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "itertools" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "either 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "itoa" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "kernel32-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "lazy_static" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "libc" +version = "0.2.49" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "libloading" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "llvm-sys" +version = "70.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "lock_api" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "log" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "memchr" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "memmap" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "memoffset" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "nix" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "nix" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "nodrop" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "nom" +version = "4.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-traits" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "num_cpus" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "owning_ref" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "page_size" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parking_lot" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parking_lot_core" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "peeking_take_while" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "plain" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "proc-macro2" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "proc-macro2" +version = "0.4.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "quick-error" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "quote" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "quote" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "quote" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_chacha" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_core" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rand_hc" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_isaac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_jitter" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_os" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (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.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_pcg" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_xorshift" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_xoshiro" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "raw-cpuid" +version = "6.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rayon" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rayon-core" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rdrand" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "redox_syscall" +version = "0.1.51" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "redox_termios" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "regex" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "regex-syntax" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "remove_dir_all" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ryu" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "same-file" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "scopeguard" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "scroll" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "scroll_derive 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "scroll_derive" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.27 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "serde" +version = "1.0.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde-bench" +version = "0.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_bytes" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_derive" +version = "1.0.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.13.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_json" +version = "1.0.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "smallvec" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "stable_deref_trait" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "strsim" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "structopt" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", + "structopt-derive 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "structopt-derive" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.27 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "syn" +version = "0.11.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "syn" +version = "0.13.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "syn" +version = "0.15.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "synom" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "synstructure" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.27 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "target-lexicon" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tempfile" +version = "3.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", + "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "termcolor" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "termion" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "textwrap" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "thread_local" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "time" +version = "0.1.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tinytemplate" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "toml" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "typenum" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "ucd-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unicode-segmentation" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unicode-width" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unicode-xid" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unicode-xid" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "utf8-ranges" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "vec_map" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "version_check" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "wabt" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", + "wabt-sys 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wabt-sys" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", + "cmake 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", + "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "walkdir" +version = "2.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasmer" +version = "0.2.1" +dependencies = [ + "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "structopt 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", + "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmer-clif-backend 0.2.0", + "wasmer-emscripten 0.2.1", + "wasmer-runtime 0.2.1", + "wasmer-runtime-core 0.2.1", +] + +[[package]] +name = "wasmer-clif-backend" +version = "0.2.0" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-codegen 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-entity 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-native 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-wasm 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "nix 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde-bench 0.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_bytes 0.10.5 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", + "target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmer-runtime-core 0.2.1", + "wasmer-win-exception-handler 0.2.0", + "wasmparser 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasmer-emscripten" +version = "0.2.1" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmer-clif-backend 0.2.0", + "wasmer-runtime-core 0.2.1", +] + +[[package]] +name = "wasmer-llvm-backend" +version = "0.1.0" +dependencies = [ + "capstone 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", + "goblin 0.0.20 (registry+https://github.com/rust-lang/crates.io-index)", + "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "inkwell 0.1.0 (git+https://github.com/TheDan64/inkwell?branch=llvm7-0)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "nix 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmer-runtime-core 0.2.1", + "wasmparser 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasmer-runtime" +version = "0.2.1" +dependencies = [ + "criterion 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmer-clif-backend 0.2.0", + "wasmer-llvm-backend 0.1.0", + "wasmer-runtime-core 0.2.1", +] + +[[package]] +name = "wasmer-runtime-c-api" +version = "0.2.1" +dependencies = [ + "cbindgen 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmer-runtime 0.2.1", + "wasmer-runtime-core 0.2.1", +] + +[[package]] +name = "wasmer-runtime-core" +version = "0.2.1" +dependencies = [ + "blake2b_simd 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.0 (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)", + "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "nix 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "page_size 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde-bench 0.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_bytes 0.10.5 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmparser 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasmer-spectests" +version = "0.2.0" +dependencies = [ + "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmer-clif-backend 0.2.0", + "wasmer-llvm-backend 0.1.0", + "wasmer-runtime-core 0.2.1", +] + +[[package]] +name = "wasmer-win-exception-handler" +version = "0.2.0" +dependencies = [ + "bindgen 0.46.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cmake 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmer-runtime-core 0.2.1", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasmparser" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "wasmparser" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "wasmparser" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "which" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winapi" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winapi-build" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-util" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "wincolor" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[metadata] +"checksum aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "81ce3d38065e618af2d7b77e10c5ad9a069859b4be3c2250f674af3840d9c8a5" +"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" +"checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" +"checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" +"checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" +"checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799" +"checksum backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "cd5a90e2b463010cd0e0ce9a11d4a9d5d58d9f41d4a6ba3dcaf9e68b466e88b4" +"checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6" +"checksum bindgen 0.46.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8f7f7f0701772b17de73e4f5cbcb1dd6926f4706cba4c1ab62c5367f8bdc94e1" +"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" +"checksum blake2b_simd 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ce2571a6cd634670daa2977cc894c1cc2ba57c563c498e5a82c35446f34d056e" +"checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" +"checksum capstone 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "00be9d203fa0e078b93b24603633fb081851dfe0c1086364431f52587a47157e" +"checksum capstone-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2dc8d32bc5c1e6d0fcde10af411c98b07d93498d51654f678757f08fa2acd6a6" +"checksum cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "926013f2860c46252efceabb19f4a6b308197505082c609025aa6706c011d427" +"checksum cbindgen 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "32e01024aaf5390d6a8145047371a4f5b0063a14c1e411bc731353bd2278ca44" +"checksum cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)" = "d01c69d08ff207f231f07196e30f84c70f1c815b04f980f8b7b01ff01f05eb92" +"checksum cexpr 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "644d693ecfa91955ed32dcc7eda4914e1be97a641fb6f0645a37348e20b230da" +"checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" +"checksum clang-sys 0.26.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6ef0c1bcf2e99c649104bd7a7012d8f8802684400e03db0ec0af48583c6fa0e4" +"checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e" +"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" +"checksum cmake 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "6ec65ee4f9c9d16f335091d23693457ed4928657ba4982289d7fafee03bc614a" +"checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" +"checksum cranelift-bforest 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "40f8ff24e9a6c89b8a846b14df9a34d2cac17cea7bdb5c81ed6b4744ee0e38bf" +"checksum cranelift-codegen 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "42f5b809bd885c368e01aeec8fe04f21dcb07569834b907d75b4a7bed8d067eb" +"checksum cranelift-codegen-meta 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "014c23ed3ebdc8377d41540af638245207dd169f421df042dfccc867465734ed" +"checksum cranelift-entity 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4df40e26c0cf7b4d86919cb995bb412ee3001cc18e4f3c83a903f30b7007d8b" +"checksum cranelift-frontend 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "789907218eeebebcea8122c2053d71affac91c96ce72cea35ebfdbbf547e82af" +"checksum cranelift-native 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "474bee81d620a473bf43411a3d6f10ffbf7965141dc5e5b76d8d2151dde3285d" +"checksum cranelift-wasm 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49723365dab9a48b354bdc24cb6d9d5719bc1d3b858ffd2ea179d0d7d885804a" +"checksum criterion 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "1c6e5ee5b9652d4f851418c448af105642e1f99e9a2741a8ff45c0d2c911b1e0" +"checksum criterion-plot 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4107e4a5abb94267e0149922b8ff49dc70a87cc202820fdbfc0d3e1edbdc4b16" +"checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3" +"checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150" +"checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9" +"checksum csv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "9fd1c44c58078cfbeaf11fbb3eac9ae5534c23004ed770cc4bfb48e658ae4f04" +"checksum csv-core 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa5cdef62f37e6ffe7d1f07a381bc0db32b7a3ff1cac0de56cb0d81e71f53d65" +"checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c" +"checksum either 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c67353c641dc847124ea1902d69bd753dee9bb3beff9aa3662ecf86c971d1fac" +"checksum enum-methods 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7798e7da2d4cb0d6d6fc467e8d6b5bf247e9e989f786dde1732d79899c32bb10" +"checksum env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "afb070faf94c85d17d50ca44f6ad076bce18ae92f0037d350947240a36e9d42e" +"checksum errno 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c2a071601ed01b988f896ab14b95e67335d1eeb50190932a1320f7fe3cadc84e" +"checksum errno-dragonfly 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "14ca354e36190500e1e1fb267c647932382b54053c50b14970856c0b00a35067" +"checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" +"checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" +"checksum field-offset 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "64e9bc339e426139e02601fa69d101e96a92aee71b58bc01697ec2a63a5c9e68" +"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" +"checksum gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)" = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" +"checksum generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c0f28c2f5bfb5960175af447a2da7c18900693738343dc896ffbcabd9839592" +"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" +"checksum goblin 0.0.20 (registry+https://github.com/rust-lang/crates.io-index)" = "84473a5302fa5094d3d9911c2f312f522f9a37462a777f195f63fae1bf7faf4d" +"checksum hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3bae29b6653b3412c2e71e9d486db9f9df5d701941d86683005efb9f2d28e3da" +"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" +"checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" +"checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114" +"checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d" +"checksum inkwell 0.1.0 (git+https://github.com/TheDan64/inkwell?branch=llvm7-0)" = "" +"checksum inkwell_internal_macros 0.1.0 (git+https://github.com/TheDan64/inkwell?branch=llvm7-0)" = "" +"checksum itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358" +"checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" +"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" +"checksum libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)" = "413f3dfc802c5dc91dc570b05125b6cda9855edfaa9825c9849807876376e70e" +"checksum libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3ad660d7cb8c5822cd83d10897b0f1f1526792737a179e73896152f85b88c2" +"checksum llvm-sys 70.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60a9ee82fe0fa72ae6ef6d018b407296085863836451c7a97384f84ed7e26b9f" +"checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" +"checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" +"checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39" +"checksum memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" +"checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" +"checksum nix 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "921f61dc817b379d0834e45d5ec45beaacfae97082090a49c2cf30dcbc30206f" +"checksum nix 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46f0f3210768d796e8fa79ec70ee6af172dacbe7147f5e69be5240a47778302b" +"checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" +"checksum nom 4.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "22293d25d3f33a8567cc8a1dc20f40c7eeb761ce83d0fcca059858580790cac3" +"checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" +"checksum num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a23f0ed30a54abaa0c7e83b1d2d87ada7c3c23078d1d87815af3e3b6385fbba" +"checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" +"checksum page_size 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f89ef58b3d32420dbd1a43d2f38ae92f6239ef12bb556ab09ca55445f5a67242" +"checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" +"checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" +"checksum peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" +"checksum plain 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" +"checksum proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1b06e2f335f48d24442b35a19df506a835fb3547bc3c06ef27340da9acf5cae7" +"checksum proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915" +"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" +"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" +"checksum quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9949cfe66888ffe1d53e6ec9d9f3b70714083854be20fd5e271b232a017401e8" +"checksum quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cdd8e04bd9c52e0342b406469d494fcb033be4bdbe5c606016defbb1681411e1" +"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" +"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" +"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +"checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" +"checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" +"checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" +"checksum rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b9ea758282efe12823e0d952ddb269d2e1897227e464919a554f2a03ef1b832" +"checksum rand_os 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b7c690732391ae0abafced5015ffb53656abfaec61b342290e5eb56b286a679d" +"checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" +"checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" +"checksum rand_xoshiro 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "03b418169fb9c46533f326efd6eed2576699c44ca92d3052a066214a8d828929" +"checksum raw-cpuid 6.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "30a9d219c32c9132f7be513c18be77c9881c7107d2ab5569d205a6a0f0e6dc7d" +"checksum rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "373814f27745b2686b350dd261bfd24576a6fb0e2c5919b3a2b6005f820b0473" +"checksum rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b055d1e92aba6877574d8fe604a63c8b5df60f60e5982bf7ccbb1338ea527356" +"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" +"checksum redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)" = "423e376fffca3dfa06c9e9790a9ccd282fafb3cc6e6397d01dbf64f9bacc6b85" +"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" +"checksum regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53ee8cfdddb2e0291adfb9f13d31d3bbe0a03c9a402c01b1e24188d86c35b24f" +"checksum regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8c2f35eedad5295fdf00a63d7d4b238135723f92b434ec06774dad15c7ab0861" +"checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" +"checksum rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "adacaae16d02b6ec37fdc7acfcddf365978de76d1983d3ee22afc260e1ca9619" +"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +"checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7" +"checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267" +"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" +"checksum scroll 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2f84d114ef17fd144153d608fba7c446b0145d038985e7a8cc5d08bb0ce20383" +"checksum scroll_derive 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8f1aa96c45e7f5a91cb7fabe7b279f02fea7126239fc40b732316e8b6a2d0fcb" +"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" +"checksum serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)" = "92514fb95f900c9b5126e32d020f5c6d40564c27a5ea6d1d7d9f157a96623560" +"checksum serde-bench 0.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "d733da87e79faaac25616e33d26299a41143fd4cd42746cbb0e91d8feea243fd" +"checksum serde_bytes 0.10.5 (registry+https://github.com/rust-lang/crates.io-index)" = "defbb8a83d7f34cc8380751eeb892b825944222888aff18996ea7901f24aec88" +"checksum serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)" = "ac38f51a52a556cd17545798e29536885fb1a3fa63d6399f5ef650f4a7d35901" +"checksum serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)" = "5a23aa71d4a4d43fdbfaac00eff68ba8a06a51759a89ac3304323e800c4dd40d" +"checksum smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c4488ae950c49d403731982257768f48fada354a5203fe81f9bb6f43ca9002be" +"checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" +"checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" +"checksum structopt 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "670ad348dc73012fcf78c71f06f9d942232cdd4c859d4b6975e27836c3efc0c3" +"checksum structopt-derive 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "ef98172b1a00b0bec738508d3726540edcbd186d50dfd326f2b1febbb3559f04" +"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" +"checksum syn 0.13.11 (registry+https://github.com/rust-lang/crates.io-index)" = "14f9bf6292f3a61d2c716723fdb789a41bbe104168e6f496dc6497e531ea1b9b" +"checksum syn 0.15.27 (registry+https://github.com/rust-lang/crates.io-index)" = "525bd55255f03c816e5d7f615587bd13030c7103354fadb104993dcee6a788ec" +"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" +"checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" +"checksum target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4af5e2227f0b887d591d3724b796a96eff04226104d872f5b3883fcd427d64b9" +"checksum tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b86c784c88d98c801132806dadd3819ed29d8600836c4088e855cdf3e178ed8a" +"checksum termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f" +"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" +"checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6" +"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" +"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" +"checksum tinytemplate 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7655088894274afb52b807bd3c87072daa1fedd155068b8705cabfd628956115" +"checksum toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "758664fc71a3a69038656bee8b6be6477d2a6c315a6b81f7081f591bffa4111f" +"checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" +"checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" +"checksum unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa6024fc12ddfd1c6dbc14a80fa2324d4568849869b779f6bd37e5e4c03344d1" +"checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" +"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" +"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" +"checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737" +"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" +"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" +"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" +"checksum wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "74e463a508e390cc7447e70f640fbf44ad52e1bd095314ace1fdf99516d32add" +"checksum wabt-sys 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a6265b25719e82598d104b3717375e37661d41753e2c84cde3f51050c7ed7e3c" +"checksum walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d9d7ed3431229a144296213105a390676cc49c9b6a72bd19f3176c98e129fa1" +"checksum wasmparser 0.22.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f46e666ecb4a406483a59a49f9d0c17f327e70da53a128eccddae2eadb95865c" +"checksum wasmparser 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b5e01c420bc7d36e778bd242e1167b079562ba8b34087122cc9057187026d060" +"checksum wasmparser 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)" = "40f426b1929bd26517fb10702e2a8e520d1845c49567aa4d244f426f10b206c1" +"checksum which 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b57acb10231b9493c8472b20cb57317d0679a49e0bdbee44b3b803a6473af164" +"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" +"checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" +"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" +"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +"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.1 (registry+https://github.com/rust-lang/crates.io-index)" = "561ed901ae465d6185fa7864d63fbd5720d0ef718366c9a4dc83cf6170d7e9ba" diff --git a/lib/llvm-backend/Cargo.toml b/lib/llvm-backend/Cargo.toml index cdbfe63bf..a3290f3fd 100644 --- a/lib/llvm-backend/Cargo.toml +++ b/lib/llvm-backend/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Lachlan Sneff "] edition = "2018" [dependencies] -wasmer-runtime-core = { path = "../runtime-core", version = "0.1.2" } +wasmer-runtime-core = { path = "../runtime-core", version = "0.2.1" } wasmparser = "0.28.0" inkwell = { git = "https://github.com/TheDan64/inkwell", branch = "llvm7-0" } hashbrown = "0.1.8" diff --git a/lib/llvm-backend/src/backend.rs b/lib/llvm-backend/src/backend.rs index f08f0fd84..60cbef939 100644 --- a/lib/llvm-backend/src/backend.rs +++ b/lib/llvm-backend/src/backend.rs @@ -10,6 +10,7 @@ use libc::{ PROT_WRITE, }; use std::{ + any::Any, ffi::CString, mem, ptr::{self, NonNull}, @@ -397,20 +398,17 @@ impl ProtectedCaller for LLVMProtectedCaller { .collect()) } else { Err(match trap_out { - WasmTrapType::Unreachable => RuntimeError::User { + WasmTrapType::Unreachable => RuntimeError::Trap { msg: "unreachable".into(), }, - WasmTrapType::IncorrectCallIndirectSignature => { - RuntimeError::IndirectCallSignature { - table: TableIndex::new(0), - } - } - WasmTrapType::MemoryOutOfBounds => RuntimeError::OutOfBoundsAccess { - memory: MemoryIndex::new(0), - addr: None, + WasmTrapType::IncorrectCallIndirectSignature => RuntimeError::Trap { + msg: "uncorrect call_indirect signature".into(), }, - WasmTrapType::Unknown => RuntimeError::Unknown { - msg: "unknown error".into(), + WasmTrapType::MemoryOutOfBounds => RuntimeError::Trap { + msg: "memory out-of-bounds access".into(), + }, + WasmTrapType::Unknown => RuntimeError::Trap { + msg: "unknown trap".into(), }, }) } @@ -422,8 +420,8 @@ impl ProtectedCaller for LLVMProtectedCaller { } impl UserTrapper for Placeholder { - unsafe fn do_early_trap(&self, msg: String) -> ! { - unimplemented!("do early trap: {}", msg) + unsafe fn do_early_trap(&self, _data: Box) -> ! { + unimplemented!("do early trap") } } From 7ef2c0dece933830ba6aa4640e1933afdf13f5af Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Mon, 4 Mar 2019 14:41:56 -0800 Subject: [PATCH 181/262] Fix execute after free issue with llvm (and presumably cranelift?) --- lib/llvm-backend/src/backend.rs | 2 +- lib/llvm-backend/src/code.rs | 16 +++---- lib/llvm-backend/src/intrinsics.rs | 8 +--- lib/runtime-core/src/import.rs | 28 +++++++++-- lib/runtime-core/src/instance.rs | 8 +++- lib/runtime/examples/call.rs | 74 +++++++++++++++++++----------- 6 files changed, 88 insertions(+), 48 deletions(-) diff --git a/lib/llvm-backend/src/backend.rs b/lib/llvm-backend/src/backend.rs index 60cbef939..d951c7fa0 100644 --- a/lib/llvm-backend/src/backend.rs +++ b/lib/llvm-backend/src/backend.rs @@ -278,7 +278,7 @@ impl LLVMBackend { info: &ModuleInfo, local_func_index: LocalFuncIndex, ) -> Option> { - let index = local_func_index.index(); + let index = info.imported_functions.len() + local_func_index.index(); let name = if cfg!(target_os = "macos") { format!("_fn{}", index) } else { diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index 51815f3f6..e58a5d06a 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -136,6 +136,8 @@ pub fn parse_function_bodies( pass_manager.add_aggressive_dce_pass(); pass_manager.run_on_module(&module); + // module.print_to_stderr(); + Ok((module, intrinsics)) } @@ -671,15 +673,11 @@ fn parse_function( let func_ptr_ty = llvm_sig.ptr_type(AddressSpace::Generic); - // Once we can just bitcast between pointer types, remove this. - let func_ptr = { - let ptr_int = builder.build_ptr_to_int( - func_ptr_untyped, - intrinsics.i64_ty, - "func_ptr_int", - ); - builder.build_int_to_ptr(ptr_int, func_ptr_ty, "typed_func_ptr") - }; + let func_ptr = builder.build_pointer_cast( + func_ptr_untyped, + func_ptr_ty, + "typed_func_ptr", + ); builder.build_call(func_ptr, ¶ms, &state.var_name()) } diff --git a/lib/llvm-backend/src/intrinsics.rs b/lib/llvm-backend/src/intrinsics.rs index 9e91c5911..78ce0ae12 100644 --- a/lib/llvm-backend/src/intrinsics.rs +++ b/lib/llvm-backend/src/intrinsics.rs @@ -197,7 +197,6 @@ impl Intrinsics { .ptr_type(AddressSpace::Generic) .as_basic_type_enum(), imported_func_ty - .ptr_type(AddressSpace::Generic) .ptr_type(AddressSpace::Generic) .as_basic_type_enum(), sigindex_ty @@ -713,16 +712,13 @@ impl<'a> CtxType<'a> { .build_load(func_array_ptr_ptr, "func_array_ptr") .into_pointer_value(); let const_index = intrinsics.i32_ty.const_int(index.index() as u64, false); - let imported_func_ptr_ptr = unsafe { + let imported_func_ptr = unsafe { cache_builder.build_in_bounds_gep( func_array_ptr, &[const_index], - "imported_func_ptr_ptr", + "imported_func_ptr", ) }; - let imported_func_ptr = cache_builder - .build_load(imported_func_ptr_ptr, "imported_func_ptr") - .into_pointer_value(); let (func_ptr_ptr, ctx_ptr_ptr) = unsafe { ( cache_builder.build_struct_gep(imported_func_ptr, 0, "func_ptr_ptr"), diff --git a/lib/runtime-core/src/import.rs b/lib/runtime-core/src/import.rs index 7073a5ac1..59d9da555 100644 --- a/lib/runtime-core/src/import.rs +++ b/lib/runtime-core/src/import.rs @@ -1,5 +1,9 @@ use crate::export::Export; use hashbrown::{hash_map::Entry, HashMap}; +use std::{ + cell::{Ref, RefCell}, + rc::Rc, +}; pub trait LikeNamespace { fn get_export(&self, name: &str) -> Option; @@ -37,14 +41,14 @@ impl IsExport for Export { /// } /// ``` pub struct ImportObject { - map: HashMap>, + map: Rc>>>, } impl ImportObject { /// Create a new `ImportObject`. pub fn new() -> Self { Self { - map: HashMap::new(), + map: Rc::new(RefCell::new(HashMap::new())), } } @@ -67,7 +71,9 @@ impl ImportObject { S: Into, N: LikeNamespace + 'static, { - match self.map.entry(name.into()) { + let mut map = self.map.borrow_mut(); + + match map.entry(name.into()) { Entry::Vacant(empty) => { empty.insert(Box::new(namespace)); None @@ -76,8 +82,20 @@ impl ImportObject { } } - pub fn get_namespace(&self, namespace: &str) -> Option<&(dyn LikeNamespace + 'static)> { - self.map.get(namespace).map(|namespace| &**namespace) + pub fn get_namespace(&self, namespace: &str) -> Option> { + let map_ref = self.map.borrow(); + + if map_ref.contains_key(namespace) { + Some(Ref::map(map_ref, |map| &*map[namespace])) + } else { + None + } + } + + pub fn clone_ref(&self) -> Self { + Self { + map: Rc::clone(&self.map), + } } } diff --git a/lib/runtime-core/src/instance.rs b/lib/runtime-core/src/instance.rs index 61e8f556d..3dee6ee50 100644 --- a/lib/runtime-core/src/instance.rs +++ b/lib/runtime-core/src/instance.rs @@ -39,6 +39,8 @@ impl Drop for InstanceInner { pub struct Instance { module: Arc, inner: Box, + #[allow(dead_code)] + import_object: ImportObject, } impl Instance { @@ -64,7 +66,11 @@ impl Instance { *inner.vmctx = vm::Ctx::new(&mut inner.backing, &mut inner.import_backing, &module) }; - let instance = Instance { module, inner }; + let instance = Instance { + module, + inner, + import_object: imports.clone_ref(), + }; if let Some(start_index) = instance.module.info.start_func { instance.call_with_index(start_index, &[])?; diff --git a/lib/runtime/examples/call.rs b/lib/runtime/examples/call.rs index e9ac58acc..679f01d27 100644 --- a/lib/runtime/examples/call.rs +++ b/lib/runtime/examples/call.rs @@ -1,53 +1,75 @@ -use wasmer_runtime::{compile, error, imports, Func, Value}; +use wasmer_runtime::{compile, error, imports, Ctx, Func, Value}; use wabt::wat2wasm; static WAT: &'static str = r#" (module - (type (;0;) (func (result i32))) - (type (;1;) (func (param i32 i32))) - (type (;2;) (func (param i32) (result i32))) - (func (;0;) (type 0) (result i32) - memory.size - i32.const 65536 - i32.mul) - (func (;1;) (type 1) (param i32 i32) - call 0 + (type (;0;) (func)) + (type (;1;) (func)) + (type (;2;) (func)) + (type (;3;) (func (result i32))) + (type (;4;) (func (result i32))) + (type (;5;) (func (param i32) (result i32))) + (type (;6;) (func (param i32))) + (import "spectest" "print_i32" (func (;0;) (type 6))) + (func (;1;) (type 0)) + (func (;2;) (type 1)) + (func (;3;) (type 4) (result i32) + i32.const 13) + (func (;4;) (type 5) (param i32) (result i32) local.get 0 - i32.sub - local.get 1 - i32.store) - (func (;2;) (type 2) (param i32) (result i32) - call 0 + i32.const 1 + i32.add) + (func (;5;) (type 5) (param i32) (result i32) local.get 0 - i32.add - i32.load) - (func (;3;) (type 2) (param i32) (result i32) + i32.const 2 + i32.sub) + (func (;6;) (type 6) (param i32) local.get 0 - memory.grow) - (memory (;0;) 1 2) - (export "store" (func 1)) - (export "load" (func 2)) - (export "memory.grow" (func 3))) + call 0) + (export "one" (func 3)) + (export "two" (func 4)) + (export "three" (func 5)) + (export "four" (func 6))) +"#; + +static WAT2: &'static str = r#" + (module + (type $t0 (func (param i32))) + (type $t1 (func)) + (func $print_i32 (export "print_i32") (type $t0) (param $lhs i32)) + (func $print (export "print") (type $t1)) + (table $table (export "table") 10 20 anyfunc) + (memory $memory (export "memory") 1 2) + (global $global_i32 (export "global_i32") i32 (i32.const 666))) "#; fn get_wasm() -> Vec { wat2wasm(WAT).unwrap() } +fn foobar(ctx: &mut Ctx) -> i32 { + 42 +} + fn main() -> Result<(), error::Error> { let wasm = get_wasm(); let module = compile(&wasm)?; - let imports = imports! {}; + let import_module = compile(&wat2wasm(WAT2).unwrap())?; + let import_instance = import_module.instantiate(&imports! {})?; + + let imports = imports! { + "spectest" => import_instance, + }; println!("instantiating"); let instance = module.instantiate(&imports)?; - let foo = instance.dyn_func("store")?; + let foo = instance.dyn_func("four")?; - let result = foo.call(&[Value::I32(0), Value::I32(1)]); + let result = foo.call(&[Value::I32(10)]); println!("result: {:?}", result); From 25c0cef5f7a40bc5aa6fef74cb84f70047457854 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Mon, 4 Mar 2019 15:51:45 -0800 Subject: [PATCH 182/262] Up to 1242 passing spectests --- lib/llvm-backend/src/code.rs | 124 ++++++++++++++++++++++++++++- lib/llvm-backend/src/intrinsics.rs | 13 +-- 2 files changed, 125 insertions(+), 12 deletions(-) diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index e58a5d06a..7566d53dc 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -3,8 +3,8 @@ use inkwell::{ context::Context, module::{Linkage, Module}, passes::PassManager, - types::{BasicType, BasicTypeEnum, FunctionType, PointerType}, - values::{BasicValue, FunctionValue, PhiValue, PointerValue}, + types::{BasicType, BasicTypeEnum, FunctionType, IntType, PointerType}, + values::{BasicValue, FunctionValue, IntValue, PhiValue, PointerValue}, AddressSpace, FloatPredicate, IntPredicate, }; use smallvec::SmallVec; @@ -613,7 +613,7 @@ fn parse_function( let global_cache = ctx.global_cache(index); match global_cache { GlobalCache::Const { value } => { - state.push1(value.as_basic_value_enum()); + state.push1(value); } GlobalCache::Mut { ptr_to_value } => { let value = builder.build_load(ptr_to_value, "global_value"); @@ -882,24 +882,36 @@ fn parse_function( Operator::I32DivS | Operator::I64DivS => { let (v1, v2) = state.pop2()?; let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); + + trap_if_zero_or_overflow(builder, intrinsics, context, &function, v1, v2); + let res = builder.build_int_signed_div(v1, v2, &state.var_name()); state.push1(res); } Operator::I32DivU | Operator::I64DivU => { let (v1, v2) = state.pop2()?; let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); + + trap_if_zero(builder, intrinsics, context, &function, v2); + let res = builder.build_int_unsigned_div(v1, v2, &state.var_name()); state.push1(res); } Operator::I32RemS | Operator::I64RemS => { let (v1, v2) = state.pop2()?; let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); + + trap_if_zero(builder, intrinsics, context, &function, v2); + let res = builder.build_int_signed_rem(v1, v2, &state.var_name()); state.push1(res); } Operator::I32RemU | Operator::I64RemU => { let (v1, v2) = state.pop2()?; let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); + + trap_if_zero(builder, intrinsics, context, &function, v2); + let res = builder.build_int_unsigned_rem(v1, v2, &state.var_name()); state.push1(res); } @@ -2001,6 +2013,112 @@ fn parse_function( Ok(()) } +fn trap_if_zero_or_overflow( + builder: &Builder, + intrinsics: &Intrinsics, + context: &Context, + function: &FunctionValue, + left: IntValue, + right: IntValue, +) { + let int_type = left.get_type(); + + let (min_value, neg_one_value) = if int_type == intrinsics.i32_ty { + let min_value = int_type.const_int(i32::min_value() as u64, false); + let neg_one_value = int_type.const_int(-1i32 as u32 as u64, false); + (min_value, neg_one_value) + } else if int_type == intrinsics.i64_ty { + let min_value = int_type.const_int(i64::min_value() as u64, false); + let neg_one_value = int_type.const_int(-1i64 as u64, false); + (min_value, neg_one_value) + } else { + unreachable!() + }; + + let should_trap = builder.build_or( + builder.build_int_compare( + IntPredicate::EQ, + right, + int_type.const_int(0, false), + "divisor_is_zero", + ), + builder.build_and( + builder.build_int_compare(IntPredicate::EQ, left, min_value, "left_is_min"), + builder.build_int_compare(IntPredicate::EQ, right, neg_one_value, "right_is_neg_one"), + "div_will_overflow", + ), + "div_should_trap", + ); + + let should_trap = builder + .build_call( + intrinsics.expect_i1, + &[ + should_trap.as_basic_value_enum(), + intrinsics.i1_ty.const_int(0, false).as_basic_value_enum(), + ], + "should_trap_expect", + ) + .try_as_basic_value() + .left() + .unwrap() + .into_int_value(); + + let shouldnt_trap_block = context.append_basic_block(function, "shouldnt_trap_block"); + let should_trap_block = context.append_basic_block(function, "should_trap_block"); + builder.build_conditional_branch(should_trap, &should_trap_block, &shouldnt_trap_block); + builder.position_at_end(&should_trap_block); + builder.build_call( + intrinsics.throw_trap, + &[intrinsics.trap_memory_oob], + "throw", + ); + builder.build_unreachable(); + builder.position_at_end(&shouldnt_trap_block); +} + +fn trap_if_zero( + builder: &Builder, + intrinsics: &Intrinsics, + context: &Context, + function: &FunctionValue, + value: IntValue, +) { + let int_type = value.get_type(); + let should_trap = builder.build_int_compare( + IntPredicate::EQ, + value, + int_type.const_int(0, false), + "divisor_is_zero", + ); + + let should_trap = builder + .build_call( + intrinsics.expect_i1, + &[ + should_trap.as_basic_value_enum(), + intrinsics.i1_ty.const_int(0, false).as_basic_value_enum(), + ], + "should_trap_expect", + ) + .try_as_basic_value() + .left() + .unwrap() + .into_int_value(); + + let shouldnt_trap_block = context.append_basic_block(function, "shouldnt_trap_block"); + let should_trap_block = context.append_basic_block(function, "should_trap_block"); + builder.build_conditional_branch(should_trap, &should_trap_block, &shouldnt_trap_block); + builder.position_at_end(&should_trap_block); + builder.build_call( + intrinsics.throw_trap, + &[intrinsics.trap_memory_oob], + "throw", + ); + builder.build_unreachable(); + builder.position_at_end(&shouldnt_trap_block); +} + fn resolve_memory_ptr( builder: &Builder, intrinsics: &Intrinsics, diff --git a/lib/llvm-backend/src/intrinsics.rs b/lib/llvm-backend/src/intrinsics.rs index 78ce0ae12..f0764742b 100644 --- a/lib/llvm-backend/src/intrinsics.rs +++ b/lib/llvm-backend/src/intrinsics.rs @@ -419,7 +419,7 @@ struct TableCache { #[derive(Clone, Copy)] pub enum GlobalCache { Mut { ptr_to_value: PointerValue }, - Const { value: IntValue }, + Const { value: BasicValueEnum }, } struct ImportedFuncCache { @@ -675,11 +675,8 @@ impl<'a> CtxType<'a> { .build_load(global_ptr_ptr, "global_ptr") .into_pointer_value(); - let global_ptr_typed = { - let int = - cache_builder.build_ptr_to_int(global_ptr, intrinsics.i64_ty, "global_ptr_int"); - cache_builder.build_int_to_ptr(int, llvm_ptr_ty, "global_ptr_typed") - }; + let global_ptr_typed = + cache_builder.build_pointer_cast(global_ptr, llvm_ptr_ty, "global_ptr_typed"); if mutable { GlobalCache::Mut { @@ -687,9 +684,7 @@ impl<'a> CtxType<'a> { } } else { GlobalCache::Const { - value: cache_builder - .build_load(global_ptr_typed, "global_value") - .into_int_value(), + value: cache_builder.build_load(global_ptr_typed, "global_value"), } } }) From 2969409ca74ccd0b3ece01d9ad9a11968bbc0c09 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Mon, 4 Mar 2019 16:44:46 -0800 Subject: [PATCH 183/262] Add hacky reinterpret instructions and pop used arguments off the value stack --- lib/llvm-backend/src/code.rs | 64 ++++++++++++++++--- lib/runtime/examples/call.rs | 119 ++++++++++++++++++++++++----------- 2 files changed, 136 insertions(+), 47 deletions(-) diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index 7566d53dc..5cff36abd 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -581,13 +581,23 @@ fn parse_function( state.push1(i); } Operator::F32Const { value } => { - let f = intrinsics - .f32_ty - .const_float(f32::from_bits(value.bits()) as f64); + let bits = intrinsics.i32_ty.const_int(value.bits() as u64, false); + let space = + builder.build_alloca(intrinsics.f32_ty.as_basic_type_enum(), "const_space"); + let i32_space = + builder.build_pointer_cast(space, intrinsics.i32_ptr_ty, "i32_space"); + builder.build_store(i32_space, bits); + let f = builder.build_load(space, "f"); state.push1(f); } Operator::F64Const { value } => { - let f = intrinsics.f64_ty.const_float(f64::from_bits(value.bits())); + let bits = intrinsics.i64_ty.const_int(value.bits(), false); + let space = + builder.build_alloca(intrinsics.f64_ty.as_basic_type_enum(), "const_space"); + let i64_space = + builder.build_pointer_cast(space, intrinsics.i64_ptr_ty, "i32_space"); + builder.build_store(i64_space, bits); + let f = builder.build_load(space, "f"); state.push1(f); } @@ -683,6 +693,8 @@ fn parse_function( } }; + state.popn(func_sig.params().len())?; + if let Some(basic_value) = call_site.try_as_basic_value().left() { match func_sig.returns().len() { 1 => state.push1(basic_value), @@ -1521,11 +1533,45 @@ fn parse_function( builder.build_unsigned_int_to_float(v1, intrinsics.f64_ty, &state.var_name()); state.push1(res); } - Operator::I32ReinterpretF32 - | Operator::F32ReinterpretI32 - | Operator::I64ReinterpretF64 - | Operator::F64ReinterpretI64 => { - unimplemented!("waiting on better bitcasting support in inkwell") + Operator::I32ReinterpretF32 => { + let v = state.pop1()?; + let space = + builder.build_alloca(intrinsics.i32_ty.as_basic_type_enum(), &state.var_name()); + let f32_space = + builder.build_pointer_cast(space, intrinsics.f32_ptr_ty, &state.var_name()); + builder.build_store(f32_space, v); + let int = builder.build_load(space, &state.var_name()); + state.push1(int); + } + Operator::I64ReinterpretF64 => { + let v = state.pop1()?; + let space = + builder.build_alloca(intrinsics.i64_ty.as_basic_type_enum(), &state.var_name()); + let f64_space = + builder.build_pointer_cast(space, intrinsics.f64_ptr_ty, &state.var_name()); + builder.build_store(f64_space, v); + let int = builder.build_load(space, &state.var_name()); + state.push1(int); + } + Operator::F32ReinterpretI32 => { + let v = state.pop1()?; + let space = + builder.build_alloca(intrinsics.f32_ty.as_basic_type_enum(), &state.var_name()); + let i32_space = + builder.build_pointer_cast(space, intrinsics.i32_ptr_ty, &state.var_name()); + builder.build_store(i32_space, v); + let f = builder.build_load(space, &state.var_name()); + state.push1(f); + } + Operator::F64ReinterpretI64 => { + let v = state.pop1()?; + let space = + builder.build_alloca(intrinsics.f64_ty.as_basic_type_enum(), &state.var_name()); + let i64_space = + builder.build_pointer_cast(space, intrinsics.i64_ptr_ty, &state.var_name()); + builder.build_store(i64_space, v); + let f = builder.build_load(space, &state.var_name()); + state.push1(f); } /*************************** diff --git a/lib/runtime/examples/call.rs b/lib/runtime/examples/call.rs index 679f01d27..c2716bb6c 100644 --- a/lib/runtime/examples/call.rs +++ b/lib/runtime/examples/call.rs @@ -4,45 +4,88 @@ use wabt::wat2wasm; static WAT: &'static str = r#" (module - (type (;0;) (func)) - (type (;1;) (func)) - (type (;2;) (func)) - (type (;3;) (func (result i32))) - (type (;4;) (func (result i32))) - (type (;5;) (func (param i32) (result i32))) - (type (;6;) (func (param i32))) - (import "spectest" "print_i32" (func (;0;) (type 6))) - (func (;1;) (type 0)) - (func (;2;) (type 1)) - (func (;3;) (type 4) (result i32) - i32.const 13) - (func (;4;) (type 5) (param i32) (result i32) + (type (;0;) (func (param i32 i32))) + (type (;1;) (func (param i32 i64))) + (type (;2;) (func (param i32) (result i32))) + (type (;3;) (func (param i32) (result i64))) + (type (;4;) (func (param i64) (result i64))) + (type (;5;) (func (param f32) (result f32))) + (type (;6;) (func (param f64) (result f64))) + (func (;0;) (type 0) (param i32 i32) + local.get 0 + local.get 1 + i32.store8 local.get 0 i32.const 1 - i32.add) - (func (;5;) (type 5) (param i32) (result i32) + i32.add + local.get 1 + i32.const 8 + i32.shr_u + i32.store8) + (func (;1;) (type 0) (param i32 i32) + local.get 0 + local.get 1 + call 0 local.get 0 i32.const 2 - i32.sub) - (func (;6;) (type 6) (param i32) - local.get 0 + i32.add + local.get 1 + i32.const 16 + i32.shr_u call 0) - (export "one" (func 3)) - (export "two" (func 4)) - (export "three" (func 5)) - (export "four" (func 6))) + (func (;2;) (type 1) (param i32 i64) + local.get 0 + local.get 1 + i32.wrap_i64 + call 1 + local.get 0 + i32.const 4 + i32.add + local.get 1 + i64.const 32 + i64.shr_u + i32.wrap_i64 + call 1) + (func (;3;) (type 2) (param i32) (result i32) + local.get 0 + i32.load8_u + local.get 0 + i32.const 1 + i32.add + i32.load8_u + i32.const 8 + i32.shl + i32.or) + (func (;4;) (type 2) (param i32) (result i32) + local.get 0 + call 3 + local.get 0 + i32.const 2 + i32.add + call 3 + i32.const 16 + i32.shl + i32.or) + (func (;5;) (type 3) (param i32) (result i64) + local.get 0 + i64.extend_i32_u + local.get 0 + call 4 + i64.extend_i32_u + i64.or) + (memory (;0;) 1)) "#; -static WAT2: &'static str = r#" - (module - (type $t0 (func (param i32))) - (type $t1 (func)) - (func $print_i32 (export "print_i32") (type $t0) (param $lhs i32)) - (func $print (export "print") (type $t1)) - (table $table (export "table") 10 20 anyfunc) - (memory $memory (export "memory") 1 2) - (global $global_i32 (export "global_i32") i32 (i32.const 666))) -"#; +// static WAT2: &'static str = r#" +// (module +// (type $t0 (func (param i32))) +// (type $t1 (func)) +// (func $print_i32 (export "print_i32") (type $t0) (param $lhs i32)) +// (func $print (export "print") (type $t1)) +// (table $table (export "table") 10 20 anyfunc) +// (memory $memory (export "memory") 1 2) +// (global $global_i32 (export "global_i32") i32 (i32.const 666))) +// "#; fn get_wasm() -> Vec { wat2wasm(WAT).unwrap() @@ -57,15 +100,15 @@ fn main() -> Result<(), error::Error> { let module = compile(&wasm)?; - let import_module = compile(&wat2wasm(WAT2).unwrap())?; - let import_instance = import_module.instantiate(&imports! {})?; + // let import_module = compile(&wat2wasm(WAT2).unwrap())?; + // let import_instance = import_module.instantiate(&imports! {})?; - let imports = imports! { - "spectest" => import_instance, - }; + // let imports = imports! { + // "spectest" => import_instance, + // }; println!("instantiating"); - let instance = module.instantiate(&imports)?; + let instance = module.instantiate(&imports! {})?; let foo = instance.dyn_func("four")?; From 3be714489287f975335614949ae8927bf5e05209 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Mon, 4 Mar 2019 17:37:05 -0800 Subject: [PATCH 184/262] Some cleanup --- lib/llvm-backend/cpp/object_loader.cpp | 1 - lib/llvm-backend/src/backend.rs | 2 +- lib/llvm-backend/src/code.rs | 8 ++++---- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/lib/llvm-backend/cpp/object_loader.cpp b/lib/llvm-backend/cpp/object_loader.cpp index ff6dbe2d1..968618068 100644 --- a/lib/llvm-backend/cpp/object_loader.cpp +++ b/lib/llvm-backend/cpp/object_loader.cpp @@ -153,7 +153,6 @@ public: private: llvm::JITEvaluatedSymbol symbol_lookup(llvm::StringRef name) { - std::cout << "symbol name: " << (std::string)name << std::endl; uint64_t addr = callbacks.lookup_vm_symbol(name.data(), name.size()); return llvm::JITEvaluatedSymbol(addr, llvm::JITSymbolFlags::None); diff --git a/lib/llvm-backend/src/backend.rs b/lib/llvm-backend/src/backend.rs index d951c7fa0..749f47af1 100644 --- a/lib/llvm-backend/src/backend.rs +++ b/lib/llvm-backend/src/backend.rs @@ -233,7 +233,7 @@ impl LLVMBackend { &triple, &TargetMachine::get_host_cpu_name().to_string(), &TargetMachine::get_host_cpu_features().to_string(), - OptimizationLevel::Default, + OptimizationLevel::Aggressive, RelocMode::PIC, CodeModel::Default, ) diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index 5cff36abd..ef9ca15af 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -123,13 +123,13 @@ pub fn parse_function_bodies( generate_trampolines(info, &signatures, &module, &context, &builder, &intrinsics); let pass_manager = PassManager::create_for_module(); - pass_manager.add_verifier_pass(); + // pass_manager.add_verifier_pass(); pass_manager.add_function_inlining_pass(); pass_manager.add_promote_memory_to_register_pass(); pass_manager.add_cfg_simplification_pass(); - pass_manager.add_instruction_combining_pass(); - // pass_manager.add_aggressive_inst_combiner_pass(); - // pass_manager.add_merged_load_store_motion_pass(); + // pass_manager.add_instruction_combining_pass(); + pass_manager.add_aggressive_inst_combiner_pass(); + pass_manager.add_merged_load_store_motion_pass(); // pass_manager.add_sccp_pass(); pass_manager.add_gvn_pass(); // pass_manager.add_new_gvn_pass(); From fe8f8a013284b2f3631c54edd8329fbe974b0028 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Mon, 4 Mar 2019 19:56:02 -0800 Subject: [PATCH 185/262] Add illegal arithmetic runtime error --- lib/llvm-backend/cpp/object_loader.hh | 8 ++- lib/llvm-backend/src/backend.rs | 8 +++ lib/llvm-backend/src/code.rs | 12 ++-- lib/llvm-backend/src/intrinsics.rs | 2 + lib/runtime/examples/call.rs | 82 ++++----------------------- 5 files changed, 35 insertions(+), 77 deletions(-) diff --git a/lib/llvm-backend/cpp/object_loader.hh b/lib/llvm-backend/cpp/object_loader.hh index 880d97b3f..d22acb919 100644 --- a/lib/llvm-backend/cpp/object_loader.hh +++ b/lib/llvm-backend/cpp/object_loader.hh @@ -70,6 +70,7 @@ public: IncorrectCallIndirectSignature = 1, MemoryOutOfBounds = 2, CallIndirectOOB = 3, + IllegalArithmetic = 4, Unknown, }; @@ -98,6 +99,12 @@ private: case Type::MemoryOutOfBounds: out << "memory access out-of-bounds"; break; + case Type::CallIndirectOOB: + out << "call_indirect out-of-bounds"; + break; + case Type::IllegalArithmetic: + out << "illegal arithmetic operation"; + break; case Type::Unknown: default: out << "unknown"; @@ -142,7 +149,6 @@ extern "C" { } [[noreturn]] void throw_trap(WasmTrap::Type ty) { - std::cout << "throwing trap: " << ty << std::endl; throw WasmTrap(ty); } diff --git a/lib/llvm-backend/src/backend.rs b/lib/llvm-backend/src/backend.rs index 749f47af1..bd8f25bb3 100644 --- a/lib/llvm-backend/src/backend.rs +++ b/lib/llvm-backend/src/backend.rs @@ -61,6 +61,8 @@ enum WasmTrapType { Unreachable = 0, IncorrectCallIndirectSignature = 1, MemoryOutOfBounds = 2, + CallIndirectOOB = 3, + IllegalArithmetic = 4, Unknown, } @@ -407,6 +409,12 @@ impl ProtectedCaller for LLVMProtectedCaller { WasmTrapType::MemoryOutOfBounds => RuntimeError::Trap { msg: "memory out-of-bounds access".into(), }, + WasmTrapType::CallIndirectOOB => RuntimeError::Trap { + msg: "call_indirect out-of-bounds".into(), + }, + WasmTrapType::IllegalArithmetic => RuntimeError::Trap { + msg: "illegal arithmetic operation".into(), + }, WasmTrapType::Unknown => RuntimeError::Trap { msg: "unknown trap".into(), }, diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index ef9ca15af..c223900f5 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -122,6 +122,8 @@ pub fn parse_function_bodies( generate_trampolines(info, &signatures, &module, &context, &builder, &intrinsics); + println!("done generating ir"); + let pass_manager = PassManager::create_for_module(); // pass_manager.add_verifier_pass(); pass_manager.add_function_inlining_pass(); @@ -131,11 +133,13 @@ pub fn parse_function_bodies( pass_manager.add_aggressive_inst_combiner_pass(); pass_manager.add_merged_load_store_motion_pass(); // pass_manager.add_sccp_pass(); - pass_manager.add_gvn_pass(); - // pass_manager.add_new_gvn_pass(); + // pass_manager.add_gvn_pass(); + pass_manager.add_new_gvn_pass(); pass_manager.add_aggressive_dce_pass(); pass_manager.run_on_module(&module); + println!("done optimizing ir"); + // module.print_to_stderr(); Ok((module, intrinsics)) @@ -2116,7 +2120,7 @@ fn trap_if_zero_or_overflow( builder.position_at_end(&should_trap_block); builder.build_call( intrinsics.throw_trap, - &[intrinsics.trap_memory_oob], + &[intrinsics.trap_illegal_arithmetic], "throw", ); builder.build_unreachable(); @@ -2158,7 +2162,7 @@ fn trap_if_zero( builder.position_at_end(&should_trap_block); builder.build_call( intrinsics.throw_trap, - &[intrinsics.trap_memory_oob], + &[intrinsics.trap_illegal_arithmetic], "throw", ); builder.build_unreachable(); diff --git a/lib/llvm-backend/src/intrinsics.rs b/lib/llvm-backend/src/intrinsics.rs index f0764742b..98c41326e 100644 --- a/lib/llvm-backend/src/intrinsics.rs +++ b/lib/llvm-backend/src/intrinsics.rs @@ -97,6 +97,7 @@ pub struct Intrinsics { pub trap_call_indirect_sig: BasicValueEnum, pub trap_call_indirect_oob: BasicValueEnum, pub trap_memory_oob: BasicValueEnum, + pub trap_illegal_arithmetic: BasicValueEnum, // VM intrinsics. pub memory_grow_dynamic_local: FunctionValue, @@ -295,6 +296,7 @@ impl Intrinsics { trap_call_indirect_sig: i32_ty.const_int(1, false).as_basic_value_enum(), trap_call_indirect_oob: i32_ty.const_int(3, false).as_basic_value_enum(), trap_memory_oob: i32_ty.const_int(2, false).as_basic_value_enum(), + trap_illegal_arithmetic: i32_ty.const_int(4, false).as_basic_value_enum(), // VM intrinsics. memory_grow_dynamic_local: module.add_function( diff --git a/lib/runtime/examples/call.rs b/lib/runtime/examples/call.rs index c2716bb6c..dbd29c7e8 100644 --- a/lib/runtime/examples/call.rs +++ b/lib/runtime/examples/call.rs @@ -4,76 +4,14 @@ use wabt::wat2wasm; static WAT: &'static str = r#" (module - (type (;0;) (func (param i32 i32))) - (type (;1;) (func (param i32 i64))) - (type (;2;) (func (param i32) (result i32))) - (type (;3;) (func (param i32) (result i64))) - (type (;4;) (func (param i64) (result i64))) - (type (;5;) (func (param f32) (result f32))) - (type (;6;) (func (param f64) (result f64))) - (func (;0;) (type 0) (param i32 i32) - local.get 0 - local.get 1 - i32.store8 - local.get 0 - i32.const 1 - i32.add - local.get 1 - i32.const 8 - i32.shr_u - i32.store8) - (func (;1;) (type 0) (param i32 i32) - local.get 0 - local.get 1 - call 0 - local.get 0 - i32.const 2 - i32.add - local.get 1 - i32.const 16 - i32.shr_u - call 0) - (func (;2;) (type 1) (param i32 i64) - local.get 0 - local.get 1 - i32.wrap_i64 - call 1 - local.get 0 - i32.const 4 - i32.add - local.get 1 - i64.const 32 - i64.shr_u - i32.wrap_i64 - call 1) - (func (;3;) (type 2) (param i32) (result i32) - local.get 0 - i32.load8_u - local.get 0 - i32.const 1 - i32.add - i32.load8_u - i32.const 8 - i32.shl - i32.or) - (func (;4;) (type 2) (param i32) (result i32) - local.get 0 - call 3 - local.get 0 - i32.const 2 - i32.add - call 3 - i32.const 16 - i32.shl - i32.or) - (func (;5;) (type 3) (param i32) (result i64) - local.get 0 - i64.extend_i32_u - local.get 0 - call 4 - i64.extend_i32_u - i64.or) - (memory (;0;) 1)) + (type (;0;) (func (result i32))) + (func $dbz (result i32) + i32.const 42 + i32.const 0 + i32.div_u + ) + (export "dbz" (func $dbz)) + ) "#; // static WAT2: &'static str = r#" @@ -110,9 +48,9 @@ fn main() -> Result<(), error::Error> { println!("instantiating"); let instance = module.instantiate(&imports! {})?; - let foo = instance.dyn_func("four")?; + let foo = instance.dyn_func("dbz")?; - let result = foo.call(&[Value::I32(10)]); + let result = foo.call(&[]); println!("result: {:?}", result); From f2b927bcd86891c3c644ee3f85f3cfe8977e6d32 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Mon, 4 Mar 2019 20:00:56 -0800 Subject: [PATCH 186/262] Remove debug print --- lib/llvm-backend/src/code.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index c223900f5..38d5ac7b6 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -122,8 +122,6 @@ pub fn parse_function_bodies( generate_trampolines(info, &signatures, &module, &context, &builder, &intrinsics); - println!("done generating ir"); - let pass_manager = PassManager::create_for_module(); // pass_manager.add_verifier_pass(); pass_manager.add_function_inlining_pass(); @@ -138,8 +136,6 @@ pub fn parse_function_bodies( pass_manager.add_aggressive_dce_pass(); pass_manager.run_on_module(&module); - println!("done optimizing ir"); - // module.print_to_stderr(); Ok((module, intrinsics)) From 5ace3cfa2b94f758ff83de4c6f14399426448df2 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 4 Mar 2019 14:52:09 +0100 Subject: [PATCH 187/262] fix(runtime-c-api) Remove unsafe blocks inside unsafe function. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch removes `unsafe { … }` blocks inside `unsafe` functions. This patch also removes some warnings about camel case. All structures with a C representation are automatically not mangle, and allow non camel case. --- lib/runtime-c-api/src/lib.rs | 149 ++++++++++++++++------------------- 1 file changed, 70 insertions(+), 79 deletions(-) diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index 5512c0287..fc3cf1fbf 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -17,23 +17,23 @@ use wasmer_runtime_core::module::{ExportIndex, ImportName}; use wasmer_runtime_core::types::{ElementType, FuncSig, MemoryDescriptor, TableDescriptor, Type}; use wasmer_runtime_core::units::{Bytes, Pages}; -#[allow(non_camel_case_types)] -pub struct wasmer_module_t(); +#[repr(C)] +pub struct wasmer_module_t; + +#[repr(C)] +pub struct wasmer_instance_t; + +#[repr(C)] +pub struct wasmer_instance_context_t; #[allow(non_camel_case_types)] -pub struct wasmer_instance_t(); - -#[allow(non_camel_case_types)] -pub struct wasmer_instance_context_t(); - -#[allow(non_camel_case_types)] -#[no_mangle] #[repr(C)] pub enum wasmer_result_t { WASMER_OK = 1, WASMER_ERROR = 2, } +#[allow(non_camel_case_types)] #[repr(u32)] #[derive(Clone)] pub enum wasmer_value_tag { @@ -68,23 +68,23 @@ pub struct wasmer_global_descriptor_t { #[repr(C)] #[derive(Clone)] -pub struct wasmer_memory_t(); +pub struct wasmer_memory_t; #[repr(C)] #[derive(Clone)] -pub struct wasmer_table_t(); +pub struct wasmer_table_t; #[repr(C)] #[derive(Clone)] -pub struct wasmer_import_func_t(); +pub struct wasmer_import_func_t; #[repr(C)] #[derive(Clone)] -pub struct wasmer_export_func_t(); +pub struct wasmer_export_func_t; #[repr(C)] #[derive(Clone)] -pub struct wasmer_global_t(); +pub struct wasmer_global_t; #[repr(C)] pub struct wasmer_limits_t { @@ -130,6 +130,7 @@ pub struct wasmer_export_descriptor_t; #[derive(Clone)] pub struct wasmer_export_descriptors_t; +#[allow(non_camel_case_types)] #[repr(u32)] #[derive(Clone)] pub enum wasmer_import_export_kind { @@ -164,8 +165,7 @@ pub unsafe extern "C" fn wasmer_validate( if wasm_bytes.is_null() { return false; } - let bytes: &[u8] = - unsafe { ::std::slice::from_raw_parts_mut(wasm_bytes, wasm_bytes_len as usize) }; + let bytes: &[u8] = ::std::slice::from_raw_parts_mut(wasm_bytes, wasm_bytes_len as usize); wasmer_runtime_core::validate(bytes) } @@ -201,7 +201,7 @@ pub unsafe extern "C" fn wasmer_memory_new( return wasmer_result_t::WASMER_ERROR; } }; - unsafe { *memory = Box::into_raw(Box::new(new_memory)) as *mut wasmer_memory_t }; + *memory = Box::into_raw(Box::new(new_memory)) as *mut wasmer_memory_t; wasmer_result_t::WASMER_OK } @@ -269,7 +269,7 @@ pub unsafe extern "C" fn wasmer_table_new( return wasmer_result_t::WASMER_ERROR; } }; - unsafe { *table = Box::into_raw(Box::new(new_table)) as *mut wasmer_table_t }; + *table = Box::into_raw(Box::new(new_table)) as *mut wasmer_table_t; wasmer_result_t::WASMER_OK } @@ -326,7 +326,7 @@ pub unsafe extern "C" fn wasmer_global_new( } else { Global::new(value.into()) }; - unsafe { Box::into_raw(Box::new(global)) as *mut wasmer_global_t } + Box::into_raw(Box::new(global)) as *mut wasmer_global_t } /// Gets the value stored by the given Global @@ -392,8 +392,7 @@ pub unsafe extern "C" fn wasmer_compile( wasm_bytes: *mut uint8_t, wasm_bytes_len: uint32_t, ) -> wasmer_result_t { - let bytes: &[u8] = - unsafe { ::std::slice::from_raw_parts_mut(wasm_bytes, wasm_bytes_len as usize) }; + let bytes: &[u8] = ::std::slice::from_raw_parts_mut(wasm_bytes, wasm_bytes_len as usize); let result = wasmer_runtime::compile(bytes); let new_module = match result { Ok(instance) => instance, @@ -402,7 +401,7 @@ pub unsafe extern "C" fn wasmer_compile( return wasmer_result_t::WASMER_ERROR; } }; - unsafe { *module = Box::into_raw(Box::new(new_module)) as *mut wasmer_module_t }; + *module = Box::into_raw(Box::new(new_module)) as *mut wasmer_module_t; wasmer_result_t::WASMER_OK } @@ -477,7 +476,7 @@ pub unsafe extern "C" fn wasmer_module_instantiate( import_object.register(module_name, namespace); } - let module = unsafe { &*(module as *mut Module) }; + let module = &*(module as *mut Module); let new_instance = if let Ok(res) = module.instantiate(&import_object) { res } else { @@ -486,7 +485,7 @@ pub unsafe extern "C" fn wasmer_module_instantiate( }); return wasmer_result_t::WASMER_ERROR; }; - unsafe { *instance = Box::into_raw(Box::new(new_instance)) as *mut wasmer_instance_t }; + *instance = Box::into_raw(Box::new(new_instance)) as *mut wasmer_instance_t; wasmer_result_t::WASMER_OK } @@ -499,15 +498,12 @@ pub unsafe extern "C" fn wasmer_export_descriptors( module: *mut wasmer_module_t, export_descriptors: *mut *mut wasmer_export_descriptors_t, ) { - let mut module = unsafe { &*(module as *mut Module) }; + let mut module = &*(module as *mut Module); let named_export_descriptors: Box = Box::new(NamedExportDescriptors( module.info().exports.iter().map(|e| e.into()).collect(), )); - unsafe { - *export_descriptors = - Box::into_raw(named_export_descriptors) as *mut wasmer_export_descriptors_t - }; + *export_descriptors = Box::into_raw(named_export_descriptors) as *mut wasmer_export_descriptors_t; } pub struct NamedExportDescriptors(Vec); @@ -519,7 +515,7 @@ pub unsafe extern "C" fn wasmer_export_descriptors_destroy( export_descriptors: *mut wasmer_export_descriptors_t, ) { if !export_descriptors.is_null() { - drop(unsafe { Box::from_raw(export_descriptors as *mut NamedExportDescriptors) }); + drop(Box::from_raw(export_descriptors as *mut NamedExportDescriptors)); } } @@ -546,7 +542,7 @@ pub unsafe extern "C" fn wasmer_export_descriptors_get( return ptr::null_mut(); } let mut named_export_descriptors = - unsafe { &mut *(export_descriptors as *mut NamedExportDescriptors) }; + &mut *(export_descriptors as *mut NamedExportDescriptors); let ptr = &mut (*named_export_descriptors).0[idx as usize] as *mut NamedExportDescriptor as *mut wasmer_export_descriptor_t; ptr @@ -593,7 +589,7 @@ pub unsafe extern "C" fn wasmer_import_descriptors( module: *mut wasmer_module_t, import_descriptors: *mut *mut wasmer_import_descriptors_t, ) { - let mut module = unsafe { &*(module as *mut Module) }; + let mut module = &*(module as *mut Module); let total_imports = module.info().imported_functions.len() + module.info().imported_tables.len() + module.info().imported_globals.len() @@ -601,7 +597,7 @@ pub unsafe extern "C" fn wasmer_import_descriptors( let mut descriptors: Vec = Vec::with_capacity(total_imports); for ( - index, + _index, ImportName { namespace_index, name_index, @@ -618,7 +614,7 @@ pub unsafe extern "C" fn wasmer_import_descriptors( } for ( - index, + _index, ( ImportName { namespace_index, @@ -638,7 +634,7 @@ pub unsafe extern "C" fn wasmer_import_descriptors( } for ( - index, + _index, ( ImportName { namespace_index, @@ -658,7 +654,7 @@ pub unsafe extern "C" fn wasmer_import_descriptors( } for ( - index, + _index, ( ImportName { namespace_index, @@ -679,10 +675,8 @@ pub unsafe extern "C" fn wasmer_import_descriptors( let named_import_descriptors: Box = Box::new(NamedImportDescriptors(descriptors)); - unsafe { - *import_descriptors = - Box::into_raw(named_import_descriptors) as *mut wasmer_import_descriptors_t - }; + *import_descriptors = + Box::into_raw(named_import_descriptors) as *mut wasmer_import_descriptors_t; } pub struct NamedImportDescriptors(Vec); @@ -694,7 +688,7 @@ pub unsafe extern "C" fn wasmer_import_descriptors_destroy( import_descriptors: *mut wasmer_import_descriptors_t, ) { if !import_descriptors.is_null() { - drop(unsafe { Box::from_raw(import_descriptors as *mut NamedImportDescriptors) }); + drop(Box::from_raw(import_descriptors as *mut NamedImportDescriptors)); } } @@ -721,7 +715,7 @@ pub unsafe extern "C" fn wasmer_import_descriptors_get( return ptr::null_mut(); } let mut named_import_descriptors = - unsafe { &mut *(import_descriptors as *mut NamedImportDescriptors) }; + &mut *(import_descriptors as *mut NamedImportDescriptors); let ptr = &mut (*named_import_descriptors).0[idx as usize] as *mut NamedImportDescriptor as *mut wasmer_import_descriptor_t; ptr @@ -835,18 +829,17 @@ pub unsafe extern "C" fn wasmer_instantiate( Export::Table((&*table).clone()) } }; - namespace.insert(import_name, unsafe { export }); + namespace.insert(import_name, export); } for (module_name, namespace) in namespaces.into_iter() { import_object.register(module_name, namespace); } - let bytes: &[u8] = - unsafe { ::std::slice::from_raw_parts_mut(wasm_bytes, wasm_bytes_len as usize) }; + let bytes: &[u8] = ::std::slice::from_raw_parts_mut(wasm_bytes, wasm_bytes_len as usize); let result = wasmer_runtime::instantiate(bytes, &import_object); let new_instance = match result { Ok(instance) => instance, - Err(error) => { + Err(_error) => { // TODO the trait bound `wasmer_runtime::error::Error: std::error::Error` is not satisfied //update_last_error(error); update_last_error(CApiError { @@ -855,7 +848,7 @@ pub unsafe extern "C" fn wasmer_instantiate( return wasmer_result_t::WASMER_ERROR; } }; - unsafe { *instance = Box::into_raw(Box::new(new_instance)) as *mut wasmer_instance_t }; + *instance = Box::into_raw(Box::new(new_instance)) as *mut wasmer_instance_t; wasmer_result_t::WASMER_OK } @@ -898,7 +891,7 @@ pub unsafe extern "C" fn wasmer_instance_call( let params: &[wasmer_value_t] = slice::from_raw_parts(params, params_len as usize); let params: Vec = params.iter().cloned().map(|x| x.into()).collect(); - let func_name_c = unsafe { CStr::from_ptr(name) }; + let func_name_c = CStr::from_ptr(name); let func_name_r = func_name_c.to_str().unwrap(); let results: &mut [wasmer_value_t] = slice::from_raw_parts_mut(results, results_len as usize); @@ -945,7 +938,7 @@ pub unsafe extern "C" fn wasmer_instance_exports( instance: *mut wasmer_instance_t, exports: *mut *mut wasmer_exports_t, ) { - let mut instance_ref = unsafe { &mut *(instance as *mut Instance) }; + let mut instance_ref = &mut *(instance as *mut Instance); let mut exports_vec: Vec = Vec::with_capacity(instance_ref.exports().count()); for (name, export) in instance_ref.exports() { exports_vec.push(NamedExport { @@ -955,7 +948,7 @@ pub unsafe extern "C" fn wasmer_instance_exports( }); } let named_exports: Box = Box::new(NamedExports(exports_vec)); - unsafe { *exports = Box::into_raw(named_exports) as *mut wasmer_exports_t }; + *exports = Box::into_raw(named_exports) as *mut wasmer_exports_t; } pub struct NamedExports(Vec); @@ -965,7 +958,7 @@ pub struct NamedExports(Vec); #[no_mangle] pub unsafe extern "C" fn wasmer_exports_destroy(exports: *mut wasmer_exports_t) { if !exports.is_null() { - drop(unsafe { Box::from_raw(exports as *mut NamedExports) }); + drop(Box::from_raw(exports as *mut NamedExports)); } } @@ -989,7 +982,7 @@ pub unsafe extern "C" fn wasmer_exports_get( if exports.is_null() { return ptr::null_mut(); } - let mut named_exports = unsafe { &mut *(exports as *mut NamedExports) }; + let mut named_exports = &mut *(exports as *mut NamedExports); let ptr = &mut (*named_exports).0[idx as usize] as *mut NamedExport as *mut wasmer_export_t; ptr } @@ -1021,10 +1014,10 @@ pub unsafe extern "C" fn wasmer_export_func_params_arity( func: *mut wasmer_export_func_t, result: *mut uint32_t, ) -> wasmer_result_t { - let mut named_export = unsafe { &*(func as *mut NamedExport) }; + let mut named_export = &*(func as *mut NamedExport); let mut export = &named_export.export; let result = if let Export::Function { ref signature, .. } = *export { - unsafe { *result = signature.params().len() as uint32_t }; + *result = signature.params().len() as uint32_t; wasmer_result_t::WASMER_OK } else { update_last_error(CApiError { @@ -1048,7 +1041,7 @@ pub unsafe extern "C" fn wasmer_export_func_params( params: *mut wasmer_value_tag, params_len: c_int, ) -> wasmer_result_t { - let mut named_export = unsafe { &*(func as *mut NamedExport) }; + let mut named_export = &*(func as *mut NamedExport); let mut export = &named_export.export; let result = if let Export::Function { ref signature, .. } = *export { let params: &mut [wasmer_value_tag] = @@ -1079,7 +1072,7 @@ pub unsafe extern "C" fn wasmer_export_func_returns( returns: *mut wasmer_value_tag, returns_len: c_int, ) -> wasmer_result_t { - let mut named_export = unsafe { &*(func as *mut NamedExport) }; + let mut named_export = &*(func as *mut NamedExport); let mut export = &named_export.export; let result = if let Export::Function { ref signature, .. } = *export { let returns: &mut [wasmer_value_tag] = @@ -1109,10 +1102,10 @@ pub unsafe extern "C" fn wasmer_export_func_returns_arity( func: *mut wasmer_export_func_t, result: *mut uint32_t, ) -> wasmer_result_t { - let mut named_export = unsafe { &*(func as *mut NamedExport) }; + let mut named_export = &*(func as *mut NamedExport); let mut export = &named_export.export; let result = if let Export::Function { ref signature, .. } = *export { - unsafe { *result = signature.returns().len() as uint32_t }; + *result = signature.returns().len() as uint32_t; wasmer_result_t::WASMER_OK } else { update_last_error(CApiError { @@ -1135,9 +1128,9 @@ pub unsafe extern "C" fn wasmer_import_func_params_arity( func: *mut wasmer_import_func_t, result: *mut uint32_t, ) -> wasmer_result_t { - let mut export = unsafe { &mut *(func as *mut Export) }; + let mut export = &mut *(func as *mut Export); let result = if let Export::Function { ref signature, .. } = *export { - unsafe { *result = signature.params().len() as uint32_t }; + *result = signature.params().len() as uint32_t; wasmer_result_t::WASMER_OK } else { update_last_error(CApiError { @@ -1166,7 +1159,7 @@ pub unsafe extern "C" fn wasmer_import_func_new( let returns: Vec = returns.iter().cloned().map(|x| x.into()).collect(); let export = Box::new(Export::Function { - func: unsafe { FuncPointer::new(func as _) }, + func: FuncPointer::new(func as _), ctx: Context::Internal, signature: Arc::new(FuncSig::new(params, returns)), }); @@ -1186,7 +1179,7 @@ pub unsafe extern "C" fn wasmer_import_func_params( params: *mut wasmer_value_tag, params_len: c_int, ) -> wasmer_result_t { - let mut export = unsafe { &mut *(func as *mut Export) }; + let mut export = &mut *(func as *mut Export); let result = if let Export::Function { ref signature, .. } = *export { let params: &mut [wasmer_value_tag] = slice::from_raw_parts_mut(params, params_len as usize); @@ -1216,7 +1209,7 @@ pub unsafe extern "C" fn wasmer_import_func_returns( returns: *mut wasmer_value_tag, returns_len: c_int, ) -> wasmer_result_t { - let mut export = unsafe { &mut *(func as *mut Export) }; + let mut export = &mut *(func as *mut Export); let result = if let Export::Function { ref signature, .. } = *export { let returns: &mut [wasmer_value_tag] = slice::from_raw_parts_mut(returns, returns_len as usize); @@ -1245,9 +1238,9 @@ pub unsafe extern "C" fn wasmer_import_func_returns_arity( func: *mut wasmer_import_func_t, result: *mut uint32_t, ) -> wasmer_result_t { - let mut export = unsafe { &*(func as *mut Export) }; + let mut export = &*(func as *mut Export); let result = if let Export::Function { ref signature, .. } = *export { - unsafe { *result = signature.returns().len() as uint32_t }; + *result = signature.returns().len() as uint32_t; wasmer_result_t::WASMER_OK } else { update_last_error(CApiError { @@ -1319,7 +1312,7 @@ pub unsafe extern "C" fn wasmer_export_func_call( let params: &[wasmer_value_t] = slice::from_raw_parts(params, params_len as usize); let params: Vec = params.iter().cloned().map(|x| x.into()).collect(); - let named_export = unsafe { &*(func as *mut NamedExport) }; + let named_export = &*(func as *mut NamedExport); let results: &mut [wasmer_value_t] = slice::from_raw_parts_mut(results, results_len as usize); @@ -1363,7 +1356,7 @@ pub unsafe extern "C" fn wasmer_export_func_call( #[no_mangle] pub extern "C" fn wasmer_instance_context_memory( ctx: *mut wasmer_instance_context_t, - memory_idx: uint32_t, + _memory_idx: uint32_t, ) -> *const wasmer_memory_t { let mut ctx = unsafe { &mut *(ctx as *mut Ctx) }; let memory = ctx.memory(0); @@ -1402,19 +1395,19 @@ impl From for Value { unsafe { match v { wasmer_value_t { - tag: WASM_I32, + tag: wasmer_value_tag::WASM_I32, value: wasmer_value { I32 }, } => Value::I32(I32), wasmer_value_t { - tag: WASM_I64, + tag: wasmer_value_tag::WASM_I64, value: wasmer_value { I64 }, } => Value::I64(I64), wasmer_value_t { - tag: WASM_F32, + tag: wasmer_value_tag::WASM_F32, value: wasmer_value { F32 }, } => Value::F32(F32), wasmer_value_t { - tag: WASM_F64, + tag: wasmer_value_tag::WASM_F64, value: wasmer_value { F64 }, } => Value::F64(F64), _ => panic!("not implemented"), @@ -1460,14 +1453,12 @@ impl From for wasmer_value_tag { impl From for Type { fn from(v: wasmer_value_tag) -> Self { - unsafe { - match v { - wasmer_value_tag::WASM_I32 => Type::I32, - wasmer_value_tag::WASM_I64 => Type::I64, - wasmer_value_tag::WASM_F32 => Type::F32, - wasmer_value_tag::WASM_F64 => Type::F64, - _ => panic!("not implemented"), - } + match v { + wasmer_value_tag::WASM_I32 => Type::I32, + wasmer_value_tag::WASM_I64 => Type::I64, + wasmer_value_tag::WASM_F32 => Type::F32, + wasmer_value_tag::WASM_F64 => Type::F64, + _ => panic!("not implemented"), } } } From 053e5c40f4bf1b0c380d1e5405dc5e32a66b2617 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 4 Mar 2019 15:21:03 +0100 Subject: [PATCH 188/262] fix(runtime-c-api) Avoid mutable bindings as much as possible. This patch cleans several warnings where mutable bindings are declared but used only as immutable bindings. It's a little bit opinionated patch. I think it's interesting to use `const` pointers as much as possible. --- lib/runtime-c-api/src/lib.rs | 77 ++++++++++++++++++------------------ 1 file changed, 39 insertions(+), 38 deletions(-) diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index fc3cf1fbf..66d3de39a 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -166,6 +166,7 @@ pub unsafe extern "C" fn wasmer_validate( return false; } let bytes: &[u8] = ::std::slice::from_raw_parts_mut(wasm_bytes, wasm_bytes_len as usize); + wasmer_runtime_core::validate(bytes) } @@ -180,7 +181,7 @@ pub unsafe extern "C" fn wasmer_validate( /// and `wasmer_last_error_message` to get an error message. #[no_mangle] pub unsafe extern "C" fn wasmer_memory_new( - mut memory: *mut *mut wasmer_memory_t, + memory: *mut *mut wasmer_memory_t, limits: wasmer_limits_t, ) -> wasmer_result_t { let max = if limits.max.has_some { @@ -248,7 +249,7 @@ pub extern "C" fn wasmer_memory_length(memory: *mut wasmer_memory_t) -> uint32_t /// and `wasmer_last_error_message` to get an error message. #[no_mangle] pub unsafe extern "C" fn wasmer_table_new( - mut table: *mut *mut wasmer_table_t, + table: *mut *mut wasmer_table_t, limits: wasmer_limits_t, ) -> wasmer_result_t { let max = if limits.max.has_some { @@ -388,7 +389,7 @@ pub extern "C" fn wasmer_memory_destroy(memory: *mut wasmer_memory_t) { #[allow(clippy::cast_ptr_alignment)] #[no_mangle] pub unsafe extern "C" fn wasmer_compile( - mut module: *mut *mut wasmer_module_t, + module: *mut *mut wasmer_module_t, wasm_bytes: *mut uint8_t, wasm_bytes_len: uint32_t, ) -> wasmer_result_t { @@ -414,8 +415,8 @@ pub unsafe extern "C" fn wasmer_compile( #[allow(clippy::cast_ptr_alignment)] #[no_mangle] pub unsafe extern "C" fn wasmer_module_instantiate( - module: *mut wasmer_module_t, - mut instance: *mut *mut wasmer_instance_t, + module: *const wasmer_module_t, + instance: *mut *mut wasmer_instance_t, imports: *mut wasmer_import_t, imports_len: c_int, ) -> wasmer_result_t { @@ -476,7 +477,7 @@ pub unsafe extern "C" fn wasmer_module_instantiate( import_object.register(module_name, namespace); } - let module = &*(module as *mut Module); + let module = &*(module as *const Module); let new_instance = if let Ok(res) = module.instantiate(&import_object) { res } else { @@ -495,10 +496,10 @@ pub unsafe extern "C" fn wasmer_module_instantiate( #[allow(clippy::cast_ptr_alignment)] #[no_mangle] pub unsafe extern "C" fn wasmer_export_descriptors( - module: *mut wasmer_module_t, + module: *const wasmer_module_t, export_descriptors: *mut *mut wasmer_export_descriptors_t, ) { - let mut module = &*(module as *mut Module); + let module = &*(module as *const Module); let named_export_descriptors: Box = Box::new(NamedExportDescriptors( module.info().exports.iter().map(|e| e.into()).collect(), @@ -541,7 +542,7 @@ pub unsafe extern "C" fn wasmer_export_descriptors_get( if export_descriptors.is_null() { return ptr::null_mut(); } - let mut named_export_descriptors = + let named_export_descriptors = &mut *(export_descriptors as *mut NamedExportDescriptors); let ptr = &mut (*named_export_descriptors).0[idx as usize] as *mut NamedExportDescriptor as *mut wasmer_export_descriptor_t; @@ -586,10 +587,10 @@ pub extern "C" fn wasmer_module_destroy(module: *mut wasmer_module_t) { #[allow(clippy::cast_ptr_alignment)] #[no_mangle] pub unsafe extern "C" fn wasmer_import_descriptors( - module: *mut wasmer_module_t, + module: *const wasmer_module_t, import_descriptors: *mut *mut wasmer_import_descriptors_t, ) { - let mut module = &*(module as *mut Module); + let module = &*(module as *const Module); let total_imports = module.info().imported_functions.len() + module.info().imported_tables.len() + module.info().imported_globals.len() @@ -714,7 +715,7 @@ pub unsafe extern "C" fn wasmer_import_descriptors_get( if import_descriptors.is_null() { return ptr::null_mut(); } - let mut named_import_descriptors = + let named_import_descriptors = &mut *(import_descriptors as *mut NamedImportDescriptors); let ptr = &mut (*named_import_descriptors).0[idx as usize] as *mut NamedImportDescriptor as *mut wasmer_import_descriptor_t; @@ -766,7 +767,7 @@ pub unsafe extern "C" fn wasmer_import_descriptor_kind( #[allow(clippy::cast_ptr_alignment)] #[no_mangle] pub unsafe extern "C" fn wasmer_instantiate( - mut instance: *mut *mut wasmer_instance_t, + instance: *mut *mut wasmer_instance_t, wasm_bytes: *mut uint8_t, wasm_bytes_len: uint32_t, imports: *mut wasmer_import_t, @@ -938,7 +939,7 @@ pub unsafe extern "C" fn wasmer_instance_exports( instance: *mut wasmer_instance_t, exports: *mut *mut wasmer_exports_t, ) { - let mut instance_ref = &mut *(instance as *mut Instance); + let instance_ref = &mut *(instance as *mut Instance); let mut exports_vec: Vec = Vec::with_capacity(instance_ref.exports().count()); for (name, export) in instance_ref.exports() { exports_vec.push(NamedExport { @@ -982,7 +983,7 @@ pub unsafe extern "C" fn wasmer_exports_get( if exports.is_null() { return ptr::null_mut(); } - let mut named_exports = &mut *(exports as *mut NamedExports); + let named_exports = &mut *(exports as *mut NamedExports); let ptr = &mut (*named_exports).0[idx as usize] as *mut NamedExport as *mut wasmer_export_t; ptr } @@ -1011,11 +1012,11 @@ pub unsafe extern "C" fn wasmer_export_kind( #[no_mangle] #[allow(clippy::cast_ptr_alignment)] pub unsafe extern "C" fn wasmer_export_func_params_arity( - func: *mut wasmer_export_func_t, + func: *const wasmer_export_func_t, result: *mut uint32_t, ) -> wasmer_result_t { - let mut named_export = &*(func as *mut NamedExport); - let mut export = &named_export.export; + let named_export = &*(func as *const NamedExport); + let export = &named_export.export; let result = if let Export::Function { ref signature, .. } = *export { *result = signature.params().len() as uint32_t; wasmer_result_t::WASMER_OK @@ -1037,12 +1038,12 @@ pub unsafe extern "C" fn wasmer_export_func_params_arity( #[no_mangle] #[allow(clippy::cast_ptr_alignment)] pub unsafe extern "C" fn wasmer_export_func_params( - func: *mut wasmer_export_func_t, + func: *const wasmer_export_func_t, params: *mut wasmer_value_tag, params_len: c_int, ) -> wasmer_result_t { - let mut named_export = &*(func as *mut NamedExport); - let mut export = &named_export.export; + let named_export = &*(func as *const NamedExport); + let export = &named_export.export; let result = if let Export::Function { ref signature, .. } = *export { let params: &mut [wasmer_value_tag] = slice::from_raw_parts_mut(params, params_len as usize); @@ -1068,12 +1069,12 @@ pub unsafe extern "C" fn wasmer_export_func_params( #[no_mangle] #[allow(clippy::cast_ptr_alignment)] pub unsafe extern "C" fn wasmer_export_func_returns( - func: *mut wasmer_export_func_t, + func: *const wasmer_export_func_t, returns: *mut wasmer_value_tag, returns_len: c_int, ) -> wasmer_result_t { - let mut named_export = &*(func as *mut NamedExport); - let mut export = &named_export.export; + let named_export = &*(func as *const NamedExport); + let export = &named_export.export; let result = if let Export::Function { ref signature, .. } = *export { let returns: &mut [wasmer_value_tag] = slice::from_raw_parts_mut(returns, returns_len as usize); @@ -1099,11 +1100,11 @@ pub unsafe extern "C" fn wasmer_export_func_returns( #[no_mangle] #[allow(clippy::cast_ptr_alignment)] pub unsafe extern "C" fn wasmer_export_func_returns_arity( - func: *mut wasmer_export_func_t, + func: *const wasmer_export_func_t, result: *mut uint32_t, ) -> wasmer_result_t { - let mut named_export = &*(func as *mut NamedExport); - let mut export = &named_export.export; + let named_export = &*(func as *const NamedExport); + let export = &named_export.export; let result = if let Export::Function { ref signature, .. } = *export { *result = signature.returns().len() as uint32_t; wasmer_result_t::WASMER_OK @@ -1125,10 +1126,10 @@ pub unsafe extern "C" fn wasmer_export_func_returns_arity( #[no_mangle] #[allow(clippy::cast_ptr_alignment)] pub unsafe extern "C" fn wasmer_import_func_params_arity( - func: *mut wasmer_import_func_t, + func: *const wasmer_import_func_t, result: *mut uint32_t, ) -> wasmer_result_t { - let mut export = &mut *(func as *mut Export); + let export = &*(func as *const Export); let result = if let Export::Function { ref signature, .. } = *export { *result = signature.params().len() as uint32_t; wasmer_result_t::WASMER_OK @@ -1175,11 +1176,11 @@ pub unsafe extern "C" fn wasmer_import_func_new( #[no_mangle] #[allow(clippy::cast_ptr_alignment)] pub unsafe extern "C" fn wasmer_import_func_params( - func: *mut wasmer_import_func_t, + func: *const wasmer_import_func_t, params: *mut wasmer_value_tag, params_len: c_int, ) -> wasmer_result_t { - let mut export = &mut *(func as *mut Export); + let export = &*(func as *const Export); let result = if let Export::Function { ref signature, .. } = *export { let params: &mut [wasmer_value_tag] = slice::from_raw_parts_mut(params, params_len as usize); @@ -1205,11 +1206,11 @@ pub unsafe extern "C" fn wasmer_import_func_params( #[no_mangle] #[allow(clippy::cast_ptr_alignment)] pub unsafe extern "C" fn wasmer_import_func_returns( - func: *mut wasmer_import_func_t, + func: *const wasmer_import_func_t, returns: *mut wasmer_value_tag, returns_len: c_int, ) -> wasmer_result_t { - let mut export = &mut *(func as *mut Export); + let export = &*(func as *const Export); let result = if let Export::Function { ref signature, .. } = *export { let returns: &mut [wasmer_value_tag] = slice::from_raw_parts_mut(returns, returns_len as usize); @@ -1235,10 +1236,10 @@ pub unsafe extern "C" fn wasmer_import_func_returns( #[no_mangle] #[allow(clippy::cast_ptr_alignment)] pub unsafe extern "C" fn wasmer_import_func_returns_arity( - func: *mut wasmer_import_func_t, + func: *const wasmer_import_func_t, result: *mut uint32_t, ) -> wasmer_result_t { - let mut export = &*(func as *mut Export); + let export = &*(func as *const Export); let result = if let Export::Function { ref signature, .. } = *export { *result = signature.returns().len() as uint32_t; wasmer_result_t::WASMER_OK @@ -1264,7 +1265,7 @@ pub extern "C" fn wasmer_import_func_destroy(func: *mut wasmer_import_func_t) { #[no_mangle] #[allow(clippy::cast_ptr_alignment)] pub unsafe extern "C" fn wasmer_export_to_func( - export: *mut wasmer_export_t, + export: *const wasmer_export_t, ) -> *const wasmer_export_func_t { export as *const wasmer_export_func_t } @@ -1290,7 +1291,7 @@ pub unsafe extern "C" fn wasmer_export_name(export: *mut wasmer_export_t) -> was #[allow(clippy::cast_ptr_alignment)] #[no_mangle] pub unsafe extern "C" fn wasmer_export_func_call( - func: *mut wasmer_export_func_t, + func: *const wasmer_export_func_t, params: *const wasmer_value_t, params_len: c_int, results: *mut wasmer_value_t, @@ -1358,7 +1359,7 @@ pub extern "C" fn wasmer_instance_context_memory( ctx: *mut wasmer_instance_context_t, _memory_idx: uint32_t, ) -> *const wasmer_memory_t { - let mut ctx = unsafe { &mut *(ctx as *mut Ctx) }; + let ctx = unsafe { &*(ctx as *const Ctx) }; let memory = ctx.memory(0); memory as *const Memory as *const wasmer_memory_t } From 59de57e075089c7e8f7cdafb3bd7f7270f1651ad Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 4 Mar 2019 15:37:54 +0100 Subject: [PATCH 189/262] fix(runtime-c-api) Fix Clippy notes. This patch fixes warnings raised by Clippy. --- lib/runtime-c-api/src/lib.rs | 73 ++++++++++++++++-------------------- 1 file changed, 32 insertions(+), 41 deletions(-) diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index 66d3de39a..21c6c0d86 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -302,8 +302,7 @@ pub extern "C" fn wasmer_table_grow( #[no_mangle] pub extern "C" fn wasmer_table_length(table: *mut wasmer_table_t) -> uint32_t { let table = unsafe { &*(table as *mut Table) }; - let len = table.size(); - len + table.size() } /// Frees memory for the given Table @@ -355,11 +354,10 @@ pub extern "C" fn wasmer_global_get_descriptor( ) -> wasmer_global_descriptor_t { let global = unsafe { &*(global as *mut Global) }; let descriptor = global.descriptor(); - let desc = wasmer_global_descriptor_t { + wasmer_global_descriptor_t { mutable: descriptor.mutable, kind: descriptor.ty.into(), - }; - desc + } } /// Frees memory for the given Global @@ -451,7 +449,7 @@ pub unsafe extern "C" fn wasmer_module_instantiate( let namespace = namespaces .entry(module_name) - .or_insert_with(|| Namespace::new()); + .or_insert_with(Namespace::new); let export = match import.tag { wasmer_import_export_kind::WASM_MEMORY => { @@ -544,9 +542,9 @@ pub unsafe extern "C" fn wasmer_export_descriptors_get( } let named_export_descriptors = &mut *(export_descriptors as *mut NamedExportDescriptors); - let ptr = &mut (*named_export_descriptors).0[idx as usize] as *mut NamedExportDescriptor - as *mut wasmer_export_descriptor_t; - ptr + &mut (*named_export_descriptors).0[idx as usize] + as *mut NamedExportDescriptor + as *mut wasmer_export_descriptor_t } /// Gets name for the export descriptor @@ -717,9 +715,9 @@ pub unsafe extern "C" fn wasmer_import_descriptors_get( } let named_import_descriptors = &mut *(import_descriptors as *mut NamedImportDescriptors); - let ptr = &mut (*named_import_descriptors).0[idx as usize] as *mut NamedImportDescriptor - as *mut wasmer_import_descriptor_t; - ptr + &mut (*named_import_descriptors).0[idx as usize] + as *mut NamedImportDescriptor + as *mut wasmer_import_descriptor_t } /// Gets name for the import descriptor @@ -810,7 +808,7 @@ pub unsafe extern "C" fn wasmer_instantiate( let namespace = namespaces .entry(module_name) - .or_insert_with(|| Namespace::new()); + .or_insert_with(Namespace::new); let export = match import.tag { wasmer_import_export_kind::WASM_MEMORY => { @@ -900,7 +898,7 @@ pub unsafe extern "C" fn wasmer_instance_call( match result { Ok(results_vec) => { - if results_vec.len() > 0 { + if !results_vec.is_empty() { let ret = match results_vec[0] { Value::I32(x) => wasmer_value_t { tag: wasmer_value_tag::WASM_I32, @@ -984,8 +982,9 @@ pub unsafe extern "C" fn wasmer_exports_get( return ptr::null_mut(); } let named_exports = &mut *(exports as *mut NamedExports); - let ptr = &mut (*named_exports).0[idx as usize] as *mut NamedExport as *mut wasmer_export_t; - ptr + &mut (*named_exports).0[idx as usize] + as *mut NamedExport + as *mut wasmer_export_t } /// Gets wasmer_export kind @@ -1017,7 +1016,7 @@ pub unsafe extern "C" fn wasmer_export_func_params_arity( ) -> wasmer_result_t { let named_export = &*(func as *const NamedExport); let export = &named_export.export; - let result = if let Export::Function { ref signature, .. } = *export { + if let Export::Function { ref signature, .. } = *export { *result = signature.params().len() as uint32_t; wasmer_result_t::WASMER_OK } else { @@ -1025,8 +1024,7 @@ pub unsafe extern "C" fn wasmer_export_func_params_arity( msg: "func ptr error in wasmer_export_func_params_arity".to_string(), }); wasmer_result_t::WASMER_ERROR - }; - result + } } /// Sets the params buffer to the parameter types of the given wasmer_export_func_t @@ -1044,7 +1042,7 @@ pub unsafe extern "C" fn wasmer_export_func_params( ) -> wasmer_result_t { let named_export = &*(func as *const NamedExport); let export = &named_export.export; - let result = if let Export::Function { ref signature, .. } = *export { + if let Export::Function { ref signature, .. } = *export { let params: &mut [wasmer_value_tag] = slice::from_raw_parts_mut(params, params_len as usize); for (i, item) in signature.params().iter().enumerate() { @@ -1056,8 +1054,7 @@ pub unsafe extern "C" fn wasmer_export_func_params( msg: "func ptr error in wasmer_export_func_params".to_string(), }); wasmer_result_t::WASMER_ERROR - }; - result + } } /// Sets the returns buffer to the parameter types of the given wasmer_export_func_t @@ -1075,7 +1072,7 @@ pub unsafe extern "C" fn wasmer_export_func_returns( ) -> wasmer_result_t { let named_export = &*(func as *const NamedExport); let export = &named_export.export; - let result = if let Export::Function { ref signature, .. } = *export { + if let Export::Function { ref signature, .. } = *export { let returns: &mut [wasmer_value_tag] = slice::from_raw_parts_mut(returns, returns_len as usize); for (i, item) in signature.returns().iter().enumerate() { @@ -1087,8 +1084,7 @@ pub unsafe extern "C" fn wasmer_export_func_returns( msg: "func ptr error in wasmer_export_func_returns".to_string(), }); wasmer_result_t::WASMER_ERROR - }; - result + } } /// Sets the result parameter to the arity of the returns of the wasmer_export_func_t @@ -1105,7 +1101,7 @@ pub unsafe extern "C" fn wasmer_export_func_returns_arity( ) -> wasmer_result_t { let named_export = &*(func as *const NamedExport); let export = &named_export.export; - let result = if let Export::Function { ref signature, .. } = *export { + if let Export::Function { ref signature, .. } = *export { *result = signature.returns().len() as uint32_t; wasmer_result_t::WASMER_OK } else { @@ -1113,8 +1109,7 @@ pub unsafe extern "C" fn wasmer_export_func_returns_arity( msg: "func ptr error in wasmer_export_func_results_arity".to_string(), }); wasmer_result_t::WASMER_ERROR - }; - result + } } /// Sets the result parameter to the arity of the params of the wasmer_import_func_t @@ -1130,7 +1125,7 @@ pub unsafe extern "C" fn wasmer_import_func_params_arity( result: *mut uint32_t, ) -> wasmer_result_t { let export = &*(func as *const Export); - let result = if let Export::Function { ref signature, .. } = *export { + if let Export::Function { ref signature, .. } = *export { *result = signature.params().len() as uint32_t; wasmer_result_t::WASMER_OK } else { @@ -1138,8 +1133,7 @@ pub unsafe extern "C" fn wasmer_import_func_params_arity( msg: "func ptr error in wasmer_import_func_params_arity".to_string(), }); wasmer_result_t::WASMER_ERROR - }; - result + } } /// Creates new func @@ -1181,7 +1175,7 @@ pub unsafe extern "C" fn wasmer_import_func_params( params_len: c_int, ) -> wasmer_result_t { let export = &*(func as *const Export); - let result = if let Export::Function { ref signature, .. } = *export { + if let Export::Function { ref signature, .. } = *export { let params: &mut [wasmer_value_tag] = slice::from_raw_parts_mut(params, params_len as usize); for (i, item) in signature.params().iter().enumerate() { @@ -1193,8 +1187,7 @@ pub unsafe extern "C" fn wasmer_import_func_params( msg: "func ptr error in wasmer_import_func_params".to_string(), }); wasmer_result_t::WASMER_ERROR - }; - result + } } /// Sets the returns buffer to the parameter types of the given wasmer_import_func_t @@ -1211,7 +1204,7 @@ pub unsafe extern "C" fn wasmer_import_func_returns( returns_len: c_int, ) -> wasmer_result_t { let export = &*(func as *const Export); - let result = if let Export::Function { ref signature, .. } = *export { + if let Export::Function { ref signature, .. } = *export { let returns: &mut [wasmer_value_tag] = slice::from_raw_parts_mut(returns, returns_len as usize); for (i, item) in signature.returns().iter().enumerate() { @@ -1223,8 +1216,7 @@ pub unsafe extern "C" fn wasmer_import_func_returns( msg: "func ptr error in wasmer_import_func_returns".to_string(), }); wasmer_result_t::WASMER_ERROR - }; - result + } } /// Sets the result parameter to the arity of the returns of the wasmer_import_func_t @@ -1240,7 +1232,7 @@ pub unsafe extern "C" fn wasmer_import_func_returns_arity( result: *mut uint32_t, ) -> wasmer_result_t { let export = &*(func as *const Export); - let result = if let Export::Function { ref signature, .. } = *export { + if let Export::Function { ref signature, .. } = *export { *result = signature.returns().len() as uint32_t; wasmer_result_t::WASMER_OK } else { @@ -1248,8 +1240,7 @@ pub unsafe extern "C" fn wasmer_import_func_returns_arity( msg: "func ptr error in wasmer_import_func_results_arity".to_string(), }); wasmer_result_t::WASMER_ERROR - }; - result + } } /// Frees memory for the given Func @@ -1321,7 +1312,7 @@ pub unsafe extern "C" fn wasmer_export_func_call( let result = instance.call(&named_export.name, ¶ms[..]); match result { Ok(results_vec) => { - if results_vec.len() > 0 { + if !results_vec.is_empty() { let ret = match results_vec[0] { Value::I32(x) => wasmer_value_t { tag: wasmer_value_tag::WASM_I32, From 86c41264a3f86aafc746ef14b794b36e1c64ad56 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 4 Mar 2019 15:57:43 +0100 Subject: [PATCH 190/262] chore(runtime-c-api) Fix CS. --- lib/runtime-c-api/src/lib.rs | 35 +++++++++++++++-------------------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index 21c6c0d86..3b08d9103 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -447,9 +447,7 @@ pub unsafe extern "C" fn wasmer_module_instantiate( return wasmer_result_t::WASMER_ERROR; }; - let namespace = namespaces - .entry(module_name) - .or_insert_with(Namespace::new); + let namespace = namespaces.entry(module_name).or_insert_with(Namespace::new); let export = match import.tag { wasmer_import_export_kind::WASM_MEMORY => { @@ -502,7 +500,8 @@ pub unsafe extern "C" fn wasmer_export_descriptors( let named_export_descriptors: Box = Box::new(NamedExportDescriptors( module.info().exports.iter().map(|e| e.into()).collect(), )); - *export_descriptors = Box::into_raw(named_export_descriptors) as *mut wasmer_export_descriptors_t; + *export_descriptors = + Box::into_raw(named_export_descriptors) as *mut wasmer_export_descriptors_t; } pub struct NamedExportDescriptors(Vec); @@ -514,7 +513,9 @@ pub unsafe extern "C" fn wasmer_export_descriptors_destroy( export_descriptors: *mut wasmer_export_descriptors_t, ) { if !export_descriptors.is_null() { - drop(Box::from_raw(export_descriptors as *mut NamedExportDescriptors)); + drop(Box::from_raw( + export_descriptors as *mut NamedExportDescriptors, + )); } } @@ -540,10 +541,8 @@ pub unsafe extern "C" fn wasmer_export_descriptors_get( if export_descriptors.is_null() { return ptr::null_mut(); } - let named_export_descriptors = - &mut *(export_descriptors as *mut NamedExportDescriptors); - &mut (*named_export_descriptors).0[idx as usize] - as *mut NamedExportDescriptor + let named_export_descriptors = &mut *(export_descriptors as *mut NamedExportDescriptors); + &mut (*named_export_descriptors).0[idx as usize] as *mut NamedExportDescriptor as *mut wasmer_export_descriptor_t } @@ -687,7 +686,9 @@ pub unsafe extern "C" fn wasmer_import_descriptors_destroy( import_descriptors: *mut wasmer_import_descriptors_t, ) { if !import_descriptors.is_null() { - drop(Box::from_raw(import_descriptors as *mut NamedImportDescriptors)); + drop(Box::from_raw( + import_descriptors as *mut NamedImportDescriptors, + )); } } @@ -713,10 +714,8 @@ pub unsafe extern "C" fn wasmer_import_descriptors_get( if import_descriptors.is_null() { return ptr::null_mut(); } - let named_import_descriptors = - &mut *(import_descriptors as *mut NamedImportDescriptors); - &mut (*named_import_descriptors).0[idx as usize] - as *mut NamedImportDescriptor + let named_import_descriptors = &mut *(import_descriptors as *mut NamedImportDescriptors); + &mut (*named_import_descriptors).0[idx as usize] as *mut NamedImportDescriptor as *mut wasmer_import_descriptor_t } @@ -806,9 +805,7 @@ pub unsafe extern "C" fn wasmer_instantiate( return wasmer_result_t::WASMER_ERROR; }; - let namespace = namespaces - .entry(module_name) - .or_insert_with(Namespace::new); + let namespace = namespaces.entry(module_name).or_insert_with(Namespace::new); let export = match import.tag { wasmer_import_export_kind::WASM_MEMORY => { @@ -982,9 +979,7 @@ pub unsafe extern "C" fn wasmer_exports_get( return ptr::null_mut(); } let named_exports = &mut *(exports as *mut NamedExports); - &mut (*named_exports).0[idx as usize] - as *mut NamedExport - as *mut wasmer_export_t + &mut (*named_exports).0[idx as usize] as *mut NamedExport as *mut wasmer_export_t } /// Gets wasmer_export kind From 25feef7384a86ec9989ec42478bbaa0ba746803f Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 4 Mar 2019 16:54:47 +0100 Subject: [PATCH 191/262] chore(runtime-c-api) Regenerate the header files. --- lib/runtime-c-api/wasmer.h | 44 ++++++++++++++++++++++--------------- lib/runtime-c-api/wasmer.hh | 44 ++++++++++++++++++++++--------------- 2 files changed, 52 insertions(+), 36 deletions(-) diff --git a/lib/runtime-c-api/wasmer.h b/lib/runtime-c-api/wasmer.h index f790b140e..9681d5dce 100644 --- a/lib/runtime-c-api/wasmer.h +++ b/lib/runtime-c-api/wasmer.h @@ -27,11 +27,9 @@ enum wasmer_value_tag { }; typedef uint32_t wasmer_value_tag; -typedef struct wasmer_instance_context_t wasmer_instance_context_t; +typedef struct { -typedef struct wasmer_instance_t wasmer_instance_t; - -typedef struct wasmer_module_t wasmer_module_t; +} wasmer_module_t; typedef struct { @@ -93,10 +91,18 @@ typedef struct { typedef struct { +} wasmer_instance_t; + +typedef struct { + } wasmer_memory_t; typedef struct { +} wasmer_instance_context_t; + +typedef struct { + } wasmer_table_t; typedef union { @@ -147,7 +153,7 @@ wasmer_byte_array wasmer_export_descriptor_name(wasmer_export_descriptor_t *expo * Gets export descriptors for the given module * The caller owns the object and should call `wasmer_export_descriptors_destroy` to free it. */ -void wasmer_export_descriptors(wasmer_module_t *module, +void wasmer_export_descriptors(const wasmer_module_t *module, wasmer_export_descriptors_t **export_descriptors); /** @@ -173,7 +179,7 @@ int wasmer_export_descriptors_len(wasmer_export_descriptors_t *exports); * Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` * and `wasmer_last_error_message` to get an error message. */ -wasmer_result_t wasmer_export_func_call(wasmer_export_func_t *func, +wasmer_result_t wasmer_export_func_call(const wasmer_export_func_t *func, const wasmer_value_t *params, int params_len, wasmer_value_t *results, @@ -185,7 +191,7 @@ wasmer_result_t wasmer_export_func_call(wasmer_export_func_t *func, * Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` * and `wasmer_last_error_message` to get an error message. */ -wasmer_result_t wasmer_export_func_params(wasmer_export_func_t *func, +wasmer_result_t wasmer_export_func_params(const wasmer_export_func_t *func, wasmer_value_tag *params, int params_len); @@ -195,7 +201,7 @@ wasmer_result_t wasmer_export_func_params(wasmer_export_func_t *func, * Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` * and `wasmer_last_error_message` to get an error message. */ -wasmer_result_t wasmer_export_func_params_arity(wasmer_export_func_t *func, uint32_t *result); +wasmer_result_t wasmer_export_func_params_arity(const wasmer_export_func_t *func, uint32_t *result); /** * Sets the returns buffer to the parameter types of the given wasmer_export_func_t @@ -203,7 +209,7 @@ wasmer_result_t wasmer_export_func_params_arity(wasmer_export_func_t *func, uint * Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` * and `wasmer_last_error_message` to get an error message. */ -wasmer_result_t wasmer_export_func_returns(wasmer_export_func_t *func, +wasmer_result_t wasmer_export_func_returns(const wasmer_export_func_t *func, wasmer_value_tag *returns, int returns_len); @@ -213,7 +219,8 @@ wasmer_result_t wasmer_export_func_returns(wasmer_export_func_t *func, * Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` * and `wasmer_last_error_message` to get an error message. */ -wasmer_result_t wasmer_export_func_returns_arity(wasmer_export_func_t *func, uint32_t *result); +wasmer_result_t wasmer_export_func_returns_arity(const wasmer_export_func_t *func, + uint32_t *result); /** * Gets wasmer_export kind @@ -228,7 +235,7 @@ wasmer_byte_array wasmer_export_name(wasmer_export_t *export_); /** * Gets export func from export */ -const wasmer_export_func_t *wasmer_export_to_func(wasmer_export_t *export_); +const wasmer_export_func_t *wasmer_export_to_func(const wasmer_export_t *export_); /** * Frees the memory for the given exports @@ -290,7 +297,7 @@ wasmer_byte_array wasmer_import_descriptor_name(wasmer_import_descriptor_t *impo * Gets import descriptors for the given module * The caller owns the object and should call `wasmer_import_descriptors_destroy` to free it. */ -void wasmer_import_descriptors(wasmer_module_t *module, +void wasmer_import_descriptors(const wasmer_module_t *module, wasmer_import_descriptors_t **import_descriptors); /** @@ -330,7 +337,7 @@ const wasmer_import_func_t *wasmer_import_func_new(void (*func)(void *data), * Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` * and `wasmer_last_error_message` to get an error message. */ -wasmer_result_t wasmer_import_func_params(wasmer_import_func_t *func, +wasmer_result_t wasmer_import_func_params(const wasmer_import_func_t *func, wasmer_value_tag *params, int params_len); @@ -340,7 +347,7 @@ wasmer_result_t wasmer_import_func_params(wasmer_import_func_t *func, * Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` * and `wasmer_last_error_message` to get an error message. */ -wasmer_result_t wasmer_import_func_params_arity(wasmer_import_func_t *func, uint32_t *result); +wasmer_result_t wasmer_import_func_params_arity(const wasmer_import_func_t *func, uint32_t *result); /** * Sets the returns buffer to the parameter types of the given wasmer_import_func_t @@ -348,7 +355,7 @@ wasmer_result_t wasmer_import_func_params_arity(wasmer_import_func_t *func, uint * Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` * and `wasmer_last_error_message` to get an error message. */ -wasmer_result_t wasmer_import_func_returns(wasmer_import_func_t *func, +wasmer_result_t wasmer_import_func_returns(const wasmer_import_func_t *func, wasmer_value_tag *returns, int returns_len); @@ -358,7 +365,8 @@ wasmer_result_t wasmer_import_func_returns(wasmer_import_func_t *func, * Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` * and `wasmer_last_error_message` to get an error message. */ -wasmer_result_t wasmer_import_func_returns_arity(wasmer_import_func_t *func, uint32_t *result); +wasmer_result_t wasmer_import_func_returns_arity(const wasmer_import_func_t *func, + uint32_t *result); /** * Calls an instances exported function by `name` with the provided parameters. @@ -379,7 +387,7 @@ wasmer_result_t wasmer_instance_call(wasmer_instance_t *instance, * The index is always 0 until multiple memories are supported. */ const wasmer_memory_t *wasmer_instance_context_memory(wasmer_instance_context_t *ctx, - uint32_t memory_idx); + uint32_t _memory_idx); /** * Frees memory for the given Instance @@ -480,7 +488,7 @@ void wasmer_module_destroy(wasmer_module_t *module); * Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` * and `wasmer_last_error_message` to get an error message. */ -wasmer_result_t wasmer_module_instantiate(wasmer_module_t *module, +wasmer_result_t wasmer_module_instantiate(const wasmer_module_t *module, wasmer_instance_t **instance, wasmer_import_t *imports, int imports_len); diff --git a/lib/runtime-c-api/wasmer.hh b/lib/runtime-c-api/wasmer.hh index df9904e86..3bd59bd89 100644 --- a/lib/runtime-c-api/wasmer.hh +++ b/lib/runtime-c-api/wasmer.hh @@ -24,11 +24,9 @@ enum class wasmer_value_tag : uint32_t { WASM_F64, }; -struct wasmer_instance_context_t; +struct wasmer_module_t { -struct wasmer_instance_t; - -struct wasmer_module_t; +}; struct wasmer_export_descriptor_t { @@ -88,10 +86,18 @@ struct wasmer_import_func_t { }; +struct wasmer_instance_t { + +}; + struct wasmer_memory_t { }; +struct wasmer_instance_context_t { + +}; + struct wasmer_table_t { }; @@ -138,7 +144,7 @@ wasmer_byte_array wasmer_export_descriptor_name(wasmer_export_descriptor_t *expo /// Gets export descriptors for the given module /// The caller owns the object and should call `wasmer_export_descriptors_destroy` to free it. -void wasmer_export_descriptors(wasmer_module_t *module, +void wasmer_export_descriptors(const wasmer_module_t *module, wasmer_export_descriptors_t **export_descriptors); /// Frees the memory for the given export descriptors @@ -156,7 +162,7 @@ int wasmer_export_descriptors_len(wasmer_export_descriptors_t *exports); /// Returns `wasmer_result_t::WASMER_OK` upon success. /// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` /// and `wasmer_last_error_message` to get an error message. -wasmer_result_t wasmer_export_func_call(wasmer_export_func_t *func, +wasmer_result_t wasmer_export_func_call(const wasmer_export_func_t *func, const wasmer_value_t *params, int params_len, wasmer_value_t *results, @@ -166,7 +172,7 @@ wasmer_result_t wasmer_export_func_call(wasmer_export_func_t *func, /// Returns `wasmer_result_t::WASMER_OK` upon success. /// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` /// and `wasmer_last_error_message` to get an error message. -wasmer_result_t wasmer_export_func_params(wasmer_export_func_t *func, +wasmer_result_t wasmer_export_func_params(const wasmer_export_func_t *func, wasmer_value_tag *params, int params_len); @@ -174,13 +180,13 @@ wasmer_result_t wasmer_export_func_params(wasmer_export_func_t *func, /// Returns `wasmer_result_t::WASMER_OK` upon success. /// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` /// and `wasmer_last_error_message` to get an error message. -wasmer_result_t wasmer_export_func_params_arity(wasmer_export_func_t *func, uint32_t *result); +wasmer_result_t wasmer_export_func_params_arity(const wasmer_export_func_t *func, uint32_t *result); /// Sets the returns buffer to the parameter types of the given wasmer_export_func_t /// Returns `wasmer_result_t::WASMER_OK` upon success. /// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` /// and `wasmer_last_error_message` to get an error message. -wasmer_result_t wasmer_export_func_returns(wasmer_export_func_t *func, +wasmer_result_t wasmer_export_func_returns(const wasmer_export_func_t *func, wasmer_value_tag *returns, int returns_len); @@ -188,7 +194,8 @@ wasmer_result_t wasmer_export_func_returns(wasmer_export_func_t *func, /// Returns `wasmer_result_t::WASMER_OK` upon success. /// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` /// and `wasmer_last_error_message` to get an error message. -wasmer_result_t wasmer_export_func_returns_arity(wasmer_export_func_t *func, uint32_t *result); +wasmer_result_t wasmer_export_func_returns_arity(const wasmer_export_func_t *func, + uint32_t *result); /// Gets wasmer_export kind wasmer_import_export_kind wasmer_export_kind(wasmer_export_t *export_); @@ -197,7 +204,7 @@ wasmer_import_export_kind wasmer_export_kind(wasmer_export_t *export_); wasmer_byte_array wasmer_export_name(wasmer_export_t *export_); /// Gets export func from export -const wasmer_export_func_t *wasmer_export_to_func(wasmer_export_t *export_); +const wasmer_export_func_t *wasmer_export_to_func(const wasmer_export_t *export_); /// Frees the memory for the given exports void wasmer_exports_destroy(wasmer_exports_t *exports); @@ -235,7 +242,7 @@ wasmer_byte_array wasmer_import_descriptor_name(wasmer_import_descriptor_t *impo /// Gets import descriptors for the given module /// The caller owns the object and should call `wasmer_import_descriptors_destroy` to free it. -void wasmer_import_descriptors(wasmer_module_t *module, +void wasmer_import_descriptors(const wasmer_module_t *module, wasmer_import_descriptors_t **import_descriptors); /// Frees the memory for the given import descriptors @@ -263,7 +270,7 @@ const wasmer_import_func_t *wasmer_import_func_new(void (*func)(void *data), /// Returns `wasmer_result_t::WASMER_OK` upon success. /// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` /// and `wasmer_last_error_message` to get an error message. -wasmer_result_t wasmer_import_func_params(wasmer_import_func_t *func, +wasmer_result_t wasmer_import_func_params(const wasmer_import_func_t *func, wasmer_value_tag *params, int params_len); @@ -271,13 +278,13 @@ wasmer_result_t wasmer_import_func_params(wasmer_import_func_t *func, /// Returns `wasmer_result_t::WASMER_OK` upon success. /// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` /// and `wasmer_last_error_message` to get an error message. -wasmer_result_t wasmer_import_func_params_arity(wasmer_import_func_t *func, uint32_t *result); +wasmer_result_t wasmer_import_func_params_arity(const wasmer_import_func_t *func, uint32_t *result); /// Sets the returns buffer to the parameter types of the given wasmer_import_func_t /// Returns `wasmer_result_t::WASMER_OK` upon success. /// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` /// and `wasmer_last_error_message` to get an error message. -wasmer_result_t wasmer_import_func_returns(wasmer_import_func_t *func, +wasmer_result_t wasmer_import_func_returns(const wasmer_import_func_t *func, wasmer_value_tag *returns, int returns_len); @@ -285,7 +292,8 @@ wasmer_result_t wasmer_import_func_returns(wasmer_import_func_t *func, /// Returns `wasmer_result_t::WASMER_OK` upon success. /// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` /// and `wasmer_last_error_message` to get an error message. -wasmer_result_t wasmer_import_func_returns_arity(wasmer_import_func_t *func, uint32_t *result); +wasmer_result_t wasmer_import_func_returns_arity(const wasmer_import_func_t *func, + uint32_t *result); /// Calls an instances exported function by `name` with the provided parameters. /// Results are set using the provided `results` pointer. @@ -302,7 +310,7 @@ wasmer_result_t wasmer_instance_call(wasmer_instance_t *instance, /// Gets the memory within the context at the index `memory_idx`. /// The index is always 0 until multiple memories are supported. const wasmer_memory_t *wasmer_instance_context_memory(wasmer_instance_context_t *ctx, - uint32_t memory_idx); + uint32_t _memory_idx); /// Frees memory for the given Instance void wasmer_instance_destroy(wasmer_instance_t *instance); @@ -377,7 +385,7 @@ void wasmer_module_destroy(wasmer_module_t *module); /// Returns `wasmer_result_t::WASMER_OK` upon success. /// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` /// and `wasmer_last_error_message` to get an error message. -wasmer_result_t wasmer_module_instantiate(wasmer_module_t *module, +wasmer_result_t wasmer_module_instantiate(const wasmer_module_t *module, wasmer_instance_t **instance, wasmer_import_t *imports, int imports_len); From 8ed340b6f1da89848bb51ad39de3ccbbcedd5c0a Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Tue, 5 Mar 2019 14:28:35 +0100 Subject: [PATCH 192/262] fix(runtime-c-api) Update `cbindgen`. When requiring `wasmer-runtime-c-api`, I get the following conflicts: ``` error: failed to select a version for `serde_derive`. ... required by package `cbindgen v0.7.1` ... which is depended on by `wasmer-runtime-c-api v0.2.1` ... which is depended on by `foo v0.1.0 (/private/tmp/foo)` versions that meet the requirements `= 1.0.58` are: 1.0.58 all possible versions conflict with previously selected packages. previously selected package `serde_derive v1.0.89` ... which is depended on by `wasmer-runtime-core v0.2.1` ... which is depended on by `wasmer-runtime-c-api v0.2.1` ... which is depended on by `foo v0.1.0 (/private/tmp/foo)` failed to select a version for `serde_derive` which could resolve this conflict ``` This issue resolves by updating `cbindgen` to 0.8. --- lib/runtime-c-api/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/runtime-c-api/Cargo.toml b/lib/runtime-c-api/Cargo.toml index 3a88431f7..6541d482e 100644 --- a/lib/runtime-c-api/Cargo.toml +++ b/lib/runtime-c-api/Cargo.toml @@ -17,7 +17,7 @@ libc = "0.2" crate-type = ["cdylib"] [build-dependencies] -cbindgen = { version = "0.7.1", optional = true } +cbindgen = { version = "0.8", optional = true } [features] generate-c-api-headers = ["cbindgen"] From c86c910054610368688b63c90a8b8143b8a4d654 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Tue, 5 Mar 2019 11:50:56 -0800 Subject: [PATCH 193/262] Add partiality to float truncation --- lib/llvm-backend/src/code.rs | 252 ++++++++++++++++++++++++++++++++--- 1 file changed, 235 insertions(+), 17 deletions(-) diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index 38d5ac7b6..3d9f82153 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -4,7 +4,7 @@ use inkwell::{ module::{Linkage, Module}, passes::PassManager, types::{BasicType, BasicTypeEnum, FunctionType, IntType, PointerType}, - values::{BasicValue, FunctionValue, IntValue, PhiValue, PointerValue}, + values::{BasicValue, FloatValue, FunctionValue, IntValue, PhiValue, PointerValue}, AddressSpace, FloatPredicate, IntPredicate, }; use smallvec::SmallVec; @@ -1463,37 +1463,145 @@ fn parse_function( let res = builder.build_int_z_extend(v1, intrinsics.i64_ty, &state.var_name()); state.push1(res); } - Operator::I32TruncSF32 - | Operator::I32TruncSF64 - | Operator::I32TruncSSatF32 - | Operator::I32TruncSSatF64 => { + Operator::I32TruncSF32 => { + let v1 = state.pop1()?.into_float_value(); + trap_if_not_representatable_as_int( + builder, + intrinsics, + context, + &function, + -2147483904.0, + 2147483648.0, + v1, + ); + let res = + builder.build_float_to_signed_int(v1, intrinsics.i32_ty, &state.var_name()); + state.push1(res); + } + Operator::I32TruncSF64 => { + let v1 = state.pop1()?.into_float_value(); + trap_if_not_representatable_as_int( + builder, + intrinsics, + context, + &function, + -2147483649.0, + 2147483648.0, + v1, + ); + let res = + builder.build_float_to_signed_int(v1, intrinsics.i32_ty, &state.var_name()); + state.push1(res); + } + Operator::I32TruncSSatF32 | Operator::I32TruncSSatF64 => { let v1 = state.pop1()?.into_float_value(); let res = builder.build_float_to_signed_int(v1, intrinsics.i32_ty, &state.var_name()); state.push1(res); } - Operator::I64TruncSF32 - | Operator::I64TruncSF64 - | Operator::I64TruncSSatF32 - | Operator::I64TruncSSatF64 => { + Operator::I64TruncSF32 => { + let v1 = state.pop1()?.into_float_value(); + trap_if_not_representatable_as_int( + builder, + intrinsics, + context, + &function, + -9223373136366403584.0, + 9223372036854775808.0, + v1, + ); + let res = + builder.build_float_to_signed_int(v1, intrinsics.i64_ty, &state.var_name()); + state.push1(res); + } + Operator::I64TruncSF64 => { + let v1 = state.pop1()?.into_float_value(); + trap_if_not_representatable_as_int( + builder, + intrinsics, + context, + &function, + -9223372036854777856.0, + 9223372036854775808.0, + v1, + ); + let res = + builder.build_float_to_signed_int(v1, intrinsics.i64_ty, &state.var_name()); + state.push1(res); + } + Operator::I64TruncSSatF32 | Operator::I64TruncSSatF64 => { let v1 = state.pop1()?.into_float_value(); let res = builder.build_float_to_signed_int(v1, intrinsics.i64_ty, &state.var_name()); state.push1(res); } - Operator::I32TruncUF32 - | Operator::I32TruncUF64 - | Operator::I32TruncUSatF32 - | Operator::I32TruncUSatF64 => { + Operator::I32TruncUF32 => { + let v1 = state.pop1()?.into_float_value(); + trap_if_not_representatable_as_int( + builder, + intrinsics, + context, + &function, + -1.0, + 4294967296.0, + v1, + ); + let res = + builder.build_float_to_unsigned_int(v1, intrinsics.i32_ty, &state.var_name()); + state.push1(res); + } + Operator::I32TruncUF64 => { + let v1 = state.pop1()?.into_float_value(); + trap_if_not_representatable_as_int( + builder, + intrinsics, + context, + &function, + -1.0, + 4294967296.0, + v1, + ); + let res = + builder.build_float_to_unsigned_int(v1, intrinsics.i32_ty, &state.var_name()); + state.push1(res); + } + Operator::I32TruncUSatF32 | Operator::I32TruncUSatF64 => { let v1 = state.pop1()?.into_float_value(); let res = builder.build_float_to_unsigned_int(v1, intrinsics.i32_ty, &state.var_name()); state.push1(res); } - Operator::I64TruncUF32 - | Operator::I64TruncUF64 - | Operator::I64TruncUSatF32 - | Operator::I64TruncUSatF64 => { + Operator::I64TruncUF32 => { + let v1 = state.pop1()?.into_float_value(); + trap_if_not_representatable_as_int( + builder, + intrinsics, + context, + &function, + -1.0, + 18446744073709551616.0, + v1, + ); + let res = + builder.build_float_to_unsigned_int(v1, intrinsics.i64_ty, &state.var_name()); + state.push1(res); + } + Operator::I64TruncUF64 => { + let v1 = state.pop1()?.into_float_value(); + trap_if_not_representatable_as_int( + builder, + intrinsics, + context, + &function, + -1.0, + 18446744073709551616.0, + v1, + ); + let res = + builder.build_float_to_unsigned_int(v1, intrinsics.i64_ty, &state.var_name()); + state.push1(res); + } + Operator::I64TruncUSatF32 | Operator::I64TruncUSatF64 => { let v1 = state.pop1()?.into_float_value(); let res = builder.build_float_to_unsigned_int(v1, intrinsics.i64_ty, &state.var_name()); @@ -2059,6 +2167,116 @@ fn parse_function( Ok(()) } +fn trap_if_not_representatable_as_int( + builder: &Builder, + intrinsics: &Intrinsics, + context: &Context, + function: &FunctionValue, + lower_bounds: f64, + upper_bound: f64, + value: FloatValue, +) { + enum FloatSize { + Bits32, + Bits64, + } + + let failure_block = context.append_basic_block(function, "conversion_failure_block"); + let continue_block = context.append_basic_block(function, "conversion_success_block"); + + let float_ty = value.get_type(); + let (int_ty, float_ptr_ty, float_size) = if float_ty == intrinsics.f32_ty { + (intrinsics.i32_ty, intrinsics.f32_ptr_ty, FloatSize::Bits32) + } else if float_ty == intrinsics.f64_ty { + (intrinsics.i64_ty, intrinsics.f64_ptr_ty, FloatSize::Bits64) + } else { + unreachable!() + }; + + let (exponent, invalid_exponent) = { + let float_bits = { + let space = builder.build_alloca(int_ty, "space"); + let float_ptr = builder.build_pointer_cast(space, float_ptr_ty, "float_ptr"); + builder.build_store(float_ptr, value); + builder.build_load(space, "float_bits").into_int_value() + }; + + let (shift_amount, exponent_mask, invalid_exponent) = match float_size { + FloatSize::Bits32 => (23, 0b01111111100000000000000000000000, 0b11111111), + FloatSize::Bits64 => ( + 52, + 0b0111111111110000000000000000000000000000000000000000000000000000, + 0b11111111111, + ), + }; + + let masked = builder.build_and( + float_bits, + int_ty.const_int(exponent_mask, false), + "masked_bits", + ); + + ( + builder.build_right_shift( + float_bits, + int_ty.const_int(shift_amount, false), + false, + "exponent", + ), + invalid_exponent, + ) + }; + + let is_invalid_float = builder.build_or( + builder.build_int_compare( + IntPredicate::EQ, + exponent, + int_ty.const_int(invalid_exponent, false), + "is_not_normal", + ), + builder.build_or( + builder.build_float_compare( + FloatPredicate::ULT, + value, + float_ty.const_float(lower_bounds), + "less_than_lower_bounds", + ), + builder.build_float_compare( + FloatPredicate::UGT, + value, + float_ty.const_float(upper_bound), + "greater_than_upper_bounds", + ), + "float_not_in_bounds", + ), + "is_invalid_float", + ); + + let is_invalid_float = builder + .build_call( + intrinsics.expect_i1, + &[ + is_invalid_float.as_basic_value_enum(), + intrinsics.i1_ty.const_int(0, false).as_basic_value_enum(), + ], + "is_invalid_float_expect", + ) + .try_as_basic_value() + .left() + .unwrap() + .into_int_value(); + + builder.build_conditional_branch(is_invalid_float, &failure_block, &continue_block); + builder.position_at_end(&failure_block); + builder.build_call( + intrinsics.throw_trap, + &[intrinsics.trap_illegal_arithmetic], + "throw", + ); + builder.build_unreachable(); + builder.position_at_end(&continue_block); +} + fn trap_if_zero_or_overflow( builder: &Builder, intrinsics: &Intrinsics, From 276e5125b512d4a680c43145bf1be429353bf605 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Tue, 5 Mar 2019 13:23:26 -0800 Subject: [PATCH 194/262] Filter out -fno-exceptions from `llvm-config --cxxflags` --- lib/llvm-backend/build.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/llvm-backend/build.rs b/lib/llvm-backend/build.rs index 33ce4525d..062a5a5fe 100644 --- a/lib/llvm-backend/build.rs +++ b/lib/llvm-backend/build.rs @@ -199,6 +199,7 @@ fn get_llvm_cxxflags() -> String { output .split(&[' ', '\n'][..]) .filter(|word| !word.starts_with("-W")) + .filter(|word| word != &"-fno-exceptions") .collect::>() .join(" ") } From ae8676df443edd0c3f619da16ef86f7abe647527 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Tue, 5 Mar 2019 13:32:02 -0800 Subject: [PATCH 195/262] Attempt to update circleci config to install llvm --- .circleci/config.yml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 52160f216..260717e0b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -13,6 +13,9 @@ jobs: name: Install dependencies command: | sudo apt-get install -y cmake + curl -O https://releases.llvm.org/7.0.0/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz + tar xf clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz + export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/" - run: name: Install lint deps command: | @@ -41,6 +44,9 @@ jobs: name: Install dependencies command: | sudo apt-get install -y cmake + curl -O https://releases.llvm.org/7.0.0/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz + tar xf clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz + export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/" - run: make test - run: make integration-tests - save_cache: @@ -66,6 +72,10 @@ jobs: curl -O https://cmake.org/files/v3.4/cmake-3.4.1-Darwin-x86_64.tar.gz tar xf cmake-3.4.1-Darwin-x86_64.tar.gz export PATH="`pwd`/cmake-3.4.1-Darwin-x86_64/CMake.app/Contents/bin:$PATH" + # Installing LLVM outside of brew + curl -O https://releases.llvm.org/7.0.0/clang+llvm-7.0.0-x86_64-apple-darwin.tar.xz + tar xf clang+llvm-7.0.0-x86_64-apple-darwin.tar.xz + export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-apple-darwin/" - run: name: Install Rust command: | @@ -110,6 +120,9 @@ jobs: name: Install dependencies command: | sudo apt-get install -y cmake + curl -O https://releases.llvm.org/7.0.0/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz + tar xf clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz + export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/" - run: name: Execute tests command: make test @@ -153,6 +166,10 @@ jobs: curl -O https://cmake.org/files/v3.4/cmake-3.4.1-Darwin-x86_64.tar.gz tar xf cmake-3.4.1-Darwin-x86_64.tar.gz export PATH="`pwd`/cmake-3.4.1-Darwin-x86_64/CMake.app/Contents/bin:$PATH" + # Installing LLVM outside of brew + curl -O https://releases.llvm.org/7.0.0/clang+llvm-7.0.0-x86_64-apple-darwin.tar.xz + tar xf clang+llvm-7.0.0-x86_64-apple-darwin.tar.xz + export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-apple-darwin/" - run: name: Install Rust command: | @@ -205,6 +222,9 @@ jobs: name: Install dependencies command: | sudo apt-get install -y cmake + curl -O https://releases.llvm.org/7.0.0/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz + tar xf clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz + export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/" - run: rustup default nightly - run: make test - save_cache: From fa3ef2e88dd316056cefdfa8305fbc601976bc58 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Tue, 5 Mar 2019 13:34:22 -0800 Subject: [PATCH 196/262] Remove .llvmenv --- lib/llvm-backend/.llvmenv | 1 - 1 file changed, 1 deletion(-) delete mode 100644 lib/llvm-backend/.llvmenv diff --git a/lib/llvm-backend/.llvmenv b/lib/llvm-backend/.llvmenv deleted file mode 100644 index 6d1e3080f..000000000 --- a/lib/llvm-backend/.llvmenv +++ /dev/null @@ -1 +0,0 @@ -/usr/local/opt/llvm/bin \ No newline at end of file From 13850929d7bd43384bf1057bb8f07f1aa20aed80 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Tue, 5 Mar 2019 13:45:19 -0800 Subject: [PATCH 197/262] Try again with path instead of environment var --- .circleci/config.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 260717e0b..66ac286da 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -15,7 +15,7 @@ jobs: sudo apt-get install -y cmake curl -O https://releases.llvm.org/7.0.0/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz tar xf clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz - export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/" + export PATH=$PATH:`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/bin/ - run: name: Install lint deps command: | @@ -46,7 +46,7 @@ jobs: sudo apt-get install -y cmake curl -O https://releases.llvm.org/7.0.0/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz tar xf clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz - export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/" + export PATH=$PATH:`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/bin/ - run: make test - run: make integration-tests - save_cache: @@ -122,7 +122,7 @@ jobs: sudo apt-get install -y cmake curl -O https://releases.llvm.org/7.0.0/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz tar xf clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz - export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/" + export PATH=$PATH:`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/bin/ - run: name: Execute tests command: make test @@ -224,7 +224,7 @@ jobs: sudo apt-get install -y cmake curl -O https://releases.llvm.org/7.0.0/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz tar xf clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz - export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/" + export PATH=$PATH:`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/bin/ - run: rustup default nightly - run: make test - save_cache: From 48b36a3b013a2e57f8644b1b10c0419e79a9e8df Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Tue, 5 Mar 2019 14:54:44 -0800 Subject: [PATCH 198/262] Runs on linux and also hopefully ci --- .circleci/config.yml | 31 +++++++++++++++++--------- lib/llvm-backend/cpp/object_loader.cpp | 14 +++++++++--- 2 files changed, 31 insertions(+), 14 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 66ac286da..0aa57b5bb 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -15,7 +15,6 @@ jobs: sudo apt-get install -y cmake curl -O https://releases.llvm.org/7.0.0/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz tar xf clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz - export PATH=$PATH:`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/bin/ - run: name: Install lint deps command: | @@ -23,7 +22,9 @@ jobs: rustup component add clippy - run: name: Execute lints - command: make lint + command: | + export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/" + make lint - save_cache: paths: - /usr/local/cargo/registry @@ -46,9 +47,12 @@ jobs: sudo apt-get install -y cmake curl -O https://releases.llvm.org/7.0.0/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz tar xf clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz - export PATH=$PATH:`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/bin/ - - run: make test - - run: make integration-tests + - run: | + export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/" + make test + - run: | + export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/" + make integration-tests - save_cache: paths: - /usr/local/cargo/registry @@ -75,7 +79,6 @@ jobs: # Installing LLVM outside of brew curl -O https://releases.llvm.org/7.0.0/clang+llvm-7.0.0-x86_64-apple-darwin.tar.xz tar xf clang+llvm-7.0.0-x86_64-apple-darwin.tar.xz - export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-apple-darwin/" - run: name: Install Rust command: | @@ -87,6 +90,7 @@ jobs: command: | export PATH="$HOME/.cargo/bin:$PATH" export PATH="`pwd`/cmake-3.4.1-Darwin-x86_64/CMake.app/Contents/bin:$PATH" + export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-apple-darwin/" # We increase the ulimit for fixing cargo unclosed files in mac ulimit -n 8000 sudo sysctl -w kern.maxfiles=655360 kern.maxfilesperproc=327680 @@ -96,6 +100,7 @@ jobs: command: | export PATH="$HOME/.cargo/bin:$PATH" export PATH="`pwd`/cmake-3.4.1-Darwin-x86_64/CMake.app/Contents/bin:$PATH" + export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-apple-darwin/" make integration-tests - save_cache: paths: @@ -122,13 +127,15 @@ jobs: sudo apt-get install -y cmake curl -O https://releases.llvm.org/7.0.0/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz tar xf clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz - export PATH=$PATH:`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/bin/ - run: name: Execute tests - command: make test + command: | + export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/" + make test - run: name: Make release build command: | + export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/" make release mkdir -p artifacts VERSION=$(cargo pkgid | cut -d# -f2 | cut -d: -f2) @@ -169,7 +176,6 @@ jobs: # Installing LLVM outside of brew curl -O https://releases.llvm.org/7.0.0/clang+llvm-7.0.0-x86_64-apple-darwin.tar.xz tar xf clang+llvm-7.0.0-x86_64-apple-darwin.tar.xz - export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-apple-darwin/" - run: name: Install Rust command: | @@ -181,6 +187,7 @@ jobs: command: | export PATH="`pwd`/cmake-3.4.1-Darwin-x86_64/CMake.app/Contents/bin:$PATH" export PATH="$HOME/.cargo/bin:$PATH" + export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-apple-darwin/" # We increase the ulimit for fixing cargo unclosed files in mac ulimit -n 8000 sudo sysctl -w kern.maxfiles=655360 kern.maxfilesperproc=327680 @@ -190,6 +197,7 @@ jobs: command: | export PATH="`pwd`/cmake-3.4.1-Darwin-x86_64/CMake.app/Contents/bin:$PATH" export PATH="$HOME/.cargo/bin:$PATH" + export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-apple-darwin/" make release mkdir -p artifacts # VERSION=$(cargo pkgid | cut -d# -f2 | cut -d: -f2) @@ -224,9 +232,10 @@ jobs: sudo apt-get install -y cmake curl -O https://releases.llvm.org/7.0.0/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz tar xf clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz - export PATH=$PATH:`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/bin/ - run: rustup default nightly - - run: make test + - run: | + export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/" + make test - save_cache: paths: - /usr/local/cargo/registry diff --git a/lib/llvm-backend/cpp/object_loader.cpp b/lib/llvm-backend/cpp/object_loader.cpp index 968618068..cef7c7214 100644 --- a/lib/llvm-backend/cpp/object_loader.cpp +++ b/lib/llvm-backend/cpp/object_loader.cpp @@ -39,23 +39,31 @@ public: uintptr_t read_write_data_size, uint32_t read_write_data_align ) override { + auto aligner = [](uintptr_t ptr, size_t align) { + if (ptr == 0) { + return align; + } + return (ptr + align - 1) & ~(align - 1); + }; + + uint8_t *code_ptr_out = nullptr; size_t code_size_out = 0; - auto code_result = callbacks.alloc_memory(code_size, PROTECT_READ_WRITE, &code_ptr_out, &code_size_out); + auto code_result = callbacks.alloc_memory(aligner(code_size, 4096), PROTECT_READ_WRITE, &code_ptr_out, &code_size_out); assert(code_result == RESULT_OK); code_section = Section { code_ptr_out, code_size_out }; code_bump_ptr = (uintptr_t)code_ptr_out; uint8_t *read_ptr_out = nullptr; size_t read_size_out = 0; - auto read_result = callbacks.alloc_memory(read_data_size, PROTECT_READ_WRITE, &read_ptr_out, &read_size_out); + auto read_result = callbacks.alloc_memory(aligner(read_data_size, 4096), PROTECT_READ_WRITE, &read_ptr_out, &read_size_out); assert(read_result == RESULT_OK); read_section = Section { read_ptr_out, read_size_out }; read_bump_ptr = (uintptr_t)read_ptr_out; uint8_t *readwrite_ptr_out = nullptr; size_t readwrite_size_out = 0; - auto readwrite_result = callbacks.alloc_memory(read_write_data_size, PROTECT_READ_WRITE, &readwrite_ptr_out, &readwrite_size_out); + auto readwrite_result = callbacks.alloc_memory(aligner(read_write_data_size, 4096), PROTECT_READ_WRITE, &readwrite_ptr_out, &readwrite_size_out); assert(readwrite_result == RESULT_OK); readwrite_section = Section { readwrite_ptr_out, readwrite_size_out }; readwrite_bump_ptr = (uintptr_t)readwrite_ptr_out; From f36aade2e5aad0399977e37f77797f05edccb5f3 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Tue, 5 Mar 2019 14:57:37 -0800 Subject: [PATCH 199/262] Fix broken test --- lib/runtime-core/src/vm.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/runtime-core/src/vm.rs b/lib/runtime-core/src/vm.rs index c016c76e7..bc0aa71e8 100644 --- a/lib/runtime-core/src/vm.rs +++ b/lib/runtime-core/src/vm.rs @@ -468,6 +468,8 @@ mod vm_ctx_tests { vm_memories: Map::new().into_boxed_map(), vm_tables: Map::new().into_boxed_map(), vm_globals: Map::new().into_boxed_map(), + + dynamic_sigindices: Map::new().into_boxed_map(), }; let mut import_backing = ImportBacking { memories: Map::new().into_boxed_map(), @@ -478,8 +480,6 @@ mod vm_ctx_tests { vm_memories: Map::new().into_boxed_map(), vm_tables: Map::new().into_boxed_map(), vm_globals: Map::new().into_boxed_map(), - - dynamic_sigindices: Map::new().into_boxed_map(), }; let module = generate_module(); let data = &mut data as *mut _ as *mut c_void; From 0e5d1172d636d94501bedb89638fe05eaa2e9d5a Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Tue, 5 Mar 2019 16:50:49 -0800 Subject: [PATCH 200/262] Just install the signal handler once --- lib/llvm-backend/src/backend.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/llvm-backend/src/backend.rs b/lib/llvm-backend/src/backend.rs index bd8f25bb3..742069d48 100644 --- a/lib/llvm-backend/src/backend.rs +++ b/lib/llvm-backend/src/backend.rs @@ -15,6 +15,7 @@ use std::{ mem, ptr::{self, NonNull}, slice, str, + sync::Once, }; use wasmer_runtime_core::{ backend::{FuncResolver, ProtectedCaller, Token, UserTrapper}, @@ -258,9 +259,11 @@ impl LLVMBackend { ) }; - unsafe { + static SIGNAL_HANDLER_INSTALLED: Once = Once::new(); + + SIGNAL_HANDLER_INSTALLED.call_once(|| unsafe { crate::platform::install_signal_handler(); - } + }); if res != LLVMResult::OK { panic!("failed to load object") From 03909fe3c245e4075fa960a65e85d0ba6a6a2687 Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Wed, 6 Mar 2019 00:15:07 -0600 Subject: [PATCH 201/262] Run spectests with both compilers, activate using features --- Makefile | 2 ++ lib/spectests/Cargo.toml | 4 +++- lib/spectests/build/spectests.rs | 30 +++++++++++++++++++++------ lib/spectests/examples/simple/main.rs | 25 +++++++++++++++++++--- 4 files changed, 51 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index 74e3428fc..8270778f2 100644 --- a/Makefile +++ b/Makefile @@ -39,6 +39,8 @@ test: # We use one thread so the emscripten stdouts doesn't collide cargo test --all --exclude wasmer-runtime-c-api -- --test-threads=1 $(runargs) # cargo test --all --exclude wasmer-emscripten -- --test-threads=1 $(runargs) + cargo test --manifest-path lib/spectests/Cargo.toml --features clif + cargo test --manifest-path lib/spectests/Cargo.toml --features llvm cargo build -p wasmer-runtime-c-api cargo test -p wasmer-runtime-c-api -- --nocapture diff --git a/lib/spectests/Cargo.toml b/lib/spectests/Cargo.toml index 32b14e421..e9ce75132 100644 --- a/lib/spectests/Cargo.toml +++ b/lib/spectests/Cargo.toml @@ -21,4 +21,6 @@ wabt = "0.7.2" [features] default = ["fast-tests"] -fast-tests = [] \ No newline at end of file +fast-tests = [] +clif = [] +llvm = [] \ No newline at end of file diff --git a/lib/spectests/build/spectests.rs b/lib/spectests/build/spectests.rs index c533a2951..c1d28ca29 100644 --- a/lib/spectests/build/spectests.rs +++ b/lib/spectests/build/spectests.rs @@ -77,13 +77,12 @@ const TESTS: &[&str] = &[ static COMMON: &'static str = r##" use std::{{f32, f64}}; use wabt::wat2wasm; -use wasmer_clif_backend::CraneliftCompiler; -use wasmer_llvm_backend::LLVMCompiler; use wasmer_runtime_core::import::ImportObject; use wasmer_runtime_core::types::Value; use wasmer_runtime_core::{{Instance, module::Module}}; use wasmer_runtime_core::error::Result; use wasmer_runtime_core::vm::Ctx; +use wasmer_runtime_core::backend::Compiler; static IMPORT_MODULE: &str = r#" (module @@ -96,9 +95,28 @@ static IMPORT_MODULE: &str = r#" (global $global_i32 (export "global_i32") i32 (i32.const 666))) "#; +#[cfg(feature = "clif")] +fn get_compiler() -> impl Compiler { + use wasmer_clif_backend::CraneliftCompiler; + CraneliftCompiler::new() +} + +#[cfg(feature = "llvm")] +fn get_compiler() -> impl Compiler { + use wasmer_llvm_backend::LLVMCompiler; + LLVMCompiler::new() +} + +#[cfg(not(any(feature = "llvm", feature = "clif")))] +fn get_compiler() -> impl Compiler { + panic!("compiler not specified, activate a compiler via features"); + use wasmer_clif_backend::CraneliftCompiler; + CraneliftCompiler::new() +} + pub fn generate_imports() -> ImportObject { let wasm_binary = wat2wasm(IMPORT_MODULE.as_bytes()).expect("WAST not valid or malformed"); - let module = wasmer_runtime_core::compile_with(&wasm_binary[..], &LLVMCompiler::new()) + let module = wasmer_runtime_core::compile_with(&wasm_binary[..], &get_compiler()) .expect("WASM can't be compiled"); let instance = module .instantiate(&ImportObject::new()) @@ -359,7 +377,7 @@ fn test_module_{}() {{ let module_str = \"{}\"; println!(\"{{}}\", module_str); let wasm_binary = wat2wasm(module_str.as_bytes()).expect(\"WAST not valid or malformed\"); - let module = wasmer_runtime_core::compile_with(&wasm_binary[..], &LLVMCompiler::new()).expect(\"WASM can't be compiled\"); + let module = wasmer_runtime_core::compile_with(&wasm_binary[..], &get_compiler()).expect(\"WASM can't be compiled\"); module.instantiate(&generate_imports()).expect(\"WASM can't be instantiated\") }}\n", self.last_module, @@ -382,7 +400,7 @@ fn test_module_{}() {{ "#[test] fn {}_assert_invalid() {{ let wasm_binary = {:?}; - let module = wasmer_runtime_core::compile_with(&wasm_binary, &LLVMCompiler::new()); + let module = wasmer_runtime_core::compile_with(&wasm_binary, &get_compiler()); assert!(module.is_err(), \"WASM should not compile as is invalid\"); }}\n", command_name, @@ -513,7 +531,7 @@ fn {}_assert_invalid() {{ "#[test] fn {}_assert_malformed() {{ let wasm_binary = {:?}; - let compilation = wasmer_runtime_core::compile_with(&wasm_binary, &LLVMCompiler::new()); + let compilation = wasmer_runtime_core::compile_with(&wasm_binary, &get_compiler()); assert!(compilation.is_err(), \"WASM should not compile as is malformed\"); }}\n", command_name, diff --git a/lib/spectests/examples/simple/main.rs b/lib/spectests/examples/simple/main.rs index 029cec1ac..595bb3680 100644 --- a/lib/spectests/examples/simple/main.rs +++ b/lib/spectests/examples/simple/main.rs @@ -1,6 +1,6 @@ use wabt::wat2wasm; -use wasmer_clif_backend::CraneliftCompiler; use wasmer_runtime_core::{ + backend::Compiler, error, global::Global, memory::Memory, @@ -10,12 +10,31 @@ use wasmer_runtime_core::{ units::Pages, }; +#[cfg(feature = "clif")] +fn get_compiler() -> impl Compiler { + use wasmer_clif_backend::CraneliftCompiler; + CraneliftCompiler::new() +} + +#[cfg(feature = "llvm")] +fn get_compiler() -> impl Compiler { + use wasmer_llvm_backend::LLVMCompiler; + LLVMCompiler::new() +} + +#[cfg(not(any(feature = "llvm", feature = "clif")))] +fn get_compiler() -> impl Compiler { + panic!("compiler not specified, activate a compiler via features"); + use wasmer_clif_backend::CraneliftCompiler; + CraneliftCompiler::new() +} + static EXAMPLE_WASM: &'static [u8] = include_bytes!("simple.wasm"); fn main() -> error::Result<()> { let wasm_binary = wat2wasm(IMPORT_MODULE.as_bytes()).expect("WAST not valid or malformed"); - let inner_module = wasmer_runtime_core::compile_with(&wasm_binary, &CraneliftCompiler::new())?; + let inner_module = wasmer_runtime_core::compile_with(&wasm_binary, &get_compiler())?; let memory = Memory::new(MemoryDescriptor { minimum: Pages(1), @@ -50,7 +69,7 @@ fn main() -> error::Result<()> { "env" => inner_instance, }; - let outer_module = wasmer_runtime_core::compile_with(EXAMPLE_WASM, &CraneliftCompiler::new())?; + let outer_module = wasmer_runtime_core::compile_with(EXAMPLE_WASM, &get_compiler())?; let outer_instance = outer_module.instantiate(&outer_imports)?; let ret = outer_instance.call("main", &[Value::I32(42)])?; println!("ret: {:?}", ret); From 7c56d893c2604c3b6917885d19d084c2a5a77b59 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Tue, 5 Mar 2019 15:52:18 +0100 Subject: [PATCH 202/262] feat(runtime-c-api) Generate the C header file in `OUT_DIR`. This patch changes the directory where the C header files are generated, from `CARGO_MANIFEST_DIR` to `OUT_DIR`. The goal is: When `wasm-runtime-c-api` is used as a dependency of another Rust project, then the C header files are accessible in the `target/` directory (i.e. the `OUT_DIR`). Also, since `rustc` has a `--out-dir` directory, it increases the flexibility of this approach: The user can generate the C header files where she wants. --- lib/runtime-c-api/build.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/lib/runtime-c-api/build.rs b/lib/runtime-c-api/build.rs index f78c5cf69..5b05670ba 100644 --- a/lib/runtime-c-api/build.rs +++ b/lib/runtime-c-api/build.rs @@ -1,7 +1,7 @@ #[cfg(feature = "generate-c-api-headers")] extern crate cbindgen; -use std::env; +use std::{env, path::Path}; static CAPI_ENV_VAR: &str = "WASM_EMSCRIPTEN_GENERATE_C_API_HEADERS"; @@ -14,6 +14,12 @@ fn main() { #[cfg(feature = "generate-c-api-headers")] fn build() { let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap(); + let out_dir = env::var("OUT_DIR").unwrap(); + let out_path = Path::new(&out_dir); + let mut wasmer_h = out_path.to_path_buf(); + wasmer_h.push("wasmer.h"); + let mut wasmer_hh = out_path.to_path_buf(); + wasmer_hh.push("wasmer.hh"); use cbindgen::Language; cbindgen::Builder::new() @@ -22,7 +28,7 @@ fn build() { .with_include_guard("WASMER_H") .generate() .expect("Unable to generate C bindings") - .write_to_file("wasmer.h"); + .write_to_file(wasmer_h); cbindgen::Builder::new() .with_crate(crate_dir) @@ -30,7 +36,7 @@ fn build() { .with_include_guard("WASMER_H") .generate() .expect("Unable to generate C++ bindings") - .write_to_file("wasmer.hh"); + .write_to_file(wasmer_hh); } #[cfg(not(feature = "generate-c-api-headers"))] From f2997357fce942a6e9c810371b44c98ba3525e65 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Wed, 6 Mar 2019 10:39:34 +0100 Subject: [PATCH 203/262] feat(runtime-c-api) Remove the flag `WASM_EMSCRIPTEN_GENERATE_C_API_HEADERS`. This patch removes the `WASM_EMSCRIPTEN_GENERATE_C_API_HEADERS` flag. Consequently, the C header files will be generated for each build. The `generate-c-api-headers` feature is also removed, since it becomes useless. --- Makefile | 2 +- lib/runtime-c-api/Cargo.toml | 9 ++------- lib/runtime-c-api/build.rs | 24 ++++++------------------ 3 files changed, 9 insertions(+), 26 deletions(-) diff --git a/Makefile b/Makefile index 74e3428fc..cf38c43fd 100644 --- a/Makefile +++ b/Makefile @@ -13,7 +13,7 @@ emtests: WASM_EMSCRIPTEN_GENERATE_EMTESTS=1 cargo build -p wasmer-emscripten capi: - WASM_EMSCRIPTEN_GENERATE_C_API_HEADERS=1 cargo build --manifest-path lib/runtime-c-api/Cargo.toml --features generate-c-api-headers + cargo build --manifest-path lib/runtime-c-api/Cargo.toml # clean: # rm -rf artifacts diff --git a/lib/runtime-c-api/Cargo.toml b/lib/runtime-c-api/Cargo.toml index 6541d482e..077b2a226 100644 --- a/lib/runtime-c-api/Cargo.toml +++ b/lib/runtime-c-api/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "wasmer-runtime-c-api" version = "0.2.1" -description = "Wasmer c-api library" +description = "Wasmer C API library" license = "MIT" authors = ["The Wasmer Engineering Team "] repository = "https://github.com/wasmerio/wasmer" @@ -17,9 +17,4 @@ libc = "0.2" crate-type = ["cdylib"] [build-dependencies] -cbindgen = { version = "0.8", optional = true } - -[features] -generate-c-api-headers = ["cbindgen"] - - +cbindgen = "0.8" \ No newline at end of file diff --git a/lib/runtime-c-api/build.rs b/lib/runtime-c-api/build.rs index 5b05670ba..8b4e8f8ee 100644 --- a/lib/runtime-c-api/build.rs +++ b/lib/runtime-c-api/build.rs @@ -1,28 +1,21 @@ -#[cfg(feature = "generate-c-api-headers")] extern crate cbindgen; +use cbindgen::{Builder, Language}; use std::{env, path::Path}; -static CAPI_ENV_VAR: &str = "WASM_EMSCRIPTEN_GENERATE_C_API_HEADERS"; - fn main() { - if env::var(CAPI_ENV_VAR).unwrap_or("0".to_string()) == "1" { - build(); - } -} - -#[cfg(feature = "generate-c-api-headers")] -fn build() { let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap(); + let out_dir = env::var("OUT_DIR").unwrap(); let out_path = Path::new(&out_dir); + let mut wasmer_h = out_path.to_path_buf(); wasmer_h.push("wasmer.h"); + let mut wasmer_hh = out_path.to_path_buf(); wasmer_hh.push("wasmer.hh"); - use cbindgen::Language; - cbindgen::Builder::new() + Builder::new() .with_crate(crate_dir.clone()) .with_language(Language::C) .with_include_guard("WASMER_H") @@ -30,7 +23,7 @@ fn build() { .expect("Unable to generate C bindings") .write_to_file(wasmer_h); - cbindgen::Builder::new() + Builder::new() .with_crate(crate_dir) .with_language(Language::Cxx) .with_include_guard("WASMER_H") @@ -38,8 +31,3 @@ fn build() { .expect("Unable to generate C++ bindings") .write_to_file(wasmer_hh); } - -#[cfg(not(feature = "generate-c-api-headers"))] -fn build() { - panic!("environment var set to generate wasmer c API headers but generate-c-api-headers feature not enabled") -} From 0f74133be3a3997567496f1f9b2b33fd1e5998a2 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Wed, 6 Mar 2019 10:58:40 +0100 Subject: [PATCH 204/262] feat(runtime-c-api) Build: Copy the C header files from `OUT_DIR` to `CARGO_MANIFEST_DIR`. This patch copies the generated C and C++ header files from the `OUT_DIR` to the root of the crate. --- lib/runtime-c-api/build.rs | 39 ++++++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/lib/runtime-c-api/build.rs b/lib/runtime-c-api/build.rs index 8b4e8f8ee..1db19a197 100644 --- a/lib/runtime-c-api/build.rs +++ b/lib/runtime-c-api/build.rs @@ -1,33 +1,52 @@ extern crate cbindgen; use cbindgen::{Builder, Language}; -use std::{env, path::Path}; +use std::{env, fs, path::PathBuf}; fn main() { let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap(); + let mut crate_wasmer_header_file = PathBuf::from(&crate_dir); + crate_wasmer_header_file.push("wasmer"); let out_dir = env::var("OUT_DIR").unwrap(); - let out_path = Path::new(&out_dir); - - let mut wasmer_h = out_path.to_path_buf(); - wasmer_h.push("wasmer.h"); - - let mut wasmer_hh = out_path.to_path_buf(); - wasmer_hh.push("wasmer.hh"); + let mut out_wasmer_header_file = PathBuf::from(&out_dir); + out_wasmer_header_file.push("wasmer"); + // Generate the C bindings in the `OUT_DIR`. + out_wasmer_header_file.set_extension("h"); Builder::new() .with_crate(crate_dir.clone()) .with_language(Language::C) .with_include_guard("WASMER_H") .generate() .expect("Unable to generate C bindings") - .write_to_file(wasmer_h); + .write_to_file(out_wasmer_header_file.as_path()); + // Generate the C++ bindings in the `OUT_DIR`. + out_wasmer_header_file.set_extension("hh"); Builder::new() .with_crate(crate_dir) .with_language(Language::Cxx) .with_include_guard("WASMER_H") .generate() .expect("Unable to generate C++ bindings") - .write_to_file(wasmer_hh); + .write_to_file(out_wasmer_header_file.as_path()); + + // Copy the generated C bindings from `OUT_DIR` to + // `CARGO_MANIFEST_DIR`. + crate_wasmer_header_file.set_extension("h"); + out_wasmer_header_file.set_extension("h"); + fs::copy( + out_wasmer_header_file.as_path(), + crate_wasmer_header_file.as_path(), + ) + .expect("Unable to copy the generated C bindings"); + + // Copy the generated C++ bindings from `OUT_DIR` to + // `CARGO_MANIFEST_DIR`. + crate_wasmer_header_file.set_extension("h"); + crate_wasmer_header_file.set_extension("hh"); + out_wasmer_header_file.set_extension("hh"); + fs::copy(out_wasmer_header_file, crate_wasmer_header_file) + .expect("Unable to copy the generated C++ bindings"); } From 76caebebb4ab56cbd17d815e020aea5cad99bfde Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Wed, 6 Mar 2019 11:02:14 +0100 Subject: [PATCH 205/262] fix(runtime-c-api) Provide a link target. When compiling `wasmer-runtime-c-api` as a dependency of another crate, `rustc` emits this warning: ``` warning: The package `wasmer_runtime_c_api` provides no linkable target. The compiler might raise an error while compiling `foo`. Consider adding 'dylib' or 'rlib' to key `crate-type` in `wasmer_runtime_c_api`'s Cargo.toml. This warning might turn into a hard error in the future. ``` To solve this issue, the `rlib` type has been added to the `crate-type` list. --- lib/runtime-c-api/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/runtime-c-api/Cargo.toml b/lib/runtime-c-api/Cargo.toml index 077b2a226..f4908f29a 100644 --- a/lib/runtime-c-api/Cargo.toml +++ b/lib/runtime-c-api/Cargo.toml @@ -14,7 +14,7 @@ wasmer-runtime-core = { path = "../runtime-core", version = "0.2.1" } libc = "0.2" [lib] -crate-type = ["cdylib"] +crate-type = ["cdylib", "rlib"] [build-dependencies] cbindgen = "0.8" \ No newline at end of file From 365d00979baeb1ae9bf454edba82dc2fe7030ac7 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Wed, 6 Mar 2019 11:03:38 +0100 Subject: [PATCH 206/262] chore(runtime-c-api) Update the `Cargo.lock` file. --- Cargo.lock | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6940f529c..bd5fbd81e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -115,11 +115,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cbindgen" -version = "0.7.1" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1271,7 +1273,7 @@ dependencies = [ name = "wasmer-runtime-c-api" version = "0.2.1" dependencies = [ - "cbindgen 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cbindgen 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-runtime 0.2.1", "wasmer-runtime-core 0.2.1", @@ -1401,7 +1403,7 @@ dependencies = [ "checksum blake2b_simd 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ce2571a6cd634670daa2977cc894c1cc2ba57c563c498e5a82c35446f34d056e" "checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" "checksum cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "926013f2860c46252efceabb19f4a6b308197505082c609025aa6706c011d427" -"checksum cbindgen 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "32e01024aaf5390d6a8145047371a4f5b0063a14c1e411bc731353bd2278ca44" +"checksum cbindgen 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "93aabdea4371364a6b05c72a64d26417ad7eae2b06ddf3c7eaf62b3699701ebe" "checksum cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4a8b715cb4597106ea87c7c84b2f1d452c7492033765df7f32651e66fcf749" "checksum cexpr 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "644d693ecfa91955ed32dcc7eda4914e1be97a641fb6f0645a37348e20b230da" "checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" From d709191be13a0e70d3bd5271d17fa1ae646a8e0d Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Wed, 6 Mar 2019 12:02:20 +0100 Subject: [PATCH 207/262] doc(runtime-c-api) Declare the example as C, so that they are not tested. Those examples contain C code. They must not be run by `rustdoc` as tests. --- lib/runtime-c-api/src/lib.rs | 6 ++++-- lib/runtime-c-api/wasmer.h | 4 ++-- lib/runtime-c-api/wasmer.hh | 4 ++-- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index 3b08d9103..591a03a54 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -1498,7 +1498,8 @@ fn take_last_error() -> Option> { /// bytes needed to store a message. /// /// # Example -/// ``` +/// +/// ```c /// int error_len = wasmer_last_error_length(); /// char *error_str = malloc(error_len); /// ``` @@ -1517,7 +1518,8 @@ pub extern "C" fn wasmer_last_error_length() -> c_int { /// Returns `-1` if an error occurs. /// /// # Example -/// ``` +/// +/// ```c /// int error_len = wasmer_last_error_length(); /// char *error_str = malloc(error_len); /// wasmer_last_error_message(error_str, error_len); diff --git a/lib/runtime-c-api/wasmer.h b/lib/runtime-c-api/wasmer.h index 9681d5dce..8ecdd1d7d 100644 --- a/lib/runtime-c-api/wasmer.h +++ b/lib/runtime-c-api/wasmer.h @@ -417,7 +417,7 @@ wasmer_result_t wasmer_instantiate(wasmer_instance_t **instance, * This can be used to dynamically allocate a buffer with the correct number of * bytes needed to store a message. * # Example - * ``` + * ```c * int error_len = wasmer_last_error_length(); * char *error_str = malloc(error_len); * ``` @@ -430,7 +430,7 @@ int wasmer_last_error_length(void); * Returns the length of the string in bytes. * Returns `-1` if an error occurs. * # Example - * ``` + * ```c * int error_len = wasmer_last_error_length(); * char *error_str = malloc(error_len); * wasmer_last_error_message(error_str, error_len); diff --git a/lib/runtime-c-api/wasmer.hh b/lib/runtime-c-api/wasmer.hh index 3bd59bd89..b093b2b64 100644 --- a/lib/runtime-c-api/wasmer.hh +++ b/lib/runtime-c-api/wasmer.hh @@ -333,7 +333,7 @@ wasmer_result_t wasmer_instantiate(wasmer_instance_t **instance, /// This can be used to dynamically allocate a buffer with the correct number of /// bytes needed to store a message. /// # Example -/// ``` +/// ```c /// int error_len = wasmer_last_error_length(); /// char *error_str = malloc(error_len); /// ``` @@ -344,7 +344,7 @@ int wasmer_last_error_length(); /// Returns the length of the string in bytes. /// Returns `-1` if an error occurs. /// # Example -/// ``` +/// ```c /// int error_len = wasmer_last_error_length(); /// char *error_str = malloc(error_len); /// wasmer_last_error_message(error_str, error_len); From f5ce1e8b6007c688f8932f5055a8aa0488ce43c5 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Wed, 6 Mar 2019 14:11:12 +0100 Subject: [PATCH 208/262] doc(runtime-c-api) Improve the `README.md`. This patch updates the `README.md` by adding badges, a Usage Section, and a License Section. The Testing Section is slightly revamped. --- lib/runtime-c-api/README.md | 134 ++++++++++++++++++++++++++++++++++-- 1 file changed, 128 insertions(+), 6 deletions(-) diff --git a/lib/runtime-c-api/README.md b/lib/runtime-c-api/README.md index 02ba9a705..18b196d16 100644 --- a/lib/runtime-c-api/README.md +++ b/lib/runtime-c-api/README.md @@ -1,10 +1,132 @@ +

+ + Wasmer logo + +

+ +

+ + Build Status + + + License + + + Join the Wasmer Community + + + Number of downloads from crates.io + + + Read our API documentation + +

+ # Wasmer Runtime C API -## Generating header files -Run `make capi` from wasmer project root directory +Wasmer is a standalone JIT WebAssembly runtime, aiming to be fully +compatible with Emscripten, Rust and Go. [Learn +more](https://github.com/wasmerio/wasmer). -## Running tests -The tests can be run via `cargo test`, E.g. `cargo test -p wasmer-runtime-c-api -- --nocapture` +This crate exposes a C and a C++ API for the Wasmer runtime. -*Running manually* -`cmake . && make && make test` from the `lib/runtime-c-api/tests` directory +# Usage + +The C and C++ header files can be found in the source tree of this +crate, respectively [`wasmer.h`][wasmer_h] and +[`wasmer.hh`][wasmer_hh]. They are automatically generated, and always +up-to-date in this repository. + +Here is a simple example to use the C API: + +```c +#include +#include "../wasmer.h" +#include +#include + +int main() +{ + // Read the Wasm file bytes. + FILE *file = fopen("sum.wasm", "r"); + fseek(file, 0, SEEK_END); + long len = ftell(file); + uint8_t *bytes = malloc(len); + fseek(file, 0, SEEK_SET); + fread(bytes, 1, len, file); + fclose(file); + + // Prepare the imports. + wasmer_import_t imports[] = {}; + + // Instantiate! + wasmer_instance_t *instance = NULL; + wasmer_result_t instantiation_result = wasmer_instantiate(&instance, bytes, len, imports, 0); + + assert(instantiation_result == WASMER_OK); + + // Let's call a function. + // Start by preparing the arguments. + + // Value of argument #1 is `7i32`. + wasmer_value_t argument_one; + argument_one.tag = WASM_I32; + argument_one.value.I32 = 7; + + // Value of argumen #2 is `8i32`. + wasmer_value_t argument_two; + argument_two.tag = WASM_I32; + argument_two.value.I32 = 8; + + // Prepare the arguments. + wasmer_value_t arguments[] = {argument_one, argument_two}; + + // Prepare the return value. + wasmer_value_t result_one; + wasmer_value_t results[] = {result_one}; + + // Call the `sum` function with the prepared arguments and the return value. + wasmer_result_t call_result = wasmer_instance_call(instance, "sum", arguments, 2, results, 1); + + // Let's display the result. + printf("Call result: %d\n", call_result); + printf("Result: %d\n", results[0].value.I32); + + // `sum(7, 8) == 15`. + assert(results[0].value.I32 == 15); + assert(call_result == WASMER_OK); + + wasmer_instance_destroy(instance); + + return 0; +} +``` + +# Testing + +The tests can be run via `cargo test`, such as: + +```sh +$ cargo test -- --nocapture +``` + +To run tests manually, enter the `lib/runtime-c-api/tests` directory +and run the following commands: + +```sh +$ cmake . +$ make +$ make test +``` + + +# License + +Wasmer is primarily distributed under the terms of the [MIT +license][mit-license] ([LICENSE][license]). + + +[wasmer_h]: ./wasmer.h +[wasmer_hh]: ./wasmer.hh +[mit-license]: http://opensource.org/licenses/MIT +[license]: https://github.com/wasmerio/wasmer/blob/master/LICENSE From 86644ed89f203e8c9ebad8ff6d2ee326031aed15 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Wed, 6 Mar 2019 14:53:10 +0100 Subject: [PATCH 209/262] chore(github) Update issue templates This patch provides issue templates. It's a mix between Github defaults, and https://github.com/rustwasm/wasm-bindgen templates. Thoughts? --- .github/ISSUE_TEMPLATE/---bug-report.md | 37 ++++++++++++++++++++ .github/ISSUE_TEMPLATE/---feature-request.md | 26 ++++++++++++++ .github/ISSUE_TEMPLATE/--question.md | 16 +++++++++ .github/ISSUE_TEMPLATE/bug_report.md | 35 ++++++++++++++++++ 4 files changed, 114 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/---bug-report.md create mode 100644 .github/ISSUE_TEMPLATE/---feature-request.md create mode 100644 .github/ISSUE_TEMPLATE/--question.md create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md diff --git a/.github/ISSUE_TEMPLATE/---bug-report.md b/.github/ISSUE_TEMPLATE/---bug-report.md new file mode 100644 index 000000000..3d0341b8b --- /dev/null +++ b/.github/ISSUE_TEMPLATE/---bug-report.md @@ -0,0 +1,37 @@ +--- +name: "\U0001F41E Bug report" +about: Create a report to help us improve +title: '' +labels: "\U0001F6A8 \U0001F41E bug" +assignees: '' + +--- + +Thanks for the bug report! + +### Describe the bug + +A clear and concise description of what the bug is. + +### Steps to reproduce + +1. Go to '…' +2. Compile with '…' +3. Run '…' +4. See error + +If applicable, add a link to a test case (as a zip file or link to a repository we can clone). + +### Expected behavior + +A clear and concise description of what you expected to happen. + +### Actual behavior + +A clear and concise description of what actually happened. + +If applicable, add screenshots to help explain your problem. + +### Additional context + +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/---feature-request.md b/.github/ISSUE_TEMPLATE/---feature-request.md new file mode 100644 index 000000000..be5746331 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/---feature-request.md @@ -0,0 +1,26 @@ +--- +name: "\U0001F389 Feature request" +about: Suggest an idea for this project +title: '' +labels: "\U0001F389 enhancement" +assignees: '' + +--- + +Thanks for proposing a new feature! + +### Motivation + +A clear and concise description of what the motivation for the new feature is, and what problem it is solving. + +### Proposed solution + +A clear and concise description of the feature you would like to add, and how it solves the motivating problem. + +### Alternatives + +A clear and concise description of any alternative solutions or features you've considered, and why you're proposed solution is better. + +### Additional context + +Add any other context or screenshots about the feature request here. diff --git a/.github/ISSUE_TEMPLATE/--question.md b/.github/ISSUE_TEMPLATE/--question.md new file mode 100644 index 000000000..ad79ab2f5 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/--question.md @@ -0,0 +1,16 @@ +--- +name: "❓ Question" +about: Ask a question about this project +title: '' +labels: "❓ question" +assignees: '' + +--- + +### Summary + +A clear and concise summary of your question. + +### Additional details + +Provide any additional details here. diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 000000000..ae27101cd --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,35 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: "\U0001F6A8 \U0001F41E bug" +assignees: '' + +--- + +### Describe the Bug + +A clear and concise description of what the bug is. + +### Steps to Reproduce + +1. Go to '…' +2. Compile with '…' +3. Run '…' +4. See error + +If applicable, add a link to a test case (as a zip file or link to a repository we can clone). + +### Expected Behavior + +A clear and concise description of what you expected to happen. + +### Actual Behavior + +A clear and concise description of what actually happened. + +If applicable, add screenshots to help explain your problem. + +### Additional Context + +Add any other context about the problem here. From 145c6e1f18c5d7faecbcdf8afa457a801b0d6f20 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Wed, 6 Mar 2019 15:55:16 +0100 Subject: [PATCH 210/262] Update ---bug-report.md --- .github/ISSUE_TEMPLATE/---bug-report.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/---bug-report.md b/.github/ISSUE_TEMPLATE/---bug-report.md index 3d0341b8b..246699475 100644 --- a/.github/ISSUE_TEMPLATE/---bug-report.md +++ b/.github/ISSUE_TEMPLATE/---bug-report.md @@ -2,7 +2,7 @@ name: "\U0001F41E Bug report" about: Create a report to help us improve title: '' -labels: "\U0001F6A8 \U0001F41E bug" +labels: "\U0001F41E bug" assignees: '' --- From b1739d93eca5c0008f5d343ae1febdf20176d0f6 Mon Sep 17 00:00:00 2001 From: Mackenzie Clark Date: Wed, 6 Mar 2019 10:18:00 -0800 Subject: [PATCH 211/262] remove leading underscores from execvp and exit --- lib/emscripten/src/exec.rs | 6 +++--- lib/emscripten/src/exit.rs | 4 ++-- lib/emscripten/src/lib.rs | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/emscripten/src/exec.rs b/lib/emscripten/src/exec.rs index 8f95c20f8..f47f09bf0 100644 --- a/lib/emscripten/src/exec.rs +++ b/lib/emscripten/src/exec.rs @@ -1,9 +1,9 @@ -use libc::execvp; +use libc::execvp as libc_execvp; use std::cell::Cell; use std::ffi::CString; use wasmer_runtime_core::vm::Ctx; -pub fn _execvp(ctx: &mut Ctx, command_name_offset: u32, argv_offset: u32) -> i32 { +pub fn execvp(ctx: &mut Ctx, command_name_offset: u32, argv_offset: u32) -> i32 { // a single reference to re-use let emscripten_memory = ctx.memory(0); @@ -36,5 +36,5 @@ pub fn _execvp(ctx: &mut Ctx, command_name_offset: u32, argv_offset: u32) -> i32 // construct raw pointers and hand them to `execvp` let command_pointer = command_name_string.as_ptr() as *const i8; let args_pointer = argv.as_ptr(); - unsafe { execvp(command_pointer, args_pointer) } + unsafe { libc_execvp(command_pointer, args_pointer) } } diff --git a/lib/emscripten/src/exit.rs b/lib/emscripten/src/exit.rs index c53fd2bd2..d3f57a7a2 100644 --- a/lib/emscripten/src/exit.rs +++ b/lib/emscripten/src/exit.rs @@ -1,7 +1,7 @@ use wasmer_runtime_core::vm::Ctx; // __exit -pub fn __exit(_ctx: &mut Ctx, value: i32) { - debug!("emscripten::__exit {}", value); +pub fn exit(_ctx: &mut Ctx, value: i32) { + debug!("emscripten::exit {}", value); ::std::process::exit(value); } diff --git a/lib/emscripten/src/lib.rs b/lib/emscripten/src/lib.rs index 822fbdc0e..20ff81553 100644 --- a/lib/emscripten/src/lib.rs +++ b/lib/emscripten/src/lib.rs @@ -442,10 +442,10 @@ pub fn generate_emscripten_env(globals: &mut EmscriptenGlobals) -> ImportObject "___wait" => func!(crate::lock::___wait), // exec - "_execvp" => func!(crate::exec::_execvp), + "_execvp" => func!(crate::exec::execvp), // exit - "__exit" => func!(crate::exit::__exit), + "__exit" => func!(crate::exit::exit), // Env "___assert_fail" => func!(crate::env::___assert_fail), From fd99ed60bf12de4cc60c97b4937c512354a337c2 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Wed, 6 Mar 2019 12:44:19 -0800 Subject: [PATCH 212/262] Split tests into spectests/code-tests and emscripten tests --- .circleci/config.yml | 50 +++++++++++++++++++++++++++++++++++++------- Makefile | 5 ++++- 2 files changed, 46 insertions(+), 9 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 0aa57b5bb..0c7073764 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -47,10 +47,19 @@ jobs: sudo apt-get install -y cmake curl -O https://releases.llvm.org/7.0.0/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz tar xf clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz - - run: | + - run: + name: Tests + command: | export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/" make test - - run: | + - run: + name: Emscripten Tests + command: | + export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/" + make test-emscripten + - run: + name: Integration Tests + command: | export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/" make integration-tests - save_cache: @@ -86,7 +95,7 @@ jobs: export PATH="$HOME/.cargo/bin:$PATH" cargo --version - run: - name: Execute tests + name: Tests command: | export PATH="$HOME/.cargo/bin:$PATH" export PATH="`pwd`/cmake-3.4.1-Darwin-x86_64/CMake.app/Contents/bin:$PATH" @@ -96,7 +105,17 @@ jobs: sudo sysctl -w kern.maxfiles=655360 kern.maxfilesperproc=327680 make test - run: - name: Execute integration tests + name: Emscripten Tests + command: | + export PATH="$HOME/.cargo/bin:$PATH" + export PATH="`pwd`/cmake-3.4.1-Darwin-x86_64/CMake.app/Contents/bin:$PATH" + export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-apple-darwin/" + # We increase the ulimit for fixing cargo unclosed files in mac + ulimit -n 8000 + sudo sysctl -w kern.maxfiles=655360 kern.maxfilesperproc=327680 + make test-emscripten + - run: + name: Integration Tests command: | export PATH="$HOME/.cargo/bin:$PATH" export PATH="`pwd`/cmake-3.4.1-Darwin-x86_64/CMake.app/Contents/bin:$PATH" @@ -128,12 +147,17 @@ jobs: curl -O https://releases.llvm.org/7.0.0/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz tar xf clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz - run: - name: Execute tests + name: Tests command: | export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/" make test - run: - name: Make release build + name: Emscripten Tests + command: | + export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/" + make test-emscripten + - run: + name: Release Build command: | export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/" make release @@ -183,7 +207,7 @@ jobs: export PATH="$HOME/.cargo/bin:$PATH" cargo --version - run: - name: Execute tests + name: Tests command: | export PATH="`pwd`/cmake-3.4.1-Darwin-x86_64/CMake.app/Contents/bin:$PATH" export PATH="$HOME/.cargo/bin:$PATH" @@ -193,7 +217,17 @@ jobs: sudo sysctl -w kern.maxfiles=655360 kern.maxfilesperproc=327680 make test - run: - name: Make release build + name: Emscripten Tests + command: | + export PATH="`pwd`/cmake-3.4.1-Darwin-x86_64/CMake.app/Contents/bin:$PATH" + export PATH="$HOME/.cargo/bin:$PATH" + export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-apple-darwin/" + # We increase the ulimit for fixing cargo unclosed files in mac + ulimit -n 8000 + sudo sysctl -w kern.maxfiles=655360 kern.maxfilesperproc=327680 + make test-emscripten + - run: + name: Release Build command: | export PATH="`pwd`/cmake-3.4.1-Darwin-x86_64/CMake.app/Contents/bin:$PATH" export PATH="$HOME/.cargo/bin:$PATH" diff --git a/Makefile b/Makefile index 8270778f2..487a0e4cb 100644 --- a/Makefile +++ b/Makefile @@ -37,13 +37,16 @@ precommit: lint test test: # We use one thread so the emscripten stdouts doesn't collide - cargo test --all --exclude wasmer-runtime-c-api -- --test-threads=1 $(runargs) + cargo test --all --exclude wasmer-runtime-c-api --exclude wasmer-emscripten --exclude wasmer-spectests -- $(runargs) # cargo test --all --exclude wasmer-emscripten -- --test-threads=1 $(runargs) cargo test --manifest-path lib/spectests/Cargo.toml --features clif cargo test --manifest-path lib/spectests/Cargo.toml --features llvm cargo build -p wasmer-runtime-c-api cargo test -p wasmer-runtime-c-api -- --nocapture +test-emscripten: + cargo test -p wasmer-emscripten -- --test-threads=1 $(runargs) + release: # If you are in OS-X, you will need mingw-w64 for cross compiling to windows # brew install mingw-w64 From 8f2d90186dabf6bc0a35fd20961f510703b32fb8 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Wed, 6 Mar 2019 12:45:42 -0800 Subject: [PATCH 213/262] Fix circleci config --- .circleci/config.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 0c7073764..c5ea7e219 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -50,18 +50,18 @@ jobs: - run: name: Tests command: | - export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/" - make test + export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/" + make test - run: name: Emscripten Tests command: | - export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/" - make test-emscripten + export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/" + make test-emscripten - run: name: Integration Tests command: | - export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/" - make integration-tests + export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/" + make integration-tests - save_cache: paths: - /usr/local/cargo/registry From 9f93ac2fe5a70b1d234eecca97310e78816b2759 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Wed, 6 Mar 2019 13:18:30 -0800 Subject: [PATCH 214/262] Fix integration tests --- integration_tests/lua/test.sh | 3 +-- integration_tests/nginx/test.sh | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/integration_tests/lua/test.sh b/integration_tests/lua/test.sh index b45752f0b..7c3cc9b6c 100755 --- a/integration_tests/lua/test.sh +++ b/integration_tests/lua/test.sh @@ -1,7 +1,6 @@ #! /bin/bash -nohup ./target/release/wasmer run examples/lua.wasm & -sleep 3s +nohup ./target/release/wasmer run examples/lua.wasm --disable-cache -- -v if grep "Lua 5.4.0 Copyright (C) 1994-2018 Lua.org, PUC-Rio" ./nohup.out then diff --git a/integration_tests/nginx/test.sh b/integration_tests/nginx/test.sh index aeb790e28..496b6ae6d 100755 --- a/integration_tests/nginx/test.sh +++ b/integration_tests/nginx/test.sh @@ -1,7 +1,7 @@ #! /bin/bash -nohup ./target/release/wasmer run examples/nginx/nginx.wasm -- -p integration_tests/nginx/ -c nginx.conf & -sleep 3s +nohup ./target/release/wasmer run examples/nginx/nginx.wasm --disable-cache -- -p integration_tests/nginx/ -c nginx.conf & +sleep 10s curl localhost:8080 > ./nginx.out From 334a1310df1cf6836e09ffccfa0c644638c1f4ce Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Wed, 6 Mar 2019 13:28:07 -0800 Subject: [PATCH 215/262] Change nginx integration just to test it it starts --- integration_tests/nginx/test.sh | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/integration_tests/nginx/test.sh b/integration_tests/nginx/test.sh index 496b6ae6d..a2cfb7159 100755 --- a/integration_tests/nginx/test.sh +++ b/integration_tests/nginx/test.sh @@ -1,22 +1,14 @@ #! /bin/bash -nohup ./target/release/wasmer run examples/nginx/nginx.wasm --disable-cache -- -p integration_tests/nginx/ -c nginx.conf & -sleep 10s +nohup ./target/release/wasmer run examples/nginx/nginx.wasm --disable-cache -- -v -curl localhost:8080 > ./nginx.out - - -if grep "wasmer" ./nginx.out +if grep "nginx version: nginx/1.15.3" ./nohup.out then echo "nginx integration test succeeded" rm ./nohup.out - rm ./nginx.out - rm -rf ./integration_tests/nginx/*_temp exit 0 else echo "nginx integration test failed" rm ./nohup.out - rm ./nginx.out - rm -rf ./integration_tests/nginx/*_temp exit -1 fi From 9f589de0310df49b29acab9b9650f76895129dc4 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Wed, 6 Mar 2019 13:53:06 -0800 Subject: [PATCH 216/262] Reset Cargo.lock --- Cargo.lock | 149 +++++++++++++++++++++-------------------------------- 1 file changed, 60 insertions(+), 89 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b9a0622bc..f93daf2a7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -32,7 +32,7 @@ name = "atty" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -49,8 +49,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -61,7 +61,7 @@ version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -71,7 +71,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "cexpr 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "clang-sys 0.26.4 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -129,15 +129,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cbindgen" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.15.27 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -159,7 +159,7 @@ dependencies = [ [[package]] name = "cfg-if" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -168,7 +168,7 @@ version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -291,11 +291,11 @@ dependencies = [ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_os 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "rand_xoshiro 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", "tinytemplate 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -326,7 +326,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -339,7 +339,7 @@ name = "crossbeam-utils" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -399,7 +399,7 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "errno-dragonfly 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -409,7 +409,7 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -514,7 +514,7 @@ dependencies = [ "either 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "enum-methods 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "inkwell_internal_macros 0.1.0 (git+https://github.com/TheDan64/inkwell?branch=llvm7-0)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "llvm-sys 70.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -556,7 +556,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.49" +version = "0.2.50" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -575,7 +575,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -594,7 +594,7 @@ name = "log" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -602,7 +602,7 @@ name = "memchr" version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -610,7 +610,7 @@ name = "memmap" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -626,8 +626,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -638,8 +638,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -667,7 +667,7 @@ name = "num_cpus" version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -684,7 +684,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -702,7 +702,7 @@ name = "parking_lot_core" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -719,14 +719,6 @@ name = "plain" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "proc-macro2" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "proc-macro2" version = "0.4.27" @@ -745,14 +737,6 @@ name = "quote" version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "quote" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "quote" version = "0.6.11" @@ -767,13 +751,13 @@ version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_os 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -822,19 +806,19 @@ name = "rand_jitter" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_os" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (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.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -893,7 +877,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1014,7 +998,7 @@ name = "serde" version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1036,12 +1020,12 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.58" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.13.11 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.27 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1099,16 +1083,6 @@ dependencies = [ "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "syn" -version = "0.13.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "syn" version = "0.15.27" @@ -1153,8 +1127,8 @@ name = "tempfile" version = "3.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1174,7 +1148,7 @@ name = "termion" version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1200,7 +1174,7 @@ name = "time" version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1278,7 +1252,7 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", "wabt-sys 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1326,13 +1300,13 @@ dependencies = [ "cranelift-native 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", "cranelift-wasm 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "nix 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "serde-bench 0.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "serde_bytes 0.10.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-runtime-core 0.2.1", "wasmer-win-exception-handler 0.2.0", @@ -1347,7 +1321,7 @@ dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1365,7 +1339,7 @@ dependencies = [ "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "inkwell 0.1.0 (git+https://github.com/TheDan64/inkwell?branch=llvm7-0)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "nix 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1393,8 +1367,8 @@ dependencies = [ name = "wasmer-runtime-c-api" version = "0.2.1" dependencies = [ - "cbindgen 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "cbindgen 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-runtime 0.2.1", "wasmer-runtime-core 0.2.1", ] @@ -1411,14 +1385,14 @@ dependencies = [ "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "nix 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "page_size 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "serde-bench 0.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "serde_bytes 0.10.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "wasmparser 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1439,7 +1413,7 @@ version = "0.2.0" dependencies = [ "bindgen 0.46.0 (registry+https://github.com/rust-lang/crates.io-index)", "cmake 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-runtime-core 0.2.1", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1466,7 +1440,7 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1531,10 +1505,10 @@ dependencies = [ "checksum capstone 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "00be9d203fa0e078b93b24603633fb081851dfe0c1086364431f52587a47157e" "checksum capstone-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2dc8d32bc5c1e6d0fcde10af411c98b07d93498d51654f678757f08fa2acd6a6" "checksum cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "926013f2860c46252efceabb19f4a6b308197505082c609025aa6706c011d427" -"checksum cbindgen 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "32e01024aaf5390d6a8145047371a4f5b0063a14c1e411bc731353bd2278ca44" +"checksum cbindgen 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f61c5411fe3ac196fae7ea397dd13959b1323edda046eec50d648a8e92015a53" "checksum cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)" = "d01c69d08ff207f231f07196e30f84c70f1c815b04f980f8b7b01ff01f05eb92" "checksum cexpr 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "644d693ecfa91955ed32dcc7eda4914e1be97a641fb6f0645a37348e20b230da" -"checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" +"checksum cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11d43355396e872eefb45ce6342e4374ed7bc2b3a502d1b28e36d6e23c05d1f4" "checksum clang-sys 0.26.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6ef0c1bcf2e99c649104bd7a7012d8f8802684400e03db0ec0af48583c6fa0e4" "checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" @@ -1579,7 +1553,7 @@ dependencies = [ "checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" -"checksum libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)" = "413f3dfc802c5dc91dc570b05125b6cda9855edfaa9825c9849807876376e70e" +"checksum libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)" = "aab692d7759f5cd8c859e169db98ae5b52c924add2af5fbbca11d12fefb567c1" "checksum libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3ad660d7cb8c5822cd83d10897b0f1f1526792737a179e73896152f85b88c2" "checksum llvm-sys 70.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60a9ee82fe0fa72ae6ef6d018b407296085863836451c7a97384f84ed7e26b9f" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" @@ -1599,11 +1573,9 @@ dependencies = [ "checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" "checksum peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" "checksum plain 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" -"checksum proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1b06e2f335f48d24442b35a19df506a835fb3547bc3c06ef27340da9acf5cae7" "checksum proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" -"checksum quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9949cfe66888ffe1d53e6ec9d9f3b70714083854be20fd5e271b232a017401e8" "checksum quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cdd8e04bd9c52e0342b406469d494fcb033be4bdbe5c606016defbb1681411e1" "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" "checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" @@ -1612,7 +1584,7 @@ dependencies = [ "checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" "checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" "checksum rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b9ea758282efe12823e0d952ddb269d2e1897227e464919a554f2a03ef1b832" -"checksum rand_os 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b7c690732391ae0abafced5015ffb53656abfaec61b342290e5eb56b286a679d" +"checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" "checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" "checksum rand_xoshiro 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "03b418169fb9c46533f326efd6eed2576699c44ca92d3052a066214a8d828929" @@ -1637,7 +1609,7 @@ dependencies = [ "checksum serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)" = "92514fb95f900c9b5126e32d020f5c6d40564c27a5ea6d1d7d9f157a96623560" "checksum serde-bench 0.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "d733da87e79faaac25616e33d26299a41143fd4cd42746cbb0e91d8feea243fd" "checksum serde_bytes 0.10.5 (registry+https://github.com/rust-lang/crates.io-index)" = "defbb8a83d7f34cc8380751eeb892b825944222888aff18996ea7901f24aec88" -"checksum serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)" = "ac38f51a52a556cd17545798e29536885fb1a3fa63d6399f5ef650f4a7d35901" +"checksum serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)" = "bb6eabf4b5914e88e24eea240bb7c9f9a2cbc1bbbe8d961d381975ec3c6b806c" "checksum serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)" = "5a23aa71d4a4d43fdbfaac00eff68ba8a06a51759a89ac3304323e800c4dd40d" "checksum smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c4488ae950c49d403731982257768f48fada354a5203fe81f9bb6f43ca9002be" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" @@ -1645,7 +1617,6 @@ dependencies = [ "checksum structopt 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "670ad348dc73012fcf78c71f06f9d942232cdd4c859d4b6975e27836c3efc0c3" "checksum structopt-derive 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "ef98172b1a00b0bec738508d3726540edcbd186d50dfd326f2b1febbb3559f04" "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" -"checksum syn 0.13.11 (registry+https://github.com/rust-lang/crates.io-index)" = "14f9bf6292f3a61d2c716723fdb789a41bbe104168e6f496dc6497e531ea1b9b" "checksum syn 0.15.27 (registry+https://github.com/rust-lang/crates.io-index)" = "525bd55255f03c816e5d7f615587bd13030c7103354fadb104993dcee6a788ec" "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" "checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" From 95c90f84b7471adc46f97e32bc3bf816647e64e3 Mon Sep 17 00:00:00 2001 From: Syrus Date: Wed, 6 Mar 2019 15:13:38 -0800 Subject: [PATCH 217/262] Added LLVM to the PATH in windows appveyor --- .appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.appveyor.yml b/.appveyor.yml index 2a67567e4..57a6f5fd3 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -20,7 +20,7 @@ install: # uncomment these lines if the cache is cleared, or if we must re-install rust for some reason # - appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe # - rustup-init.exe -yv --default-host %target% - - set PATH=%PATH%;%USERPROFILE%\.cargo\bin + - set PATH=%PATH%;"C:\Program Files\LLVM\bin";%USERPROFILE%\.cargo\bin - rustup default stable-%target% - rustup update - rustc -vV From 0540c50b871d67d20d60344c1fa872315809515f Mon Sep 17 00:00:00 2001 From: Syrus Date: Wed, 6 Mar 2019 15:27:41 -0800 Subject: [PATCH 218/262] Use LLVM 5.0 instead of the default one --- .appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.appveyor.yml b/.appveyor.yml index 57a6f5fd3..ec30e348f 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -20,7 +20,7 @@ install: # uncomment these lines if the cache is cleared, or if we must re-install rust for some reason # - appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe # - rustup-init.exe -yv --default-host %target% - - set PATH=%PATH%;"C:\Program Files\LLVM\bin";%USERPROFILE%\.cargo\bin + - set PATH=%PATH%;C:\\Libraries\\llvm-5.0.0\\bin;%USERPROFILE%\.cargo\bin - rustup default stable-%target% - rustup update - rustc -vV From 9812fa09c729f15223735cc0880e16a87f568272 Mon Sep 17 00:00:00 2001 From: Syrus Date: Wed, 6 Mar 2019 15:49:35 -0800 Subject: [PATCH 219/262] Trying custom LLVM install in windows appveyor --- .appveyor.yml | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/.appveyor.yml b/.appveyor.yml index ec30e348f..1eaca6c23 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -17,14 +17,24 @@ cache: - target install: + # Install LLVM + - mkdir C:\projects\deps + - cd C:\projects\deps + - appveyor DownloadFile http://prereleases.llvm.org/win-snapshots/LLVM-7.0.0-r336178-win64.exe -FileName llvm.exe + - 7z x llvm.exe -oC:\projects\deps\llvm + - set "PATH=C:\projects\deps\llvm\bin;%PATH%" + - set "LLD_LINK=C:\projects\deps\llvm\bin\lld-link.exe" + + # Install Rust # uncomment these lines if the cache is cleared, or if we must re-install rust for some reason # - appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe # - rustup-init.exe -yv --default-host %target% - - set PATH=%PATH%;C:\\Libraries\\llvm-5.0.0\\bin;%USERPROFILE%\.cargo\bin + - set PATH=%PATH%;%USERPROFILE%\.cargo\bin - rustup default stable-%target% - rustup update - rustc -vV - cargo -vV + # Install InnoSetup - appveyor-retry appveyor DownloadFile https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/2017-08-22-is.exe - 2017-08-22-is.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /SP- From bd76a276fcf7a7b22ced7538d3b342f3eb61d5ae Mon Sep 17 00:00:00 2001 From: Syrus Date: Wed, 6 Mar 2019 15:57:38 -0800 Subject: [PATCH 220/262] Fixed path --- .appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.appveyor.yml b/.appveyor.yml index 1eaca6c23..f513d1aa1 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -22,7 +22,7 @@ install: - cd C:\projects\deps - appveyor DownloadFile http://prereleases.llvm.org/win-snapshots/LLVM-7.0.0-r336178-win64.exe -FileName llvm.exe - 7z x llvm.exe -oC:\projects\deps\llvm - - set "PATH=C:\projects\deps\llvm\bin;%PATH%" + - set "PATH=%PATH%;C:\projects\deps\llvm\bin" - set "LLD_LINK=C:\projects\deps\llvm\bin\lld-link.exe" # Install Rust From a0ff2733cee315a9725ceda4c49d5845001901bf Mon Sep 17 00:00:00 2001 From: Syrus Date: Wed, 6 Mar 2019 16:03:25 -0800 Subject: [PATCH 221/262] Go back to the appveyor build folder --- .appveyor.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.appveyor.yml b/.appveyor.yml index f513d1aa1..0d309666f 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -24,6 +24,7 @@ install: - 7z x llvm.exe -oC:\projects\deps\llvm - set "PATH=%PATH%;C:\projects\deps\llvm\bin" - set "LLD_LINK=C:\projects\deps\llvm\bin\lld-link.exe" + - cd "%APPVEYOR_BUILD_FOLDER%" # Install Rust # uncomment these lines if the cache is cleared, or if we must re-install rust for some reason From 58897aba5a8e74f182d80ce5112911f535c3ccc3 Mon Sep 17 00:00:00 2001 From: Syrus Date: Wed, 6 Mar 2019 16:18:35 -0800 Subject: [PATCH 222/262] Try to use LLVM path uniformily for appveyor --- .appveyor.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 0d309666f..b50fb31d4 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -22,7 +22,7 @@ install: - cd C:\projects\deps - appveyor DownloadFile http://prereleases.llvm.org/win-snapshots/LLVM-7.0.0-r336178-win64.exe -FileName llvm.exe - 7z x llvm.exe -oC:\projects\deps\llvm - - set "PATH=%PATH%;C:\projects\deps\llvm\bin" + # - set "PATH=%PATH%;C:\projects\deps\llvm\bin" - set "LLD_LINK=C:\projects\deps\llvm\bin\lld-link.exe" - cd "%APPVEYOR_BUILD_FOLDER%" @@ -30,7 +30,7 @@ install: # uncomment these lines if the cache is cleared, or if we must re-install rust for some reason # - appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe # - rustup-init.exe -yv --default-host %target% - - set PATH=%PATH%;%USERPROFILE%\.cargo\bin + - set PATH=%PATH%;C:\\projects\\deps\\llvm\\bin;%USERPROFILE%\.cargo\bin - rustup default stable-%target% - rustup update - rustc -vV From e63515279f2c0167b256dbcaf86ae824cecf0fb6 Mon Sep 17 00:00:00 2001 From: Syrus Date: Wed, 6 Mar 2019 16:35:23 -0800 Subject: [PATCH 223/262] Try to use LLVM_SYS_70_PREFIX for appveyor --- .appveyor.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.appveyor.yml b/.appveyor.yml index b50fb31d4..46c989086 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -24,6 +24,7 @@ install: - 7z x llvm.exe -oC:\projects\deps\llvm # - set "PATH=%PATH%;C:\projects\deps\llvm\bin" - set "LLD_LINK=C:\projects\deps\llvm\bin\lld-link.exe" + - set "LLVM_SYS_70_PREFIX=C:\projects\deps\llvm" - cd "%APPVEYOR_BUILD_FOLDER%" # Install Rust From 6fae46d0d36150ddf823efca2f5a9234ad8eb889 Mon Sep 17 00:00:00 2001 From: Syrus Akbary Date: Wed, 6 Mar 2019 18:18:58 -0800 Subject: [PATCH 224/262] Improved bug report to get more info about the environment Based on this feedback: https://github.com/wasmerio/wasmer/pull/243#pullrequestreview-211289058 --- .github/ISSUE_TEMPLATE/---bug-report.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/ISSUE_TEMPLATE/---bug-report.md b/.github/ISSUE_TEMPLATE/---bug-report.md index 246699475..7a7e83e12 100644 --- a/.github/ISSUE_TEMPLATE/---bug-report.md +++ b/.github/ISSUE_TEMPLATE/---bug-report.md @@ -13,6 +13,12 @@ Thanks for the bug report! A clear and concise description of what the bug is. +Copy and paste the result of executing the following in your shell, so we can know the version of wasmer, Rust (if available) and architecture of your environment. + +```bash +echo "`wasmer -V` | `rustc -V` | `uname -m`" +``` + ### Steps to reproduce 1. Go to '…' From af9c26f4f967bb518578b7cb2633cbb0363a528c Mon Sep 17 00:00:00 2001 From: Syrus Akbary Date: Wed, 6 Mar 2019 18:22:16 -0800 Subject: [PATCH 225/262] Fixed links of wasmer runtime C api in crates.io and docs.rs --- lib/runtime-c-api/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/runtime-c-api/README.md b/lib/runtime-c-api/README.md index 18b196d16..efec3e50d 100644 --- a/lib/runtime-c-api/README.md +++ b/lib/runtime-c-api/README.md @@ -14,10 +14,10 @@ Join the Wasmer Community - + Number of downloads from crates.io - + Read our API documentation

From 1957ddef5332b58a34061fe0e572df1a226b0737 Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Wed, 6 Mar 2019 21:36:46 -0600 Subject: [PATCH 226/262] Run emscripten tests with both compilers --- Cargo.lock | 1 + Makefile | 3 ++- lib/emscripten/Cargo.toml | 5 +++++ lib/emscripten/src/utils.rs | 29 ++++++++++++++++++++----- lib/emscripten/tests/emtests/_common.rs | 23 ++++++++++++++++++-- 5 files changed, 53 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f93daf2a7..a903bc9dc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1326,6 +1326,7 @@ dependencies = [ "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-clif-backend 0.2.0", + "wasmer-llvm-backend 0.1.0", "wasmer-runtime-core 0.2.1", ] diff --git a/Makefile b/Makefile index 6963cfc7f..77af8ae8f 100644 --- a/Makefile +++ b/Makefile @@ -45,7 +45,8 @@ test: cargo test -p wasmer-runtime-c-api -- --nocapture test-emscripten: - cargo test -p wasmer-emscripten -- --test-threads=1 $(runargs) + cargo test --manifest-path lib/spectests/Cargo.toml --features clif -- --test-threads=1 $(runargs) + cargo test --manifest-path lib/spectests/Cargo.toml --features llvm -- --test-threads=1 $(runargs) release: # If you are in OS-X, you will need mingw-w64 for cross compiling to windows diff --git a/lib/emscripten/Cargo.toml b/lib/emscripten/Cargo.toml index 62fb40c5a..3106d905c 100644 --- a/lib/emscripten/Cargo.toml +++ b/lib/emscripten/Cargo.toml @@ -20,7 +20,12 @@ rand = "0.6" [dev-dependencies] wasmer-clif-backend = { path = "../clif-backend", version = "0.2.0" } +wasmer-llvm-backend = { path = "../llvm-backend", version = "0.1.0" } wabt = "0.7.2" [build-dependencies] glob = "0.2.11" + +[features] +clif = [] +llvm = [] \ No newline at end of file diff --git a/lib/emscripten/src/utils.rs b/lib/emscripten/src/utils.rs index 678032374..56b080207 100644 --- a/lib/emscripten/src/utils.rs +++ b/lib/emscripten/src/utils.rs @@ -169,15 +169,34 @@ mod tests { use super::is_emscripten_module; use std::sync::Arc; use wabt::wat2wasm; - use wasmer_clif_backend::CraneliftCompiler; + use wasmer_runtime_core::backend::Compiler; use wasmer_runtime_core::compile_with; + #[cfg(feature = "clif")] + fn get_compiler() -> impl Compiler { + use wasmer_clif_backend::CraneliftCompiler; + CraneliftCompiler::new() + } + + #[cfg(feature = "llvm")] + fn get_compiler() -> impl Compiler { + use wasmer_llvm_backend::LLVMCompiler; + LLVMCompiler::new() + } + + #[cfg(not(any(feature = "llvm", feature = "clif")))] + fn get_compiler() -> impl Compiler { + panic!("compiler not specified, activate a compiler via features"); + use wasmer_clif_backend::CraneliftCompiler; + CraneliftCompiler::new() + } + #[test] fn should_detect_emscripten_files() { const WAST_BYTES: &[u8] = include_bytes!("tests/is_emscripten_true.wast"); let wasm_binary = wat2wasm(WAST_BYTES.to_vec()).expect("Can't convert to wasm"); - let module = compile_with(&wasm_binary[..], &CraneliftCompiler::new()) - .expect("WASM can't be compiled"); + let module = + compile_with(&wasm_binary[..], &get_compiler()).expect("WASM can't be compiled"); let module = Arc::new(module); assert!(is_emscripten_module(&module)); } @@ -186,8 +205,8 @@ mod tests { fn should_detect_non_emscripten_files() { const WAST_BYTES: &[u8] = include_bytes!("tests/is_emscripten_false.wast"); let wasm_binary = wat2wasm(WAST_BYTES.to_vec()).expect("Can't convert to wasm"); - let module = compile_with(&wasm_binary[..], &CraneliftCompiler::new()) - .expect("WASM can't be compiled"); + let module = + compile_with(&wasm_binary[..], &get_compiler()).expect("WASM can't be compiled"); let module = Arc::new(module); assert!(!is_emscripten_module(&module)); } diff --git a/lib/emscripten/tests/emtests/_common.rs b/lib/emscripten/tests/emtests/_common.rs index 8d3e00296..c252c9e98 100644 --- a/lib/emscripten/tests/emtests/_common.rs +++ b/lib/emscripten/tests/emtests/_common.rs @@ -1,16 +1,35 @@ macro_rules! assert_emscripten_output { ($file:expr, $name:expr, $args:expr, $expected:expr) => {{ - use wasmer_clif_backend::CraneliftCompiler; use wasmer_emscripten::{ EmscriptenGlobals, generate_emscripten_env, stdio::StdioCapturer }; + use wasmer_runtime_core::backend::Compiler; + + #[cfg(feature = "clif")] + fn get_compiler() -> impl Compiler { + use wasmer_clif_backend::CraneliftCompiler; + CraneliftCompiler::new() + } + + #[cfg(feature = "llvm")] + fn get_compiler() -> impl Compiler { + use wasmer_llvm_backend::LLVMCompiler; + LLVMCompiler::new() + } + + #[cfg(not(any(feature = "llvm", feature = "clif")))] + fn get_compiler() -> impl Compiler { + panic!("compiler not specified, activate a compiler via features"); + use wasmer_clif_backend::CraneliftCompiler; + CraneliftCompiler::new() + } let wasm_bytes = include_bytes!($file); - let module = wasmer_runtime_core::compile_with(&wasm_bytes[..], &CraneliftCompiler::new()) + let module = wasmer_runtime_core::compile_with(&wasm_bytes[..], &get_compiler()) .expect("WASM can't be compiled"); // let module = compile(&wasm_bytes[..]) From cad4110e10ff74d80810eb0e0030237dc7529e5c Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Wed, 6 Mar 2019 23:58:07 -0600 Subject: [PATCH 227/262] Fix typo in Makefile test-emscripten --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 77af8ae8f..a8e7c53de 100644 --- a/Makefile +++ b/Makefile @@ -45,8 +45,8 @@ test: cargo test -p wasmer-runtime-c-api -- --nocapture test-emscripten: - cargo test --manifest-path lib/spectests/Cargo.toml --features clif -- --test-threads=1 $(runargs) - cargo test --manifest-path lib/spectests/Cargo.toml --features llvm -- --test-threads=1 $(runargs) + cargo test --manifest-path lib/emscripten/Cargo.toml --features clif -- --test-threads=1 $(runargs) + cargo test --manifest-path lib/emscripten/Cargo.toml --features llvm -- --test-threads=1 $(runargs) release: # If you are in OS-X, you will need mingw-w64 for cross compiling to windows From c658224f0c0d2fb140090198191c629181c1c732 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Wed, 6 Mar 2019 12:03:38 +0100 Subject: [PATCH 228/262] test(runtime-c-api) Transforms all C/C++ warnings into errors. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch ensures that all our examples and tests do not generate warnings. In C, it can be catastrophic sometimes… Also, be sure that the `cmake` command doesn't emit any warnings too. --- lib/runtime-c-api/tests/CMakeLists.txt | 89 +++++++++++-------- .../tests/runtime_c_api_tests.rs | 12 ++- 2 files changed, 65 insertions(+), 36 deletions(-) diff --git a/lib/runtime-c-api/tests/CMakeLists.txt b/lib/runtime-c-api/tests/CMakeLists.txt index 6f899b5b5..c94c748e1 100644 --- a/lib/runtime-c-api/tests/CMakeLists.txt +++ b/lib/runtime-c-api/tests/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required (VERSION 2.6) -project (WasmerCApiTests) +project (WasmerRuntimeCApiTests) add_executable(test-imports test-imports.c) add_executable(test-exports test-exports.c) @@ -22,39 +22,58 @@ if(NOT WASMER_LIB) message(FATAL_ERROR "wasmer library not found") endif() -target_link_libraries(test-imports - general ${WASMER_LIB}) -target_link_libraries(test-exports - general ${WASMER_LIB}) -target_link_libraries(test-globals - general ${WASMER_LIB}) -target_link_libraries(test-instantiate - general ${WASMER_LIB}) -target_link_libraries(test-import-function - general ${WASMER_LIB}) -target_link_libraries(test-memory - general ${WASMER_LIB}) -target_link_libraries(test-module-imports - general ${WASMER_LIB}) -target_link_libraries(test-module - general ${WASMER_LIB}) -target_link_libraries(test-module-exports - general ${WASMER_LIB}) -target_link_libraries(test-validate - general ${WASMER_LIB}) -target_link_libraries(test-tables - general ${WASMER_LIB}) - enable_testing() -add_test(test-imports test-imports) -add_test(test-exports test-exports) -add_test(test-globals test-globals) -add_test(test-instantiate test-instantiate) -add_test(test-import-function test-import-function) -add_test(test-memory test-memory) -add_test(test-module-imports test-module-imports) -add_test(test-module test-module) -add_test(test-module-exports test-module-exports) -add_test(test-validate test-validate) -add_test(test-tables test-tables) +set( + COMPILER_OPTIONS + # Clang or gcc + $<$,$>: + "-Werror" > + # MSVC + $<$: + "/WX" > +) + +target_link_libraries(test-imports general ${WASMER_LIB}) +target_compile_options(test-imports PRIVATE ${COMPILER_OPTIONS}) +add_test(test-imports test-imports) + +target_link_libraries(test-exports general ${WASMER_LIB}) +target_compile_options(test-exports PRIVATE ${COMPILER_OPTIONS}) +add_test(test-exports test-exports) + +target_link_libraries(test-globals general ${WASMER_LIB}) +target_compile_options(test-globals PRIVATE ${COMPILER_OPTIONS}) +add_test(test-globals test-globals) + +target_link_libraries(test-instantiate general ${WASMER_LIB}) +target_compile_options(test-instantiate PRIVATE ${COMPILER_OPTIONS}) +add_test(test-instantiate test-instantiate) + +target_link_libraries(test-import-function general ${WASMER_LIB}) +target_compile_options(test-import-function PRIVATE ${COMPILER_OPTIONS}) +add_test(test-import-function test-import-function) + +target_link_libraries(test-memory general ${WASMER_LIB}) +target_compile_options(test-memory PRIVATE ${COMPILER_OPTIONS}) +add_test(test-memory test-memory) + +target_link_libraries(test-module-imports general ${WASMER_LIB}) +target_compile_options(test-module-imports PRIVATE ${COMPILER_OPTIONS}) +add_test(test-module-imports test-module-imports) + +target_link_libraries(test-module general ${WASMER_LIB}) +target_compile_options(test-module PRIVATE ${COMPILER_OPTIONS}) +add_test(test-module test-module) + +target_link_libraries(test-module-exports general ${WASMER_LIB}) +target_compile_options(test-module-exports PRIVATE ${COMPILER_OPTIONS}) +add_test(test-module-exports test-module-exports) + +target_link_libraries(test-validate general ${WASMER_LIB}) +target_compile_options(test-validate PRIVATE ${COMPILER_OPTIONS}) +add_test(test-validate test-validate) + +target_link_libraries(test-tables general ${WASMER_LIB}) +target_compile_options(test-tables PRIVATE ${COMPILER_OPTIONS}) +add_test(test-tables test-tables) diff --git a/lib/runtime-c-api/tests/runtime_c_api_tests.rs b/lib/runtime-c-api/tests/runtime_c_api_tests.rs index b605da49e..4349133a7 100644 --- a/lib/runtime-c-api/tests/runtime_c_api_tests.rs +++ b/lib/runtime-c-api/tests/runtime_c_api_tests.rs @@ -3,37 +3,47 @@ use std::process::Command; #[test] fn test_c_api() { let project_tests_dir = concat!(env!("CARGO_MANIFEST_DIR"), "/tests"); + run_command("cmake", project_tests_dir, Some(".")); - run_command("make", project_tests_dir, None); + run_command("make", project_tests_dir, Some("-Wdev -Werror=dev")); run_command("make", project_tests_dir, Some("test")); } fn run_command(command_str: &str, dir: &str, arg: Option<&str>) { println!("Running command: `{}` arg: {:?}", command_str, arg); + let mut command = Command::new(command_str); + if let Some(a) = arg { command.arg(a); } + command.current_dir(dir); + let result = command.output(); + match result { Ok(r) => { println!("output:"); + if let Some(code) = r.status.code() { println!("status: {}", code); } else { println!("status: None"); } + println!("stdout:"); println!("{}", String::from_utf8_lossy(&r.stdout[..])); println!("stderr:"); println!("{}", String::from_utf8_lossy(&r.stderr[..])); + if r.status.success() { assert!(true) } else { panic!("Command failed with exit status: {:?}", r.status); } } + Err(e) => panic!("Command failed: {}", e), } } From dcb4032e9d2cfbf3ddd7b8c494bdd9431143f19e Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Wed, 6 Mar 2019 12:21:50 +0100 Subject: [PATCH 229/262] test(runtime-c-api) Fix compilation errors in `test-imports.c`. --- lib/runtime-c-api/src/lib.rs | 14 ++++++------- lib/runtime-c-api/tests/test-imports.c | 29 +++++++++++++------------- lib/runtime-c-api/wasmer.h | 8 +++---- lib/runtime-c-api/wasmer.hh | 8 +++---- 4 files changed, 30 insertions(+), 29 deletions(-) diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index 591a03a54..3d078cbb7 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -232,8 +232,8 @@ pub extern "C" fn wasmer_memory_grow( /// Returns the current length in pages of the given memory #[allow(clippy::cast_ptr_alignment)] #[no_mangle] -pub extern "C" fn wasmer_memory_length(memory: *mut wasmer_memory_t) -> uint32_t { - let memory = unsafe { &*(memory as *mut Memory) }; +pub extern "C" fn wasmer_memory_length(memory: *const wasmer_memory_t) -> uint32_t { + let memory = unsafe { &*(memory as *const Memory) }; let Pages(len) = memory.size(); len } @@ -1153,7 +1153,7 @@ pub unsafe extern "C" fn wasmer_import_func_new( ctx: Context::Internal, signature: Arc::new(FuncSig::new(params, returns)), }); - Box::into_raw(export) as *mut wasmer_import_func_t + Box::into_raw(export) as *const wasmer_import_func_t } /// Sets the params buffer to the parameter types of the given wasmer_import_func_t @@ -1241,7 +1241,7 @@ pub unsafe extern "C" fn wasmer_import_func_returns_arity( /// Frees memory for the given Func #[allow(clippy::cast_ptr_alignment)] #[no_mangle] -pub extern "C" fn wasmer_import_func_destroy(func: *mut wasmer_import_func_t) { +pub extern "C" fn wasmer_import_func_destroy(func: *const wasmer_import_func_t) { if !func.is_null() { drop(unsafe { Box::from_raw(func as *mut Export) }); } @@ -1342,7 +1342,7 @@ pub unsafe extern "C" fn wasmer_export_func_call( #[allow(clippy::cast_ptr_alignment)] #[no_mangle] pub extern "C" fn wasmer_instance_context_memory( - ctx: *mut wasmer_instance_context_t, + ctx: *const wasmer_instance_context_t, _memory_idx: uint32_t, ) -> *const wasmer_memory_t { let ctx = unsafe { &*(ctx as *const Ctx) }; @@ -1353,8 +1353,8 @@ pub extern "C" fn wasmer_instance_context_memory( /// Gets the start pointer to the bytes within a Memory #[allow(clippy::cast_ptr_alignment)] #[no_mangle] -pub extern "C" fn wasmer_memory_data(mem: *mut wasmer_memory_t) -> *mut uint8_t { - let memory = mem as *mut Memory; +pub extern "C" fn wasmer_memory_data(mem: *const wasmer_memory_t) -> *mut uint8_t { + let memory = mem as *const Memory; use std::cell::Cell; unsafe { ((*memory).view::()[..]).as_ptr() as *mut Cell as *mut u8 } } diff --git a/lib/runtime-c-api/tests/test-imports.c b/lib/runtime-c-api/tests/test-imports.c index 4410c4dd6..26734e17b 100644 --- a/lib/runtime-c-api/tests/test-imports.c +++ b/lib/runtime-c-api/tests/test-imports.c @@ -2,14 +2,15 @@ #include "../wasmer.h" #include #include +#include -static print_str_called = false; +bool static print_str_called = false; // Host function that will be imported into the Web Assembly Instance -void print_str(wasmer_instance_context_t *ctx, int32_t ptr, int32_t len) +void print_str(const wasmer_instance_context_t *ctx, int32_t ptr, int32_t len) { print_str_called = true; - wasmer_memory_t *memory = wasmer_instance_context_memory(ctx, 0); + const wasmer_memory_t *memory = wasmer_instance_context_memory(ctx, 0); uint32_t mem_len = wasmer_memory_length(memory); uint8_t *mem_bytes = wasmer_memory_data(memory); printf("%.*s", len, mem_bytes + ptr); @@ -31,19 +32,19 @@ int main() // of our `print_str` host function wasmer_value_tag params_sig[] = {WASM_I32, WASM_I32}; wasmer_value_tag returns_sig[] = {}; - wasmer_import_func_t *func = wasmer_import_func_new(print_str, params_sig, 2, returns_sig, 0); + const wasmer_import_func_t *func = wasmer_import_func_new((void (*)(void *)) print_str, params_sig, 2, returns_sig, 0); // Create module name for our imports // represented in bytes for UTF-8 compatability - char *module_name = "env"; + const char *module_name = "env"; wasmer_byte_array module_name_bytes; - module_name_bytes.bytes = module_name; + module_name_bytes.bytes = (const uint8_t *) module_name; module_name_bytes.bytes_len = strlen(module_name); // Define a function import - char *import_name = "_print_str"; + const char *import_name = "_print_str"; wasmer_byte_array import_name_bytes; - import_name_bytes.bytes = import_name; + import_name_bytes.bytes = (const uint8_t *) import_name; import_name_bytes.bytes_len = strlen(import_name); wasmer_import_t func_import; func_import.module_name = module_name_bytes; @@ -52,9 +53,9 @@ int main() func_import.value.func = func; // Define a memory import - char *import_memory_name = "memory"; + const char *import_memory_name = "memory"; wasmer_byte_array import_memory_name_bytes; - import_memory_name_bytes.bytes = import_memory_name; + import_memory_name_bytes.bytes = (const uint8_t *) import_memory_name; import_memory_name_bytes.bytes_len = strlen(import_memory_name); wasmer_import_t memory_import; memory_import.module_name = module_name_bytes; @@ -75,9 +76,9 @@ int main() memory_import.value.memory = memory; // Define a global import - char *import_global_name = "__memory_base"; + const char *import_global_name = "__memory_base"; wasmer_byte_array import_global_name_bytes; - import_global_name_bytes.bytes = import_global_name; + import_global_name_bytes.bytes = (const uint8_t *) import_global_name; import_global_name_bytes.bytes_len = strlen(import_global_name); wasmer_import_t global_import; global_import.module_name = module_name_bytes; @@ -90,9 +91,9 @@ int main() global_import.value.global = global; // Define a table import - char *import_table_name = "table"; + const char *import_table_name = "table"; wasmer_byte_array import_table_name_bytes; - import_table_name_bytes.bytes = import_table_name; + import_table_name_bytes.bytes = (const uint8_t *) import_table_name; import_table_name_bytes.bytes_len = strlen(import_table_name); wasmer_import_t table_import; table_import.module_name = module_name_bytes; diff --git a/lib/runtime-c-api/wasmer.h b/lib/runtime-c-api/wasmer.h index 8ecdd1d7d..02265c2ff 100644 --- a/lib/runtime-c-api/wasmer.h +++ b/lib/runtime-c-api/wasmer.h @@ -319,7 +319,7 @@ int wasmer_import_descriptors_len(wasmer_import_descriptors_t *exports); /** * Frees memory for the given Func */ -void wasmer_import_func_destroy(wasmer_import_func_t *func); +void wasmer_import_func_destroy(const wasmer_import_func_t *func); /** * Creates new func @@ -386,7 +386,7 @@ wasmer_result_t wasmer_instance_call(wasmer_instance_t *instance, * Gets the memory within the context at the index `memory_idx`. * The index is always 0 until multiple memories are supported. */ -const wasmer_memory_t *wasmer_instance_context_memory(wasmer_instance_context_t *ctx, +const wasmer_memory_t *wasmer_instance_context_memory(const wasmer_instance_context_t *ctx, uint32_t _memory_idx); /** @@ -442,7 +442,7 @@ int wasmer_last_error_message(char *buffer, int length); /** * Gets the start pointer to the bytes within a Memory */ -uint8_t *wasmer_memory_data(wasmer_memory_t *mem); +uint8_t *wasmer_memory_data(const wasmer_memory_t *mem); /** * Gets the size in bytes of a Memory @@ -465,7 +465,7 @@ wasmer_result_t wasmer_memory_grow(wasmer_memory_t *memory, uint32_t delta); /** * Returns the current length in pages of the given memory */ -uint32_t wasmer_memory_length(wasmer_memory_t *memory); +uint32_t wasmer_memory_length(const wasmer_memory_t *memory); /** * Creates a new Memory for the given descriptor and initializes the given diff --git a/lib/runtime-c-api/wasmer.hh b/lib/runtime-c-api/wasmer.hh index b093b2b64..ce3bcc660 100644 --- a/lib/runtime-c-api/wasmer.hh +++ b/lib/runtime-c-api/wasmer.hh @@ -256,7 +256,7 @@ wasmer_import_descriptor_t *wasmer_import_descriptors_get(wasmer_import_descript int wasmer_import_descriptors_len(wasmer_import_descriptors_t *exports); /// Frees memory for the given Func -void wasmer_import_func_destroy(wasmer_import_func_t *func); +void wasmer_import_func_destroy(const wasmer_import_func_t *func); /// Creates new func /// The caller owns the object and should call `wasmer_import_func_destroy` to free it. @@ -309,7 +309,7 @@ wasmer_result_t wasmer_instance_call(wasmer_instance_t *instance, /// Gets the memory within the context at the index `memory_idx`. /// The index is always 0 until multiple memories are supported. -const wasmer_memory_t *wasmer_instance_context_memory(wasmer_instance_context_t *ctx, +const wasmer_memory_t *wasmer_instance_context_memory(const wasmer_instance_context_t *ctx, uint32_t _memory_idx); /// Frees memory for the given Instance @@ -353,7 +353,7 @@ int wasmer_last_error_length(); int wasmer_last_error_message(char *buffer, int length); /// Gets the start pointer to the bytes within a Memory -uint8_t *wasmer_memory_data(wasmer_memory_t *mem); +uint8_t *wasmer_memory_data(const wasmer_memory_t *mem); /// Gets the size in bytes of a Memory uint32_t wasmer_memory_data_length(wasmer_memory_t *mem); @@ -368,7 +368,7 @@ void wasmer_memory_destroy(wasmer_memory_t *memory); wasmer_result_t wasmer_memory_grow(wasmer_memory_t *memory, uint32_t delta); /// Returns the current length in pages of the given memory -uint32_t wasmer_memory_length(wasmer_memory_t *memory); +uint32_t wasmer_memory_length(const wasmer_memory_t *memory); /// Creates a new Memory for the given descriptor and initializes the given /// pointer to pointer to a pointer to the new memory. From 2a0e42c1e5e3760551475b0ac4537f2574239d68 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Wed, 6 Mar 2019 12:23:16 +0100 Subject: [PATCH 230/262] test(runtime-c-api) Fix compilation errors in `test-memory.c`. --- lib/runtime-c-api/tests/test-memory.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/runtime-c-api/tests/test-memory.c b/lib/runtime-c-api/tests/test-memory.c index 64e028693..9adf9215c 100644 --- a/lib/runtime-c-api/tests/test-memory.c +++ b/lib/runtime-c-api/tests/test-memory.c @@ -2,6 +2,7 @@ #include "../wasmer.h" #include #include +#include int main() { From 603f1fc57d2fdcf26fa0aad57c6f57dc0b79dcb6 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Wed, 6 Mar 2019 13:01:05 +0100 Subject: [PATCH 231/262] test(runtime-c-api) Fix compilation errors in `test-import-function.c`. --- lib/runtime-c-api/tests/test-import-function.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/runtime-c-api/tests/test-import-function.c b/lib/runtime-c-api/tests/test-import-function.c index b28465683..72be9afbc 100644 --- a/lib/runtime-c-api/tests/test-import-function.c +++ b/lib/runtime-c-api/tests/test-import-function.c @@ -4,14 +4,14 @@ #include #include -static print_str_called = false; -static memory_len = 0; -static ptr_len = 0; +static bool print_str_called = false; +static int memory_len = 0; +static int ptr_len = 0; static char actual_str[14] = {}; void print_str(wasmer_instance_context_t *ctx, int32_t ptr, int32_t len) { - wasmer_memory_t *memory = wasmer_instance_context_memory(ctx, 0); + const wasmer_memory_t *memory = wasmer_instance_context_memory(ctx, 0); uint32_t mem_len = wasmer_memory_length(memory); uint8_t *mem_bytes = wasmer_memory_data(memory); for (int32_t idx = 0; idx < len; idx++) @@ -31,16 +31,16 @@ int main() wasmer_value_tag returns_sig[] = {}; printf("Creating new func\n"); - wasmer_import_func_t *func = wasmer_import_func_new(print_str, params_sig, 2, returns_sig, 0); + const wasmer_import_func_t *func = wasmer_import_func_new((void (*)(void *)) print_str, params_sig, 2, returns_sig, 0); wasmer_import_t import; char *module_name = "env"; wasmer_byte_array module_name_bytes; - module_name_bytes.bytes = module_name; + module_name_bytes.bytes = (const uint8_t *) module_name; module_name_bytes.bytes_len = strlen(module_name); char *import_name = "print_str"; wasmer_byte_array import_name_bytes; - import_name_bytes.bytes = import_name; + import_name_bytes.bytes = (const uint8_t *) import_name; import_name_bytes.bytes_len = strlen(import_name); import.module_name = module_name_bytes; @@ -88,4 +88,4 @@ int main() printf("Destroy instance\n"); wasmer_instance_destroy(instance); return 0; -} \ No newline at end of file +} From 725aff6fee9beac4597d4da612f69b20da05c05b Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Wed, 6 Mar 2019 13:14:40 +0100 Subject: [PATCH 232/262] test(runtime-c-api) Fix a compilation error in `test-instantiate.c`. --- lib/runtime-c-api/tests/test-instantiate.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/runtime-c-api/tests/test-instantiate.c b/lib/runtime-c-api/tests/test-instantiate.c index 2a675de12..e7fae37e4 100644 --- a/lib/runtime-c-api/tests/test-instantiate.c +++ b/lib/runtime-c-api/tests/test-instantiate.c @@ -2,6 +2,7 @@ #include "../wasmer.h" #include #include +#include int main() { @@ -53,4 +54,4 @@ int main() printf("Destroy instance\n"); wasmer_instance_destroy(instance); return 0; -} \ No newline at end of file +} From 1dfae80c65188e53b5b5acddd22e03c9ff14d321 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Wed, 6 Mar 2019 13:16:37 +0100 Subject: [PATCH 233/262] test(runtime-c-api) Fix compilation errors in `test-exports.c`. --- lib/runtime-c-api/tests/test-exports.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/runtime-c-api/tests/test-exports.c b/lib/runtime-c-api/tests/test-exports.c index 75368ad16..b282f1911 100644 --- a/lib/runtime-c-api/tests/test-exports.c +++ b/lib/runtime-c-api/tests/test-exports.c @@ -31,7 +31,7 @@ int main() wasmer_import_export_kind kind = wasmer_export_kind(export); assert(kind == WASM_FUNCTION); - wasmer_export_func_t *func = wasmer_export_to_func(export); + const wasmer_export_func_t *func = wasmer_export_to_func(export); wasmer_byte_array name_bytes = wasmer_export_name(export); assert(name_bytes.bytes_len == 3); @@ -83,4 +83,4 @@ int main() printf("Destroy exports\n"); wasmer_exports_destroy(exports); return 0; -} \ No newline at end of file +} From 9a95aaae15ba38ed77778efd7646b3bae4a89e13 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 7 Mar 2019 10:17:15 +0100 Subject: [PATCH 234/262] fix(github) Remove a duplicate issue template --- .github/ISSUE_TEMPLATE/bug_report.md | 35 ---------------------------- 1 file changed, 35 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/bug_report.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index ae27101cd..000000000 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -name: Bug report -about: Create a report to help us improve -title: '' -labels: "\U0001F6A8 \U0001F41E bug" -assignees: '' - ---- - -### Describe the Bug - -A clear and concise description of what the bug is. - -### Steps to Reproduce - -1. Go to '…' -2. Compile with '…' -3. Run '…' -4. See error - -If applicable, add a link to a test case (as a zip file or link to a repository we can clone). - -### Expected Behavior - -A clear and concise description of what you expected to happen. - -### Actual Behavior - -A clear and concise description of what actually happened. - -If applicable, add screenshots to help explain your problem. - -### Additional Context - -Add any other context about the problem here. From 7a9816ff12070186e22d35a4b9c7099e3dce495c Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 7 Mar 2019 10:19:02 +0100 Subject: [PATCH 235/262] feat(runtime-c-api) Ask `rustc` to generate a static library. This is required to correctly link to the embedded runtime. --- lib/runtime-c-api/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/runtime-c-api/Cargo.toml b/lib/runtime-c-api/Cargo.toml index f4908f29a..201c400a0 100644 --- a/lib/runtime-c-api/Cargo.toml +++ b/lib/runtime-c-api/Cargo.toml @@ -14,7 +14,7 @@ wasmer-runtime-core = { path = "../runtime-core", version = "0.2.1" } libc = "0.2" [lib] -crate-type = ["cdylib", "rlib"] +crate-type = ["cdylib", "rlib", "staticlib"] [build-dependencies] cbindgen = "0.8" \ No newline at end of file From 6570bd433d5060140926b40076be7354f3d4b15c Mon Sep 17 00:00:00 2001 From: Syrus Akbary Date: Thu, 7 Mar 2019 10:19:03 -0800 Subject: [PATCH 236/262] Fixed import func to be mutable --- lib/runtime-c-api/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index 3d078cbb7..c633dc5ba 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -1241,7 +1241,7 @@ pub unsafe extern "C" fn wasmer_import_func_returns_arity( /// Frees memory for the given Func #[allow(clippy::cast_ptr_alignment)] #[no_mangle] -pub extern "C" fn wasmer_import_func_destroy(func: *const wasmer_import_func_t) { +pub extern "C" fn wasmer_import_func_destroy(func: *mut wasmer_import_func_t) { if !func.is_null() { drop(unsafe { Box::from_raw(func as *mut Export) }); } From 671ff09e6a80529a086f438a5a1a1e88bf83cfc2 Mon Sep 17 00:00:00 2001 From: Syrus Date: Thu, 7 Mar 2019 18:06:47 -0800 Subject: [PATCH 237/262] Use LLVM 5 for Windows --- .appveyor.yml | 20 ++++++++++---------- lib/llvm-backend/Cargo.toml | 7 ++++++- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 46c989086..dec078c91 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -17,21 +17,21 @@ cache: - target install: - # Install LLVM - - mkdir C:\projects\deps - - cd C:\projects\deps - - appveyor DownloadFile http://prereleases.llvm.org/win-snapshots/LLVM-7.0.0-r336178-win64.exe -FileName llvm.exe - - 7z x llvm.exe -oC:\projects\deps\llvm - # - set "PATH=%PATH%;C:\projects\deps\llvm\bin" - - set "LLD_LINK=C:\projects\deps\llvm\bin\lld-link.exe" - - set "LLVM_SYS_70_PREFIX=C:\projects\deps\llvm" - - cd "%APPVEYOR_BUILD_FOLDER%" + # # Install LLVM + # - mkdir C:\projects\deps + # - cd C:\projects\deps + # - appveyor DownloadFile http://prereleases.llvm.org/win-snapshots/LLVM-7.0.0-r336178-win64.exe -FileName llvm.exe + # - 7z x llvm.exe -oC:\projects\deps\llvm + # # - set "PATH=%PATH%;C:\projects\deps\llvm\bin" + # - set "LLD_LINK=C:\projects\deps\llvm\bin\lld-link.exe" + # - set "LLVM_SYS_70_PREFIX=C:\projects\deps\llvm" + # - cd "%APPVEYOR_BUILD_FOLDER%" # Install Rust # uncomment these lines if the cache is cleared, or if we must re-install rust for some reason # - appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe # - rustup-init.exe -yv --default-host %target% - - set PATH=%PATH%;C:\\projects\\deps\\llvm\\bin;%USERPROFILE%\.cargo\bin + - set PATH=%PATH%;C:\\Libraries\\llvm-5.0.0\\bin;%USERPROFILE%\.cargo\bin - rustup default stable-%target% - rustup update - rustc -vV diff --git a/lib/llvm-backend/Cargo.toml b/lib/llvm-backend/Cargo.toml index a3290f3fd..1dbb63a96 100644 --- a/lib/llvm-backend/Cargo.toml +++ b/lib/llvm-backend/Cargo.toml @@ -7,7 +7,6 @@ edition = "2018" [dependencies] wasmer-runtime-core = { path = "../runtime-core", version = "0.2.1" } wasmparser = "0.28.0" -inkwell = { git = "https://github.com/TheDan64/inkwell", branch = "llvm7-0" } hashbrown = "0.1.8" smallvec = "0.6.8" goblin = "0.0.20" @@ -15,6 +14,12 @@ libc = "0.2.49" nix = "0.13.0" capstone = { version = "0.5.0", optional = true } +[target.'cfg(windows)'.dependencies] +inkwell = { git = "https://github.com/TheDan64/inkwell", branch = "llvm5-0" } + +[target.'cfg(not(windows))'.dependencies] +inkwell = { git = "https://github.com/TheDan64/inkwell", branch = "llvm7-0" } + [build-dependencies] cc = "1.0" lazy_static = "1.2.0" From 7c2667ab0bd6a8fc488e7dae3fc62612a8321800 Mon Sep 17 00:00:00 2001 From: Syrus Date: Thu, 7 Mar 2019 18:06:53 -0800 Subject: [PATCH 238/262] Updated README --- README.md | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 74e9ef575..53677bca9 100644 --- a/README.md +++ b/README.md @@ -97,13 +97,19 @@ sudo apt install cmake Windows support is _highly experimental_. Only simple Wasm programs may be run, and no syscalls are allowed. This means nginx and Lua do not work on Windows. See [this issue](https://github.com/wasmerio/wasmer/issues/176) regarding Emscripten syscall polyfills for Windows. -1. Install [Python for Windows](https://www.python.org/downloads/release/python-2714/). The Windows x86-64 MSI installer is fine. +1. Install [Visual Studio](https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/?sku=Community&rel=15) + +2. Install [Rust for Windows](https://win.rustup.rs) + +3. Install [Python for Windows](https://www.python.org/downloads/release/python-2714/). The Windows x86-64 MSI installer is fine. Make sure to enable "Add python.exe to Path" during installation. -2. Install [Git for Windows](https://git-scm.com/download/win). Allow it to add `git.exe` to your PATH (default +4. Install [Git for Windows](https://git-scm.com/download/win). Allow it to add `git.exe` to your PATH (default settings for the installer are fine). -3. Install [CMake](https://cmake.org/download/). Ensure CMake is in your PATH. +5. Install [CMake](https://cmake.org/download/). Ensure CMake is in your PATH. + +6. Install [LLVM 7.0](https://prereleases.llvm.org/win-snapshots/LLVM-7.0.0-r336178-win64.exe) ## Building From 3a4325c5a3c6df990797f1d40c54609bcd832a25 Mon Sep 17 00:00:00 2001 From: Syrus Date: Thu, 7 Mar 2019 18:26:29 -0800 Subject: [PATCH 239/262] Only use llvm in non windows envs --- Cargo.lock | 1 + Cargo.toml | 6 ++++++ lib/emscripten/Cargo.toml | 4 +++- lib/llvm-backend/Cargo.toml | 7 +------ lib/runtime/Cargo.toml | 2 +- lib/spectests/Cargo.toml | 4 +++- 6 files changed, 15 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a903bc9dc..2ee89b128 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1286,6 +1286,7 @@ dependencies = [ "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-clif-backend 0.2.0", "wasmer-emscripten 0.2.1", + "wasmer-llvm-backend 0.1.0", "wasmer-runtime 0.2.1", "wasmer-runtime-core 0.2.1", ] diff --git a/Cargo.toml b/Cargo.toml index d987498cf..67672e097 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,7 +26,13 @@ wasmer-runtime = { path = "lib/runtime" } wasmer-runtime-core = { path = "lib/runtime-core" } wasmer-emscripten = { path = "lib/emscripten" } +[target.'cfg(not(windows))'.dependencies] +wasmer-llvm-backend = { path = "lib/llvm-backend" } + [workspace] +members = ["lib/clif-backend", "lib/runtime", "lib/runtime-core", "lib/emscripten", "lib/spectests", "lib/win-exception-handler", "lib/runtime-c-api"] + +[target.'cfg(not(windows))'.workspace] members = ["lib/clif-backend", "lib/runtime", "lib/runtime-core", "lib/emscripten", "lib/spectests", "lib/win-exception-handler", "lib/runtime-c-api", "lib/llvm-backend"] [build-dependencies] diff --git a/lib/emscripten/Cargo.toml b/lib/emscripten/Cargo.toml index 3106d905c..cd691e566 100644 --- a/lib/emscripten/Cargo.toml +++ b/lib/emscripten/Cargo.toml @@ -20,9 +20,11 @@ rand = "0.6" [dev-dependencies] wasmer-clif-backend = { path = "../clif-backend", version = "0.2.0" } -wasmer-llvm-backend = { path = "../llvm-backend", version = "0.1.0" } wabt = "0.7.2" +[target.'cfg(not(windows))'.dev-dependencies] +wasmer-llvm-backend = { path = "../llvm-backend", version = "0.1.0" } + [build-dependencies] glob = "0.2.11" diff --git a/lib/llvm-backend/Cargo.toml b/lib/llvm-backend/Cargo.toml index 1dbb63a96..e6f58e6e7 100644 --- a/lib/llvm-backend/Cargo.toml +++ b/lib/llvm-backend/Cargo.toml @@ -6,6 +6,7 @@ edition = "2018" [dependencies] wasmer-runtime-core = { path = "../runtime-core", version = "0.2.1" } +inkwell = { git = "https://github.com/TheDan64/inkwell", branch = "llvm7-0" } wasmparser = "0.28.0" hashbrown = "0.1.8" smallvec = "0.6.8" @@ -14,12 +15,6 @@ libc = "0.2.49" nix = "0.13.0" capstone = { version = "0.5.0", optional = true } -[target.'cfg(windows)'.dependencies] -inkwell = { git = "https://github.com/TheDan64/inkwell", branch = "llvm5-0" } - -[target.'cfg(not(windows))'.dependencies] -inkwell = { git = "https://github.com/TheDan64/inkwell", branch = "llvm7-0" } - [build-dependencies] cc = "1.0" lazy_static = "1.2.0" diff --git a/lib/runtime/Cargo.toml b/lib/runtime/Cargo.toml index 12b719248..895423ead 100644 --- a/lib/runtime/Cargo.toml +++ b/lib/runtime/Cargo.toml @@ -25,7 +25,7 @@ tempfile = "3.0.7" criterion = "0.2" wabt = "0.7.4" -[dependencies.wasmer-llvm-backend] +[target.'cfg(not(windows))'.dependencies.wasmer-llvm-backend] path = "../llvm-backend" [features] diff --git a/lib/spectests/Cargo.toml b/lib/spectests/Cargo.toml index e9ce75132..fea4560c5 100644 --- a/lib/spectests/Cargo.toml +++ b/lib/spectests/Cargo.toml @@ -16,9 +16,11 @@ wabt = "0.7.2" [dev-dependencies] wasmer-clif-backend = { path = "../clif-backend", version = "0.2.0" } -wasmer-llvm-backend = { path = "../llvm-backend", version = "0.1.0" } wabt = "0.7.2" +[target.'cfg(not(windows))'.dev-dependencies] +wasmer-llvm-backend = { path = "../llvm-backend", version = "0.1.0" } + [features] default = ["fast-tests"] fast-tests = [] From 4acb826bf23723693c08147261223549d3d32f73 Mon Sep 17 00:00:00 2001 From: Syrus Date: Thu, 7 Mar 2019 19:11:15 -0800 Subject: [PATCH 240/262] Fixed default compiler on windows --- lib/runtime/src/lib.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/runtime/src/lib.rs b/lib/runtime/src/lib.rs index 4c5ce88cd..4ad74c345 100644 --- a/lib/runtime/src/lib.rs +++ b/lib/runtime/src/lib.rs @@ -154,11 +154,15 @@ pub fn instantiate(wasm: &[u8], import_object: &ImportObject) -> error::Result &'static dyn Compiler { use lazy_static::lazy_static; - // use wasmer_clif_backend::CraneliftCompiler; - use wasmer_llvm_backend::LLVMCompiler; + + #[cfg(feature = "llvm")] + use wasmer_llvm_backend::LLVMCompiler as DefaultCompiler; + + #[cfg(not(feature = "llvm"))] + use wasmer_clif_backend::CraneliftCompiler as DefaultCompiler; lazy_static! { - static ref DEFAULT_COMPILER: LLVMCompiler = { LLVMCompiler::new() }; + static ref DEFAULT_COMPILER: DefaultCompiler = { DefaultCompiler::new() }; } &*DEFAULT_COMPILER as &dyn Compiler From 3866f8fd73c307099ec580de01a0537d9b1081b2 Mon Sep 17 00:00:00 2001 From: Syrus Date: Thu, 7 Mar 2019 19:32:04 -0800 Subject: [PATCH 241/262] Updated test script --- .appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.appveyor.yml b/.appveyor.yml index dec078c91..eca2e24ae 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -48,7 +48,7 @@ build_script: - cargo build --release --verbose test_script: - - cargo test --package wasmer-spectests + - cargo test --manifest-path lib/spectests/Cargo.toml --features clif after_build: - cd ./src/installer From b321ca339bec88bb434c9e22f5924a0a07071a54 Mon Sep 17 00:00:00 2001 From: Syrus Akbary Date: Thu, 7 Mar 2019 20:39:44 -0800 Subject: [PATCH 242/262] Update README.md --- lib/README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/README.md b/lib/README.md index 79ae446d3..0a90ba835 100644 --- a/lib/README.md +++ b/lib/README.md @@ -31,6 +31,7 @@ Wasmer intends to support different integrations: The Wasmer [runtime](./runtime) is designed to support multiple compiler backends, allowing the user to tune the codegen properties (compile speed, performance, etc) to best fit their use case. -Currently, we support a Cranelift compiler backend: +Currently, we support multiple backends for compiling WebAssembly to machine code: -- [clif-backend](./clif-backend/): The integration of Wasmer with Cranelift +- [clif-backend](./clif-backend/): Cranelift backend +- [llvm-backend](./clif-backend/): LLVM backend From 60a74540d979a70ba307552d0c3001ccd6967067 Mon Sep 17 00:00:00 2001 From: Syrus Akbary Date: Thu, 7 Mar 2019 20:39:58 -0800 Subject: [PATCH 243/262] Update README.md --- lib/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/README.md b/lib/README.md index 0a90ba835..47f3264e7 100644 --- a/lib/README.md +++ b/lib/README.md @@ -34,4 +34,4 @@ to tune the codegen properties (compile speed, performance, etc) to best fit the Currently, we support multiple backends for compiling WebAssembly to machine code: - [clif-backend](./clif-backend/): Cranelift backend -- [llvm-backend](./clif-backend/): LLVM backend +- [llvm-backend](./llvm-backend/): LLVM backend From 628caf0a74610aec2138001dd26692f04346393d Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Thu, 7 Mar 2019 22:59:11 -0600 Subject: [PATCH 244/262] Make import_func_new/destroy not const --- lib/runtime-c-api/src/lib.rs | 4 ++-- lib/runtime-c-api/tests/test-import-function.c | 2 +- lib/runtime-c-api/tests/test-imports.c | 2 +- lib/runtime-c-api/wasmer.h | 12 ++++++------ lib/runtime-c-api/wasmer.hh | 12 ++++++------ 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index c633dc5ba..8055fc445 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -1142,7 +1142,7 @@ pub unsafe extern "C" fn wasmer_import_func_new( params_len: c_int, returns: *const wasmer_value_tag, returns_len: c_int, -) -> *const wasmer_import_func_t { +) -> *mut wasmer_import_func_t { let params: &[wasmer_value_tag] = slice::from_raw_parts(params, params_len as usize); let params: Vec = params.iter().cloned().map(|x| x.into()).collect(); let returns: &[wasmer_value_tag] = slice::from_raw_parts(returns, returns_len as usize); @@ -1153,7 +1153,7 @@ pub unsafe extern "C" fn wasmer_import_func_new( ctx: Context::Internal, signature: Arc::new(FuncSig::new(params, returns)), }); - Box::into_raw(export) as *const wasmer_import_func_t + Box::into_raw(export) as *mut wasmer_import_func_t } /// Sets the params buffer to the parameter types of the given wasmer_import_func_t diff --git a/lib/runtime-c-api/tests/test-import-function.c b/lib/runtime-c-api/tests/test-import-function.c index 72be9afbc..f8214535c 100644 --- a/lib/runtime-c-api/tests/test-import-function.c +++ b/lib/runtime-c-api/tests/test-import-function.c @@ -31,7 +31,7 @@ int main() wasmer_value_tag returns_sig[] = {}; printf("Creating new func\n"); - const wasmer_import_func_t *func = wasmer_import_func_new((void (*)(void *)) print_str, params_sig, 2, returns_sig, 0); + wasmer_import_func_t *func = wasmer_import_func_new((void (*)(void *)) print_str, params_sig, 2, returns_sig, 0); wasmer_import_t import; char *module_name = "env"; diff --git a/lib/runtime-c-api/tests/test-imports.c b/lib/runtime-c-api/tests/test-imports.c index 26734e17b..cecb9ec94 100644 --- a/lib/runtime-c-api/tests/test-imports.c +++ b/lib/runtime-c-api/tests/test-imports.c @@ -32,7 +32,7 @@ int main() // of our `print_str` host function wasmer_value_tag params_sig[] = {WASM_I32, WASM_I32}; wasmer_value_tag returns_sig[] = {}; - const wasmer_import_func_t *func = wasmer_import_func_new((void (*)(void *)) print_str, params_sig, 2, returns_sig, 0); + wasmer_import_func_t *func = wasmer_import_func_new((void (*)(void *)) print_str, params_sig, 2, returns_sig, 0); // Create module name for our imports // represented in bytes for UTF-8 compatability diff --git a/lib/runtime-c-api/wasmer.h b/lib/runtime-c-api/wasmer.h index 02265c2ff..c9cb61709 100644 --- a/lib/runtime-c-api/wasmer.h +++ b/lib/runtime-c-api/wasmer.h @@ -319,17 +319,17 @@ int wasmer_import_descriptors_len(wasmer_import_descriptors_t *exports); /** * Frees memory for the given Func */ -void wasmer_import_func_destroy(const wasmer_import_func_t *func); +void wasmer_import_func_destroy(wasmer_import_func_t *func); /** * Creates new func * The caller owns the object and should call `wasmer_import_func_destroy` to free it. */ -const wasmer_import_func_t *wasmer_import_func_new(void (*func)(void *data), - const wasmer_value_tag *params, - int params_len, - const wasmer_value_tag *returns, - int returns_len); +wasmer_import_func_t *wasmer_import_func_new(void (*func)(void *data), + const wasmer_value_tag *params, + int params_len, + const wasmer_value_tag *returns, + int returns_len); /** * Sets the params buffer to the parameter types of the given wasmer_import_func_t diff --git a/lib/runtime-c-api/wasmer.hh b/lib/runtime-c-api/wasmer.hh index ce3bcc660..4578eae49 100644 --- a/lib/runtime-c-api/wasmer.hh +++ b/lib/runtime-c-api/wasmer.hh @@ -256,15 +256,15 @@ wasmer_import_descriptor_t *wasmer_import_descriptors_get(wasmer_import_descript int wasmer_import_descriptors_len(wasmer_import_descriptors_t *exports); /// Frees memory for the given Func -void wasmer_import_func_destroy(const wasmer_import_func_t *func); +void wasmer_import_func_destroy(wasmer_import_func_t *func); /// Creates new func /// The caller owns the object and should call `wasmer_import_func_destroy` to free it. -const wasmer_import_func_t *wasmer_import_func_new(void (*func)(void *data), - const wasmer_value_tag *params, - int params_len, - const wasmer_value_tag *returns, - int returns_len); +wasmer_import_func_t *wasmer_import_func_new(void (*func)(void *data), + const wasmer_value_tag *params, + int params_len, + const wasmer_value_tag *returns, + int returns_len); /// Sets the params buffer to the parameter types of the given wasmer_import_func_t /// Returns `wasmer_result_t::WASMER_OK` upon success. From 3cfdb868ef523376e057cb595b464ab606b5ef43 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Fri, 8 Mar 2019 10:20:46 +0100 Subject: [PATCH 245/262] feat(bors) Set up Bors. --- .appveyor.yml | 9 +++++++-- bors.toml | 9 +++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 bors.toml diff --git a/.appveyor.yml b/.appveyor.yml index eca2e24ae..40194cd06 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -2,8 +2,10 @@ version: "{build} ~ {branch}" os: Visual Studio 2017 -# Do not build feature branch with open Pull Requests -skip_branch_with_pr: true +branches: + only: + - staging + - trying environment: matrix: @@ -57,6 +59,9 @@ after_build: - appveyor PushArtifact ..\..\WasmerInstaller-%APPVEYOR_REPO_TAG_NAME%.exe - cd ..\..\ +matrix: + fast_finish: true + deploy: description: 'WasmerInstaller' artifact: /.*\.exe/ diff --git a/bors.toml b/bors.toml new file mode 100644 index 000000000..c56141cd5 --- /dev/null +++ b/bors.toml @@ -0,0 +1,9 @@ +status = [ + "ci/circleci: lint", + "ci/circleci: test", + "ci/circleci: test-macos", + "continuous-integration/appveyor/branch" +] +required_approvals = 1 +timeout_sec = 900 +delete_merged_branches = true \ No newline at end of file From 8823bb09f626e0b72abb2ebf7db0f75b5660962d Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Fri, 8 Mar 2019 10:31:44 +0100 Subject: [PATCH 246/262] chore(makefile) Remove the `capi` target. This target is no longer useful since the C and C++ header files are generated each time for each build. --- Makefile | 3 --- 1 file changed, 3 deletions(-) diff --git a/Makefile b/Makefile index a8e7c53de..0c9a0692d 100644 --- a/Makefile +++ b/Makefile @@ -12,9 +12,6 @@ spectests: emtests: WASM_EMSCRIPTEN_GENERATE_EMTESTS=1 cargo build -p wasmer-emscripten -capi: - cargo build --manifest-path lib/runtime-c-api/Cargo.toml - # clean: # rm -rf artifacts From a4454ebae87ca6d53d686ee34b979de2c7583fa7 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Fri, 8 Mar 2019 13:26:04 +0100 Subject: [PATCH 247/262] doc(readme) Fix a typo. This patch fixes a typo in the C example. --- lib/runtime-c-api/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/runtime-c-api/README.md b/lib/runtime-c-api/README.md index efec3e50d..1e741cfd1 100644 --- a/lib/runtime-c-api/README.md +++ b/lib/runtime-c-api/README.md @@ -73,7 +73,7 @@ int main() argument_one.tag = WASM_I32; argument_one.value.I32 = 7; - // Value of argumen #2 is `8i32`. + // Value of argument #2 is `8i32`. wasmer_value_t argument_two; argument_two.tag = WASM_I32; argument_two.value.I32 = 8; From 80ac7af2b023f0cc51b7d9676822f82ead61fa4b Mon Sep 17 00:00:00 2001 From: Mackenzie Clark Date: Fri, 8 Mar 2019 11:52:24 -0800 Subject: [PATCH 248/262] remove unnecessary conditional compilation in cargo file for windows --- Cargo.toml | 3 --- 1 file changed, 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 67672e097..946b045b3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,9 +30,6 @@ wasmer-emscripten = { path = "lib/emscripten" } wasmer-llvm-backend = { path = "lib/llvm-backend" } [workspace] -members = ["lib/clif-backend", "lib/runtime", "lib/runtime-core", "lib/emscripten", "lib/spectests", "lib/win-exception-handler", "lib/runtime-c-api"] - -[target.'cfg(not(windows))'.workspace] members = ["lib/clif-backend", "lib/runtime", "lib/runtime-core", "lib/emscripten", "lib/spectests", "lib/win-exception-handler", "lib/runtime-c-api", "lib/llvm-backend"] [build-dependencies] From 9bf786db5ed6691580e1999eaebc7cb0da6de792 Mon Sep 17 00:00:00 2001 From: Mackenzie Clark Date: Fri, 8 Mar 2019 13:00:39 -0800 Subject: [PATCH 249/262] run installer setup in before_deploy step --- .appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.appveyor.yml b/.appveyor.yml index eca2e24ae..0c612592a 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -50,7 +50,7 @@ build_script: test_script: - cargo test --manifest-path lib/spectests/Cargo.toml --features clif -after_build: +before_deploy: - cd ./src/installer - iscc wasmer.iss - copy /y .\WasmerInstaller.exe ..\..\WasmerInstaller-%APPVEYOR_REPO_TAG_NAME%.exe From 16f72e30f4851040f8e3b3e81324a9767b50a94b Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Fri, 8 Mar 2019 15:06:39 -0800 Subject: [PATCH 250/262] Just build trying and staging branches --- .circleci/config.yml | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index c5ea7e219..aca9afd1c 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -310,25 +310,30 @@ workflows: jobs: - lint - test: - filters: - branches: - ignore: master + branches: + only: + - trying + - staging - test-macos: - filters: - branches: - ignore: master + branches: + only: + - trying + - staging - test-and-build: - filters: - branches: - only: master + branches: + only: + - trying + - staging - test-and-build-macos: - filters: - branches: - only: master + branches: + only: + - trying + - staging - test-rust-nightly: - filters: - branches: - only: master + branches: + only: + - trying + - staging - publish-github-release: requires: - lint From ba66d82b72be9266e386093ed63aae508c4f8c15 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Fri, 8 Mar 2019 15:08:28 -0800 Subject: [PATCH 251/262] Attempt to fix circleci config --- .circleci/config.yml | 45 ++++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index aca9afd1c..1ca2ddcb1 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -310,30 +310,35 @@ workflows: jobs: - lint - test: - branches: - only: - - trying - - staging + filters: + branches: + only: + - trying + - staging - test-macos: - branches: - only: - - trying - - staging + filters: + branches: + only: + - trying + - staging - test-and-build: - branches: - only: - - trying - - staging + filters: + branches: + only: + - trying + - staging - test-and-build-macos: - branches: - only: - - trying - - staging + filters: + branches: + only: + - trying + - staging - test-rust-nightly: - branches: - only: - - trying - - staging + filters: + branches: + only: + - trying + - staging - publish-github-release: requires: - lint From 17eada53f34a81e56157f033e0ac2c235d5628ce Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Fri, 8 Mar 2019 15:15:16 -0800 Subject: [PATCH 252/262] feat(runtime) Get ready for tiering (#257) * Add local_function field to context * Add local call indirection to llvm * local call indirection * Fix vm test * Fix cranelift local call indirection * Fix unwinding on nightly --- Cargo.lock | 3 ++ lib/clif-backend/src/func_env.rs | 31 ++++++++++++++++++-- lib/llvm-backend/Cargo.toml | 1 + lib/llvm-backend/build.rs | 6 ++++ lib/llvm-backend/src/code.rs | 5 ++-- lib/llvm-backend/src/intrinsics.rs | 39 +++++++++++++++++++++++-- lib/llvm-backend/src/lib.rs | 2 ++ lib/llvm-backend/src/platform/unix.rs | 6 ++-- lib/runtime-core/src/backing.rs | 20 +++++++++++-- lib/runtime-core/src/sys/unix/memory.rs | 2 ++ lib/runtime-core/src/vm.rs | 14 +++++++++ 11 files changed, 118 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2ee89b128..b6a7f4718 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,3 +1,5 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. [[package]] name = "aho-corasick" version = "0.6.10" @@ -1344,6 +1346,7 @@ dependencies = [ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "nix 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/lib/clif-backend/src/func_env.rs b/lib/clif-backend/src/func_env.rs index b08f56dd2..8a65444b7 100644 --- a/lib/clif-backend/src/func_env.rs +++ b/lib/clif-backend/src/func_env.rs @@ -445,6 +445,12 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> { pos.ins().symbol_value(ir::types::I64, sig_index_global) + // let dynamic_sigindices_array_ptr = pos.ins().load( + // ptr_type, + // mflags, + + // ) + // let expected_sig = pos.ins().iconst(ir::types::I32, sig_index.index() as i64); // self.env.deduplicated[clif_sig_index] @@ -477,9 +483,10 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> { call_args: &[ir::Value], ) -> cranelift_wasm::WasmResult { let callee_index: FuncIndex = Converter(clif_callee_index).into(); + let ptr_type = self.pointer_type(); match callee_index.local_or_import(&self.env.module.info) { - LocalOrImport::Local(_) => { + LocalOrImport::Local(local_function_index) => { // this is an internal function let vmctx = pos .func @@ -490,10 +497,28 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> { args.push(vmctx); args.extend(call_args.iter().cloned()); - Ok(pos.ins().call(callee, &args)) + let sig_ref = pos.func.dfg.ext_funcs[callee].signature; + let function_ptr = { + let mflags = ir::MemFlags::trusted(); + + let function_array_ptr = pos.ins().load( + ptr_type, + mflags, + vmctx, + vm::Ctx::offset_local_functions() as i32, + ); + + pos.ins().load( + ptr_type, + mflags, + function_array_ptr, + (local_function_index.index() as i32) * 8, + ) + }; + + Ok(pos.ins().call_indirect(sig_ref, function_ptr, &args)) } LocalOrImport::Import(imported_func_index) => { - let ptr_type = self.pointer_type(); // this is an imported function let vmctx = pos.func.create_global_value(ir::GlobalValueData::VMContext); diff --git a/lib/llvm-backend/Cargo.toml b/lib/llvm-backend/Cargo.toml index e6f58e6e7..646bbd157 100644 --- a/lib/llvm-backend/Cargo.toml +++ b/lib/llvm-backend/Cargo.toml @@ -20,6 +20,7 @@ cc = "1.0" lazy_static = "1.2.0" regex = "1.1.0" semver = "0.9" +rustc_version = "0.2.3" [dev-dependencies] wabt = "0.7.4" diff --git a/lib/llvm-backend/build.rs b/lib/llvm-backend/build.rs index 062a5a5fe..ed96cae9d 100644 --- a/lib/llvm-backend/build.rs +++ b/lib/llvm-backend/build.rs @@ -212,4 +212,10 @@ fn main() { .compile("llvm-backend"); println!("cargo:rustc-link-lib=static=llvm-backend"); + println!("cargo:rerun-if-changed=build.rs"); + + // Enable "nightly" cfg if the current compiler is nightly. + if rustc_version::version_meta().unwrap().channel == rustc_version::Channel::Nightly { + println!("cargo:rustc-cfg=nightly"); + } } diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index 3d9f82153..173262b67 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -664,14 +664,15 @@ fn parse_function( let call_site = match func_index.local_or_import(info) { LocalOrImport::Local(local_func_index) => { - let func_value = functions[local_func_index]; let params: Vec<_> = [ctx.basic()] .iter() .chain(state.peekn(func_sig.params().len())?.iter()) .map(|v| *v) .collect(); - builder.build_call(func_value, ¶ms, &state.var_name()) + let func_ptr = ctx.local_func(local_func_index, llvm_sig); + + builder.build_call(func_ptr, ¶ms, &state.var_name()) } LocalOrImport::Import(import_func_index) => { let (func_ptr_untyped, ctx_ptr) = ctx.imported_func(import_func_index); diff --git a/lib/llvm-backend/src/intrinsics.rs b/lib/llvm-backend/src/intrinsics.rs index 98c41326e..ba1e3abd3 100644 --- a/lib/llvm-backend/src/intrinsics.rs +++ b/lib/llvm-backend/src/intrinsics.rs @@ -3,7 +3,7 @@ use inkwell::{ builder::Builder, context::Context, module::Module, - types::{BasicType, FloatType, IntType, PointerType, StructType, VoidType}, + types::{BasicType, FloatType, FunctionType, IntType, PointerType, StructType, VoidType}, values::{ BasicValue, BasicValueEnum, FloatValue, FunctionValue, InstructionValue, IntValue, PointerValue, @@ -16,7 +16,8 @@ use wasmer_runtime_core::{ module::ModuleInfo, structures::TypedIndex, types::{ - GlobalIndex, ImportedFuncIndex, LocalOrImport, MemoryIndex, SigIndex, TableIndex, Type, + GlobalIndex, ImportedFuncIndex, LocalFuncIndex, LocalOrImport, MemoryIndex, SigIndex, + TableIndex, Type, }, }; @@ -161,6 +162,7 @@ impl Intrinsics { let imported_func_ty = context.struct_type(&[i8_ptr_ty_basic, ctx_ptr_ty.as_basic_type_enum()], false); let sigindex_ty = i32_ty; + let local_function_ty = i8_ptr_ty; let anyfunc_ty = context.struct_type( &[ @@ -203,6 +205,9 @@ impl Intrinsics { sigindex_ty .ptr_type(AddressSpace::Generic) .as_basic_type_enum(), + local_function_ty + .ptr_type(AddressSpace::Generic) + .as_basic_type_enum(), ], false, ); @@ -582,6 +587,36 @@ impl<'a> CtxType<'a> { ) } + pub fn local_func(&mut self, index: LocalFuncIndex, fn_ty: FunctionType) -> PointerValue { + let local_func_array_ptr_ptr = unsafe { + self.builder + .build_struct_gep(self.ctx_ptr_value, 8, "local_func_array_ptr_ptr") + }; + let local_func_array_ptr = self + .builder + .build_load(local_func_array_ptr_ptr, "local_func_array_ptr") + .into_pointer_value(); + let local_func_ptr_ptr = unsafe { + self.builder.build_in_bounds_gep( + local_func_array_ptr, + &[self + .intrinsics + .i32_ty + .const_int(index.index() as u64, false)], + "local_func_ptr_ptr", + ) + }; + let local_func_ptr = self + .builder + .build_load(local_func_ptr_ptr, "local_func_ptr") + .into_pointer_value(); + self.builder.build_pointer_cast( + local_func_ptr, + fn_ty.ptr_type(AddressSpace::Generic), + "local_func_ptr", + ) + } + pub fn dynamic_sigindex(&mut self, index: SigIndex) -> IntValue { let (cached_sigindices, builder, info, ctx_ptr_value, intrinsics, cache_builder) = ( &mut self.cached_sigindices, diff --git a/lib/llvm-backend/src/lib.rs b/lib/llvm-backend/src/lib.rs index d70f0f363..85bcc7e19 100644 --- a/lib/llvm-backend/src/lib.rs +++ b/lib/llvm-backend/src/lib.rs @@ -1,3 +1,5 @@ +#![cfg_attr(nightly, feature(unwind_attributes))] + use inkwell::{ execution_engine::JitFunction, targets::{CodeModel, FileType, InitializationConfig, RelocMode, Target, TargetMachine}, diff --git a/lib/llvm-backend/src/platform/unix.rs b/lib/llvm-backend/src/platform/unix.rs index c17f56359..2267ab129 100644 --- a/lib/llvm-backend/src/platform/unix.rs +++ b/lib/llvm-backend/src/platform/unix.rs @@ -41,6 +41,7 @@ pub unsafe fn visit_fde(addr: *mut u8, size: usize, visitor: extern "C" fn(*mut } extern "C" { + #[cfg_attr(nightly, unwind(allowed))] fn throw_trap(ty: i32) -> !; } @@ -50,12 +51,13 @@ pub unsafe fn install_signal_handler() { SaFlags::SA_ONSTACK | SaFlags::SA_SIGINFO, SigSet::empty(), ); - sigaction(SIGFPE, &sa).unwrap(); - sigaction(SIGILL, &sa).unwrap(); + // sigaction(SIGFPE, &sa).unwrap(); + // sigaction(SIGILL, &sa).unwrap(); sigaction(SIGSEGV, &sa).unwrap(); sigaction(SIGBUS, &sa).unwrap(); } +#[cfg_attr(nightly, unwind(allowed))] extern "C" fn signal_trap_handler( signum: ::nix::libc::c_int, siginfo: *mut siginfo_t, diff --git a/lib/runtime-core/src/backing.rs b/lib/runtime-core/src/backing.rs index 33cd80182..48f2d2256 100644 --- a/lib/runtime-core/src/backing.rs +++ b/lib/runtime-core/src/backing.rs @@ -10,8 +10,8 @@ use crate::{ table::Table, types::{ ImportedFuncIndex, ImportedGlobalIndex, ImportedMemoryIndex, ImportedTableIndex, - Initializer, LocalGlobalIndex, LocalMemoryIndex, LocalOrImport, LocalTableIndex, SigIndex, - Value, + Initializer, LocalFuncIndex, LocalGlobalIndex, LocalMemoryIndex, LocalOrImport, + LocalTableIndex, SigIndex, Value, }, vm, }; @@ -28,6 +28,7 @@ pub struct LocalBacking { pub(crate) vm_globals: BoxedMap, pub(crate) dynamic_sigindices: BoxedMap, + pub(crate) local_functions: BoxedMap, } // impl LocalBacking { @@ -51,6 +52,7 @@ impl LocalBacking { let vm_globals = Self::finalize_globals(&mut globals); let dynamic_sigindices = Self::generate_sigindices(&module.info); + let local_functions = Self::generate_local_functions(module); Self { memories, @@ -62,9 +64,23 @@ impl LocalBacking { vm_globals, dynamic_sigindices, + local_functions, } } + fn generate_local_functions(module: &ModuleInner) -> BoxedMap { + (0..module.info.func_assoc.len() - module.info.imported_functions.len()) + .map(|index| { + module + .func_resolver + .get(module, LocalFuncIndex::new(index)) + .unwrap() + .as_ptr() as *const _ + }) + .collect::>() + .into_boxed_map() + } + fn generate_sigindices(info: &ModuleInfo) -> BoxedMap { info.signatures .iter() diff --git a/lib/runtime-core/src/sys/unix/memory.rs b/lib/runtime-core/src/sys/unix/memory.rs index 338024d09..9ffb663eb 100644 --- a/lib/runtime-core/src/sys/unix/memory.rs +++ b/lib/runtime-core/src/sys/unix/memory.rs @@ -245,6 +245,7 @@ pub enum Protect { Read, ReadWrite, ReadExec, + ReadWriteExec, } impl Protect { @@ -254,6 +255,7 @@ impl Protect { Protect::Read => 1, Protect::ReadWrite => 1 | 2, Protect::ReadExec => 1 | 4, + Protect::ReadWriteExec => 1 | 2 | 4, } } diff --git a/lib/runtime-core/src/vm.rs b/lib/runtime-core/src/vm.rs index bc0aa71e8..508ca031b 100644 --- a/lib/runtime-core/src/vm.rs +++ b/lib/runtime-core/src/vm.rs @@ -40,6 +40,8 @@ pub struct Ctx { /// modules safely. pub(crate) dynamic_sigindices: *const SigId, + pub(crate) local_functions: *const *const Func, + local_backing: *mut LocalBacking, import_backing: *mut ImportBacking, module: *const ModuleInner, @@ -66,6 +68,7 @@ impl Ctx { imported_funcs: import_backing.vm_functions.as_mut_ptr(), dynamic_sigindices: local_backing.dynamic_sigindices.as_ptr(), + local_functions: local_backing.local_functions.as_ptr(), local_backing, import_backing, @@ -95,6 +98,7 @@ impl Ctx { imported_funcs: import_backing.vm_functions.as_mut_ptr(), dynamic_sigindices: local_backing.dynamic_sigindices.as_ptr(), + local_functions: local_backing.local_functions.as_ptr(), local_backing, import_backing, @@ -173,6 +177,10 @@ impl Ctx { pub fn offset_signatures() -> u8 { 7 * (mem::size_of::() as u8) } + + pub fn offset_local_functions() -> u8 { + 8 * (mem::size_of::() as u8) + } } enum InnerFunc {} @@ -363,6 +371,11 @@ mod vm_offset_tests { Ctx::offset_imported_funcs() as usize, offset_of!(Ctx => imported_funcs).get_byte_offset(), ); + + assert_eq!( + Ctx::offset_local_functions() as usize, + offset_of!(Ctx => local_functions).get_byte_offset(), + ); } #[test] @@ -470,6 +483,7 @@ mod vm_ctx_tests { vm_globals: Map::new().into_boxed_map(), dynamic_sigindices: Map::new().into_boxed_map(), + local_functions: Map::new().into_boxed_map(), }; let mut import_backing = ImportBacking { memories: Map::new().into_boxed_map(), From 3fea07dc8a290a8cca42d056283e32d0283f10e6 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 11 Mar 2019 14:35:51 +0100 Subject: [PATCH 253/262] fix(runtime-c-api) Fix the `imports` length. `imports` contains `func_import`, `global_import`, `memory_import` and `table_import`, so 4 items. This patch updates the length of `imports` when calling the `wasmer_instantiate` function. --- lib/runtime-c-api/tests/test-imports.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/runtime-c-api/tests/test-imports.c b/lib/runtime-c-api/tests/test-imports.c index cecb9ec94..9c0c45467 100644 --- a/lib/runtime-c-api/tests/test-imports.c +++ b/lib/runtime-c-api/tests/test-imports.c @@ -127,7 +127,7 @@ int main() // Creates a WebAssembly Instance from wasm bytes and imports wasmer_instance_t *instance = NULL; - wasmer_result_t compile_result = wasmer_instantiate(&instance, bytes, len, imports, 3); + wasmer_result_t compile_result = wasmer_instantiate(&instance, bytes, len, imports, 4); printf("Compile result: %d\n", compile_result); if (compile_result != WASMER_OK) { From a11d45413057d34d1ddd00ea7ebd07a6d3d7411d Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 11 Mar 2019 16:50:18 +0100 Subject: [PATCH 254/262] feat(runtime-c-api) Add an API to update `vm::Ctx.data`. This patch adds 2 functions for the runtime C API, respectively `wasmer_instance_context_data_set` and `wasmer_instance_context_data_get`. The goal is to modify the `vm::Ctx.data` field in the `runtime-core` library. This is required to pass dynamic data to imported functions for instance. --- lib/runtime-c-api/src/lib.rs | 20 ++++++++++++++++++++ lib/runtime-c-api/wasmer.h | 15 +++++++++++++-- lib/runtime-c-api/wasmer.hh | 11 +++++++++-- 3 files changed, 42 insertions(+), 4 deletions(-) diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index 8055fc445..3d571533d 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -947,6 +947,17 @@ pub unsafe extern "C" fn wasmer_instance_exports( *exports = Box::into_raw(named_exports) as *mut wasmer_exports_t; } +/// Sets the `data` field of the instance context. This context will be +/// passed to all imported function for instance. +#[no_mangle] +pub extern "C" fn wasmer_instance_context_data_set( + instance: *mut wasmer_instance_t, + data_ptr: *mut c_void, +) { + let instance_ref = unsafe { &mut *(instance as *mut Instance) }; + instance_ref.context_mut().data = data_ptr; +} + pub struct NamedExports(Vec); /// Frees the memory for the given exports @@ -1350,6 +1361,15 @@ pub extern "C" fn wasmer_instance_context_memory( memory as *const Memory as *const wasmer_memory_t } +/// Gets the `data` field within the context. +#[no_mangle] +pub extern "C" fn wasmer_instance_context_data_get( + ctx: *const wasmer_instance_context_t, +) -> *mut c_void { + let ctx = unsafe { &*(ctx as *const Ctx) }; + ctx.data +} + /// Gets the start pointer to the bytes within a Memory #[allow(clippy::cast_ptr_alignment)] #[no_mangle] diff --git a/lib/runtime-c-api/wasmer.h b/lib/runtime-c-api/wasmer.h index c9cb61709..43d97ecb8 100644 --- a/lib/runtime-c-api/wasmer.h +++ b/lib/runtime-c-api/wasmer.h @@ -95,11 +95,11 @@ typedef struct { typedef struct { -} wasmer_memory_t; +} wasmer_instance_context_t; typedef struct { -} wasmer_instance_context_t; +} wasmer_memory_t; typedef struct { @@ -382,6 +382,17 @@ wasmer_result_t wasmer_instance_call(wasmer_instance_t *instance, wasmer_value_t *results, int results_len); +/** + * Gets the `data` field within the context. + */ +void *wasmer_instance_context_data_get(const wasmer_instance_context_t *ctx); + +/** + * Sets the `data` field of the instance context. This context will be + * passed to all imported function for instance. + */ +void wasmer_instance_context_data_set(wasmer_instance_t *instance, void *data_ptr); + /** * Gets the memory within the context at the index `memory_idx`. * The index is always 0 until multiple memories are supported. diff --git a/lib/runtime-c-api/wasmer.hh b/lib/runtime-c-api/wasmer.hh index 4578eae49..76c27d46e 100644 --- a/lib/runtime-c-api/wasmer.hh +++ b/lib/runtime-c-api/wasmer.hh @@ -90,11 +90,11 @@ struct wasmer_instance_t { }; -struct wasmer_memory_t { +struct wasmer_instance_context_t { }; -struct wasmer_instance_context_t { +struct wasmer_memory_t { }; @@ -307,6 +307,13 @@ wasmer_result_t wasmer_instance_call(wasmer_instance_t *instance, wasmer_value_t *results, int results_len); +/// Gets the `data` field within the context. +void *wasmer_instance_context_data_get(const wasmer_instance_context_t *ctx); + +/// Sets the `data` field of the instance context. This context will be +/// passed to all imported function for instance. +void wasmer_instance_context_data_set(wasmer_instance_t *instance, void *data_ptr); + /// Gets the memory within the context at the index `memory_idx`. /// The index is always 0 until multiple memories are supported. const wasmer_memory_t *wasmer_instance_context_memory(const wasmer_instance_context_t *ctx, From 170de02dd3acb587ba7c177c5894d91306bccc43 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 11 Mar 2019 17:34:13 +0100 Subject: [PATCH 255/262] test(runtime-c-api) Test the `wasmer_instance_context_data_*` functions. --- lib/runtime-c-api/tests/test-import-function.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/lib/runtime-c-api/tests/test-import-function.c b/lib/runtime-c-api/tests/test-import-function.c index f8214535c..a0027f9fd 100644 --- a/lib/runtime-c-api/tests/test-import-function.c +++ b/lib/runtime-c-api/tests/test-import-function.c @@ -8,6 +8,11 @@ static bool print_str_called = false; static int memory_len = 0; static int ptr_len = 0; static char actual_str[14] = {}; +static int actual_context_data_value = 0; + +typedef struct { + int value; +} context_data; void print_str(wasmer_instance_context_t *ctx, int32_t ptr, int32_t len) { @@ -23,6 +28,8 @@ void print_str(wasmer_instance_context_t *ctx, int32_t ptr, int32_t len) print_str_called = true; memory_len = mem_len; ptr_len = len; + + actual_context_data_value = ((context_data *) wasmer_instance_context_data_get(ctx))->value; } int main() @@ -65,6 +72,11 @@ int main() assert(compile_result == WASMER_OK); + context_data* context_data = malloc(sizeof(context_data)); + int context_data_value = 42; + context_data->value = context_data_value; + wasmer_instance_context_data_set(instance, context_data); + wasmer_value_t params[] = {}; wasmer_value_t results[] = {}; wasmer_result_t call_result = wasmer_instance_call(instance, "hello_wasm", params, 0, results, 0); @@ -82,6 +94,7 @@ int main() assert(memory_len == 17); assert(ptr_len == 13); assert(0 == strcmp(actual_str, "Hello, World!")); + assert(context_data_value == actual_context_data_value); printf("Destroying func\n"); wasmer_import_func_destroy(func); From 675f6817baa48843c895ddc80917394f103f695d Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 11 Mar 2019 17:41:17 +0100 Subject: [PATCH 256/262] test(runtime-c-api) Free allocations. Don't forget to free `context_data` :-). --- lib/runtime-c-api/tests/test-import-function.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/runtime-c-api/tests/test-import-function.c b/lib/runtime-c-api/tests/test-import-function.c index a0027f9fd..ce6736deb 100644 --- a/lib/runtime-c-api/tests/test-import-function.c +++ b/lib/runtime-c-api/tests/test-import-function.c @@ -100,5 +100,6 @@ int main() wasmer_import_func_destroy(func); printf("Destroy instance\n"); wasmer_instance_destroy(instance); + free(context_data); return 0; } From e591cd0607bd8b267d1f724d5f29dbadd28ba223 Mon Sep 17 00:00:00 2001 From: Syrus Date: Mon, 11 Mar 2019 10:03:40 -0700 Subject: [PATCH 257/262] Use wasmerio fork of inkwell --- Cargo.lock | 50 ++++++++++++++++++------------------- lib/llvm-backend/Cargo.toml | 2 +- 2 files changed, 25 insertions(+), 27 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b6a7f4718..a6d14b571 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,5 +1,3 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. [[package]] name = "aho-corasick" version = "0.6.10" @@ -76,7 +74,7 @@ dependencies = [ "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "clang-sys 0.26.4 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -141,7 +139,7 @@ dependencies = [ "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.27 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -385,7 +383,7 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -430,7 +428,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.27 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -511,11 +509,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "inkwell" version = "0.1.0" -source = "git+https://github.com/TheDan64/inkwell?branch=llvm7-0#b8699b0ee594e4162ce850fbedb37892e9cdb7e4" +source = "git+https://github.com/wasmerio/inkwell?branch=llvm7-0#b541566a0ac18a0f52bef54596d00c740c8b0597" dependencies = [ "either 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "enum-methods 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)", - "inkwell_internal_macros 0.1.0 (git+https://github.com/TheDan64/inkwell?branch=llvm7-0)", + "inkwell_internal_macros 0.1.0 (git+https://github.com/wasmerio/inkwell?branch=llvm7-0)", "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "llvm-sys 70.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -523,10 +521,10 @@ dependencies = [ [[package]] name = "inkwell_internal_macros" version = "0.1.0" -source = "git+https://github.com/TheDan64/inkwell?branch=llvm7-0#b8699b0ee594e4162ce850fbedb37892e9cdb7e4" +source = "git+https://github.com/wasmerio/inkwell?branch=llvm7-0#b541566a0ac18a0f52bef54596d00c740c8b0597" dependencies = [ "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.27 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -979,7 +977,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.27 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1027,7 +1025,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.27 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1057,22 +1055,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "structopt" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", - "structopt-derive 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", + "structopt-derive 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "structopt-derive" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.27 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1087,7 +1085,7 @@ dependencies = [ [[package]] name = "syn" -version = "0.15.27" +version = "0.15.29" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1110,7 +1108,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.27 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1284,7 +1282,7 @@ name = "wasmer" version = "0.2.1" dependencies = [ "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "structopt 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", + "structopt 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-clif-backend 0.2.0", "wasmer-emscripten 0.2.1", @@ -1341,7 +1339,7 @@ dependencies = [ "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", "goblin 0.0.20 (registry+https://github.com/rust-lang/crates.io-index)", "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "inkwell 0.1.0 (git+https://github.com/TheDan64/inkwell?branch=llvm7-0)", + "inkwell 0.1.0 (git+https://github.com/wasmerio/inkwell?branch=llvm7-0)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "nix 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1536,7 +1534,7 @@ dependencies = [ "checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c" "checksum either 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c67353c641dc847124ea1902d69bd753dee9bb3beff9aa3662ecf86c971d1fac" "checksum enum-methods 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7798e7da2d4cb0d6d6fc467e8d6b5bf247e9e989f786dde1732d79899c32bb10" -"checksum env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "afb070faf94c85d17d50ca44f6ad076bce18ae92f0037d350947240a36e9d42e" +"checksum env_logger 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b61fa891024a945da30a9581546e8cfaf5602c7b3f4c137a2805cf388f92075a" "checksum errno 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c2a071601ed01b988f896ab14b95e67335d1eeb50190932a1320f7fe3cadc84e" "checksum errno-dragonfly 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "14ca354e36190500e1e1fb267c647932382b54053c50b14970856c0b00a35067" "checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" @@ -1552,8 +1550,8 @@ dependencies = [ "checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" "checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114" "checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d" -"checksum inkwell 0.1.0 (git+https://github.com/TheDan64/inkwell?branch=llvm7-0)" = "" -"checksum inkwell_internal_macros 0.1.0 (git+https://github.com/TheDan64/inkwell?branch=llvm7-0)" = "" +"checksum inkwell 0.1.0 (git+https://github.com/wasmerio/inkwell?branch=llvm7-0)" = "" +"checksum inkwell_internal_macros 0.1.0 (git+https://github.com/wasmerio/inkwell?branch=llvm7-0)" = "" "checksum itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358" "checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" @@ -1619,10 +1617,10 @@ dependencies = [ "checksum smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c4488ae950c49d403731982257768f48fada354a5203fe81f9bb6f43ca9002be" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" -"checksum structopt 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "670ad348dc73012fcf78c71f06f9d942232cdd4c859d4b6975e27836c3efc0c3" -"checksum structopt-derive 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "ef98172b1a00b0bec738508d3726540edcbd186d50dfd326f2b1febbb3559f04" +"checksum structopt 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)" = "3d0760c312538987d363c36c42339b55f5ee176ea8808bbe4543d484a291c8d1" +"checksum structopt-derive 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)" = "528aeb7351d042e6ffbc2a6fb76a86f9b622fdf7c25932798e7a82cb03bc94c6" "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" -"checksum syn 0.15.27 (registry+https://github.com/rust-lang/crates.io-index)" = "525bd55255f03c816e5d7f615587bd13030c7103354fadb104993dcee6a788ec" +"checksum syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)" = "1825685f977249735d510a242a6727b46efe914bb67e38d30c071b1b72b1d5c2" "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" "checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" "checksum target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4af5e2227f0b887d591d3724b796a96eff04226104d872f5b3883fcd427d64b9" diff --git a/lib/llvm-backend/Cargo.toml b/lib/llvm-backend/Cargo.toml index 646bbd157..8be5aaa32 100644 --- a/lib/llvm-backend/Cargo.toml +++ b/lib/llvm-backend/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" [dependencies] wasmer-runtime-core = { path = "../runtime-core", version = "0.2.1" } -inkwell = { git = "https://github.com/TheDan64/inkwell", branch = "llvm7-0" } +inkwell = { git = "https://github.com/wasmerio/inkwell", branch = "llvm7-0" } wasmparser = "0.28.0" hashbrown = "0.1.8" smallvec = "0.6.8" From a390a28384826166bade832a04685119ad2818e6 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Tue, 12 Mar 2019 08:58:22 +0100 Subject: [PATCH 258/262] fix(runtime-c-api) Fix Clippy errors. --- lib/runtime-c-api/src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index 3d571533d..b63e69d9c 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -949,6 +949,7 @@ pub unsafe extern "C" fn wasmer_instance_exports( /// Sets the `data` field of the instance context. This context will be /// passed to all imported function for instance. +#[allow(clippy::cast_ptr_alignment)] #[no_mangle] pub extern "C" fn wasmer_instance_context_data_set( instance: *mut wasmer_instance_t, @@ -1362,6 +1363,7 @@ pub extern "C" fn wasmer_instance_context_memory( } /// Gets the `data` field within the context. +#[allow(clippy::cast_ptr_alignment)] #[no_mangle] pub extern "C" fn wasmer_instance_context_data_get( ctx: *const wasmer_instance_context_t, From 6e62ea7cfb9a5f51bd393a4ddec224ce08d0da0f Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Tue, 12 Mar 2019 09:51:54 +0100 Subject: [PATCH 259/262] fix(runtime-core) Remove unused imports. This patch removes unused imports as reported by `rustc` as warnings. --- lib/runtime-core/src/error.rs | 7 ++----- lib/runtime-core/src/typed_func.rs | 2 +- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/lib/runtime-core/src/error.rs b/lib/runtime-core/src/error.rs index 45c627aec..9e99c2833 100644 --- a/lib/runtime-core/src/error.rs +++ b/lib/runtime-core/src/error.rs @@ -1,9 +1,6 @@ -use crate::types::{ - FuncSig, GlobalDescriptor, MemoryDescriptor, MemoryIndex, TableDescriptor, TableIndex, Type, - Value, -}; +use crate::types::{FuncSig, GlobalDescriptor, MemoryDescriptor, TableDescriptor, Type, Value}; use core::borrow::Borrow; -use std::{any::Any, sync::Arc}; +use std::any::Any; pub type Result = std::result::Result; pub type CompileResult = std::result::Result; diff --git a/lib/runtime-core/src/typed_func.rs b/lib/runtime-core/src/typed_func.rs index 6e2a4d26c..4191f347e 100644 --- a/lib/runtime-core/src/typed_func.rs +++ b/lib/runtime-core/src/typed_func.rs @@ -6,7 +6,7 @@ use crate::{ types::{FuncSig, Type, WasmExternType}, vm::Ctx, }; -use std::{any::Any, cell::UnsafeCell, fmt, marker::PhantomData, mem, panic, ptr, sync::Arc}; +use std::{any::Any, cell::UnsafeCell, marker::PhantomData, mem, panic, ptr, sync::Arc}; thread_local! { pub static EARLY_TRAPPER: UnsafeCell>> = UnsafeCell::new(None); From 2c8fc5238d64c156b649e0be99c5297e2e77982e Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Tue, 12 Mar 2019 10:03:55 +0100 Subject: [PATCH 260/262] fix(clif-backend) Remove unused imports. This patch removes unused imports reported by `rustc` as warnings. --- lib/clif-backend/src/signal/unix.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/lib/clif-backend/src/signal/unix.rs b/lib/clif-backend/src/signal/unix.rs index 86cc53638..feaf4e2e2 100644 --- a/lib/clif-backend/src/signal/unix.rs +++ b/lib/clif-backend/src/signal/unix.rs @@ -18,11 +18,7 @@ use nix::sys::signal::{ use std::cell::{Cell, UnsafeCell}; use std::ptr; use std::sync::Once; -use wasmer_runtime_core::{ - error::{RuntimeError, RuntimeResult}, - structures::TypedIndex, - types::{MemoryIndex, TableIndex}, -}; +use wasmer_runtime_core::error::{RuntimeError, RuntimeResult}; extern "C" fn signal_trap_handler( signum: ::nix::libc::c_int, From ef69f6151c686805b1065e46341215e90209d0a1 Mon Sep 17 00:00:00 2001 From: Syrus Date: Tue, 12 Mar 2019 10:07:23 -0700 Subject: [PATCH 261/262] Run test-and-build always on master --- .circleci/config.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 1ca2ddcb1..1a462b680 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -325,14 +325,12 @@ workflows: filters: branches: only: - - trying - - staging + - master - test-and-build-macos: filters: branches: only: - - trying - - staging + - master - test-rust-nightly: filters: branches: From 20d1023abeff06106d09fcf359d2c00633809049 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Tue, 12 Mar 2019 22:00:33 +0100 Subject: [PATCH 262/262] fix(emscripten) Various warning fixes and cleanups (#266) * fix(emscripten) Remove unused imports. This patch removes unused imports reported by `rustc` as warnings. * fix(emscripten) Allow unreachable patterns in `_clock_gettime`. The compiler thinks `CLOCK_MONOTONIC_COARSE` is unreachable, which is not always the case. Add an attribute to allow unreachable patterns to remove the warning. * fix(emscripten) Rename unused variables. This patch renames various unused variables by appending an underscore to them. * fix(emscripten) Declare `table` as immutable. The `table` variable in `EmscriptenGlobals::new` was declared as mutable, but it's never mutated. * fix(emscripten) Remove an unnecessary `unsafe` block. * fix(emscripten) Remove duplicate definition of `SO_NOSIGPIPE`. The `SO_NOSIGPIPE` constant is defined in `syscalls/mod.rs` and `syscalls/unix.rs`. It's never used in the first case. We can safely remove it in this file, and keep it in `unix.rs`. * fix(emscripten) `read_string_from_wasm` is used only on Windows. Mark `read_string_from_wasm` as possible deadcode, since it's used only on Windows. * fix(emscripten) Remove `DYNAMICTOP_PTR_DIFF`, `stacktop`, `stack_max`, `dynamic_base` and `dynamic_ptr`. Four functions and one constant are used together but never used inside or outside this file. They are deadcode. * fix(emscripten) Remove `infinity` and `nan` fields of `EmscriptenGlobalsData`. Those fields are never used. * fix(emscripten) Allow non snake case in `emscripten_target.rs`. Many functions in this file don't follow the snake case style for Rust function names. The reason is that we want the names to match the emscripten symbol names; even if a mapping is done in `lib.rs`, it's easier to get the same names. * fix(emscripten) Rename `STATIC_TOP` to `static_top`. This variable is not a constant. --- lib/emscripten/src/emscripten_target.rs | 104 +++++++++++++----------- lib/emscripten/src/env/mod.rs | 4 +- lib/emscripten/src/errno.rs | 4 +- lib/emscripten/src/io/unix.rs | 2 +- lib/emscripten/src/lib.rs | 37 ++------- lib/emscripten/src/lock.rs | 8 +- lib/emscripten/src/memory.rs | 13 +-- lib/emscripten/src/nullfunc.rs | 44 +++++----- lib/emscripten/src/process.rs | 2 +- lib/emscripten/src/signal.rs | 8 +- lib/emscripten/src/syscalls/mod.rs | 91 ++++++++------------- lib/emscripten/src/syscalls/unix.rs | 52 ++++++------ lib/emscripten/src/syscalls/windows.rs | 1 - lib/emscripten/src/time.rs | 12 +-- lib/emscripten/src/utils.rs | 5 +- 15 files changed, 177 insertions(+), 210 deletions(-) diff --git a/lib/emscripten/src/emscripten_target.rs b/lib/emscripten/src/emscripten_target.rs index e850757f6..4508f4f54 100644 --- a/lib/emscripten/src/emscripten_target.rs +++ b/lib/emscripten/src/emscripten_target.rs @@ -1,14 +1,16 @@ +#![allow(non_snake_case)] + use crate::env::get_emscripten_data; use wasmer_runtime_core::vm::Ctx; -pub fn setTempRet0(ctx: &mut Ctx, a: i32) { +pub fn setTempRet0(_ctx: &mut Ctx, _a: i32) { debug!("emscripten::setTempRet0"); } -pub fn getTempRet0(ctx: &mut Ctx) -> i32 { +pub fn getTempRet0(_ctx: &mut Ctx) -> i32 { debug!("emscripten::getTempRet0"); 0 } -pub fn nullFunc_ji(ctx: &mut Ctx, a: i32) { +pub fn nullFunc_ji(_ctx: &mut Ctx, _a: i32) { debug!("emscripten::nullFunc_ji"); } pub fn invoke_i(ctx: &mut Ctx, index: i32) -> i32 { @@ -83,158 +85,166 @@ pub fn invoke_viiii(ctx: &mut Ctx, index: i32, a1: i32, a2: i32, a3: i32, a4: i3 panic!("dyn_call_viiii is set to None"); } } -pub fn __Unwind_Backtrace(ctx: &mut Ctx, a: i32, b: i32) -> i32 { +pub fn __Unwind_Backtrace(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 { debug!("emscripten::__Unwind_Backtrace"); 0 } -pub fn __Unwind_FindEnclosingFunction(ctx: &mut Ctx, a: i32) -> i32 { +pub fn __Unwind_FindEnclosingFunction(_ctx: &mut Ctx, _a: i32) -> i32 { debug!("emscripten::__Unwind_FindEnclosingFunction"); 0 } -pub fn __Unwind_GetIPInfo(ctx: &mut Ctx, a: i32, b: i32) -> i32 { +pub fn __Unwind_GetIPInfo(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 { debug!("emscripten::__Unwind_GetIPInfo"); 0 } -pub fn ___cxa_find_matching_catch_2(ctx: &mut Ctx) -> i32 { +pub fn ___cxa_find_matching_catch_2(_ctx: &mut Ctx) -> i32 { debug!("emscripten::___cxa_find_matching_catch_2"); 0 } -pub fn ___cxa_find_matching_catch_3(ctx: &mut Ctx, a: i32) -> i32 { +pub fn ___cxa_find_matching_catch_3(_ctx: &mut Ctx, _a: i32) -> i32 { debug!("emscripten::___cxa_find_matching_catch_3"); 0 } -pub fn ___cxa_free_exception(ctx: &mut Ctx, a: i32) { +pub fn ___cxa_free_exception(_ctx: &mut Ctx, _a: i32) { debug!("emscripten::___cxa_free_exception"); } -pub fn ___resumeException(ctx: &mut Ctx, a: i32) { +pub fn ___resumeException(_ctx: &mut Ctx, _a: i32) { debug!("emscripten::___resumeException"); } -pub fn _dladdr(ctx: &mut Ctx, a: i32, b: i32) -> i32 { +pub fn _dladdr(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 { debug!("emscripten::_dladdr"); 0 } -pub fn _pthread_cond_destroy(ctx: &mut Ctx, a: i32) -> i32 { +pub fn _pthread_cond_destroy(_ctx: &mut Ctx, _a: i32) -> i32 { debug!("emscripten::_pthread_cond_destroy"); 0 } -pub fn _pthread_cond_init(ctx: &mut Ctx, a: i32, b: i32) -> i32 { +pub fn _pthread_cond_init(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 { debug!("emscripten::_pthread_cond_init"); 0 } -pub fn _pthread_cond_signal(ctx: &mut Ctx, a: i32) -> i32 { +pub fn _pthread_cond_signal(_ctx: &mut Ctx, _a: i32) -> i32 { debug!("emscripten::_pthread_cond_signal"); 0 } -pub fn _pthread_cond_wait(ctx: &mut Ctx, a: i32, b: i32) -> i32 { +pub fn _pthread_cond_wait(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 { debug!("emscripten::_pthread_cond_wait"); 0 } -pub fn _pthread_condattr_destroy(ctx: &mut Ctx, a: i32) -> i32 { +pub fn _pthread_condattr_destroy(_ctx: &mut Ctx, _a: i32) -> i32 { debug!("emscripten::_pthread_condattr_destroy"); 0 } -pub fn _pthread_condattr_init(ctx: &mut Ctx, a: i32) -> i32 { +pub fn _pthread_condattr_init(_ctx: &mut Ctx, _a: i32) -> i32 { debug!("emscripten::_pthread_condattr_init"); 0 } -pub fn _pthread_condattr_setclock(ctx: &mut Ctx, a: i32, b: i32) -> i32 { +pub fn _pthread_condattr_setclock(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 { debug!("emscripten::_pthread_condattr_setclock"); 0 } -pub fn _pthread_mutex_destroy(ctx: &mut Ctx, a: i32) -> i32 { +pub fn _pthread_mutex_destroy(_ctx: &mut Ctx, _a: i32) -> i32 { debug!("emscripten::_pthread_mutex_destroy"); 0 } -pub fn _pthread_mutex_init(ctx: &mut Ctx, a: i32, b: i32) -> i32 { +pub fn _pthread_mutex_init(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 { debug!("emscripten::_pthread_mutex_init"); 0 } -pub fn _pthread_mutexattr_destroy(ctx: &mut Ctx, a: i32) -> i32 { +pub fn _pthread_mutexattr_destroy(_ctx: &mut Ctx, _a: i32) -> i32 { debug!("emscripten::_pthread_mutexattr_destroy"); 0 } -pub fn _pthread_mutexattr_init(ctx: &mut Ctx, a: i32) -> i32 { +pub fn _pthread_mutexattr_init(_ctx: &mut Ctx, _a: i32) -> i32 { debug!("emscripten::_pthread_mutexattr_init"); 0 } -pub fn _pthread_mutexattr_settype(ctx: &mut Ctx, a: i32, b: i32) -> i32 { +pub fn _pthread_mutexattr_settype(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 { debug!("emscripten::_pthread_mutexattr_settype"); 0 } -pub fn _pthread_rwlock_rdlock(ctx: &mut Ctx, a: i32) -> i32 { +pub fn _pthread_rwlock_rdlock(_ctx: &mut Ctx, _a: i32) -> i32 { debug!("emscripten::_pthread_rwlock_rdlock"); 0 } -pub fn _pthread_rwlock_unlock(ctx: &mut Ctx, a: i32) -> i32 { +pub fn _pthread_rwlock_unlock(_ctx: &mut Ctx, _a: i32) -> i32 { debug!("emscripten::_pthread_rwlock_unlock"); 0 } -pub fn ___gxx_personality_v0(ctx: &mut Ctx, a: i32, b: i32, c: i32, d: i32, e: i32, f: i32) -> i32 { +pub fn ___gxx_personality_v0( + _ctx: &mut Ctx, + _a: i32, + _b: i32, + _c: i32, + _d: i32, + _e: i32, + _f: i32, +) -> i32 { debug!("emscripten::___gxx_personality_v0"); 0 } // round 2 -pub fn nullFunc_dii(ctx: &mut Ctx, index: i32) { +pub fn nullFunc_dii(_ctx: &mut Ctx, _index: i32) { debug!("emscripten::nullFunc_dii"); } -pub fn nullFunc_diiii(ctx: &mut Ctx, index: i32) { +pub fn nullFunc_diiii(_ctx: &mut Ctx, _index: i32) { debug!("emscripten::nullFunc_diiii"); } -pub fn nullFunc_iiji(ctx: &mut Ctx, index: i32) { +pub fn nullFunc_iiji(_ctx: &mut Ctx, _index: i32) { debug!("emscripten::nullFunc_iiji"); } -pub fn nullFunc_j(ctx: &mut Ctx, index: i32) { +pub fn nullFunc_j(_ctx: &mut Ctx, _index: i32) { debug!("emscripten::nullFunc_j"); } -pub fn nullFunc_jij(ctx: &mut Ctx, index: i32) { +pub fn nullFunc_jij(_ctx: &mut Ctx, _index: i32) { debug!("emscripten::nullFunc_jij"); } -pub fn nullFunc_jjj(ctx: &mut Ctx, index: i32) { +pub fn nullFunc_jjj(_ctx: &mut Ctx, _index: i32) { debug!("emscripten::nullFunc_jjj"); } -pub fn nullFunc_vd(ctx: &mut Ctx, index: i32) { +pub fn nullFunc_vd(_ctx: &mut Ctx, _index: i32) { debug!("emscripten::nullFunc_vd"); } -pub fn nullFunc_viiiiiii(ctx: &mut Ctx, index: i32) { +pub fn nullFunc_viiiiiii(_ctx: &mut Ctx, _index: i32) { debug!("emscripten::nullFunc_viiiiiii"); } -pub fn nullFunc_viiiiiiii(ctx: &mut Ctx, index: i32) { +pub fn nullFunc_viiiiiiii(_ctx: &mut Ctx, _index: i32) { debug!("emscripten::nullFunc_viiiiiiii"); } -pub fn nullFunc_viiiiiiiii(ctx: &mut Ctx, index: i32) { +pub fn nullFunc_viiiiiiiii(_ctx: &mut Ctx, _index: i32) { debug!("emscripten::nullFunc_viiiiiiiii"); } -pub fn nullFunc_viiij(ctx: &mut Ctx, index: i32) { +pub fn nullFunc_viiij(_ctx: &mut Ctx, _index: i32) { debug!("emscripten::nullFunc_viiij"); } -pub fn nullFunc_viiijiiii(ctx: &mut Ctx, index: i32) { +pub fn nullFunc_viiijiiii(_ctx: &mut Ctx, _index: i32) { debug!("emscripten::nullFunc_viiijiiii"); } -pub fn nullFunc_viiijiiiiii(ctx: &mut Ctx, index: i32) { +pub fn nullFunc_viiijiiiiii(_ctx: &mut Ctx, _index: i32) { debug!("emscripten::nullFunc_viiijiiiiii"); } -pub fn nullFunc_viij(ctx: &mut Ctx, index: i32) { +pub fn nullFunc_viij(_ctx: &mut Ctx, _index: i32) { debug!("emscripten::nullFunc_viij"); } -pub fn nullFunc_viiji(ctx: &mut Ctx, index: i32) { +pub fn nullFunc_viiji(_ctx: &mut Ctx, _index: i32) { debug!("emscripten::nullFunc_viiji"); } -pub fn nullFunc_viijiii(ctx: &mut Ctx, index: i32) { +pub fn nullFunc_viijiii(_ctx: &mut Ctx, _index: i32) { debug!("emscripten::nullFunc_viijiii"); } -pub fn nullFunc_viijj(ctx: &mut Ctx, index: i32) { +pub fn nullFunc_viijj(_ctx: &mut Ctx, _index: i32) { debug!("emscripten::nullFunc_viijj"); } -pub fn nullFunc_vij(ctx: &mut Ctx, index: i32) { +pub fn nullFunc_vij(_ctx: &mut Ctx, _index: i32) { debug!("emscripten::nullFunc_vij"); } -pub fn nullFunc_viji(ctx: &mut Ctx, index: i32) { +pub fn nullFunc_viji(_ctx: &mut Ctx, _index: i32) { debug!("emscripten::nullFunc_viji"); } -pub fn nullFunc_vijiii(ctx: &mut Ctx, index: i32) { +pub fn nullFunc_vijiii(_ctx: &mut Ctx, _index: i32) { debug!("emscripten::nullFunc_vijiii"); } -pub fn nullFunc_vijj(ctx: &mut Ctx, index: i32) { +pub fn nullFunc_vijj(_ctx: &mut Ctx, _index: i32) { debug!("emscripten::nullFunc_vijj"); } pub fn invoke_dii(ctx: &mut Ctx, index: i32, a1: i32, a2: i32) -> f64 { diff --git a/lib/emscripten/src/env/mod.rs b/lib/emscripten/src/env/mod.rs index 89f55fd09..662d4ba94 100644 --- a/lib/emscripten/src/env/mod.rs +++ b/lib/emscripten/src/env/mod.rs @@ -70,8 +70,8 @@ pub fn ___build_environment(ctx: &mut Ctx, environ: c_int) { // }; } -pub fn ___assert_fail(_ctx: &mut Ctx, a: c_int, b: c_int, c: c_int, d: c_int) { - debug!("emscripten::___assert_fail {} {} {} {}", a, b, c, d); +pub fn ___assert_fail(_ctx: &mut Ctx, _a: c_int, _b: c_int, _c: c_int, _d: c_int) { + debug!("emscripten::___assert_fail {} {} {} {}", _a, _b, _c, _d); // TODO: Implement like emscripten expects regarding memory/page size // TODO raise an error } diff --git a/lib/emscripten/src/errno.rs b/lib/emscripten/src/errno.rs index 06267e210..ff1d09b7f 100644 --- a/lib/emscripten/src/errno.rs +++ b/lib/emscripten/src/errno.rs @@ -1,8 +1,8 @@ // use std::collections::HashMap; use wasmer_runtime_core::vm::Ctx; -pub fn ___seterrno(_ctx: &mut Ctx, value: i32) { - debug!("emscripten::___seterrno {}", value); +pub fn ___seterrno(_ctx: &mut Ctx, _value: i32) { + debug!("emscripten::___seterrno {}", _value); // TODO: Incomplete impl eprintln!("failed to set errno!"); // value diff --git a/lib/emscripten/src/io/unix.rs b/lib/emscripten/src/io/unix.rs index 38324ac1e..da3ddeff9 100644 --- a/lib/emscripten/src/io/unix.rs +++ b/lib/emscripten/src/io/unix.rs @@ -3,7 +3,7 @@ use libc::printf as _printf; use wasmer_runtime_core::vm::Ctx; /// putchar -pub fn putchar(ctx: &mut Ctx, chr: i32) { +pub fn putchar(_ctx: &mut Ctx, chr: i32) { unsafe { libc::putchar(chr) }; } diff --git a/lib/emscripten/src/lib.rs b/lib/emscripten/src/lib.rs index 66d9b75ff..1cde93620 100644 --- a/lib/emscripten/src/lib.rs +++ b/lib/emscripten/src/lib.rs @@ -56,8 +56,6 @@ pub use self::utils::{ // TODO: Magic number - how is this calculated? const TOTAL_STACK: u32 = 5_242_880; -// TODO: Magic number - how is this calculated? -const DYNAMICTOP_PTR_DIFF: u32 = 1088; // TODO: make this variable const STATIC_BUMP: u32 = 215_536; @@ -73,22 +71,6 @@ lazy_static! { const GLOBAL_BASE: u32 = 1024; const STATIC_BASE: u32 = GLOBAL_BASE; -fn stacktop(static_bump: u32) -> u32 { - align_memory(dynamictop_ptr(static_bump) + 4) -} - -fn stack_max(static_bump: u32) -> u32 { - stacktop(static_bump) + TOTAL_STACK -} - -fn dynamic_base(static_bump: u32) -> u32 { - align_memory(stack_max(static_bump)) -} - -fn dynamictop_ptr(static_bump: u32) -> u32 { - static_bump + DYNAMICTOP_PTR_DIFF -} - pub struct EmscriptenData<'a> { pub malloc: Func<'a, u32, u32>, pub free: Func<'a, u32>, @@ -311,10 +293,6 @@ pub struct EmscriptenGlobalsData { table_base: u32, temp_double_ptr: u32, use_old_abort_on_cannot_grow_memory: bool, - - // Global namespace - infinity: f64, - nan: f64, } pub struct EmscriptenGlobals { @@ -366,22 +344,22 @@ impl EmscriptenGlobals { minimum: table_min, maximum: table_max, }; - let mut table = Table::new(table_type).unwrap(); + let table = Table::new(table_type).unwrap(); let data = { let static_bump = STATIC_BUMP; - let mut STATIC_TOP = STATIC_BASE + static_bump; + let mut static_top = STATIC_BASE + static_bump; let memory_base = STATIC_BASE; let table_base = 0; - let temp_double_ptr = STATIC_TOP; - STATIC_TOP += 16; + let temp_double_ptr = static_top; + static_top += 16; - let dynamictop_ptr = static_alloc(&mut STATIC_TOP, 4); + let dynamictop_ptr = static_alloc(&mut static_top, 4); - let stacktop = align_memory(STATIC_TOP); + let stacktop = align_memory(static_top); let stack_max = stacktop + TOTAL_STACK; EmscriptenGlobalsData { @@ -393,9 +371,6 @@ impl EmscriptenGlobals { table_base, temp_double_ptr, use_old_abort_on_cannot_grow_memory, - - infinity: std::f64::INFINITY, - nan: std::f64::NAN, } }; diff --git a/lib/emscripten/src/lock.rs b/lib/emscripten/src/lock.rs index 45f09581f..badb47a1b 100644 --- a/lib/emscripten/src/lock.rs +++ b/lib/emscripten/src/lock.rs @@ -2,13 +2,13 @@ use libc::c_int; use wasmer_runtime_core::vm::Ctx; // NOTE: Not implemented by Emscripten -pub fn ___lock(_ctx: &mut Ctx, what: c_int) { - debug!("emscripten::___lock {}", what); +pub fn ___lock(_ctx: &mut Ctx, _what: c_int) { + debug!("emscripten::___lock {}", _what); } // NOTE: Not implemented by Emscripten -pub fn ___unlock(_ctx: &mut Ctx, what: c_int) { - debug!("emscripten::___unlock {}", what); +pub fn ___unlock(_ctx: &mut Ctx, _what: c_int) { + debug!("emscripten::___unlock {}", _what); } // NOTE: Not implemented by Emscripten diff --git a/lib/emscripten/src/memory.rs b/lib/emscripten/src/memory.rs index dcd98c317..02877a011 100644 --- a/lib/emscripten/src/memory.rs +++ b/lib/emscripten/src/memory.rs @@ -17,15 +17,15 @@ pub fn _emscripten_memcpy_big(ctx: &mut Ctx, dest: u32, src: u32, len: u32) -> u } /// emscripten: _emscripten_get_heap_size -pub fn _emscripten_get_heap_size(ctx: &mut Ctx) -> u32 { +pub fn _emscripten_get_heap_size(_ctx: &mut Ctx) -> u32 { debug!("emscripten::_emscripten_get_heap_size",); // TODO: Fix implementation 16_777_216 } /// emscripten: _emscripten_resize_heap -pub fn _emscripten_resize_heap(ctx: &mut Ctx, requested_size: u32) -> u32 { - debug!("emscripten::_emscripten_resize_heap {}", requested_size); +pub fn _emscripten_resize_heap(_ctx: &mut Ctx, _requested_size: u32) -> u32 { + debug!("emscripten::_emscripten_resize_heap {}", _requested_size); // TODO: Fix implementation 0 } @@ -47,8 +47,11 @@ pub fn enlarge_memory(_ctx: &mut Ctx) -> u32 { } /// emscripten: abortOnCannotGrowMemory -pub fn abort_on_cannot_grow_memory(ctx: &mut Ctx, requested_size: u32) -> u32 { - debug!("emscripten::abort_on_cannot_grow_memory {}", requested_size); +pub fn abort_on_cannot_grow_memory(ctx: &mut Ctx, _requested_size: u32) -> u32 { + debug!( + "emscripten::abort_on_cannot_grow_memory {}", + _requested_size + ); abort_with_message(ctx, "Cannot enlarge memory arrays!"); 0 } diff --git a/lib/emscripten/src/nullfunc.rs b/lib/emscripten/src/nullfunc.rs index 7fb44ab11..8f289599b 100644 --- a/lib/emscripten/src/nullfunc.rs +++ b/lib/emscripten/src/nullfunc.rs @@ -1,58 +1,58 @@ use super::process::abort_with_message; use wasmer_runtime_core::vm::Ctx; -pub fn nullfunc_i(ctx: &mut Ctx, x: u32) { - debug!("emscripten::nullfunc_i {}", x); +pub fn nullfunc_i(ctx: &mut Ctx, _x: u32) { + debug!("emscripten::nullfunc_i {}", _x); abort_with_message(ctx, "Invalid function pointer called with signature 'i'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)"); } -pub fn nullfunc_ii(ctx: &mut Ctx, x: u32) { - debug!("emscripten::nullfunc_ii {}", x); +pub fn nullfunc_ii(ctx: &mut Ctx, _x: u32) { + debug!("emscripten::nullfunc_ii {}", _x); abort_with_message(ctx, "Invalid function pointer called with signature 'ii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)"); } -pub fn nullfunc_iii(ctx: &mut Ctx, x: u32) { - debug!("emscripten::nullfunc_iii {}", x); +pub fn nullfunc_iii(ctx: &mut Ctx, _x: u32) { + debug!("emscripten::nullfunc_iii {}", _x); abort_with_message(ctx, "Invalid function pointer called with signature 'iii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)"); } -pub fn nullfunc_iiii(ctx: &mut Ctx, x: u32) { - debug!("emscripten::nullfunc_iiii {}", x); +pub fn nullfunc_iiii(ctx: &mut Ctx, _x: u32) { + debug!("emscripten::nullfunc_iiii {}", _x); abort_with_message(ctx, "Invalid function pointer called with signature 'iiii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)"); } -pub fn nullfunc_iiiii(ctx: &mut Ctx, x: u32) { - debug!("emscripten::nullfunc_iiiii {}", x); +pub fn nullfunc_iiiii(ctx: &mut Ctx, _x: u32) { + debug!("emscripten::nullfunc_iiiii {}", _x); abort_with_message(ctx, "Invalid function pointer called with signature 'iiiii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)"); } -pub fn nullfunc_iiiiii(ctx: &mut Ctx, x: u32) { - debug!("emscripten::nullfunc_iiiiii {}", x); +pub fn nullfunc_iiiiii(ctx: &mut Ctx, _x: u32) { + debug!("emscripten::nullfunc_iiiiii {}", _x); abort_with_message(ctx, "Invalid function pointer called with signature 'iiiiii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)"); } -pub fn nullfunc_v(ctx: &mut Ctx, x: u32) { - debug!("emscripten::nullfunc_v {}", x); +pub fn nullfunc_v(ctx: &mut Ctx, _x: u32) { + debug!("emscripten::nullfunc_v {}", _x); abort_with_message(ctx, "Invalid function pointer called with signature 'v'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)"); } -pub fn nullfunc_vi(ctx: &mut Ctx, x: u32) { - debug!("emscripten::nullfunc_vi {}", x); +pub fn nullfunc_vi(ctx: &mut Ctx, _x: u32) { + debug!("emscripten::nullfunc_vi {}", _x); abort_with_message(ctx, "Invalid function pointer called with signature 'vi'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)"); } -pub fn nullfunc_vii(ctx: &mut Ctx, x: u32) { - debug!("emscripten::nullfunc_vii {}", x); +pub fn nullfunc_vii(ctx: &mut Ctx, _x: u32) { + debug!("emscripten::nullfunc_vii {}", _x); abort_with_message(ctx, "Invalid function pointer called with signature 'vii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)"); } -pub fn nullfunc_viii(ctx: &mut Ctx, x: u32) { - debug!("emscripten::nullfunc_viii {}", x); +pub fn nullfunc_viii(ctx: &mut Ctx, _x: u32) { + debug!("emscripten::nullfunc_viii {}", _x); abort_with_message(ctx, "Invalid function pointer called with signature 'viii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)"); } -pub fn nullfunc_viiii(ctx: &mut Ctx, x: u32) { - debug!("emscripten::nullfunc_viiii {}", x); +pub fn nullfunc_viiii(ctx: &mut Ctx, _x: u32) { + debug!("emscripten::nullfunc_viiii {}", _x); abort_with_message(ctx, "Invalid function pointer called with signature 'viiii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)"); } diff --git a/lib/emscripten/src/process.rs b/lib/emscripten/src/process.rs index 8d1dddb48..2dbf90ca5 100644 --- a/lib/emscripten/src/process.rs +++ b/lib/emscripten/src/process.rs @@ -98,7 +98,7 @@ pub fn _sem_wait(_ctx: &mut Ctx, _one: i32) -> i32 { } #[allow(clippy::cast_ptr_alignment)] -pub fn _getgrent(ctx: &mut Ctx) -> c_int { +pub fn _getgrent(_ctx: &mut Ctx) -> c_int { debug!("emscripten::_getgrent"); -1 } diff --git a/lib/emscripten/src/signal.rs b/lib/emscripten/src/signal.rs index f7657630b..37c3ed8df 100644 --- a/lib/emscripten/src/signal.rs +++ b/lib/emscripten/src/signal.rs @@ -11,8 +11,8 @@ pub fn _sigemptyset(ctx: &mut Ctx, set: u32) -> i32 { 0 } -pub fn _sigaction(_ctx: &mut Ctx, signum: u32, act: u32, oldact: u32) -> i32 { - debug!("emscripten::_sigaction {}, {}, {}", signum, act, oldact); +pub fn _sigaction(_ctx: &mut Ctx, _signum: u32, _act: u32, _oldact: u32) -> i32 { + debug!("emscripten::_sigaction {}, {}, {}", _signum, _act, _oldact); 0 } @@ -36,7 +36,7 @@ pub fn _sigprocmask(_ctx: &mut Ctx, _one: i32, _two: i32, _three: i32) -> i32 { 0 } -pub fn _signal(_ctx: &mut Ctx, sig: u32, _two: i32) -> i32 { - debug!("emscripten::_signal ({})", sig); +pub fn _signal(_ctx: &mut Ctx, _sig: u32, _two: i32) -> i32 { + debug!("emscripten::_signal ({})", _sig); 0 } diff --git a/lib/emscripten/src/syscalls/mod.rs b/lib/emscripten/src/syscalls/mod.rs index 39bd2750d..806ea8187 100644 --- a/lib/emscripten/src/syscalls/mod.rs +++ b/lib/emscripten/src/syscalls/mod.rs @@ -42,24 +42,10 @@ use wasmer_runtime_core::vm::Ctx; use super::env; use std::cell::Cell; use std::slice; -// use std::sys::fd::FileDesc; - -// Another conditional constant for name resolution: Macos et iOS use -// SO_NOSIGPIPE as a setsockopt flag to disable SIGPIPE emission on socket. -// Other platforms do otherwise. -use crate::env::get_emscripten_data; -use crate::utils::copy_cstr_into_wasm; -use crate::utils::read_string_from_wasm; -#[cfg(target_os = "darwin")] -use libc::SO_NOSIGPIPE; -use std::ffi::CString; - -#[cfg(not(target_os = "darwin"))] -const SO_NOSIGPIPE: c_int = 0; /// exit -pub fn ___syscall1(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) { - debug!("emscripten::___syscall1 (exit) {}", which); +pub fn ___syscall1(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) { + debug!("emscripten::___syscall1 (exit) {}", _which); let status: i32 = varargs.get(ctx); unsafe { exit(status); @@ -67,9 +53,9 @@ pub fn ___syscall1(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) { } /// read -pub fn ___syscall3(ctx: &mut Ctx, which: i32, mut varargs: VarArgs) -> i32 { +pub fn ___syscall3(ctx: &mut Ctx, _which: i32, mut varargs: VarArgs) -> i32 { // -> ssize_t - debug!("emscripten::___syscall3 (read) {}", which); + debug!("emscripten::___syscall3 (read) {}", _which); let fd: i32 = varargs.get(ctx); let buf: u32 = varargs.get(ctx); let count: i32 = varargs.get(ctx); @@ -81,8 +67,8 @@ pub fn ___syscall3(ctx: &mut Ctx, which: i32, mut varargs: VarArgs) -> i32 { } /// write -pub fn ___syscall4(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int { - debug!("emscripten::___syscall4 (write) {}", which); +pub fn ___syscall4(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { + debug!("emscripten::___syscall4 (write) {}", _which); let fd: i32 = varargs.get(ctx); let buf: u32 = varargs.get(ctx); let count: i32 = varargs.get(ctx); @@ -92,22 +78,22 @@ pub fn ___syscall4(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int { } /// close -pub fn ___syscall6(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int { - debug!("emscripten::___syscall6 (close) {}", which); +pub fn ___syscall6(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { + debug!("emscripten::___syscall6 (close) {}", _which); let fd: i32 = varargs.get(ctx); debug!("fd: {}", fd); unsafe { close(fd) } } // chdir -pub fn ___syscall12(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int { - debug!("emscripten::___syscall12 (chdir) {}", which); +pub fn ___syscall12(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { + debug!("emscripten::___syscall12 (chdir) {}", _which); let path_addr: i32 = varargs.get(ctx); unsafe { let path_ptr = emscripten_memory_pointer!(ctx.memory(0), path_addr) as *const i8; - let path = std::ffi::CStr::from_ptr(path_ptr); + let _path = std::ffi::CStr::from_ptr(path_ptr); let ret = chdir(path_ptr); - debug!("=> path: {:?}, ret: {}", path, ret); + debug!("=> path: {:?}, ret: {}", _path, ret); ret } } @@ -147,7 +133,6 @@ pub fn ___syscall42(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int // offset to a file descriptor, which contains a read end and write end, 2 integers let fd_offset: u32 = varargs.get(ctx); - use std::cell::Cell; let emscripten_memory = ctx.memory(0); // convert the file descriptor into a vec with two slots @@ -174,8 +159,8 @@ pub fn ___syscall60(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { } // dup2 -pub fn ___syscall63(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int { - debug!("emscripten::___syscall63 (dup2) {}", which); +pub fn ___syscall63(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { + debug!("emscripten::___syscall63 (dup2) {}", _which); let src: i32 = varargs.get(ctx); let dst: i32 = varargs.get(ctx); @@ -239,17 +224,17 @@ pub fn ___syscall183(ctx: &mut Ctx, buf_offset: u32, _size: u32) -> u32 { } // mmap2 -pub fn ___syscall192(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int { - debug!("emscripten::___syscall192 (mmap2) {}", which); - let addr: i32 = varargs.get(ctx); +pub fn ___syscall192(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { + debug!("emscripten::___syscall192 (mmap2) {}", _which); + let _addr: i32 = varargs.get(ctx); let len: u32 = varargs.get(ctx); - let prot: i32 = varargs.get(ctx); - let flags: i32 = varargs.get(ctx); + let _prot: i32 = varargs.get(ctx); + let _flags: i32 = varargs.get(ctx); let fd: i32 = varargs.get(ctx); - let off: i32 = varargs.get(ctx); + let _off: i32 = varargs.get(ctx); debug!( "=> addr: {}, len: {}, prot: {}, flags: {}, fd: {}, off: {}", - addr, len, prot, flags, fd, off + _addr, len, _prot, _flags, fd, _off ); if fd == -1 { @@ -265,9 +250,9 @@ pub fn ___syscall192(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int } /// lseek -pub fn ___syscall140(ctx: &mut Ctx, which: i32, mut varargs: VarArgs) -> i32 { +pub fn ___syscall140(ctx: &mut Ctx, _which: i32, mut varargs: VarArgs) -> i32 { // -> c_int - debug!("emscripten::___syscall140 (lseek) {}", which); + debug!("emscripten::___syscall140 (lseek) {}", _which); let fd: i32 = varargs.get(ctx); let offset: i32 = varargs.get(ctx); let whence: i32 = varargs.get(ctx); @@ -277,15 +262,9 @@ pub fn ___syscall140(ctx: &mut Ctx, which: i32, mut varargs: VarArgs) -> i32 { /// readv #[allow(clippy::cast_ptr_alignment)] -pub fn ___syscall145(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> i32 { +pub fn ___syscall145(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> i32 { // -> ssize_t - debug!("emscripten::___syscall145 (readv) {}", which); - // let fd: i32 = varargs.get(ctx); - // let iov: u32 = varargs.get(ctx); - // let iovcnt: i32 = varargs.get(ctx); - // debug!("=> fd: {}, iov: {}, iovcnt = {}", fd, iov, iovcnt); - // let iov_addr = emscripten_memory_pointer!(ctx.memory(0), iov) as *mut iovec; - // unsafe { readv(fd, iov_addr, iovcnt) } + debug!("emscripten::___syscall145 (readv) {}", _which); let fd: i32 = varargs.get(ctx); let iov: i32 = varargs.get(ctx); @@ -320,9 +299,9 @@ pub fn ___syscall145(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> i32 { // writev #[allow(clippy::cast_ptr_alignment)] -pub fn ___syscall146(ctx: &mut Ctx, which: i32, mut varargs: VarArgs) -> i32 { +pub fn ___syscall146(ctx: &mut Ctx, _which: i32, mut varargs: VarArgs) -> i32 { // -> ssize_t - debug!("emscripten::___syscall146 (writev) {}", which); + debug!("emscripten::___syscall146 (writev) {}", _which); let fd: i32 = varargs.get(ctx); let iov: i32 = varargs.get(ctx); let iovcnt: i32 = varargs.get(ctx); @@ -380,8 +359,8 @@ pub fn ___syscall199(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { } // stat64 -pub fn ___syscall195(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int { - debug!("emscripten::___syscall195 (stat64) {}", which); +pub fn ___syscall195(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { + debug!("emscripten::___syscall195 (stat64) {}", _which); let pathname: u32 = varargs.get(ctx); let buf: u32 = varargs.get(ctx); @@ -400,8 +379,8 @@ pub fn ___syscall195(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int } // fstat64 -pub fn ___syscall197(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int { - debug!("emscripten::___syscall197 (fstat64) {}", which); +pub fn ___syscall197(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { + debug!("emscripten::___syscall197 (fstat64) {}", _which); let fd: c_int = varargs.get(ctx); let buf: u32 = varargs.get(ctx); @@ -424,8 +403,8 @@ pub fn ___syscall220(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { } // fcntl64 -pub fn ___syscall221(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int { - debug!("emscripten::___syscall221 (fcntl64) {}", which); +pub fn ___syscall221(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { + debug!("emscripten::___syscall221 (fcntl64) {}", _which); // fcntl64 let _fd: i32 = varargs.get(ctx); let cmd: u32 = varargs.get(ctx); @@ -461,8 +440,8 @@ pub fn ___syscall334(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { } // prlimit64 -pub fn ___syscall340(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int { - debug!("emscripten::___syscall340 (prlimit64), {}", which); +pub fn ___syscall340(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { + debug!("emscripten::___syscall340 (prlimit64), {}", _which); // NOTE: Doesn't really matter. Wasm modules cannot exceed WASM_PAGE_SIZE anyway. let _pid: i32 = varargs.get(ctx); let _resource: i32 = varargs.get(ctx); diff --git a/lib/emscripten/src/syscalls/unix.rs b/lib/emscripten/src/syscalls/unix.rs index a73456d09..1102b7a59 100644 --- a/lib/emscripten/src/syscalls/unix.rs +++ b/lib/emscripten/src/syscalls/unix.rs @@ -78,24 +78,24 @@ use libc::SO_NOSIGPIPE; const SO_NOSIGPIPE: c_int = 0; /// open -pub fn ___syscall5(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int { - debug!("emscripten::___syscall5 (open) {}", which); +pub fn ___syscall5(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { + debug!("emscripten::___syscall5 (open) {}", _which); let pathname: u32 = varargs.get(ctx); let flags: i32 = varargs.get(ctx); let mode: u32 = varargs.get(ctx); let pathname_addr = emscripten_memory_pointer!(ctx.memory(0), pathname) as *const i8; - let path_str = unsafe { std::ffi::CStr::from_ptr(pathname_addr).to_str().unwrap() }; + let _path_str = unsafe { std::ffi::CStr::from_ptr(pathname_addr).to_str().unwrap() }; let fd = unsafe { open(pathname_addr, flags, mode) }; debug!( "=> pathname: {}, flags: {}, mode: {} = fd: {}\npath: {}", - pathname, flags, mode, fd, path_str + pathname, flags, mode, fd, _path_str ); fd } // chown -pub fn ___syscall212(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int { - debug!("emscripten::___syscall212 (chown) {}", which); +pub fn ___syscall212(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { + debug!("emscripten::___syscall212 (chown) {}", _which); let pathname: u32 = varargs.get(ctx); let owner: u32 = varargs.get(ctx); @@ -107,8 +107,8 @@ pub fn ___syscall212(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int } // mkdir -pub fn ___syscall39(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int { - debug!("emscripten::___syscall39 (mkdir) {}", which); +pub fn ___syscall39(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { + debug!("emscripten::___syscall39 (mkdir) {}", _which); let pathname: u32 = varargs.get(ctx); let mode: u32 = varargs.get(ctx); let pathname_addr = emscripten_memory_pointer!(ctx.memory(0), pathname) as *const i8; @@ -169,8 +169,8 @@ pub fn ___syscall330(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> pid_ } /// ioctl -pub fn ___syscall54(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int { - debug!("emscripten::___syscall54 (ioctl) {}", which); +pub fn ___syscall54(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { + debug!("emscripten::___syscall54 (ioctl) {}", _which); let fd: i32 = varargs.get(ctx); let request: u32 = varargs.get(ctx); debug!("fd: {}, op: {}", fd, request); @@ -212,8 +212,8 @@ pub fn ___syscall54(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int // socketcall #[allow(clippy::cast_ptr_alignment)] -pub fn ___syscall102(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int { - debug!("emscripten::___syscall102 (socketcall) {}", which); +pub fn ___syscall102(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { + debug!("emscripten::___syscall102 (socketcall) {}", _which); let call: u32 = varargs.get(ctx); let mut socket_varargs: VarArgs = varargs.get(ctx); @@ -279,13 +279,11 @@ pub fn ___syscall102(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int let address = emscripten_memory_pointer!(ctx.memory(0), address) as *mut sockaddr; // Debug received address - unsafe { - let proper_address = address as *const GuestSockaddrIn; - debug!( + let _proper_address = address as *const GuestSockaddrIn; + debug!( "=> address.sin_family: {:?}, address.sin_port: {:?}, address.sin_addr.s_addr: {:?}", - (*proper_address).sin_family, (*proper_address).sin_port, (*proper_address).sin_addr.s_addr + (*_proper_address).sin_family, (*_proper_address).sin_port, (*_proper_address).sin_addr.s_addr ); - } let status = unsafe { bind(socket, address, address_len) }; // debug!("=> status: {}", status); @@ -464,8 +462,8 @@ pub fn ___syscall102(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int } // pread -pub fn ___syscall180(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int { - debug!("emscripten::___syscall180 (pread) {}", which); +pub fn ___syscall180(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { + debug!("emscripten::___syscall180 (pread) {}", _which); let fd: i32 = varargs.get(ctx); let buf: u32 = varargs.get(ctx); let count: u32 = varargs.get(ctx); @@ -481,8 +479,8 @@ pub fn ___syscall180(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int } // pwrite -pub fn ___syscall181(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int { - debug!("emscripten::___syscall181 (pwrite) {}", which); +pub fn ___syscall181(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { + debug!("emscripten::___syscall181 (pwrite) {}", _which); let fd: i32 = varargs.get(ctx); let buf: u32 = varargs.get(ctx); let count: u32 = varargs.get(ctx); @@ -521,8 +519,8 @@ pub fn ___syscall114(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> pid_ // select #[allow(clippy::cast_ptr_alignment)] -pub fn ___syscall142(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int { - debug!("emscripten::___syscall142 (newselect) {}", which); +pub fn ___syscall142(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { + debug!("emscripten::___syscall142 (newselect) {}", _which); let nfds: i32 = varargs.get(ctx); let readfds: u32 = varargs.get(ctx); @@ -540,8 +538,8 @@ pub fn ___syscall142(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int } // setpgid -pub fn ___syscall57(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int { - debug!("emscripten::___syscall57 (setpgid) {}", which); +pub fn ___syscall57(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { + debug!("emscripten::___syscall57 (setpgid) {}", _which); let pid: i32 = varargs.get(ctx); let pgid: i32 = varargs.get(ctx); unsafe { setpgid(pid, pgid) } @@ -549,8 +547,8 @@ pub fn ___syscall57(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int /// uname // NOTE: Wondering if we should return custom utsname, like Emscripten. -pub fn ___syscall122(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int { - debug!("emscripten::___syscall122 (uname) {}", which); +pub fn ___syscall122(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { + debug!("emscripten::___syscall122 (uname) {}", _which); let buf: u32 = varargs.get(ctx); debug!("=> buf: {}", buf); let buf_addr = emscripten_memory_pointer!(ctx.memory(0), buf) as *mut utsname; diff --git a/lib/emscripten/src/syscalls/windows.rs b/lib/emscripten/src/syscalls/windows.rs index d2584bbd4..bd32d3b53 100644 --- a/lib/emscripten/src/syscalls/windows.rs +++ b/lib/emscripten/src/syscalls/windows.rs @@ -1,5 +1,4 @@ use crate::utils::copy_cstr_into_wasm; -use crate::utils::read_string_from_wasm; use crate::varargs::VarArgs; use libc::mkdir; use libc::open; diff --git a/lib/emscripten/src/time.rs b/lib/emscripten/src/time.rs index 7efb22e15..459124f10 100644 --- a/lib/emscripten/src/time.rs +++ b/lib/emscripten/src/time.rs @@ -75,8 +75,10 @@ pub fn _clock_gettime(ctx: &mut Ctx, clk_id: clockid_t, tp: c_int) -> c_int { tv_nsec: i32, } + #[allow(unreachable_patterns)] let timespec = match clk_id { CLOCK_REALTIME => time::get_time(), + CLOCK_MONOTONIC | CLOCK_MONOTONIC_COARSE => { let precise_ns = time::precise_time_ns(); time::Timespec::new( @@ -296,14 +298,14 @@ pub fn _time(ctx: &mut Ctx, time_p: u32) -> i32 { /// emscripten: _strftime pub fn _strftime( _ctx: &mut Ctx, - s_ptr: c_int, - maxsize: u32, - format_ptr: c_int, - tm_ptr: c_int, + _s_ptr: c_int, + _maxsize: u32, + _format_ptr: c_int, + _tm_ptr: c_int, ) -> i32 { debug!( "emscripten::_strftime {} {} {} {}", - s_ptr, maxsize, format_ptr, tm_ptr + _s_ptr, _maxsize, _format_ptr, _tm_ptr ); 0 } diff --git a/lib/emscripten/src/utils.rs b/lib/emscripten/src/utils.rs index 56b080207..79936f2f4 100644 --- a/lib/emscripten/src/utils.rs +++ b/lib/emscripten/src/utils.rs @@ -91,7 +91,7 @@ pub unsafe fn allocate_cstr_on_stack<'a>(ctx: &'a mut Ctx, s: &str) -> (u32, &'a } pub unsafe fn copy_terminated_array_of_cstrs(_ctx: &mut Ctx, cstrs: *mut *mut c_char) -> u32 { - let total_num = { + let _total_num = { let mut ptr = cstrs; let mut counter = 0; while !(*ptr).is_null() { @@ -102,7 +102,7 @@ pub unsafe fn copy_terminated_array_of_cstrs(_ctx: &mut Ctx, cstrs: *mut *mut c_ }; debug!( "emscripten::copy_terminated_array_of_cstrs::total_num: {}", - total_num + _total_num ); 0 } @@ -155,6 +155,7 @@ pub unsafe fn copy_stat_into_wasm(ctx: &mut Ctx, buf: u32, stat: &stat) { (*stat_ptr).st_ino = stat.st_ino as _; } +#[allow(dead_code)] // it's used in `env/windows/mod.rs`. pub fn read_string_from_wasm(memory: &Memory, offset: u32) -> String { let v: Vec = memory.view()[(offset as usize)..] .iter()

z7E;q@F~J9;#*!;32}Vuy0S%%_4I$x$mnK-^yP^;Np!g(eqC}&{GrL9lz$9~izI*=W zoO9>O75L>Nm~|wS*dQ;Jpft$nC5a6(HmH~AffB!`x18Ix?c73rN!QZZQ+9STlj)hv zrV=9~tc+AILmpthL?V&NrN$~2Hfe=)ad$r7ms|4jkf}l{naMn{DaH&ha`kd-O9cx& z#5T8Ys$k`472hSRDzci)R`RJCXlrgvq{j=X{K!NxolU%uE+$T-lM{);$ct%as*4~a z4a*JkY44G52CijFOQM9uK-SaTDYy3Yh1 z7y}a+=%xjpY*Ya=heQb+ZWGb$X>fFVTK&pbQa@cr-~%!ZyV%m>q3^bq={q;LJp((v zga5hjW2mX6uT1Cj*__weWN{>yWzv@z9?nb_POuImF`Q4QS+kKCPmW|+#78_shOCLC z^muAwimlsK7HJY}y^$yk<;Pg3|M@BU%1p+a=3{|}3aO9Rr3=O6P-diX;&3sU8aq6Z zOr=?)`caFOHmr)poYt0DEat!cJ~VXzl$?+RCxmP?8gfEzaMYbR=}AsqpB_ghG#epk z8_Wp>ZIdC3hHQVCAw=u!e?Zep^)vO;6or%fHaNNftdT1SL_|@qT8+MrYRQmCLoN&2-(}&Z<<)xAqBNphY$b~j z+WdJV0}z_$zNkiQjX!7-+bX0HUgQQYaJk5BT;wk6k+(SBQsdz!Se$<)3>MkFx~heo z)rT!_5Z%_gNYudNLqcUu}M|L#6U%F&*)dN?E>(LMF^z7Her(<4}gsZM#f|mO;;b4?bzPI znOuz#wY_%>L{y=7lmc{N7X`S}>kwic_!L9v3)-Im2rsXY$g9yJv2&@+C(= zE`kwc^V<$xT##CV+NfIDw;+^HtOK9O*UO4>LhbP7;5&|+y4Ps C5Rh&F delta 1846 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 delta 1786 zcmZuxU1%It6u#%q@6O$1CrR_So1c3#n>1+~8cmx%)V4eQvq_pCO{hhL&1RjnNhZ7L z?4~hVyA>inSZwPc2^2*9DHQ@OtoY(fU&Pux2n7*D5b9qMpVSIgA3U>3Nx;s-cklV` zIp4W+&Y4-d0bk#M%XI|;g)u0QF0)elUC#}RXvrE7HC<5vi!uZ$0674~KSQfS=fF}Kf)-f*Wg0HL z3Wo?j?9r;-g^CKio8x(zY*3F>elnXO4O((y!kx>VCUGS>;W-YeRgyEQ$qcF1aCOm< z)ZosUNzX2jt)(57kF+bv+_*PQI<#ai@3~HfG#f82UA?%<{jlWG0Ozua@?>>k(J zji40FY!E9tU(xMw4<$Acz;EmE($QZrxK8m^{KdWZVcDN~>Py5u`?_JdIK6KI(73z* zb;Oego&POTkrDu9{59TsC7u;lZ7i2)n94BB=gBEPmIf zes!6W|9$VrT1c4OG-LjyK5JV{O3(z4+2ojr@~E5$1LF#hO^Y~JZFx$x^44}rL>rI! z-}UuC%&+R7LV<4HjRK4P7BbiSKj8+~BJ3uB8RV_RynIt$j(N`=Pis2XA%tN+A8&6l zxEx{Kpa%XbC-#N0enB~v6E;rbw2;gOziXgjCl0dxUJZ5#f+nB`PSi;>+@kOei`8O&NU_Z(r7dW*q+#;n< zm;*oy1XaU;=NG@qc32zr3ZaPC;Tno{NR-Laf!pR zGhD*vdve00Q9EpEb|Jzny)<1W;ABZ$?!!a$$6o>-KrnXb=N~w+i{bYaVIg9JsT9wj HsE7Xm*bS4w diff --git a/lib/emscripten/emtests/test_main_thread_async_em_asm.wasm b/lib/emscripten/emtests/test_main_thread_async_em_asm.wasm index 9bd6baf28fa5ab5cb28edeb8e67863d1a5350be0..68db09f1d49d226c60278bae2e7cdc39a909e4b0 100644 GIT binary patch delta 3493 zcmZuzeQ;FO6~E`c_jWgVOZKrL*<{Jbx!FKsLLiU;O2FiWO&S_ROb{)o%O)(6WV3`# zKtg~GOrlnt61dDjwIZUm4r2>;t+ut=bi^41ZJDXIwOXKRM{B3F(<+SBk)FF7B{TZ| zIQQQ3&OP^@^E)5+o%i^W_xM;|5hU0;o=8Aqot8-KVCxvoXidx=3D~i}rZ$VQb$Wt6 zNbq6ZxBu6939dzATg}*(Xta4ttTWWr#ZsIplQ>`UoS{%Cx~a1#En(8CKQho1kFVG? zu}5(R`#ZzY=-k?BrYX%+Ci51gdG2ex`7>(Myp*=|-U+D;lG+kWpC^Z)wpdsC@##~T^2Tu8A~3ka z01k|S0nF*tG>vWo1}$8`Gaw_=G?`nQlEn;?@BnB^RI`9NI;;c)xJg7acR)Z_#Gs|k zt`T{e3v#o4ZocB3``I`*cfwLe-&dpaH{h8{Mn>ZC*e2!J@Icq581p+r8#Y9@^lxN0 z8lesGNQC8hLec2f-cU#XJ!ETF%{*osq26#;jAc7%jM7#%jb@SF&b~p`n3@qXtZu0h z>hFm6uwdr;!Prs~RPZ*ruPtcVoE_;O2zNxg`Zu-@ggblM`@)?O=9TYg)roKAwzL%F z`C3|9GLN6)i^>5K0k4377g=|yH{i8B-FDw*H49{~&>N6h%tY{*1`BvSrh_3X^_rQf z0iiV8Tn@TYpwUh%r69GCL; z39tADZ<^>54rKOX1rd~UCOC3yy3o*pn!39K9hOVzs9X8MKxKsCF&{RdLE+O#@KjI2 zyISGhXk)inOoP=e>abB1k@|veA%F1gF{eXVXj%EPrZrIE*BW>O`fb)CrsH(I!3`!F z=lmB|JF=-*Y@0w;?6 z*eg@fYG*D}_SvwR&eA;Q%Q{pki8%zrMVJ%?7lFcHd`$!@4ltXU?`5}Ju~2sb+6LWTATPh{;%f%GY-bH>y4GF|S* zsZ2`q&WFICeDY2T$trnUs1?eSkB9yNH0%q11~6Oh?d&IdwX>R7)$3me{_k9QHS#9R zNxr$^BMx(u<6TdH*Dp>1o=RopD}b+nHA8Ogc@%18ZZrrBD%VZN-69VVGqW4F`1WYhIfm0Y_i4~R9;w>hJhf}#>DtSWh_&zDClyBa^@c!@x> z)W7R!NRc7+7*c6ZFjLg1tQXWaDBs8l*Q+oT)IKO_o}H(?uO+7L5-K78t~%RE zebO-}bvov;p*mP7|1y*h3zJudYG9%AVlL)bRWy2SjYi!b9%udHIOT+m$nhY@Bg^(PG``XE|iG%OPm{prRznhxoV5;&C+J!A*J8q{W9hCpw^Vz~t zz|mB|-3NGIDv|F8ydP91)QLrI-K5_*yH(r^c&|c!6hxhYqjJVbGYlr9BP*Qx2z4X* z(%zCBnyhRUqZ~)6uu_K-Z3d1cKiT^W4)c;HzLy2!nybh~$~tP+Dj+%aZahmalIQoe zkx%B1-APdH8*3vd-yLfwx?q2h_(S_EiT|Vhw?ox|17Ql-jsts%ed$1uL~3Li(Y3Oc zM8;$%%|DjwN#;8T3;Yxd6QCTXI-3H8PCTs9iTe&>u@{$lOs}fMy9ju?(~Ifq^1cpr zDs2D!$U?Y5dXL;pS>AEvC7?DWjuv`J^vkMsR)bkea(rbG)X57g-!OcHickLhmSUGr z#a$le$qTpSf=^z)Wg|4oP+OVvB0!$nbpGbI%cp+XXiimHn*ADeo2*Hk43GH%hcYFc zymemYjjBS6Lep9-|8;946*uazB3~7^e7R(GWofS|abUtAqnTrUt&fSZzlS(Sp?O1dC2t6r4g43aNN^+aoynwazgp=95kZc(z} zw$JP9CsK?O=4($uhpN{I>RoZpubK;GAi0KH*HPj*sK)9Z`K!lf=YOEndy*iaO-0KP;|7&C2rIZi}98 z9@A1?NJD+O-VjK?ZKyL@Q^-210VE@RPuBV=>Zx=w8!WD7=G9!F2ZGDIlACOLs?V8> XJo#5hK6j!X_|rMkKDj_vJ#*s!C8;gR delta 3647 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 Z?WvLnvA_+gkCojoHLJCAe74WkOVPk$IAs?8; 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 diff --git a/lib/emscripten/emtests/test_mathfuncptr.wasm b/lib/emscripten/emtests/test_mathfuncptr.wasm index 0b589a7e62abd985024e87761abcf9b7e5b00666..6942507fb32aac2437ac2a91c4bbc94a86cbcaad 100644 GIT binary patch delta 3591 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 P%MpKge71P@iB10l-S1QH delta 3625 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 delta 4041 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 diff --git a/lib/emscripten/emtests/test_memcpy_memcmp.wasm b/lib/emscripten/emtests/test_memcpy_memcmp.wasm index 076fb1b026ef2842c41fa20a51d7347ecde11fba..ed5be2c51207fd38b16cf6ba20b6d2bc90738a79 100644 GIT binary patch delta 3779 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 delta 3900 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 Ue*Tc42b{=COp#n)KmW>q0Lf6$NdN!< delta 2090 zcmZuxU2GIp6u#%q%+BuIr91tj%PuYFcD6r4Ev2m_2*?gtl$JuVg%TiHO5Ix8Wf!(v zNTaxzVB%k*b`BXursYssP7V5d)hEz*cWVo9!?HLS zz!-2~U5fm9nP{^o6Zd7!0L!g9~nP7$5sV3 zcO-W_%{s~;6_MR(rDhK0r&*`-;9PbKndnBW4&M?;?5a)A6vhr^4$n-MTR41lY&^}X zMKnK~9m>rVhSP-^wlYZWMke#=6Rbux8(qaUOS`+5M;p4kyPZ$pftGfFqUT8P9Ar}o z$8-G1lz;S?<~*^(Od@j)fe;ZE^PGqXFk}fwIOPK&Aw&)H!am!oH4|Y%mI!egAfTOE zNBz0JaPjZ&YP0dPw1SP6rU zE5S&Bj-RTeRlmS3{EW*5E^vWU4DvF^%c`+14hyAqbr2-I^~;;cSnX?kmgp~ymx;dH zw2!E};xFh_f*RWS$`c6CS$a~^Janov&GkfIYd#U|ls}q2b303|-VZMMa(WNh?T)U6 zaAWe#Aif#&!)rP7nFO2_~w*s!IpN;WGlwiul;KwuDpRM za?pc4*lRk~&v^3n9N)9exO_S`Oucr=yZUSl0czpm+t%chEx#sD?qcjXR23uZ&y4~pvx4oC*2-W~lA?X28s(;_r#e?B0m>0P1rKhQ{~a}TU5N?lMre=ai0%y1J_ zTbDM%lD0)6YKFRd^JfGjB%_VaR!I#Z#cCO{NQSImJVp~hi3wK0kE{j-PRiCy+m3DW5r>^b38g`IJ#PilROEGf;8zQ?IJr}pi#P5%;&sinT$w^Xg!Tc`N` zKLZEAEP6rp_x=^DT^{qpuI(2i!V8vH)diX=1I>Oj>CzKJ4=nuvy~CuZ1`hNJQ@@=d M8c5etPaSys9}UsF9RL6T diff --git a/lib/emscripten/emtests/test_memmove2.wasm b/lib/emscripten/emtests/test_memmove2.wasm index ff460adeb1e0c0f3c9d4650244b918c340afa20a..a7aabf8677e18622a8b825a2e5e70bbc0eb33e27 100644 GIT binary patch delta 3710 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 delta 3605 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 diff --git a/lib/emscripten/emtests/test_memmove3.wasm b/lib/emscripten/emtests/test_memmove3.wasm index a50bc29d5b4c040e858908c9a6b2329742daca3f..6da6c09288f43b3d6f31d3bbc34bf4de114aee72 100644 GIT binary patch delta 2171 zcmZuxeP~-%8$Zvv_vWTK*>an%OPhY=IlXDx&A3H7tFo%O(@pKxy_@@V4ze`fy0&Rj zlT?|gnK1DW2RaW@(Lek{5C#A6HNp!jynA`y7iZ@esHiA9Hbg-X{6KJs_?%>OMGfS+ z=RD{6{{7B*`gQpHHF&&BLY*Dr^*YoKG5XVr9Wv|m(+b8<8>>$o?W%LbFWnQk{ z$Jc%hBJI?yU#XPJdcgVGbh*U3?cCHkR&FjoU1Cw2zC|)*9klZ2 z3iC(UnxJ0ImGAM{+NQF4y5;k+OF&HtF`=Oak_eV zS1n(d-8G*t_^e%x8=3n0&P=8!wmOr^g#P^sxWfQ-H!8u6BAZD@-KZCt@#gQ=E4O32 znMLL>fe;ZEbE6RvV91hD5o&%Ak{#knfPju*k!z+Iq3P#kw4WtuhLRz8M}un&cD2D& z*t|WxHjdy7$I(hgJr)sXOK>WvW1I?75NBBs$6<{VW)UFT_{~Zh^l{rF0s4$Yq}92^ zE&M;1OI+X*_t+MBn&W9Ty{ZS68V|36AlW_A+fUBw`M$?Uj`lB+gv0@o2NUNZt@h#l zkbdq%1V}eNk~YNB@(UBcFunQ~`K5_pnlyk9Oed{=9Jn`_mS343bJC59d(NTQdpAtl z!%;mO;dINFg7{L<3y*R}9Rr>UCYwh;_rMFBdQ)dMegli@t+BUAs_RBzvGL}0Q$U+_ zH#|)8)f@Ja3}=s#Jds`RE^;9(JPtC5zkqDhE3Lvsj>q_|@+po_sdL#MdKWom#6b@# zGKE3UoRLE~gek3DY<%wp4T^XEroEJI=jLPPR8;=Why?~^0GT&7LxsaIXObg#;?lqX z8oHqX2ArTY(R8|`g}O5m!2yPo*(o$MqW zK|@6rM9S9z+V!U6Z_<1`F%P!7WqT^RTH4q_^Psxky#!h;YMuZ4ytpveQ3pyVNAWTE0Kul!!GR7MQfNSqh>`!4unmM zY|igG3~N+j_mF)Cpo_w*vpYW;Hi2ys(cYQ^c>n8k4DW54_sV4&GWeRqP@Pi)uk5}uG$=zDl6}H))pxr$h5Iy{ zWVb~#=vHHUE=#6l3}YCm=+Q`<@=04@x1LoTy|Kp~OG!kO5T>_+ zIek*1)TV>9Nyz~mB>Mpg)D*Qx3qd!Hkb8(jOb@hY@2@@om@$?>4{SR-H`!Q zKkYahjv}Y`3|eme`-VFDWIN46=(;H;BYdUWzwg1+kZwB06UMMEojd&k zSJFV9*uTmYab%6o{r}>G@;e81_K|}ZtW`)lP1#ke5G_paBoW$bY`jB2-~gC)H=wp1 zOk7TYt%!SJhn}>Ea6*Kwf#x$a}81~g2WiCko(o<6ui(2Gr+CBisdeR}XezXR&N B%!2>` delta 2102 zcmZuxeQZ-z6u;-b_xjp*yY+2jthC!WckS4OS>~7+6{SxYkVDu-53z`FJqz!MzltaCIS%+FrzVOjM0FCM*h}l{EVL44k6L^$GPYH-Z|%< z&-?W|aO7QhGTO_)-vK_`!F``NqHKrh(? zcV&yiQ^nETRZtB=lVAQ-JGyhKP#h|bj!kaZpDm2%rVcPe+lc&3F1KzbKbG0Er-D>n zhg`+%OeT|?8k?NAA!#~W>?srmrsi!lGCMssn#ygca=03b?WYhOa5!++Bgh zHE3QbM956Oa-XUPsR}UItX&3&hP^d?!y5(-pJ_Q%mNWg{Hgy7eZd=j{+^{ST1~3L3 z7?=SAOkmsw0GknL27m>|YJ5m=LB!C+6uw%;qoMmD5fDUdwVK!C{jin{%Aa@u)@bJ6 z(>@P1>M365$L!4bcy4BTH*2#pxLmWQtiBzD$ir;DRIb9<(Dms>crZ*(lnYDBa! zlOLR#E)Hdj(`;#w+zsz8WDl@f)nat|H!bYyYK%5?b#*zPzYeYK0Di)ekZ_PqB%Org zMJBv`_h~L62Fx@v*ANI1VX=f05dnrQ=?JHMAS8vTWr?uI)@jXTn2;(Vo&gAGrxtnZ zEITc`@;b?tde6vpbi@$c8)9fB9gjuCr97MoYJ)RDvT(1na9yLc#moUXrT49*LC2L~ zBtXZn)zYe;;}(9vKWgIS@?A?@f=nsnRWp z%P#qjcki^@9bFsY#^kXe9t(Qmm7IA@0-gyb%fEh!!%LiUQ!n0r1rDpnSDhug?T!_2 zxb)Z^<3PescRoUNcJ)@GpRPVgbW3`9;xHG&!pA@c@i&km&1nb^b3Dk`%R?Lwsh83} zlJ-$AM$X>!f(8jE)@~tTVb4Lc-jV-PP4(*fg}2A0fdMphr~wSPLYip0i=>4*W-B6& zT9DT5xa+_Dd%E{!J0x9n-9_qnZ(?cONb@wtJ$AQ@Va!a2L7;{4NtwieXHLjgY;EUE zF2T6^t9K>DRd?S6Iaq-!$ia(!2|~{Hy@3we5pf*A)z{Y2wRqhSplhh-?-{d$RE7|l z+5PP;4w@0MqB3RyWZpwN`XongrahX>Nolw-wXwf(ISsaVvYr|Qx(B2|)AlYvjTY+u z=bGpG_t9)r4J@f`kT%v)IVi4AI3O96dIowSnyTDs(_S=be;y#GVP33qo0`b<(M`Ad zQrA(TP4)0;aXp?=0M-t5Ic?HGM>Yw!RXsFxS6J#1 zlQE0#h^dc03wu7uDANn1X0)>u;yC|?aA`AxNJ9TR70;no|x%Dkh#d&J`M%(mG z(wJK6+wBWWe{UBM7y;8y1eH6oc)81CUf8ugKOz#r@|wCpBW0l3Yo=X#Ug)uF{)IaEuzwrP7 diff --git a/lib/emscripten/emtests/test_memorygrowth.wasm b/lib/emscripten/emtests/test_memorygrowth.wasm index e9a9d5b3b11fb2f4e7e7a74d515f6c543b7cb61c..e0d5e924252cabd7cf128911358dac0a8fec7e8c 100644 GIT binary patch delta 3651 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 D;k;ih diff --git a/lib/emscripten/emtests/test_memorygrowth_2.wasm b/lib/emscripten/emtests/test_memorygrowth_2.wasm index 2d9955bf5334bb1d17815cddae2a3e3d11dae679..138953fc31c5d148a8a5f51038c2fb6058483b8f 100644 GIT binary patch delta 3746 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 LV^!kF3%~pyy1{Yp diff --git a/lib/emscripten/emtests/test_memorygrowth_3.wasm b/lib/emscripten/emtests/test_memorygrowth_3.wasm index b37ca7a26631d7676d7d2cd4c1ed3a8550f286dc..d3571b2c6f17c0f07521f5cc705ee345fa080dfc 100644 GIT binary patch delta 3893 zcmZuz4RBP|6@KUa>~8Xwyq67|-E98O%`OBINCJTXf+Y_^BrXsd6cE&92}^$2B)j=B zHn6b<#OhS&1%lA2E%mQKD|FSV6)hd5wNPtYt>cVV(c-A+Ft(zOwS}I$8zs}aGkf2? z=bn4cz2|)AyZ6lt@{cdbd%VSvkT$6a`bnGQL;@0Gd2hC>M$+Pi2@R%%+zNb)7c zyZ59wAuEw+zaH)D?5yvLHiz2Uq?BaR1j$#jtWYQvj>jXh-q6-?Tc@OmrFIf_b~SgT zm+3T$M|zjVVyn8w4GGC$ygA(2IcrXpq>43@uE?&MHK!&mbY2n8os$-&tfkkED`k*U zUo`EH?}d_ryijCYygAm^-5ZI9S|Yun)=0QJ6mPpVB5C|FVDmi_6=D%FlhTnu?8Fn^ z+!gC>j4lmFqg}n%#JUDnMz(du1|{Hsfa|y=FKMxAL6dEo3NlC%Xdr>zuBxh}s-V%x z0dfXpWa_%)R3~Lgngpt$nE*5`^i=~S+h#KXep#nR(TBjVibkWMC0%Lw-(*jsP8$CS z`PsRt_KB0Sz8#i|iLbx*-++-#p@_s{(Jm4GaBo{zR4TBCwr=h0i?>Qkwb0gBBqDi? zP-kcVw$SGI0EMNkdbYG&3vCOxMJ2bLzMZsG%B5apTXXlIw5%c3r36aXYN7b%SceqM z+%ibf>FgB9SmC@fpyA4#NW3?^xw9?ax~4bW+_9!R+#Hc|_}fZVVwJbCvB;O#*w~o) zgO}vmX#feoi-F&TQhUJVcUeZe)!id{{+v~6ElQ@OBN)0S`CW!?lTZq{^vu);A&{eI zgCY#bmSpOT#D@M48Kw!*bTU?zvYE1ERS8Sk)7ex@VosEp2Z5nEnLn=989|nT8Eguc zuuRM}bGcnx2K9WUR#O^eZk)n$(T%zF%!}S-YOVD_p*37&O}BnjWGXr`mPb~`w1U-& zuIuP$MOb7>^{g0+N%!R<^BNyc54bGJ(5zEMVr4~oB}w#mqVR%4?Dho*ZP%QzUDK43 zxwcLKSMqjyK%vjWnTCx%zciWVJ}ql_N@k~J9Z%EQ>)9C@&+rTGd^nxV%moMOIg5&D zF)uH^huWu$PgA=KH&FXF{tJTq4K@V9pWaXc5KM0H+rblLZ>spFY9;E~TPnV#Qt)3^ z%^<%eFyIKXcU6jTF!_1l?i1!kulm;Ssr4?dhSB7T#an>}$=aRNF0j^7yVn|_Hg`#-e^l0W4eti#z%PIj zLp>qFQ5i?%26j-!gS>UgKS_JzQXd)XU+Pe3kf>ivgIDWERJV(LLo|6;Fn3`gQ_zNr z*s2X}W(HGHHS?K*M?CYokG?_S|A^C`7*E&42JIm^d< zwbltbYUt}=0km0aJHctnG+AO((Z`=zQ3F1HaYZ{BsK#nC5LxLb$(<`7M;F=+{TP5L z{E7;|2`E5Q;y0~ow%Y_iY1!{qO)GJsYUtHq6Z$rktl>>TCZkMXBm8$T#Vp|2jRlod zRo0$z$`FVokOsl+X@G1o$oU30H#T;IgTL4~)s@HWm_zZPeZ3?D(t@P+?Q225n62mu zb%!=Yf}VRr4nY3rpWIdEmSws{$f|-8f{7xghW2ZproOqrw{Tc0Jrd4z4}aI>Uh-6>4bBzPC&cZn(!yiu9zk1CB`@@ znPq88a;8%N)+_l2v6&{~qS1C&x2McxHV7*g^pF+B(4SLbrqHOQB%Or`U^uG)!J#1( zftmcVP^Ghi@?>XzjUw#l=R?Oy{KHMd)E0*4)%wMe2!cddbgoJrXD}kGN=hrac&kkL zR8C~=NTuxynH-%=({Gw8PZI0$ec?k;kgVKH(5&KTn}blEoU!FYppSR!mjJW)yVz?{Y}ciji`_8nanC(4m%r4r5Nfy{dlcsLr(y?5rzyUk`bXpQp(=SU?gbM4r?+SIJPLL> zmYG#J-x?lPI65(RB}@`yfFVN_K|`gDNCd^YzT)aP;iLdq2e8?c~x?FxEkh(9MC07DUi@*DfCsX zVUdb4sya%AjQeC9lPOpGWERr!O9hW9CQF{bZ43w*`)_}eqLExVG6u7Rsn--dG;Tzs zzcrO_8C$TGEZmIGDIKhh)Sgzb&8*_nc44ttl~l0(is$IK;}(pX^O7yQ=!zXoG5VlY zxSZXJw-OBu@}WDvRCfaI?v_mXLXS6lyN8VGF@A&NyCxkjy+GwFgH1$XFg2i`GnkgaAq>1R93JVEd zy!psHSi}z>X(T@Q@W`_O1$^xOLKmriMQ~>nm?1P9t}lXb@z(2K(LChH!>zT&#U6n& zdO4*~MxZ0o5?8yyN}Q@jI*GNd(7@kcTWUWG;1yO{u6x~Ek!D&uaaXa}k_ChjFl%{B zQz2Ev&ZY&43ISAM+$3L_#J*P(shSjSjoFC4%}UXsm&8|-2Kl6lwqa(yAWl-uW*Hid zA!;RhXiE;3p<{+YZ_3n-NpxLqs@5BHhh|NXWE%Q=GL$BWHTj|qvon{9yM`6&rp0gB zu!KmNUI;8tka8aX?S}F|9lbO?Xp4y$Fgy8Ub{+G?zJ2Hu?5vuV+`X|1mhk$G{zY{R z5g9nC041}6F=Rq@3JvO52~HvX5(acAIv#bzi<1cGw)ADoAK3Ws{Npm@3sNYcYW<%F zC11X#it;nK<{ip8mG|OtCin);f(P?mGbq3|x-jTAe+N>xId6EdG^c`PQ{;4ULh>%5 zY%b=vKe!{XOa#Iz?h|(!%c3b=?3@@*98wlnP?o``KU9(To(fc3vLJxe6CWwJ<|H3V z$!!lEmbp3R=6`&sfG-&P+_r%<{We~6w0I_E)bLqOQ?n9=ZaQgi3aTsAT7UXICo-Nz z4hd$Y!$*$J@e!L5HxqPBS@d+OGkPsK^t(ODUp(4vPyXfT+mQ4>u^8kNZhriU8h+@> G=l=`VT6?ts delta 4015 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 diff --git a/lib/emscripten/emtests/test_memorygrowth_wasm_mem_max.wasm b/lib/emscripten/emtests/test_memorygrowth_wasm_mem_max.wasm index 9587238a2f382918052ea34d1aa89d309c21937a..2f62b2a4edf0551ac8bccba21cf3ccdc5fc776b1 100644 GIT binary patch delta 3597 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 MJaD>E4xKspUmeC$5dZ)H diff --git a/lib/emscripten/emtests/test_memset.wasm b/lib/emscripten/emtests/test_memset.wasm index f1a907bf603cd350afad56517b2a74f6f6c67f53..5ef44eaea4fbb98afac1525a97c63daca9a1c498 100644 GIT binary patch delta 4102 zcmZu!4Rlo15q|UD+n?ku>|-(6WXaFmY)Bx4B#;n(f{>Sl03tsJIF(xI65>L#2?3G- z1(5|$prZBn0s$hRfF7!`A`1wlwIHAf+R`JUfInCf3#AAZf6!Jsvx_Ci5LPsH-KDd#IHq&m(hVqzsf=5yn~UN|Gq2&+e#wF0 ztfuP5+Bwa^hQQ2VbD$`dTvc9rMkGhE(^N7uN8rJ@Z9unu{ zF;cBRqQdaVReLTFOLJy3tBlKGHaEUEvo>P@v%k5DnK`?bF&pE~W46c~!faQ!5@uID z(Yd1ALOj}((826i-fG%G{yF)#P$ozEHj{kO$8uv2mJ?D~-jKp_Y3gevYiZj^Zch_r z{Fk(W?8A=znGF`hnEfWBh}nz&Qf8MkEoKE-W0@_<9?Wb{uMy0C=v~QdM4#xK%$>)h zxV+by9nTN)xr+Pq{;&4mNb=M|mOm?Gxuu9@*8rAZ81M$kO~vgbE*&Vyhnzm> z8qvE3-(WiAYnm8GfgmJFCg8N>4RG5bm0cP9sK>e#dlk40(m_XarPWb}_X z34OB@_NJ*sHjJ$Y@I>OrXKKXqC%Wy#hEEZ;en(Xs9#+Ls)xe{wrBsSzDjriQ-wrxO z86I$oN*CC8P|kyqcr^0FRB)2D45pDwxnss-M9XF#CEBItZlX0c-$A*ou3Ze}Th7)3 zlt(@ZIlx;kKGN|c-3nKVk9GW5r!C&m&2o98Zh^C0e5PB9SsqzZ|EWp7r{6!_(aXcx zZkWlU-HGi^%T=r@mLdR;I5VSDU-y7*D&1IKYWWAW%6FH)Np#bSLTHV=vtkC&V90~Z ziSB>!E}}^*TZnF0neT5^4a0`N1L4H$AmUhJ6}GC_qK+18Ra`5-So!aiR+V=8c`cmtinj*2xjL2bkxlxVMD%|&26;Vpp>C3BP0ttAz8q0xXi+k7)s0xi4rUmY2-d7B;+*t zxWg_?G|eRWjr8aEv{JPceU>sx^uQi^sS6CWp|4J4qMa|(6MOP`vd||hRuzL!-nS}5 z4hpf599&xECylv!CwkD~HYh_)J`k5B>~tVB6?txTwZleXj3cvgYkC;8q9bqwW}6w5UJ7GGkzs8-#3yM>yPA{F2No-N}8D#GjYf6shU}WT8Z0m#qa^^L=QK$8ymZO zxV1;>K^^*XK=KKzv(PC8&I08?%a$PYmKV3=yK)FEhw$4d=ziIA>&v8mZ|hQ`Q=T1I z>gTgl-i@HQub6!d%oUn}`2?=!Ha^bLzEZBmt=g?VUS_f$M`gW-bo0mM+zs#Fs$$7hpbK0sIn7ny1l4 z6)zKlJi^{2nz{0myK}LWS-Fke7-ro&GF*dwhTC`v;5G))>PUrb8R)1b`esL8Dze{ncx{xz z?gM?){XRMLKs61XJ}{qVysrT`R@z_?8Ad*Rxs9GpxI z>E(l&gv!Z-gS+M$n3zc)DLJvTq#jDnAIRw@sL9Yf+Sy+_r-i#M5&UK^XykHx=Wmtm z^r<3)hf1JWK65A;iX$C|3ZWZEED;kZz6yFQjRJS$u-9FPt5gxN;rAMD*UZ#N&)1&^ zLhbk)yXj7m2ah}tVK#hU!}Vl>dJLMHC>AQt#2P~4*LYB?6ScIgL&I8Hbq`Lh6Ctd{ zP)O8c64uv=Sy78w7ImN~b`cFjF@O7&Cec8%i0rR{W@n0ki!Q2h<(-Z4<)ha;3!}Ao zp_MvHEW$GfxQ{wj=57R6X> zolv-ihJ{A)R>(bB{Is4O(;$}OB`^!KxD-)8ry#245V>XD37eNPz$+K8 zPfz#qWD+LPBUHG3Q%&Qq1-Hm>={8!kZ+#6|(%+WtI17-(2i&~&Os{S~md%QpFk4iktdfb&ibG{b%^_=u;JTdW=8$b~I>j>Kq6h>*Kyy2jL!~n!V^z+X+0~Etg)* zOa5F3hLuww`VR{NtucJ4L=IhSQ&WN3kh8gws2Qb6&5aaXoyvTjutgUC%K-b`$I6C_+OmRGNj{U7p62>t*7 delta 4004 zcmZu!3s_Xw5x#RDyUX5{y@1HF2%N+6P*gy9h_AR;9ubX?s7d_N8U$PrSOEdGT69SS zjY(Q-j}JamO`>_INn`99^UxR@HBqTm+ayiWDriVF#QLTENE&M!JF}SR*Dw2hoPW;T zxija?{BzEwwNE+Rr~JwlEkR&D1f=T7yzpSy!H_f-GzHzxElPz7Fiy`$GH@%xLH)K!#LSNCfM+@bkiXDux)_19O_-g*aTO}^%$#>VOOlCt4k)D$(e zBvLPLswngON9N>7A)Vv4E;pxNrQcTFG73Y@lDdBXVmff~BFs!6kG9!!%z~+NX3SIq z63xRx^U`VNT=6Xw-8*4C$cm=PpnxQS4EU!i0Fo-HvISAH+Q1fOw}Y-a284%8vaG7A zg=|$PNS2C-0C;2_2ZaVz4~QpZS6B;pEIJNWv0jd5El?=k`spj7fW#lr`Uymci*i)J zZ7r>=^e<^zC=Jz0D;s@2DcV`;_b**kTHds*tf90zdz3UuD_vApT_;6Z5&gJXX&_3z zMHLOprGk)zDU}Mf(x&ppTB*psV0m2u+EH1G9k(Yqy*tX+)Ld5XuWnixD(LLQhO!Eu z6rndRshe5f)I8hQ+$5PcbT?;Vqi>lMDV8f)fyskPN(Q@PN=i!XZ-1za9|92Y*g1IY zOsYw?d+esO#%x$jl1HDedYNP>Is>P!NglgXw@6G%w(Ir~Fi6(*NXg?crDC#7cA#c} zuAlrhz^gjB-LIp=uU=O}oFx83YrJu>>n3#t|Hd3_ZIZRYS7{(FX}wOa(>|ZLw>iP&nK>P~Ph%d2}4f zpTv<|KA2=J{vDK0#P33RaRSGeMZ#$E(U~}k;5&8~!Gxq7f<}**Aed|te4R3lpdf7w z!O9^;1V@J!6WE7^p3NP;gl2yn@h-upOdqZ5#z>04denB5ld?(PlTC6-4$0?oNN&h| z59R#4mr(vJFA-nXMsxHb((?Oo96aVGjbp#T2T_;^gy``yfonoMLEc>+f(IvN5o_ z+pX}`3R|t1_8Q)%ur`J7Rve(~Y`>mtH<31%>fnTpsBprDR4{H6!8DKs<y-o{)I+ttFowCM`%e+(8S*MKr;-_SGN{pQs2c5zD=Yb9F=K2!wWwESsJ&x9@ zQ#k&q>OmYwEc`bVi6PZ3P_*;8YJj5P^EFn8DdHDYc0n}*#k@;pT`E%c&#F-*j@2%+ z74gqhQ!VCvhJu-mZ1oT*li8t z1~ZIUaY%U5;}oy#WpSo7nY)==^Q-#%r*$TtgqBajnvNP4GXM=_8X@{-z zr_$b3uZhP|EmyEo^EMC8#M8{|PRGgtl?p8+r;aB=1WlrTB+RbO4M>{UEveoZZe>xJ z4_p@mjqEiHGc%M((_TWsOjwMWRGhk_-#eJ^$2s-00MTeJ9(lGiKI~T5+Y6vR=mv0+ z#n#XNYVA~DILW7b5+F%j?Rj5wF^Rdv@y`+yUBvYm7DJn&P2!4(HBO%7P&KqsK3@n0 z!vA@iWfs`UNy{@CkRo1uCK>l|_L;O1sk{K!?5N>|tdOcu#EMv&k%~SfY(L5-Y3-PO z)QaRCJ0MlOw<8h9%R3f8qPS=0Vw4Z>B+Z4LD<@N`ffj{%G$!HRWi`MgjVU1tIrWI| z^U#xSSj?-K_wYM34yS%uhBR8}w#%dJLn$zi*Nrss@#RSlPNd>)4Y%qRX;+3Nr_6|gf!GVW_WN^+IC({(1r1K<} zg7!%qu!II9LC1!}N<1t>46VoV#eb~pG{{Fe*m}H8jz6lx2%PXtTvwz%*0aWG75c>TAKCnmnpfi@q#F&E{LZ{|Zru;xt{plbEO#bLR~ z(qSy!$PoWM7?XuFGmG`g>>AR;pl3r-G%{Ge*?L53;(dSyjAgQ~fc1fqD+&)i3|Zpc zL$iu+0((Tp44DCLaaeSA6R5ks1NI$Y+HL~R(M-TcfL(@F)0l@_sCw6B%%jDr4-Yk` zXnrdx-Q(7s`d)y6RJnmnB64GY4wodZGu?DGo316?!5l`sIPz9C#EbO9Bk1lp9HU{w zG#ni!pVh^-qZK%TV@vVL&yE2UrrtVaj0tpxnunlXQ8!Em3XrU7fxq^!g^*Y{n5;dAJj(l^Z zwCvRPk5YP+K*TCeg!w|jFt6P4Erk;dlYVksTt2_5u&c@>X*O?REto^t%GauFt!m^4 zTTf=gXe!Sj7LC=BSfr^Ss{K{kgKdpflG#R??UAvJ8)aUqu^S3|MKQ(%dr$2Fq{yZ} z9KbvUr=8vdBgxfA3fp?iNvqn#7lx=HvnsX_Jv_vYDz&^C%?>K88rd@B3`?Z9f(om- z9l7pS;3`&Ux-biCR(oMKj&ENmM7`QI4E0%Eb5XOds|@YG?0Ova z%eo6ubErEF$DZySw28e~f%3|W3lef!E#IWDY`$4xh?_AfTNF$~Hrs-^6E`oq(2eU7 z8)IiBPCZhV1F#Cqj0Jg%SmD&8Nkx^Xx4;!RlAve+XIj;vI<)zo+lwqJ~?;dj1y#36c~UY0wNhqG{}9@Xzn4J|R5+Qg|(yv1;HZ6iNU>b;lptw7VKo~AVmUU_GUnjXy_dX1A>qCJ}JkmcoNp))l02sYi`8R2#v1h zMs5-R=p88L{QX~+pMo0j*u=fp5;G0iZ8{9A8F1*aF%@Bw2?ieIcvo*51o%Z^(>DzY{^XmB5WIS=-WnYDtrz6U(c<^t=853- GY5xO+hUCNm diff --git a/lib/emscripten/emtests/test_mmap.wasm b/lib/emscripten/emtests/test_mmap.wasm index 7bb65037620a4c5723de8d0581df83f289aad693..4f9395d72b70509ecbba68b229a6668d948b974f 100644 GIT binary patch delta 4168 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 delta 4002 zcmZu!3viUx6~5+$&HLW$<^jYckO$C!=1&6hkdTImij`%F3v9C4klg@H z3~YFWM|A{yQ8Gwdtd2qih5lf*)D{LA5o)V5>e$*DsYPv-!H(JvXbU}e6H3OiGdcgg z=bn4cx#xWMoSXkVET4Ep-sQ<85MKsyvP_BNk1UhoabzGRkC{^&rT#edFVnVbL#UEQ9?I6vL2YVw8xJe-6`_7va zoVJV$#(DzF!=c!!1f~|P4zvYHh8|rLY3_>kEDH9-$X#|+*SabiTu0pe8@VFBD6h5E zNAp`-TOB(uN%bWFaj%1c*Fj0U&*62Lu6A>Ew-|Z#CZ&!NL)Iy{bd`7=E?py(_#C<; z@uA?;^)%vjnq;<+^f{4}tm}JKs1{0VP+LVpX+o7*fvVDI4XZKn1MjAh->Pk&>R>TP>eaOjFzEqtelqPu7P}7Wz5T>H9m()T&j67p`|pTMHfHh z>K{emtX(*N){fpAW4t#E*{ZaK0UXwTyHCc?8QrDf=iOAMrk|HodPZXBC7qs^gw1mj zJ;!x-Hk`ML-C#$#3Hf=rna`m+k-ksQA$^)HL3)jS1I_$uK|eG|@0wMzb}(=&uIqx>B>;R^kwO(TxIj$W9O0O=pcnFtR|;+I@+oe`Uh~ z3D3ee-TpTi;vILqfwa1=5{9f$-3q|TTjn6r#r5|feW88}(#nQ%?~tVHDt!c)on8f& zBu0Woha|d1n#=Y`bPpeF_%dfmLW>w|h_WJTHBEpQ}MbjFUMYuGo z8Og%F!BCfo8|r&fg*pL&`di?aa_xcVYz}5n!(jZ_1Kx?*a-CF1vrRIGWzj69&IvkI zX?6$mQBB08kQNHVMKqhk(i%L(w59E+ppsUif`d!F$a!<=G3uZ;mwp7m5SG)>G980G zYRLR4f151{vyp_`^kpTwgDNh)5;T$E+m~hBRUnQra;i833?)NH5Fkzv7+_%TDn+!6 zOeBg>KLL;`R>s}J*#2d!!O2qtMRoa@u5lO_^p1im(6VDRvaqxtzB zai84Ojdz%cbfQNBn=V%1R8*8{J-P~-_^U^YwH9y)B|RNwa2tQR!-pt3+ffW<{2v|Z z?lRm%@Jfpqii|ig=EX)C&k6q=C4L*uNBUv-K`7>po!vNosZ(&?>s&v_fmT5{fpIey z;8`UlPKiooUBuj_r``zh?oz{M?!!2zjN!Ok`lk{U3&$@1Vv1w3FwAmwqnuB)>YWn= zlvtLEN6X?rv?lqch@(<1$~@G=Y%0~5O{ZDHdM3@Bg*QeqO8Dzm1yt}WmUqS!Mk!_B z#KJ?235-!DL}ta1Vq8zpcHf9^T;H`%Kwz&DI1_4&0Lkx&dHI+GtwhYV!z=XvAs}WX+3xyYWOeL%!fit zUi&%V=ZkgU0!-zf_r{R=`znyNtM5&a2JGD5|1M0ks@H!e!S^gW@C>9Cu-AaTmbmt3 zfSv(k27hnk&tN8ByQvZG;3qaMf$2PB^G>Mc&u*@TO8(L2!*Dy_wPgrpCJf$-<4uFp zpvF2e=mBKCv$Z>ECZci@ooLkXrfqHy&ddt>nM5xmJPffm0f)G_ew!ONJicusOylnD zE&11hZjvw_W}InG>`>Q1+?{JcuK@<>I^VuM2QRed(n}L}jGx(FFmY0r?$Tcb7%vhs zo)Upsyk@0@FrDhAr^ocH!9MCV3VG^|5ESxJF)*1B`OBfj9GkPSB7u)2!h`ONE2o&YV4Px~=8u$OI9=r+Zuv)!Nh8Kg>*c*Nr1d45LZ6vC zhxO84tQLLz%_qNAwgTPCf446$9S3Fe*&xtCk^im0YE@jhzHc`4S+jrAWK#wuI>?8f zDM-gb^L(~Nv|f}Plvs;O2dzIm^NIwu){f^=AOXolMEL##0(CDRXu*T(2Oq$kg$}l0 z&VGGx5mIBg5&3ryPeT62;d_zur{Ms~&v^b}h7}R_Tmxx*ToM7xMB(qY{b#$X@ZcYGZ7$PUGEGKf=qz(# z_tR8-`lZrTGef*&u(064GEpT~5t#u0@$oXa$WI*~4~F%}<4;Pt3Rc<(HscfHm`1 WT{i2H({&(SN$07r)o|s^)&Bzg@Tx`t diff --git a/lib/emscripten/emtests/test_negative_zero.wasm b/lib/emscripten/emtests/test_negative_zero.wasm index 25b6001506a594bf63b7f5b59895ce7c66c6b1e4..bdd0e80d8d546fae5e8454fde0a8a66a7fb9b8f3 100644 GIT binary patch delta 3767 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 delta 3814 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 Q*qStX?{l-|!0*=n7hfE9_W%F@ diff --git a/lib/emscripten/emtests/test_nested_struct_varargs.wasm b/lib/emscripten/emtests/test_nested_struct_varargs.wasm index ad58548f97192db89fc525a04d831d7920d0542f..0dbf108ad5f969a054fd8d227823bd940ce7ff39 100644 GIT binary patch delta 3621 zcmZuz3viUx75>lt|9^M0|HA%kOg7mNI5(RYd5}P2zy>9Mvcw1&A>lp6B?%kzA|#sx z42EoQ5*)PEnhV5=RYb-IwIk)Xov9W}2bm(YBYo(!(^uL`QDLmDud#Np=k7+6vE7+H z_ug~QJ?Gx@oyY&px7q7g*tgQsAf{|%u^7a*DfFiqEr((-^l))`Oi{LJG5SG_T~t%m zNcS#ZQ}fPfe`9}BOXnTCBGJ~aox2q#H;nFquCCgF?v`+SdxA4-2ImW&GaL?g?QH3s zIzy|zNdJmxw0`H*8Oa&!Yia80T2x*dQ&g#X)=Xwag6Em$-B_Mr8PlvOp(NrAbWht$ z4@Y+NwM5%{`Xk-pyCVJJwn$S?xUYRrMA4+7)S3G`B0IzZm=*BPWJV)WI(|-phmT|e zh;djaoUFQeStV#p*EL|ED4>DjaHy(ER|Aa}PGBx@CAr;-p?YR18cECsP^GBqCD~>( z20>;JQH>!8YLe)*w3KNg9%ufdkTUg?{P)Y_^u;sG*b6ms>`_x8c=8j_PxukcJSXjz*a>FaN5?rQIAiw8-gqo=7QqRbJ;)Y90k zsdaU8)BJUHb?*0GW0m;;v7nDb(1%J#wlC$NIWOvOO(8oCnnc@2kx zO195%#|MP$WaGTXmc-Z)=~zmKClgBIM`#%u zjZ~Gvg#GQRR)C4|>M`Q%uii-XPt~JDTWU&z6U;Dl{049rehNHE&Lj&b7>=^r_#+G- z5kIK;*W3w41~JEiD9=TgrFHN;%)?yCoUqS^Tq^1N`K=qsTCi?ZYfZTSD;_n_#T}?v z%R1=Zkk1s(keL}=MF*<#Jq~o3F0P?wrgL3_gu2%_qC=I$sG1-uodHoPp*idJ=bR31 zqG_g!)3*l;0%{ej!hogJ@eIt+sytwzj)6{|jShL|9L$ksb1@*?^%W2hR(%I4D8n*R zaH>8?oHy%VL?1f6#z_EE+Lb|#GwdSSJ#j~iQzvgF(XkuWx{X&#mbJrwFXgP4#mpCX+wt zULVd;jhHs9Q_k4YiLeVY#jl=tpdf`Ys`#WxMFqjkly3AI_cQQI?P(M%nskme;u4=6 zYf7JVaSCFMJ1w3232(op*V1(-U847?-5mLBob5G|L6wKKxJE8tO*Rzbd9+p1uV{8hkLdo@En*qw2_zO*uKW5DUy= zs>vfGS|9%a2;@>M!S?|_0F(A<^)AEr2tc{Q1vE{FpHcewhf*99;vbT@_(|VBC=phF z!`H6^-pj~kR*XA54g;@)<-U!74){5cAFl&1*DateAn*)XxPsh4BYw)rv5x7)vZx>? zO(mJvC`w@ayZ$WC*8+yucmd!B3AS?}6Y@pQKs(Wg28yZDo*wY)6wq(%DP(5?g5A?X zi`IK~(as<50dOABVJRK7pW8CZGT)^7F2f|1;2U8x!eoR|m}Ko;2Q^~%-fTkevAs8K zC^j%vcBg{)UE)Q80z^es)(Dx3l(ginr7~1G^%csr7ZeoBlt}d3;&3y( z3)@J;op@I5N;d>K@EWp~;$6 ze2n23RbXmkyg|oNJNDp@7%aALdU!S@ed!UgX53F<-8SAp4}E!jD`A!{8VIv4(Ma@+ z2oYaDSV;Uu2R9Mt{)0^D{#J~Gch&ZPYaYS-%1;> z+_lqP(J$*$8m7g=k6IShGWiYQ)nE$4{H!9&TRn1!5rRHDQx=5n5eIV7LO zf%3>Kk`q}Ks0i#!^gr?R=KlniPo*9u(pNrAMCS1f_X0{i2bB@cD{7A~OuwQ5#UPW3 z690}xpl=l;fQo(p@gponHX2udl&Be}Y5h^|5Lb`S6&s%Uq+tu44LW28A~~e*R)XGA zR-%ef*NZBBpG4`tsyQoQc}&fUc@5J|=2g^IYgNI-*AVqO(?d@rgh)m_`D}TBDg@Ov s#R8MbnelWg(6@%mcs$j9{X~z`{>QVEU@t$l8rbR-@yk;c;;g;$zpC>^xBvhE delta 3673 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 diff --git a/lib/emscripten/emtests/test_nl_types.wasm b/lib/emscripten/emtests/test_nl_types.wasm index 6754a6f0916656de72c3794b9a2b9c221f74f4fb..669796b963505971b5e12565dc4a12254b8e4dbf 100644 GIT binary patch delta 3697 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 delta 3595 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 LdMp0=)II+Nxz9J! diff --git a/lib/emscripten/emtests/test_perrar.wasm b/lib/emscripten/emtests/test_perrar.wasm index 4df7353bcd24358401b5a1efe23e5eea5ecfebc2..d94df23133701e3930b602ebdef2a63b63523c22 100644 GIT binary patch delta 2637 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 ADF6Tf delta 3658 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 delta 3825 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 diff --git a/lib/emscripten/emtests/test_posixtime.wasm b/lib/emscripten/emtests/test_posixtime.wasm index df3392fb1fd055cc0aac05ac3989bba7d4f9a237..a7a455af3aaae113f367ba93eda38fe52dabaeb4 100644 GIT binary patch delta 3859 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 diff --git a/lib/emscripten/emtests/test_printf_2.wasm b/lib/emscripten/emtests/test_printf_2.wasm index 000bd448918cd72793a3f42fcea52519e426ee61..839d8a3ef3037df3a6be11533d58d086d54080df 100644 GIT binary patch delta 3607 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 Hh35YPn(#PK diff --git a/lib/emscripten/emtests/test_printf_more.wasm b/lib/emscripten/emtests/test_printf_more.wasm index 5bc1b3d1d41013f5ff77bd1cda94f7c2f2e2bba8..8dec5a6f8d9b3f63d6e7842180be82e4e5f25a98 100644 GIT binary patch delta 4279 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 Hlnws}Bh|d= diff --git a/lib/emscripten/emtests/test_regex.wasm b/lib/emscripten/emtests/test_regex.wasm index 32735a4dc5c42cf1dd7a4c868c1b0c5745baf2f2..3f9fa0901ba195b83bd140c7c27bad25fcd6a08a 100644 GIT binary patch delta 9872 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 diff --git a/lib/emscripten/emtests/test_relocatable_void_function.wasm b/lib/emscripten/emtests/test_relocatable_void_function.wasm index aab5206a1434745496a029bd1e8524972c4c730e..db5e5eefc3677cfc7e6a705d8b8a06008aaf4235 100644 GIT binary patch delta 2100 zcmZuyYiL|W6rMBpwY#&;-fWugW|M5rJ?Pg(?dDqfqb>1s{I|5o(GG>K_rTD58H9YhRC%~C zGQw(>C5tTcHm6W1lq$nxb%Y>oqByy^THR5(az|UHCx(Ygr5je|n4vu{S!`Qfw?!9h zH*H>3x7EDW?_NQL2{lz-h}Tjmj!z6%M-ELE%Y_GvlZAuDp+kj+Fg`R=W=#&QB?7Xgv@4De zADU(>YCD<-yVfd9?5~co_H5*VX)3o=(nGy2x}cDHy>g9ZYQ2#QRxZos+LDP}E*JUz zb?|xs0xvGXiz6G&#J#v58}$zz);q6hhnYv_GJy~i7W3jUVKZczxQNsigiMo&0k1jm zPlVlTQZdm3hSoWGa%&E2ZhV*A_)M~HH;z0L_gPGQSB48AjlB@M8a&%$mH^_j&s!OT zmiIz2o0ho-X*JJr3qRs=jtiXQKI@YgIbM8rX)Dalwk?Ga!P0GMx~tZ;KST19_BoPg z(gP%aPhWD;Du18cJxOpyrSEpj;#3!X4K%?k4dgr z*9$YV_pdtuq#+)t6SC;X5>%IQseN%?8h39~sa|EHPiu`SEiv`PbQG<2#q+HOdiXu2)ZLY=b} z6K5^R>uGGDVdNG~F6T1!`Ic85Te|4FE$Z>D-inlw=Xp%|>~`6Tt!6$70xe99$qd@Q zIV!ubtA{hW98>DEt*arW?EX=5(2Kp~;7Gqmmb3kDVH};9cpbpiaW(gFQCy_Bm2Jb0 zMSTd09V%LX$g* zNnM^UmqKc0#AIjGv@oGg?>Y!8)a6~>&bI(b?SJ~tuano;+vCue+fL14J|IVMJvF_v zoj!q?owo#O-6ieZr7R+7xJWc`iS?GWEmAx5hKM+S7^9fBAofsp4mt#Elwpf>DEq-- zN+~460>d%UIN#>ynq9+xfqLDr$U=Z0Idli~HmEJTZ;ULL5sb)o;bzpy-5a85O)%MF zQL!!Ri`~~|x@7_rXjgR)q(kwfBd|s1P5s(TS(t8z>fDoqF12fqx3*g%qJ${D3(QSR ziBdzmNa>cH*hTox8YQSa+6elrXhx55Na)VJx##cJH#oG?UbYbz{_}RJfje?Exu@>< zE=ungy0ks1Nt867=ti2uWmcx#IVo{Rj7FxibI& delta 2187 zcmZt`OKeRITIT2Ebz=ho_txyIts>Zunh_2uf?Wo8*2QQN3i zr#5O!6jgwf*THP`VDY1IDB`Hy<83F@I{-ikP9}ExJ4tepCMj zjy*P50B$*s%fSN1fCB?NW`PZiy8z%4&yE3empUWJaY4W`z!s4nhDk7Cx{%@VC~)`>KnD$we`karLoQ) z@kn|8e7$m+b?IJfI6BZfGSa^%IWjWh|L`p+6ak`~uOR0mTgm%5KMYpFOV1lDC!Vw? zkV#7*1j1oCKM*cMmiL9<`XS_n=wi7<$fk^BK0%yaLIl8DHp8oN`EV)_MX(Ib$+ z<)mdglw>+&ipg%|c|T-;^sM{QGbBgJAo|?qpdTJ^Gjv?<`$5tqC zC~~Gaa@nUWbkQ;ix#&uvY_w%cIcPF-0&&BE3De3+>g4bPog6j;H5uZH8l#_FQHOC- z4UqZ16{X*N;#w@OBubgm$ER}-r>zM-f$5NaU8OK(Pb5H~gXvY3N7p1%z=DZq5YzhA z=|hm#+tVv#U=&Bmz}Sf#aTZS8L?2^;coRUHfVwCkd>|l{mOglLDdtfbr?MZm8hx*wbaE>&xzXs?uR=dB%>gdcR8l|7j40a_|47;f= z6viJpASpCInwf?}rIrhNWO9J2%0fVnAdzZoAwOpjlIzMT&#Vygqm8Pfn6zP3pt5nM~3=_F}I+LCZp;M+GvI9;j@>c1UJ(_B`y< zcV~x+o%e3dt3A>UU!&%9Jiti=;%^*=Oe`NhHR2bQkG|>`a!~iqO(wEt&{WDHA1Pg# zdj$6CSLPlHQpWin+;faVv!&8E=Z0ZOe>RsJ+p7>!L4wW7nkd>ZA@NjQ0fDqbg+d&C}l-&zT@i$7$D8 z2iY*^RS6U(9xe&%2!zEz{M80KqN;xX9o9P3NV6k%H7`ALgZJCvJ8YHafoz0cqfSt^ zV6stHZnJnsfcq`d&UyOLvzh&pr^1Acg;5}KUTdW#&~#a7Pumlc4i=qvdH}QQB&T0I Sdr;WsUdL%*rK8_Hd*i>8QokVp diff --git a/lib/emscripten/emtests/test_rounding.wasm b/lib/emscripten/emtests/test_rounding.wasm index 050f2db67e7c53f7e5e353a503886694c4a35ae5..20dd299ba980331c42febdccde9578e814d39ce2 100644 GIT binary patch delta 4186 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 diff --git a/lib/emscripten/emtests/test_runtime_stacksave.wasm b/lib/emscripten/emtests/test_runtime_stacksave.wasm index 5afe815a4321532f9e681faf8e6ad9b1831a2e6b..8f7a420737f7bca43d05a765965284fe791d8574 100644 GIT binary patch delta 1779 zcmZuxUu=_A6u;;8`_uO8_FX#0)^>l+O#%@wGyQKLd18|4+UMj8D`W20_sOtJi2IXgZ* zGM_6>s8O!9(l*Wsbv*lbN^J1=?Ii1VSW=fMU=ad33-n4PMnA3R8gTdRAtpMs%IHpp( zzrQ5`CbvxBz!;dofSWdG-3S7+#zX}??vMyLXTdYHFv;}Ux=`=(rtMF&wNK;cuqNNT z&Yf4_fZq6TwLgJ+^(${U*KVN}F z7eK{}O7Nn{rjk)F>bq0^>`Pkn8itKDGQk`K*D;wFbsdW#OGce=Z9zyjI2Qrxb%r_$ z6}1etIA7?vI^UR*fOXRFnPff_PEwi(Xzt=QOIm24r42w35oyzEh=`gu+V(k;Ba;EF zOGYu^n*RGC|KpG^{97RraD3)E-xuIUP?x?D{D1B0Z6gm5t?svy0a{LlT#J^nE6v6g zZsM0*u5brexX%vCn;dVdk2WV@rTW!o2$J88mNp7j_gdc~xzM&kvcLTV$;<8kKuRs+ zSx8-JlmMyfmaR54rQ{t0?-+jNpuB6~U4#1ejUiI1&szwlKn6z zQQcBUv?$oqP**elNWcf2PNU?WpI}La_kK(#8hr2mP;y!9I;ZXf2WJY+BX8zuzbf{{a=L-++W&=N^X?)lq*9 z?+kk~jA7a82&wu;`XlYSgED5)C5x$7N4i^+vI(2eD#~VTmbQtOv>lA;S&viaRz`Ni zR>hBaiKIkC2@$#qOtedhQu}m}kyPm;NCTfe@*sB40HcE3KX;wgUIe-cm}JUACNIx1|d<7Fr=%e)fVzXz34W5o6HpcHPpS?Jn$Y z#U_|b0zRn$y$`M7QB5Q%iOKq;F~J98r6E4}rUnv!P@hC48VnDfyIX7%oQE@WzBzNw zob#QT3)kSYYj8PqjDa%>4jWY*8f;W@90EwPQMLktBVAP@ayI{RFq_Y%i>I>v*_lFd zj!7O?cPd*RDU{Q>hoE~Eq9DDM3^}s5&-1gn+@aZgCN(+9sz`7R@(`;_rBdlqDO)V3 z#?zBIrg%qn0&|7TbnO@?t&}bI6pI6e6-OR2SIVSwxgA{{Os!sV6?=zLCKp* zjAc!eKnBJ@0w#l`1L&lvK44m=-hr6JNywg1xZ}Plh5Y9rrg0Lwds%99&cV}cW$;(w zptt;Q)|bGlrwe9_#eBglO1eB*$g`-P8XwQimL^zSO^p|`Sr$@LGwI1Z+o02&BSY3i ztL#kX^c>q-T~Q5Lo0=+(6{lIkcxf(wknD(@B-<8P)rgqw4cSsTJ(im+O$?XQnd#xv z=}eZb=f&ClP@z;F&X!B8)kp3|CW_g!tkIp2JDkThwzqGNgxlNOjSKHVv<<+C83JMk zvZ=TcGi-CpK7Gbp#rS}dL}tkx!Q?87879{lvbe#G>Vy#Id>xAgY<9@Aj0Xq_a()@0 z&T|?hZ&uZ5)s=0LtKAs1l_>!j6pGCRvzb*VR0LFaNi{`71vO6r1j`gU&5C8Z-AePm zIw2twG6v%Y%BE_+@3$BIwq@V+TN<~S$-mFTlFtjh1~ErWo|{qq7N5+cA#1hD%6sXvZbxRBJhDkxw&_`e}M(}t36+md}nVbEL3jp z9S2gn_P<8*Wny{a3+Ld)9Z{@xqg7Lk)u5+gP{EW#L8k^$hTVq{vxQS&;c1zXxA zCR#D#?(5qH5qGw4iX3!eCpoy&7bCfwXmpMZ!o&u86~qR!<5R-@t^Y;f?!Z9nk+9IQfeJ?n_*dMmI<_fd{lkd& z8ZF&^Kw<0FAVHJ=EWuWa?0!11(})WL4H4zm7We+Zfq?KzEy60jxv=}p;Pz;XXu>Ac ziXwy|p{u9~onzSR{f)TMy)?KRV(u4%u}F(RL;(SM8q5+xpzv&3NNI7^A*2V;I`kkc zGvGfepg1Vm=dZKs$3c%;vaCw?u`5zkv9D7xy>||_uUsT)Rb{AL6k6raVGbiF>2%EJ zaZE<^8BuT1htP{M!r?P0Q)3jBq$P#zfaS9tlgE5jQY;{TWK?=-lkDjuq7Cp`lI+}} T<6WGd8da436H9e39l!T4PZyV7 diff --git a/lib/emscripten/emtests/test_set_align.wasm b/lib/emscripten/emtests/test_set_align.wasm index 8cd2c3d7ea135e470aba6925d31c79b21b4161a1..4255623cdbcec035356cf6be8642182759afa280 100644 GIT binary patch delta 3640 zcmZuz4NzRw6@KTw_jVWFCi}7o3rh&+vILNS1BNKp@L-{&QNWOxpGn*RS>$I!fQ4jG z!V-m~{wKK+(!^;srY0sjMprx2#Jx!<=2w~BjUp4T&1*dLVIv2_aUJDdR^ z_QPsnXVtAYRD#BI(13xW(4g3Cs;bh_K%`{{JG=|7w%2mV#x3={TDb+EK zU{Y%IK)AKPTk$7u8S1GaJqdNKb9O@0x};!uprtj`8SaP$NwclDr7fr|5J%L~uJ5MQ z*Dp-<)YsQ1K6{Q;<^e=}ZVo;-DqY!bpWAYES-pLd^CdNCRj8PXf#5Q9#piYzHU*Vz zw~-hd5VDhuT5w1M4q9o(48)dMrm2WVEjP!FHkWa~O>K;@o%%2-Hjv_8n4`HDNc9oT z0=KxJHQB1X7Bk(VT#vCp?7eYTN~iT(q=J-I*kY`dK4@EUMf#^%w$R?3Tjj-uY`3Mj zjKB22E3t#V@+~KgK4A|5xT8r4*(wdooGu#;^=_^wpJO_{%=kHG;5lX~b^JWT^J2u4 z4(FnWJm4U`M=}@DVsRQDBD#{FBbt)6foNaWm*5v6-!S+ef8Ph-kA9GC2alg$(C~t0 zMe6uP4KHfs$3(lu|G>-Tb88#!WQMwEYdf ze6L!?s?cjG^*kNZwJIkVsH3-=XQR#1y7*#ToW~TNgI;lS!&2~yv4$>MUxsC7n)tlI zN0PM0=h2OJmvIWfl-tTc$2r>~ZTq*zHoH!4NT6kFoAR>UsJVon73Ie(B;`ti@c@NAaRivP)M{seoILa35bpNI@6RB=eaT z8|dPQD79$&nAX`_w?MYIdTk&0#NoA>L{G2XnJYa^b+%5r&$Q^eOpBnRqiV#j{A++@ zdBQWdoR8$pKw{=l4uJI{?M9c7dq^*-W@dbeD}GOA=5oTzWjN#bfb~YYiz=EfouJc2 znz~|U5?4qo7W9!7)n%N~ph#+z5Q5Wl%hj|h>(v9Bf{-sh-BjW%AQ0``rxO-FQGDC8 zB%Z!)lxRz!qRJ<)MDbZmIj)$61{QMFz!Jiowz!zDe$FEEM`8ef!DyqYcnOYI&?&0C z;?2Mz@J7R%DQ=5IcI!&Wi}tpD2sCWm@)ba_Sl1pV`dWJ_iN0=s9oWYy;9jh6xMV&pR`!fj5QftSG| zc)kJr2FQ_@ftTwR&?g{J4Ozo{+(sjQ!N{}JZ?2@GMRhY_CM{h?VGMJza4^exz1MIV z&j4H{W9oZ@8IUJB20MxVX0Qm{&u#bUlmV%C7O*L=sJ*j|CQshEoysu|1K97;VHvH9 zUfM9mGJa2`U&cua!8gk0RFqLh@CA3Sh8pp+o!Nxm#husX6&aY4O>Hzk9)7Z_P=HXt z$)X~2m$ICkwMiHdb2j%>bm>T~|8wVU0zudhjnV900d^g~3iTpV5 zN}axZvbzq3qSx(duxn$~tHgZ|W+fBTw33fA9H$CR{fn>CaV+|)2YYo)9PZucE78-oJ@J+bC8MXwQgdqUr%Z$?FdkkbL04I+DD8 zpoP+)IqZM$SxcF!z6^N3@ zegV|xK01=&Ce*mL%RN zI|I)!%p1gu>#C_xQb*@$vQVap#PtQ)%eeNKntx~+d{y*O3 zGf77|_5Ux`%}3J{uco$Pqxzw_#63rg)85s9!jZ|Gi9Lf6keP-TmFVk74>QqwELjx) zc%k^gv47b%kfzTjCXQzoQTv(awVWos?p%hMNG4U(ZqllJ@wX5)G}B4PCa;r@c;|Sz xm-3y8ltOP>COPAo6riVu!#I`_b)W3DN0&VLXNcbY+;U){WU(N+RD2l?{1=s?P{#lO delta 3641 zcmZ`*4RF-O72mi2kGtIe$o-R;4=#l4<}L&iAPI@#BZ&DYAtphRm{4mGxLm?vK8_^Z zU5H_T3z&ciRqS?3_!vZ>!lC|P9~J9s;Wy{ z)dfWFOo@Vr8b}mLR3j>WNVAf*fJZlw*u*}X9^C@9B*+!5*}b&hqzeKlw(%XGW*hJa#yS|A+pcLck`UGW09 z4fs0)B*h2~_O|V2GrO%}PnMA+xbDXL?p+W257h^Yqr)08x*F zgU7*0kJsUGSgsyxV58(bMw42_h^ZJ1T!uzG4ws=5M!XKg5g!kth8;@8?I@O-C+N&w-s1!*5q|q#ASTY2j}9U zp8JkiW4*Q@fFpL%?p1L3kKxjBn3l@5(n+eZvy@L#gH2N0JU>s_d5S4GW9QZEH+Ej< z1WgJxQn;N>#(bGz$JzeendnlCu!oVF{5;Zk_$s6odH;qwQR>+Ob;p110jP^T?X^K> z9e-D4@2Xa`j=!g}_f%ZscdA(@Udtb{*YQ8A7BTB$cg*^eiM~q~bl7G)WT^}@n?Ge| zPuVSJ1tk{Yz|Psd@lXHEhEo)aBc5M+8OFu&+g?Swp{fkVV~2NdkpV@MyW{yx&b zRF5LT=xnmquAuPd?RTM2 zR6nXl{|_GQTxY~u(t|O=Y)Uv~)SST;rZYvxt~1>Lj zrhukI0<79%J$wlcW)H7q)qEzppV7m`ycPRwN!(;=<}&q@S%`2TXi#%|_&3StB(ct=U@dz*Rv8ff+Ju5I$6m zGNLghjvbegaxIyoMW$};#f&CT(KubkM-&QVV2?jG-%%(R<~fErTYT_XwKGqGhPyS~ znp>0{EAke}tuj5tvlwPsV>-7P%q>@+&ZaNJBdVHQM30rg&0^x1XGsxfjB#*cvmj<3 z=Zs6!d=!d!9?M7jym;MBE*S$46=r@rg-jWb>-g8U-5M-JKDIkLN^{PrFc$@0jMcw1 zwPRkA9rL0u0Q1Ds_F|0M#%w%aMx8H)+n+&ok$(i~Q~m{2`7#0z^T=R{$qhD#4=FuUif?V=t`x1aLUH z{wshIal9*xG_$(|RrTGk0Ufc6%--KaY3$S9k13SJF7};()NKATu$SZK{w%PwVBR7g z8h8{c#Jr8Quuz0Iu7dgE^^FfhxmX*jggN41=x4A%)Q88>=Kb*9$S;m8gyL8@k_D*R zJGil>0#RAS3e94+&>9(0!~AnVP?fM^_8G9x!Nl(!(}`TaFeX&lS4T$Q@lFVjkN5(x$;7|FH^%aFub*hUNFStTRTy3Y}8dST8ddLUK`DHRj?mZ?$g*;3Y$>O#j(#vp8zb~k)6N5&BgB8^#qj4 zi5C@i5T`ITQJ=1OK`6VIbzwQyvNK9A??$s16xNN7OLwzeIV+~Hp2Q?srM`HPII|-Q6U1B*dG1AK+U7;WV(n6?1ZC{~9b3A8*AXMaJ8Zo*S=4{j>u`s9$v8 zZq)qffFCh^<-i`)j~uK;&DnzmNIyMTjy8FRI+5RbXdT*oa%hGd%Zy9P+>9$%lY>i+ zE4U;-%oaIVgUd*zGz#0W&KT5-*d_6_r%RPAJx*d^RwfX3B?TYG>Nfc{i>a{BVhmMk*P})2J!)M!7XnR+$zqc=3LyKj%^MPkwQQ;o|u<`dqS*GnY#FMmjT*M zi#>AU5Y17s_4VSr1K%c=JrY7{#%We0#PwLiNdxrNINM_vt4`$>o78PNO`8>U86JE5 zMmGW1Q<&PQR+;z?!;RsGcvxsB9zRv?R^>A^iQwZEJ2hUuPiFwJM(oDPjM%z~_aXMh XseW6m_Sq_+UFqVDXDh_7W4`|at0z!9 diff --git a/lib/emscripten/emtests/test_siglongjmp.wasm b/lib/emscripten/emtests/test_siglongjmp.wasm index 5085f747a242b6a5fba2ec2fb67ab1bdaf667794..5b6e13c7b91e4e3ab7adb8cd4023987abc54f4aa 100644 GIT binary patch delta 2628 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 L(1abIEHD2TK1VS$ diff --git a/lib/emscripten/emtests/test_sintvars.wasm b/lib/emscripten/emtests/test_sintvars.wasm index d95f735c0ae4ce2fbc0f19d5e0b708721a5a23ba..85c55ec59df53bec56ecf5e15f125533a0401c81 100644 GIT binary patch delta 3568 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 N`0~Xv@t0q${4be;Lm~hG diff --git a/lib/emscripten/emtests/test_sizeof.wasm b/lib/emscripten/emtests/test_sizeof.wasm index 7826daca1cfdfe2a55dcd1de7545d4b91e868e53..796e7053b715998d06a227ad5fcaa98964f8a073 100644 GIT binary patch delta 3731 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 delta 6582 zcmZuW33OCNw(r(^y`*0!{jzT)xs}cW2@pcUGP30X3A-T#kwp?>=$MUwNze}_>7Xov z%ZR1EDEi$M7*w!&qV^7gC=Zc2rGJeNDH8`YvyVn3wJ3r9DB9;7gWEN%*IAnpe) zPQ%nxNzqw8-5fJ%dg)ZvugGy&a9laXoGFH~Vt>V4V5-f=K-DxGC<-v3e;TL&il%7H zPG9=jKyx@D%%!`-BRrl6kKtj#iO493ijIkaSS`+oh)@{QG|d&CV3(9MCn)ynNI!U) zPK_!XO*S@aOeNTeD@+e-1Fv1D#vv}SSbrOgl{?Cx-VS5_?d$juA|r`YUvqQQLMhIw z*1CmFN{XYhrlxUmORdt+R$0^R^C_{O%Erdq7F6Eca(mUH%DRGqO0}(WK~-Io678UG zBP~^8sOMWyy=aLtKiDIEC_dY?%9fj(8BX1 zZf^j;*Tuo>LZv>#<#m~!dUMgOvgg&W*NRXvR2{*i+Z3 zh)^LBDt|_(G%CcRu!QV9o{m+RF6nl8u}Utp^=1n9Vl{eupw)!?N?2KB9?w7@X7oUP z1dViAbkq&5p){9^wV2y8S4(qWxyB?BHIJzf5bMz+=eA^+fefrS@WKRY|O?i3G50Sp5#=C-bdHZpzQ{huF!H^JQ)=!oNx>$Zor7)(HPAcG7q_)`IdhY zkHHwNh*M25bCT5}R)oo>GM*=4l2+sf z9c`H0Kn`M;(#ph4xos9Ei!bX2L$cuY^+ccm3y8pj^|6Y?3G91(A-== zHUm;pgh6t99UxK;qJLwX)s2hDT(2}{MJ90vMw2|~TnIM87n7GI$GAguz&w)X(GLN{ z$_Z!ZL3@92$ZpEAK51b+d;PMjNmhG`v?zB?5Er*32;4}C;_dj=hU zMtgR@96pAm;;!doajaB8F&1OCkwY{T@_8vp33ZX+2`Vw7?B*M!jEHL>Zjb&MgKT2KYDj~Du72`NJViHhtryc^v^!JU8c(v37?P}S(jXW5 zTbx|RlO(rH#KdB9GtJ1b#v%-WzSd#{@9_Q{5jnUiR4GO#=g1{;CJp*ikk6zQ=^Sh{ z%#aJ zcEUBj(+P%Z^-G7-B?CzZF2W`^js;cjLMI_Q%or~Td-Ol%YmcdZ)&cDxv+m<6(Rzwq zL+dFtNjd#E{8vWpa2EgumCw$3Z zuyunDnNVQep_7OUc@5U^TXej|@LKzIxQiyHxFN^hAw^VZwNqd3(6K`bu^rp3SKV+B zd{##|ozU0)eK^ckA;!8f5&}?Y=}~YK46$mX;8lpTlB3}|7;4RkhEas_NHp9{C}}b9 zEY0nXp>q~mvtr>zDC~wfC}wb7_qYV;2k<*ULq6NB;u^1BB2t4F;s1Phe-kj~%qb1xgoY#w5NGSP^c7V8S|oX#v^F zC>+Jd({jTrYQK2^3dQAbo~QQ7Zy%2+_;vr1cynt7QkUNbiH)*xQYj|~!U*^do$$h!dV z0=_bI$SXhQL(0Q_;bm$+qUe%hIRJ*acX`w<@UwP}JWxD$*Ir^g4bymzjyc5m;^p_# z>9rNais)YPE*ulfSKa}I53aJ}{2>!gj1 zxsu1>_e~>;zrRmv6z`uNR~F)<6ia!Tj%DV65nGC0$+BM;{Q=|GK+uBB__^VaZ>ufMH6!N2h zM}eQEdgd%h);HW2pccw#j$ZQY|lT%LKHxC|sdF&d&$_;H5E*|n-$@Zawf_hX)v+;=@W0@$H2 zarCJb@>B8j?eqy8eR{G6p9eBts9^f%fd8T(_!;15;=c8B2>iwRG8izD?^Kcg-cpTG z{B6}7gkcT*PS#^!7e?Wo%oxdcNd(-b8byKnjoSc<0=TI^(C(!#^+uB)QSpe%pHXFm zTqdL8GnAu_IM@uoiz0=vUMeNQefClVaaR7aOS*N%E3Z%+vH4zV*KOXfKhM-C%4cCD z{=nn~yt&6iFZ^@N$;2TZ4Xbi#*!m)V0OH zDJlj;ZomhV#M(d})i@3+`!i({&lK+lwh*{uYbUioZXHsTDZQV<*1t|yCK-ID+V5q~@l^ttldRe&kt z+t*vDt$$+xf!4k8KfpTOqJGEwaDAZYEh-kKirihZV3Sy}tBl&CyGBHB%Cea+XX%vH zwosXbHklYFi>LN4gX=~5foUZ_0(loHjk2xXZP)QfFkKV)4}d>VHl-0Slp(_26B6kz>g9In zVwV}I*6z{!hAth44y3!YlXQ>%3P21Qllb943ZUq9u#Vc52m8^@c-F$7t-7F*S$`6L+%;0BKJfn_Q$~k3Bk_$Y>S82FPGiLD9Dt-A?m82AFz9~+B zP!PR?3~x6Xo*f^OhG(~#J4OD{|FRt-_!05)(LT0g)H^PYA1#QK%8J8S(v^ZyrfN(U zcr4yijt?Vm1m|dcTQh#Kb2*Yfs5obV`*~UnOvH@_smS1{KuIp@|tmH?;-emXU7sG;avJp z=tbuW332hcY6Ab|+UW%mWUaiAMCKae_u5`jov4813j=yU#O!`IO{1BKePMZ&NV zF8e&J0Nuz)8`p{F@2nW?!WfSp|8F^x<|;$N`B`LA$%-*Almb-+tVLevA4ftWYhzLu z!G~a!*Uj+mZZE834vq3e1GiaaS#&AG47#V?l?C6~Z=xk$r`4GaX?X@qGTny5^m}x# zGx&030Bx+IHj%Cdv?IxfCP3aU2+w*q8wzzzK2n7#bV!?}_oge?Y|1d!#{(hXx@RDq u>|QzmPC@sVy)`@L&PgMOgi-XHfIG=9^S^S66p+9bHxZ z)*sd`eXcEx=ipb0ncoloVuk*xN5cj`G!Sec2n~z!(-zI_l2oku{r)Cs3bi3}rC245 z!uG1Mi@xa8^rGrO*|q`JC$uWUsXB@i`EmHWGXo5|^=gixX7VdCClOau|lsQHaSe35TTU1@E_ zw0d7n(SyGFqH8It?x5Hz0myw&zqm^t1a1)AG=tBsg(f2)?z08I3SV zqJM4e?}585X~b7sTQgOvy`;WkYK@X;FDfgmo>5n>jMt0GYJEN>+Fev#J#$LYq`Fz8 zo{FA5ln3;pDJ2y(ipNfEH7!-5sOOtfI&HQxq$t!S!zsmjQQf54Dy76Zd3MbpB9z9T zWaGZG4&;-Rb!@=l=_sm;+mT6pX~Mdk`vt9MGcTszpTJeT9tL^>VfsyFw%@k`N$4GO67^vsM1kt2-p*e;I zvRiWo&AqMXW=u#xZ@R})+{URI_{brT{E>tBnXTB7<%6lVY5-60S$n!l&1R?DM$Jx> z>oI$nj=LD&!wlTRETw?&Ww=-T7}E~+1Y={tL3G~aWLhlxq&!P-cgh}u&*21u-{6l> zA};U-C|To61tYo-7zg>`oQT)3Q9g9V${ekr+wRfEmT3Fp4a~+~fq-cK>i5jnP^j ziLhw+K!_Flh9g9Ye+>7<7A26YM58@Sd?pfBNyiFS-{l5~3pU)nLywI^h0g168^pqG zoQsEm6g@b4%vo2NhyQ^&4RmlD9jJdL2ZT(f$j!|puA&W9=^-|>nGUX@X13!xI?_F; zyNzW!Xr4goV(q{Ca-EC|FFeP7kiLe!4B)+$o zmfCf)Qv@x0sWdaygPPmu2{uVDC2TGpE@jj5EV@}$TqOm6TbkI7E~eGojeG{Arig;{ zwhf@I97O#Ao7*N&1G{LM+@W(kw__CPgU%Jh7^N6mp`t=2MX4{hv6iVGKWmDhiQu=p z6TvuXSG)SVG&u+%?)|tJQiE@P+@!{ZxV}ScRkv}it!ntSCY?yOZgfGB1JVNS7MH1IsOjI{}7uN#x7tGCx!G{3fH8KtbGxIUS24P-{jeO;vIP#Y~wbfK$Xk2ki=PGpBxQN!ihuWU7?fED$?mO z&SF$WOk8L3OohUUw2`#96P=i0b{35ltBC?DQwZi&PKGXGZRK?8$5ly8pQ^?TX+X*x z1=2d^1EeUX`BBkPHNv9o1Bj7)P2b)-JKVCk*-bjM^)^(>qe*_!HmaE!Ug8d)o|)O4 z+`&!hEo6SM4yL$`u3(qjo%D4izIv!Txt;x)u=9yIk3Zph->ohIKWo&aJ$_iW%ay}Z zFokCsm}PbsA1!|da>TtWUMJ}M^IzeTIQ-{_sXyk$Kx~svGUV_EY~W1>Hd&bk+>id} zRwjT$v|EV;`>&ixv`bblpnlq_96eFq8*y@TjAsS7A`CR8CK54G%S&^JxvOp`vhAx% zXbE549(s#AR*!@}V#(?Ow2&f^TqwR<{W6buV=-S2xE!|em4GXOuK=>`3JRC|Rp>5- zjCx`u+$JVJ@iKUYv7lW?ugomOE1t|o7gfc03RtRCrH(pJC;iJlr42D+!6MiGD0MOT zw+GDjV&$vbh9~lT%(qf0t{J3=SNI^@4>-t7;RgT@0N)}tvV}DA zco+31^Cva+BU$((Dusb&tyQ>b)+pY*{6AYrxcfGgC7yz?2!{a=13yLa?G(tnR}NQk6fhN&%B)cY%uQM9s!{I2C++<4`H! zXRo~=1*{5Al>#2we2(DzTcntAZwvso!z;#ZohO^4TW3)d9QWp38k`TVdHVrooCo|j zE8rIZF9_H6iG(iSJ_@pt?@*C`+f}nYe^0e?Frtb-$_7)VMSqub@li%$?0rdq@2h5q z;8#1g0CWhx_W{^Fbc-CP4GOxt;yPGK%hWFB~p&|e;CCOGk6 zpS(2b-;{xdkQEejpn;vaYG5}Kg(NwirGC%+Z9+kpUuVQ;N4S6s*IqlQZWH?tE+sQe zIYgN$S0o=E4n2aEhc5v&Ew!#z7ud~D249=+y!P=G2nDp_*hh*o(2Wt=;^`9L;2T$UjuLJ(p_`~SJu?9EMdO)lb9*YjM1gZH;5iDlH1*Dz5inRpp6v%i#IUnt=rAkJ7Q!9k zhqFs)?}g{aQ~#@TeIYlPdfp3!>UUxK$N~zuohTsYVqdGdS*zn$fg(vZcEihnSHYxt z8eL@gEd_Tu!j9AplkZUK_%%t6Ve)H4E^c0U1T4|?)##L;fE<*JX8F0zWi#+6u$;sA z&wxJzS@I|G-B*d+gSOw&x<$7-;#P`x8=b>ZJ@#U1)?EpP+t>&YEqy5(m2jp|J1Yt| z(6GGqmUjk~)-JP$m~^oMdWgSX>_Wxnj~C-~%5I*^o!F*Ck$bt625TmYQL;u{A(4zR`ZoHGS`q&U@4!k z;e5>;#xJSV@*65SQjE1vd~&sC)Mw;%pOe?waIy3{n{FKtQP=*YpC4X0FJ)9_=Z>2k-;6idPVRn~D{LF1wCSNfuPGl7ge+=+3=@j#T_tRl+0y zJJ|E)J$7v_mGXgkDx}6xZ{%=3kKsHSkLNNzTF1Ft-&Wx*27|ZGv_Tt)_*Lw{)ATZd zg1}lkjE2F1f7#)FC=QHs&?q;s-U0X6uBKY#$AN!4U@#HnM?fbcsEL5_M6f#oN@#IM zCp<}WTbx9a8~D))slTjBHJ}%f-)lfA&1^GZGLfST5@|HR1zsABa{;D!aG2Zh$jVbb z4N3L4O2{)B^dol*tcrm?Fg)-@42*!ptsP_GU5ea+3vrO-A@W}epS>z{CTbD!U^3h- zG9Nss(;EWg1eB+w#L4LBMX#)xWerV{R6d8?Jk_P?M3Y-y4n<;Jd4~N2fLHF4QFbKx zJ1_eN{3s7a_Z+PB;k*S{9=4DbsOVnu>=de&axs?=HE<|ZOKlg*Dq;1)wFHMQTHYpy zzYh31@XcUY?H?#KIiafq&b$(@p}7HfHZi0+*isw7?3(keR1 z9Kbn1E)<$sv$Q)M;n30z1m`a6L~zrxeqC!4hBZUp+S*S`a=3ov5(w(C2 zsnt}t#6BI%x+Zc9E$g5nUs-;xkuoUl(6iz9rD;yM8ol$`?98^mRH+|zGgWIJJzLte z!bH%+Ec|j2!#+id)RmtOB>SxYw0HYAyK75TdW%3~=$W!y#*LM&L(xhZiq20R8aaRu z#=(3ellgL^=s)cR=q^5=_B;i?>gk0rPJB3h3-udnt0`~hF;w!18#A+vMgtqA4w|q@WY5}5(eCD~Mko$G^rs0bJ#7y?93*2t(QqG( z5a$|RhZylfBI-dGax%Dfp= zpuNNJ9me0KMej1RdvMlc*#O7Hy7?_bqHzPGw|5%Pkj2hMCgs`0aFa|z;mTpTEPyiH z#@6s-Boys`=MUn>f)}WgAv^tra)i7uE1!JXex5;w?BA^F;T$htMLfwcM~lAI`Bb~m zJDSH!Tf~dUsyn3@@;Hn`Tdlm6+^(aI+YOADhe^N$c@)hYC=OL;!x&+klGeYFBO(VE z38a_$tX=e5`Gv8-;|pPxuGP)ZU5=pfeG=@F0&tH zCR^BT7cmHZG;$JcbL)DnS=M83)La_>Ulco>L`BE!TFrCCnMeQznaD_jL(96ek zktQiF5>4P(67({tgrN#Up}5ZiNy%`0t1A_z*#kF|0k?KWI01oGDbPJ|cM454bc8%$ cuf_!+3wj5xWx=dKeJ99?P!wRAUA5`|467aT?O@jH3Q13`6ks>uU@};_j}dn z|E6vFP22-f6-rc&0_L?bjk zUYwK7K2#Ib%G!D1m9;fx^)oBSRNh@zzd&IU7BRE3aZ+7lS*j+!)Xyy{crIxM&@8DmWm*=)G)j$&Y{t}{?IO$S8*2K29i3ZQ6;#%%PY zKOHo?1Hzn!D?GyOj&Pf97Tk!8f~e@27>L#4%!mkuF-_BKl8oj6#a0pN11~dZQ01V> zL8rk|t`FiObA&a4*JjXQ7vC`MTLeSpiN^J({UeBsBuc+zM#~y!*VQT>d&!I$ zHFFzgDcO3-jQYw-CDvV1Q#0@GlJbW6Wpheq_vx*a>LquV&8}6V?ewgnSCtr=Ro-1O zXMs`{oRLYCa=oOXyuMnga86%PJG6ihrCq1Hl#TYsc3$G!|7hHYgNRtw^I||N?h4@ZIyrcq zs8pppy-v$rWzD%q&b-E0EguzAH4xl}u6Uhp!=|8;?lhdi2SU1GL@8dEr4&fabQeLw z4dW_fi9TC1kxd|a>mW!sNX=TOf~ksX?SaUi+=1cf=*JZ62*+@9no#w@Fii~AvuTf^ zf$Z9zL3@k!!Cj^$VM4moQryPLS~%d4Y#(sY0p<<#O;Zh=(Q5#lfl2msl^zS6ZW}!w zG`Swz&UAc-@pfilJ0qs~L52s#zSv}F4}2U84#NA?lR__xt116W<0GjDX}leaY21N7 zK!tdTH$lbv%rtVrTj7XpFsNknHOED_~2hu+` ziS~M4aI@F=kVtm15T5Kp-rbRhKZJRHMG3@~Fv-l%x+h{>b!AYQB-g%BfN9aR}u zmPB3=i*~XSa~r3^;Th>efnKBC00{wWOq(8;fC@3ZG4dkekoHRzUZ_o*2(|C zY9g{UZa@lG(T1v2i4AS0!8O#(PFzQ+8{KWJ(IH=&eF#}S=LW0ikWZDDZnB4Q6HT*| zh${1DCad`@ACoPmkSAf1mhS=sbxf}2>1eaGDxQHEU75l=W3nhI>j%l=$+9XU&?@u={n!7QY zLV&cbSm{+J0T6VeAokyz9P`UD$5P$K5r9~^v1op~tq0iU z^oe`BdBU!p{wp6AF?fQkD=`k9``F&DLU%d;@k|PI7M;!>)5+qPATFOxO-+zK6p!&z zWT^sTLwco~r@1tpaQd8^1!ZFGxh}Se;FLt>H}-&T;)TX^V!XYvOLit7O2W9R_%IwM zZ8RK*V;3_sC?ZKpx|UEU*@mDZb?&n~lc!*k1ywwixJb2FV--h4iN%ozu};pN4r$`n zdG|o3*flSe#(&IPR47eEnZJN6q?o1TeN6MAqN5sgJ+~2g-6n7MG;P))GEBq`5SQCH z!=MX^;2#_dy`9;TC+;!KEdQTkVTdb3x+720NexNb8h>6qBQ7u6-j1_H&Pp*YUYq{+Q?gwA`4& zTPTD3Apy=8^d^fq37f(^7F2l(c{9;rW}zhPHeTzctyX=k85Thk?XFdc);e}W0Ig#b zL4&RohG$4y^KDG(YMXfC%2VJK-LI|$6mMRg3VlVVA9vFH{U56V19?Av$)KOV8^A1A zE}wxj_)G(5nqL3Y0598`i3c;+KY>A}(QII|)Yl?hDor>k$=-RfzFt z*&zVA{ti3b3H|*89k2u9{1+W?3*6+-41>XhQWXZv3FX@`SWkO?C#aKmb1?UWljayqEk5GVX&h95KDK^8p9x+@C*gyAR5`Wf!wpEB%V z_$e#k#~B{?e`~@d@cIiQVJ^M4hv6Q^_tI;7ndxmk97#?A9sZx9U~{ine3?-K_VO;$ z;@g;%aVx{EOuCR_rW?3cCA)NS8;^!Em-zhN2kq~x(2I;D`Y#?21!DQ)7a&peT$0=^ z(ZEDWfg)HYMimo?iYkLgN1dlrG{|`pCW?k7k0-Z=QU;Ivy+ipgM8i`qCx*F=EfCBm z{wHGKh3u<3442+f`1@B3EaaJ}%H#WDU(IJ75kvp|EDR5P@$Wd6;^7ur)-gpE1RvK3 zIpmvtL#ZnBhn$p)3G4#+P&ON11I2RsD83n3K5hmr-}H#LzPy`!WH1iqh4i-R6$8&d z2D#$!`R8eD_-buLF5dyT1NbXoSl@&R&xJNdkB$rVRQD$Sa|h%G^o!v@$kAVan7l6y z)2g@^z0!{9m~JIBS_yM`hI~{1W}%VGb1|3qlavAved7TF+={pIkwMZs{#7hVM|>;s z?!voxX%J6*J5u7+V?A#S;+?%zE%9!v9|TQEE+%l zZh-4ex4H^^Y>`G0ChlGE4vCwJsXWubOcHm*!bgeszb_;~#KV6&1ee5=ra#gASd%}_ z7xK?0Y~nrxeOA{3-i*y+@uDO!#o9&G0Ej({?jYpE=7(thTytMK@}uTVn(Mw>Xw3JO z(eAUp3>Y8|_{PIPk=Qaw_wX**MI3KV5DhKsJ4e2{g0BT!3%mI`z;(c%rYwa|Q}@d*Y_uyP9ccpNXLEghCx9NL8g7bFjGl@NU}O{zzP|#g76W1-?_VzmwQso~>SGK2P%i znb{W0%+{jakl9)^%4}C2*-7$j|DPG1F33VpQT-v{hrlmT#lHZO;gf(TMW08fjox%E zTWnysf$>cg_M4bQ*vN1rH4nI2<;ztmNQ#_3q|!Fere)t7WK1C$Y3D-V(?<)XjGZ5U zO3K*wM4gl|XT=vZ#;=r;)~p-^>`0i{^5io4=L$oGaL3+$!$ea7RS2&wq|Vio{M4ht4GgKHZ>0*EQE0JxavKlq%Ux$jnPO zA*+Q|aTgkvf-ZA}SpP#FbxVB3ME%=4B8*^*>WV&KG$CHsWDbp5=s z5=M#2O+BeEu~YM&A!}`hShs0AfhTTmq4DVE{`na)7gLJ+rId8%bOG#1Rw5&HWU7~$ zFCwS|{yn2}+CsO+(Cw~`E{kI1meu58r?*hkJX$>Y(kQCfCto@b^muRU6@W3~;PwU@ z^LFGAsBXt$U@b0@_sRz_HW0IuD*JfxbL&(%Af~=HfyOPb4T?UHrdtQo3@S(4shL4t zx84<3g1cjO4eWj(jb~9H^vB15--J{709S-!C9~30elC{iDKuj9`L?6 zwQCL(iQ8Tu2DgdTuXmzjT3;UoRt|p2 z@SoIdnsTojP0i7Glhx9uH1JD62#7tAO4ubZi$vqT#V}TUw{K#>&p;tXwxIfFbJ-01 z87$`r{uAI&RN!dEb7fMnUCRP=1N3s6jH~Y%S`w; z3NWnmwX2SK2bcBt4bmN5cS5ukYANpwh1cHzqU5=GK1U)?@{EH#BA_RAycJn+s&zxHm6)k*U(pbtEW_7WHXmp;GE3I z+iuLq+hjg2J~SY6GXF}&uhbz*5vR&WI)v5y0SzC}%*p(`N>6@8C5^^f{}B5Q^@;w7 ze6NFi&xR|c@7Z+g6QLizSO1FOUyCJ&yXlu`_8+nBaG(CtuyGhmc2zLSQt7FM?7NwA z2-%n63Wl2*Ilv0WOLV-V;x^U1J&^R?W*`@P=l@O(|Yv<5ya z=tK->;w+*t4c}6$`D{Ylt>SF*vnlUms(dS;V%4uF*Iqk#Cf1ro0Y9~XQ450?`fsf3l0ggutwh2ndEjP$R;3BA!CSe_|pD`sInc$l8UU zO(bit`E0E1YMMpCATEA3j5c#mX3=Kp$tkqC>tq?dl>GU_1mE!aFoJybdD?aKm{Ylg zIO0?VfnPc`J*5b%`AQZ0@F!KI=aZx!zpMs*&`(+vJx?bPt-{lIvlB zdjCzem=bc_OOf=QP;1u7tpdkqmpEXG$g6+YeoBJ@-P)BT}X>^nVGk@uE|`Jwy;jPMP)--Vw=gyvo&tFbRJJ39B=9LSk)I zSlX1}S3Z>2w(!=66JZVWXq48gDc#C|b~M)0Xa>iG#(HjR9oh*Dm~HI%&4f1q)oyn0citdgHL$=bsoqy zH2KLWOd+4p{T&{<^YrKp=-=KIdihJbLPzV^&Ts-+_ol!cduv`d$OpDD-oL*a-Me1R Sg!vBnso1XCbbt3O==cA}gWRtG diff --git a/lib/emscripten/emtests/test_sscanf_4.wasm b/lib/emscripten/emtests/test_sscanf_4.wasm index e19b937d0ea16646e99dd9c579342c20dc04af0e..e01c5db9783697abce299543d5465cde9a1a203e 100644 GIT binary patch delta 5852 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 F`u~e+uC4$8 diff --git a/lib/emscripten/emtests/test_sscanf_5.wasm b/lib/emscripten/emtests/test_sscanf_5.wasm index ff2ea0d6fae69b0c391d539bbc335506a970c466..4e47c5ea479b8b069ed0b22afe6f6e1af91673d6 100644 GIT binary patch delta 5814 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 GoBkgl?y4C8 delta 6018 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 diff --git a/lib/emscripten/emtests/test_sscanf_6.wasm b/lib/emscripten/emtests/test_sscanf_6.wasm index 37c7583fb5547af8363338d393814d0c82859792..5adcee63e5c6527b01e97ad609154f95a9cf6b21 100644 GIT binary patch delta 5855 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 delta 6082 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 V>f8-}a>%d8cGaf)k}{#!{{wcO*7E=W diff --git a/lib/emscripten/emtests/test_sscanf_caps.wasm b/lib/emscripten/emtests/test_sscanf_caps.wasm index c909033f39dfdbaf51c89c0860e17b442b861b13..d107a18f8bbb37da06de48cde03806d6b5633a2c 100644 GIT binary patch delta 5955 zcmZu#2Yggj)_>=|_hu&ZhRh=&$)s{_CYTT)gc3R=50V&)5X!Oy)MN+)X#_|pADU!> z5}K}p7aRm!5iA%HA|tYE#eyqf;X`c8PnrmJSY>q;KleL#28ExR-{jnOZaL-t&$;j8 zceRJ#)z&6*2q+aS5P(31LjP2wW>Wx~h&B<0rgbB|>lXJ)tWqEbA67K1AP0ufV_VV)bx_Ong5e|b|jsAs24GrVx zU6~_$mNr)U>gxLR&s9|6gV?F6T;FwdB(J{`?g~$jFb|0IL=n@X`l}lxmiy;6RyI`6 zU+AwdpW|OxUgh`AFK?{A#jj|h9e7g0wG0h@ITGekVBL{a0Pzo)B8IV%fwF0!FEAcAKWsS&eZhngX$1G|=J{MU4kg z6XAbZT14RU-b&Z1<>o_-79k()943WatZ$J6SGid)pX;lxS7Pi`*3ncYmTLaFmGhS>Mdjft8BVFt%Nu7l)G9vbtflp%h*27U zrt4~hnw7Es#)ZC_b=8eklNb6bYbVe5Rr;0A;*y#hnC0>N(~=Tz^!uG}?9rxW0R+4; z9K128)MUhXV=Q-#HGhGud1J?G1*n*cf#5cD#T(-`YzitFF@`f-AY{ZE7eI9f)MmAb zR*9zR`yv4yejt3Y�)&dETxzqW_Vc4jZ20@q1AEV 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 delta 5903 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 diff --git a/lib/emscripten/emtests/test_sscanf_float.wasm b/lib/emscripten/emtests/test_sscanf_float.wasm index 5807d73d64ba8c3ff255eeb9b99a4c472e0e9968..3bde6bce1f533b826b8558497fbc8bb961031b57 100644 GIT binary patch delta 5888 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 diff --git a/lib/emscripten/emtests/test_sscanf_hex.wasm b/lib/emscripten/emtests/test_sscanf_hex.wasm index 338c0ace327565d29ba412ce28fe77e5f288d18c..a3c8fd7cbff7f4e79a3a538e18dabfb34f0afd05 100644 GIT binary patch delta 7138 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 delta 7321 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 XV2eWmrrA}S?z^J|ihM7Z!1MnP2|$nr diff --git a/lib/emscripten/emtests/test_sscanf_n.wasm b/lib/emscripten/emtests/test_sscanf_n.wasm index e5dc001d6983d414488f9ea949be0bd1c6eb1d82..be7e6d8eef652bed62a43d73154ab8797bab3f26 100644 GIT binary patch delta 5945 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 diff --git a/lib/emscripten/emtests/test_sscanf_whitespace.wasm b/lib/emscripten/emtests/test_sscanf_whitespace.wasm index 19118832c20a0f08379237a688c03dcb6921dcfa..cb1b462b21b79978277fae0508de328920053b31 100644 GIT binary patch delta 5942 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 J&92(?e*yib!>j-R delta 5876 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 diff --git a/lib/emscripten/emtests/test_stack_align.wasm b/lib/emscripten/emtests/test_stack_align.wasm index a120d6f110355f146b1f2a2af3d6ead74b243e2c..10172e1a8e6723427010192e06a7d8c6193158a9 100644 GIT binary patch delta 3676 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 Xr#qbSPY(xxFHe_UN2=tS7efC7nIdua diff --git a/lib/emscripten/emtests/test_stack_varargs.wasm b/lib/emscripten/emtests/test_stack_varargs.wasm index 309f838f815ec75459cc0c9721dc643e1edf4fcb..c726a6a3c2bfab772f73463571cd11f6ff730a6e 100644 GIT binary patch delta 3657 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 delta 3569 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 XFP;bIjbnAdUd|M=UaS^Z9dG;}?-x%K delta 3621 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
X_R|46?l?$?@LlwCn$95gES)Rn-SO;O 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 delta 5950 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 diff --git a/lib/emscripten/emtests/test_strcmp_uni.wasm b/lib/emscripten/emtests/test_strcmp_uni.wasm index 0069da1a98317a68ba23d40a4658f50c30a6b8e6..c070216d667c87acccd5b9f8b6b7873e60768971 100644 GIT binary patch delta 3801 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 P?#mI6ot!83KXvfGaxrv$ delta 3885 zcmZuz3viUx6~5>G|30$+lKm4%ve~@O&2C5}Ap{Z7Ik&O^x8+jx`GooxGWBW_WZsNlc7~ZHy=m!!08_lbQ zx`(EPy1QD!TSLo3+j_z~7+12yt)YQ6Jp(OWSB3Hc$l4fNN^aTI6CPMS(9+tuVki{e z($%w_X=;zrJ=oP%H`v`8Y;TWCrd=nwDsu#b!LFXx&Z#}b^@j#(!{MeLrtN=odc7WV zNr`v#x3+Y3%`GcuF`4_CY<^i>WLy(XDJ76(usd#FHi3}Oz{+f8(Ybn!wWwjuij`V~ zDLx^_2bWvxLm`&p33hc2Z3}Md-`>(2Y%iV1me_*ZTH3qWbO()H zw3W@ES!i2p?+&&!HlxV0Wwv1drf?^#cWvI$y{L{9ReBoSii%r_|#wr=Z zERlpsB;aO^%&}D$*7}f%bPNPsnC>zD*bQf$>VUIOI>C&&9Y4S{wdk0w3&0iq%pTBa z$aHz^G!&V_Hg}TS@HH+bxq*|Md=}?8p5x^CD^5{^FFQq@8*GYMq?jc*8QqlvPTD<^ zl}#q)(d>Oh=j5Ct`bADN(cAC~sFy3nFw{T!x&Ww;{yf(KY4zf~j^}kNQYYTm@qL|+ z_?2$f%gg@l&U*1D-C|~av@>wgB-<UtwJS^yZ%tedv}_7>}O0WeX6KUp-3nx$4`A+N?c9$E-R2ac&qkdg)FC5tsOu7#rvmc4Ssn z2l)sEoC%KH%n%ydQB%I#(QX<-N8L;pHdG&B^B6~LP_437LrE*SE@>qSVKo+Zh$1#ZofxZlj+hUp2mfE_8T|QvjxND486>>l{K;lW#6>bvP+v z3AC-Uslafd?lDTiu9DE*l-lT1Ul;$_h#=HZwqj-C29+lP*0Dm$Xq@55JjROvNor;K zw;c9HQ!jzZS}`*zO*n8mg^RpHu&KkkHe}5BztOicJjNRUDQe;NyC&^)vYHMb%XAmU zd{b#LQLa6PSqW2zUvtAEBwYaTsx3W7e>ZbdgCd%XV&p39IhYd<-Aq**`It|z z{JpnqUS#N%hab;zdeveYrpcEdPX(`h=kYdJDy^gW_Eq3ghHq^yhI~2F9H1{c(VRcK zfU1dE?hdgS7c29%Sc~~)0U?s9Ln*>a>Y|L0RDRxk917%j@5~|k(w&uqU-No>Y|SasiWA;&l?Y$M_3}eDw*xd}5xfP`Me3$LTOy?+6eL>KmZfkf*D`W93WP6~0BS%M3!krBOL zd;$cw5}bqo0Q>|@S|{!Ujvo_X6o)s^)GU!Om_{bj2Y16fd1P=^&K1CWI7P^c2)o;E z;1#f3%f#1!Ujv2higXWUQfsh#jG}lYE*r{q=lKke@qK_9DtFt5vLH)7Hq=h^%Ft|T z__MdC*{C*ZhYR@|h71q467%-(5Unh~8({IwsX8_ns@`h7M5w3cs<5t+o0?gz8jr_# z8z5OhAeB-x!moqC2qy@9I8w*MdObyWWJuBvAtanrLHPqUD{~X=L@3ex21*I$6E4yAp1amG`8>P0`!#DTN9ZxKvD`Ff&ZHG#Yhl zmGDm(xFme zz34~<+#)w0SwU^#g(E+Ptj^E_R;+;>> zWg~QzKI?)Z7v9m5e#WiPstbo@6KP~C&9c$c(>mjpr|;OFYl%cm^cd6Q*7ca{GgbL` zjA!E4uiUZXDaXScGL*kZk1eL!yL7BL;Ig~}mUj?S<72Feqpwe7V1{asP6~rdmOoKT z>cdYIJ1)l`xN_G-BN%dWqO!seUbk+bF=Z$BsvWvSlmWLX#58mkF{V7Uu0WsgpvM&Q z<`d0iVf;j1ji8G|QwsE~i7C+8v?~+SF|(6i$64xvp=ZIusS>6N{l?2z-a3(ySWKC+ zQxB&Wp)rt`P86q7dIg*|%l zX#>`*r`>+1YCxoftV2PlVv{LqRb~S3rxD8=#}#4RAAPK(>R|R{rdSoKy=^99!KN#RDYE5- Ka=G>g2mS|m?R?w- diff --git a/lib/emscripten/emtests/test_strftime.wasm b/lib/emscripten/emtests/test_strftime.wasm index 561f44349df8f1c6b09eb0ef8751c61af67ee7f4..ea2687c7c3ea77b4fe6394385b685ed100219839 100644 GIT binary patch delta 5108 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 e?Amz$*h1*nKD0mB!9V^QCHh)tYfeJ| delta 6840 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 QOa7mUQ+4RJF$zZhKg-Ke>;M1& diff --git a/lib/emscripten/emtests/test_strndup.wasm b/lib/emscripten/emtests/test_strndup.wasm index 3d032b1979c10eae213d83288fd4e3db2e81e95e..2f7b39502de286e7363a4ed7929879df4b7820fe 100644 GIT binary patch delta 3879 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 Pz9(HaoSGmPJbmEbi`8f8 diff --git a/lib/emscripten/emtests/test_strptime_days.wasm b/lib/emscripten/emtests/test_strptime_days.wasm index 86c51f93e59de29fd4d11ebae17a324e2a98e6a7..988fa26413e229e4dd45c2699efdf8505030c8c6 100644 GIT binary patch delta 3582 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 delta 3496 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 W+|GO9%`3T|zcM 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 QUC0zq9IX=je*VdS0N4b25&!@I delta 3904 zcmZuz3viUx75>lv*xl^EMYW=fCIN z@1A?^dENW!=kje|$afd!Nno!8TUsgGHjRi%D<$ckni;md(T0sHRhxcb%ikzoB^+Bn zE*y)75^KU&hkN6RK}i;}>^0%!l6W!{9V;vdt%@g-?XkvCEEZ3;CgKBQXLHlDi<6;_ zp7!#%IoLxj*UpU#ENX(B* z$~|w4zfw)xD#U|*9ieFS;u$lgw9Io}cFBy4NIx$+3(6u%e=MV)&j(hh1;f{OCo`L6 z1^beTwaM<@uq5$Auwn`DXRxy~+TYhDP0@m#iEvmd zFoMzO`rhEGzJbu%V0Z0wsYwg=hPq=?o|C>&S}Nt!DBRnzc2H_gkI3m#ix%u#mFSUL z-Kz&r_~tCw^o!UNI-exFifUs>4J zHql$u*4E~J?KOE$C4lXBGw{1niUiz#w`D}Ewd=&lug_QOQ8E=B!O%6y?>2OYgi^q* zyVD(&vU^`;NOG*}sy3CvWSdLia5pY=`#GaF|MOd~d4hS?a_Zzzv_#Ln;F%lx&CgZR?k3Asc1AImEKMB3C#Y@VfEiQ$a{&_zm=GA$_s_kY!;$j_L z%z=_MCqgztr7SVZ2-8Oi;Xp;$?m&mBGfDxom@+^dLNoN88q|xRHBiiI#>A{flud($ z5jKZDW`xyY1DiFV|zSCCz1C^s4n9&{4zU9u`1{ zrAAmemJ53(VKGm&&xB%rvOPiyYO$6ST(`ha5_`cj=tifZ9{@0gLAhiQjxh*Lg)d&% z;dGJ5vS`_h3oCUus)k+*4iSW}7v^78B2Je%tj#ECC|c>-_kf5K18b;?BAQ`jq?~;L zAV;~tz zvM7;`0~88G(C21UQw|1Lv?Ftl~=boUgoG4tu>Mf~Qy4IaNpBIebouDtw> zy;A~J;^^o|utF?kP7NK*siRlyUW7%>RI;jB#&KT_Oy&#s`R7zIL}cKh-XWQO#*hhU zIWbk#e9H-6md*o{Ix*z}6&Xe1Mi~l(JqPyv*LkZ3vuT`~eB-d}JEX!?Vpuh0!|}0w z|2RTGsg)&}VMf zX@HA)Q>2gR^N|`7ort^!@{o%^AN>nVPu zbzt3sS(K$yaI#rLch=C5+Q+^DN~#*H#;*at0h8v5J1OIrlrVzBi)fgEAC&soDFMd} z{1n0YmjgG#biVfbMWtr|Z<5JpmdzXr1HI9fn?&slbVY zWu9`cZs@-Pm>{Bg)u0bbd1SDg=+VKc;)2*vpixbD?J4pRowwQ@#Qf4;PcvmhbaPBf z_YLMSuiy~M57dj^Vd!rGUBni^8!24=FvYn_w>}*iEQqxV(o&up1*07R5r0_ORacie8JZx^w_j z3Pv*eL;z#y_z8V6nq9+!qVg2c_v6U%_EWhV(l@~d%Qu$|;vhAO4Sdqp)3Y`MZceA- zEr7SAo5>cyEg)*7j$P(ab(+R$ZEOT^M8tbDusRJl^QCvRz=qUAcg%OHBQlQgf81M^ zM}q}zY*<{DgdCCCA`M4UmG}KdhD%Z(K9CLUya&&^VU$`IC8l^+&>MsDE@%59a^C9g z%PE?Fpm7b)+p(Bv_l_o#Ke=NH$=}(rlq9t~LzMjY?Yy1jY*!OWI(JnNy>r(L!W`Pw zLF0-CR}*IIgC#cQ18pfhwM{weD%x_JLe4r&;iLW&M0qaTuHbfsoI@|4pw8yu35D9j zJVVcwWg9k8u8_SiikFH>Dpf}ik9cehhhxpnt%0ZRDXhkezwhlxxQm!JWP$oO;oZJGYa=q6&S zh^KX2=M$ENiVk`hS*$XrrLh7!OM#`)yV*ME;dd?@SYfej%r^A#8EtCX+)3gMV(3?- z%Y!+n04{hJ>eS&0f*>9!N4(-@qGQuq*_=j4b&y}EC>06#XFs2oPiGQd6CO@K?GXq! zE;aoZJ7u3rt+a>UHT3qeT*(AcGffMV3Fb(hd{hU=GFt6-@zal$R-3Zd@|aG`Hgvx$ z{bDeI_ES*3Qmr>B`RQOZkv5BPymkK!uPR=-SrR>csq@q2{<{K@tRa{FTtP~E`U6Pa Yzd!CweUhpN`O`eU?wOf<`LDnFAHunX0ssI2 diff --git a/lib/emscripten/emtests/test_strstr.wasm b/lib/emscripten/emtests/test_strstr.wasm index 239a78b336f2beedf9b2cde3fb27af7105a06a50..1f9a363ae8d33b0834796c4f6ec15504a942c6a4 100644 GIT binary patch delta 4281 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 X-)1w5UMvCmOdS8!i$(m&UqADI|HkK9 diff --git a/lib/emscripten/emtests/test_strtod.wasm b/lib/emscripten/emtests/test_strtod.wasm index 3e349c2c652bf1ca105b66123153bbb528a32c4b..34243695aa9b41673ac4370c32e23be1d2c215d9 100644 GIT binary patch delta 4888 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 PMTVI8`^i@L;~@M$^>1sf delta 4886 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 b_|xl~9pSz|RRCL@_F diff --git a/lib/emscripten/emtests/test_strtok.wasm b/lib/emscripten/emtests/test_strtok.wasm index aa7bef692858437273b7e95aaa65e11640bea933..30a7fb7a7fd2a4912895c2f2e94470828806c6dd 100644 GIT binary patch delta 3400 zcmZuze^6Y-9pCT1eRs$0k@q+P#~mT;a+iPv0tSMeF&Z8TmxK@!6A~w>IetIkMj)3kf=spmz#v+}uz+~F z>@-9vM`G}Ch%!E|PS7IEzeAAuH5rGsWbRLMXI5tDQ)ehY2y66*|F7QX!OFuVBvYw@ zL7n){k>0@p680u~diwVd?1a?wG$=@4EEo+sR-ZGpPw%4n zZLCocn{WXZH%T;TaSstB7UcfSA|RH}Cn!X;hA@hrfsBfbARe@2*m(f@WFfAvl0FGS z^|7)At0Tga3k8UUB523eeJq+~F%b|<kyHvuge8ufwVK+ za4hH$i~nT+Uh-)lUh<(6_BvgWbCip7 z)FE*>OT{e3kYDi0Ch@#a#sgsL!y0{9C(gNB3&4ju+DjIrMm4V$JUET?^9+UEosC~*iT?