Merge pull request #80 from wasmerio/feature/vm_refactor

VM Refactor, new runtime, and the ability to have multiple compilers.
This commit is contained in:
Lachlan Sneff 2019-01-21 17:23:11 -08:00 committed by GitHub
commit 62b8e7cc2d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1182 changed files with 9357 additions and 289030 deletions

View File

@ -1,83 +1,127 @@
version: 2 version: 2
jobs: jobs:
# Job used for testing # Job used for testing
test: lint:
docker: docker:
- image: circleci/rust:latest - image: circleci/rust:latest
steps: steps:
- checkout - checkout
- restore_cache: - restore_cache:
keys: keys:
- v4-test-cargo-cache-linux-{{ arch }}-{{ checksum "Cargo.lock" }} - v5-lint-{{ arch }}-{{ checksum "Cargo.lock" }}
- run: sudo apt-get install -y cmake - run:
- run: make test name: Install dependencies
- run: rustup component add rustfmt command: |
- run: make lint sudo apt-get install -y cmake
sudo apt-get install texinfo
sudo apt-get install libclang-dev llvm-3.9-dev libclang-3.9-dev clang-3.9
- run:
name: Install lint deps
command: |
rustup component add rustfmt
rustup component add clippy
- run:
name: Execute lints
command: make lint
- save_cache: - save_cache:
paths: paths:
- /usr/local/cargo/registry - /usr/local/cargo/registry
- target/debug/.fingerprint - target/debug/.fingerprint
- target/debug/build - target/debug/build
- target/debug/deps - target/debug/deps
key: v4-test-cargo-cache-linux-{{ arch }}-{{ checksum "Cargo.lock" }} key: v5-lint-{{ arch }}-{{ checksum "Cargo.lock" }}
test-macos:
macos:
xcode: "9.0"
test:
docker:
- image: circleci/rust:latest
steps: steps:
- checkout - checkout
- restore_cache: - restore_cache:
keys: keys:
- v4-cargo-cache-darwin-{{ arch }}-{{ checksum "Cargo.lock" }} - v5-test-cargo-cache-linux-{{ arch }}-{{ checksum "Cargo.lock" }}
- run: - run:
name: Install CMAKE name: Install dependencies
command: | command: |
curl -O https://cmake.org/files/v3.4/cmake-3.4.1-Darwin-x86_64.tar.gz sudo apt-get install -y cmake
tar xf cmake-3.4.1-Darwin-x86_64.tar.gz sudo apt-get install texinfo
export PATH="`pwd`/cmake-3.4.1-Darwin-x86_64/CMake.app/Contents/bin:$PATH" sudo apt-get install libclang-dev llvm-3.9-dev libclang-3.9-dev clang-3.9
- run: make test
- save_cache:
paths:
- /usr/local/cargo/registry
- target/debug/.fingerprint
- target/debug/build
- target/debug/deps
key: v5-test-cargo-cache-linux-{{ arch }}-{{ checksum "Cargo.lock" }}
test-macos:
macos:
xcode: "9.0"
steps:
- checkout
- restore_cache:
keys:
- v5-cargo-cache-darwin-{{ arch }}-{{ checksum "Cargo.lock" }}
- v5-cargo-cache-darwin-{{ arch }}-brew
- run:
name: Update Brew
command: brew update || true
- run:
name: Install crate dependencies
command: |
brew install libtool || true
brew install autoconf cmake libffi || true
- save_cache:
paths:
- /usr/local/Homebrew
key: v5-cargo-cache-darwin-{{ arch }}-brew
- run: - run:
name: Install Rust name: Install Rust
command: | command: |
curl https://sh.rustup.rs -sSf | sh -s -- -y curl https://sh.rustup.rs -sSf | sh -s -- -y
export PATH="$HOME/.cargo/bin:$PATH" export PATH="$HOME/.cargo/bin:$PATH"
cargo --version cargo --version
rustup component add rustfmt
- run: - run:
name: Execute tests name: Execute tests
command: | command: |
export PATH="`pwd`/cmake-3.4.1-Darwin-x86_64/CMake.app/Contents/bin:$PATH"
export PATH="$HOME/.cargo/bin:$PATH" export PATH="$HOME/.cargo/bin:$PATH"
# We increase the ulimit for fixing cargo unclosed files in mac # We increase the ulimit for fixing cargo unclosed files in mac
ulimit -n 8000 ulimit -n 8000
sudo sysctl -w kern.maxfiles=655360 kern.maxfilesperproc=327680 sudo sysctl -w kern.maxfiles=655360 kern.maxfilesperproc=327680
make test make test
make lint
- run: - run:
name: Execute integration tests name: Execute integration tests
command: | command: |
export PATH="`pwd`/cmake-3.4.1-Darwin-x86_64/CMake.app/Contents/bin:$PATH"
export PATH="$HOME/.cargo/bin:$PATH" export PATH="$HOME/.cargo/bin:$PATH"
./integration_tests/nginx/test.sh make integration-tests
- save_cache:
paths:
- /usr/local/cargo/registry
- target/debug/.fingerprint
- target/debug/build
- target/debug/deps
- target/release/.fingerprint
- target/release/build
- target/release/deps
key: v5-cargo-cache-darwin-{{ arch }}-{{ checksum "Cargo.lock" }}
test-and-build: test-and-build:
docker: docker:
- image: circleci/rust:latest - image: circleci/rust:latest
steps: steps:
- checkout - checkout
- restore_cache: - restore_cache:
keys: keys:
- v4-cargo-cache-linux-{{ arch }}-{{ checksum "Cargo.lock" }} - v5-cargo-cache-linux-{{ arch }}-{{ checksum "Cargo.lock" }}
- run: sudo apt-get install -y cmake - run:
name: Install dependencies
command: |
sudo apt-get install -y cmake
sudo apt-get install texinfo
sudo apt-get install libclang-dev llvm-3.9-dev libclang-3.9-dev clang-3.9
- run: - run:
name: Execute tests name: Execute tests
command: make test command: make test
- run: rustup component add rustfmt
- run:
name: Execute lints
command: make lint
- run: - run:
name: Make release build name: Make release build
command: | command: |
@ -101,44 +145,47 @@ jobs:
- target/release/.fingerprint - target/release/.fingerprint
- target/release/build - target/release/build
- target/release/deps - target/release/deps
key: v4-cargo-cache-linux-{{ arch }}-{{ checksum "Cargo.lock" }} - /usr/local/Homebrew
key: v5-cargo-cache-linux-{{ arch }}-{{ checksum "Cargo.lock" }}
test-and-build-macos: test-and-build-macos:
macos: macos:
xcode: "9.0" xcode: "9.0"
steps: steps:
- checkout - checkout
- restore_cache: - restore_cache:
keys: keys:
- v4-cargo-cache-darwin-{{ arch }}-{{ checksum "Cargo.lock" }} - v5-cargo-cache-darwin-{{ arch }}-{{ checksum "Cargo.lock" }}
- v5-cargo-cache-darwin-{{ arch }}-brew
- run: - run:
name: Install CMAKE name: Update Brew
command: brew update || true
- run:
name: Install crate dependencies
command: | command: |
curl -O https://cmake.org/files/v3.4/cmake-3.4.1-Darwin-x86_64.tar.gz brew install libtool || true
tar xf cmake-3.4.1-Darwin-x86_64.tar.gz brew install autoconf cmake libffi || true
export PATH="`pwd`/cmake-3.4.1-Darwin-x86_64/CMake.app/Contents/bin:$PATH" - save_cache:
paths:
- /usr/local/Homebrew
key: v5-cargo-cache-darwin-{{ arch }}-brew
- run: - run:
name: Install Rust name: Install Rust
command: | command: |
curl https://sh.rustup.rs -sSf | sh -s -- -y curl https://sh.rustup.rs -sSf | sh -s -- -y
export PATH="$HOME/.cargo/bin:$PATH" export PATH="$HOME/.cargo/bin:$PATH"
cargo --version cargo --version
rustup component add rustfmt
- run: - run:
name: Execute tests name: Execute tests
command: | command: |
export PATH="`pwd`/cmake-3.4.1-Darwin-x86_64/CMake.app/Contents/bin:$PATH"
export PATH="$HOME/.cargo/bin:$PATH" export PATH="$HOME/.cargo/bin:$PATH"
# We increase the ulimit for fixing cargo unclosed files in mac # We increase the ulimit for fixing cargo unclosed files in mac
ulimit -n 8000 ulimit -n 8000
sudo sysctl -w kern.maxfiles=655360 kern.maxfilesperproc=327680 sudo sysctl -w kern.maxfiles=655360 kern.maxfilesperproc=327680
make test make test
make lint
- run: - run:
name: Make release build name: Make release build
command: | command: |
export PATH="`pwd`/cmake-3.4.1-Darwin-x86_64/CMake.app/Contents/bin:$PATH"
export PATH="$HOME/.cargo/bin:$PATH" export PATH="$HOME/.cargo/bin:$PATH"
make release make release
mkdir -p artifacts mkdir -p artifacts
@ -158,18 +205,22 @@ jobs:
- target/release/.fingerprint - target/release/.fingerprint
- target/release/build - target/release/build
- target/release/deps - target/release/deps
key: v4-cargo-cache-darwin-{{ arch }}-{{ checksum "Cargo.lock" }} key: v5-cargo-cache-darwin-{{ arch }}-{{ checksum "Cargo.lock" }}
test-rust-nightly: test-rust-nightly:
docker: docker:
- image: circleci/rust:latest - image: circleci/rust:latest
steps: steps:
- checkout - checkout
- restore_cache: - restore_cache:
keys: keys:
- v4-test-cargo-cache-linux-{{ arch }}-{{ checksum "Cargo.lock" }}-nightly - v5-test-cargo-cache-linux-{{ arch }}-{{ checksum "Cargo.lock" }}-nightly
- run: sudo apt-get install -y cmake - run:
name: Install dependencies
command: |
sudo apt-get install -y cmake
sudo apt-get install texinfo
sudo apt-get install libclang-dev llvm-3.9-dev libclang-3.9-dev clang-3.9
- run: rustup default nightly - run: rustup default nightly
- run: make test - run: make test
- save_cache: - save_cache:
@ -178,7 +229,7 @@ jobs:
- target/debug/.fingerprint - target/debug/.fingerprint
- target/debug/build - target/debug/build
- target/debug/deps - target/debug/deps
key: v4-test-cargo-cache-linux-{{ arch }}-{{ checksum "Cargo.lock" }}-nightly key: v5-test-cargo-cache-linux-{{ arch }}-{{ checksum "Cargo.lock" }}-nightly
publish-github-release: publish-github-release:
docker: docker:
@ -210,6 +261,7 @@ workflows:
version: 2 version: 2
main: main:
jobs: jobs:
- lint
- test: - test:
filters: filters:
branches: branches:
@ -230,15 +282,11 @@ workflows:
filters: filters:
branches: branches:
only: master only: master
# :
# filters:
# tags:
# only: /^\d+\.\d+\.\d+$/
- publish-github-release: - publish-github-release:
requires: requires:
- lint
- test-and-build - test-and-build
- test-and-build-macos - test-and-build-macos
filters: filters:
tags: branches:
only: /^\d+\.\d+\.\d+$/ only: master

2
.gitignore vendored
View File

@ -1,4 +1,4 @@
/target **/target
**/*.rs.bk **/*.rs.bk
/artifacts /artifacts
.DS_Store .DS_Store

276
Cargo.lock generated
View File

@ -1,3 +1,8 @@
[[package]]
name = "abort_on_panic"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "aho-corasick" name = "aho-corasick"
version = "0.6.8" version = "0.6.8"
@ -53,6 +58,24 @@ dependencies = [
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "bindgen"
version = "0.31.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cexpr 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"clang-sys 0.21.2 (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.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"which 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "bitflags" name = "bitflags"
version = "1.0.4" version = "1.0.4"
@ -73,11 +96,29 @@ name = "cc"
version = "1.0.25" version = "1.0.25"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "cexpr"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"nom 3.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "cfg-if" name = "cfg-if"
version = "0.1.5" version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "clang-sys"
version = "0.21.2"
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.44 (registry+https://github.com/rust-lang/crates.io-index)",
"libloading 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "clap" name = "clap"
version = "2.32.0" version = "2.32.0"
@ -253,6 +294,15 @@ name = "either"
version = "1.5.0" version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "env_logger"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "errno" name = "errno"
version = "0.2.4" version = "0.2.4"
@ -300,6 +350,11 @@ dependencies = [
"synstructure 0.10.1 (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]] [[package]]
name = "fuchsia-zircon" name = "fuchsia-zircon"
version = "0.3.3" version = "0.3.3"
@ -324,6 +379,15 @@ name = "glob"
version = "0.2.11" version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "hashbrown"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
"scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "indicatif" name = "indicatif"
version = "0.10.3" version = "0.10.3"
@ -341,6 +405,20 @@ name = "itoa"
version = "0.4.3" version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index" 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 = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "lazy_static" name = "lazy_static"
version = "1.2.0" version = "1.2.0"
@ -356,6 +434,36 @@ name = "libc"
version = "0.2.44" version = "0.2.44"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "libffi"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"abort_on_panic 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
"libffi-sys 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "libffi-sys"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bindgen 0.31.3 (registry+https://github.com/rust-lang/crates.io-index)",
"make-cmd 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "libloading"
version = "0.4.3"
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)",
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "lock_api" name = "lock_api"
version = "0.1.5" version = "0.1.5"
@ -365,6 +473,14 @@ dependencies = [
"scopeguard 0.3.3 (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.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "log" name = "log"
version = "0.4.5" version = "0.4.5"
@ -381,6 +497,19 @@ dependencies = [
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "make-cmd"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "memchr"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "memchr" name = "memchr"
version = "2.1.0" version = "2.1.0"
@ -413,6 +542,14 @@ name = "nodrop"
version = "0.1.13" version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "nom"
version = "3.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "num-traits" name = "num-traits"
version = "0.2.6" version = "0.2.6"
@ -442,6 +579,16 @@ dependencies = [
"stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "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.44 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "parking_lot" name = "parking_lot"
version = "0.7.0" version = "0.7.0"
@ -463,6 +610,16 @@ dependencies = [
"winapi 0.3.6 (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 = "pkg-config"
version = "0.3.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "0.4.20" version = "0.4.20"
@ -471,6 +628,11 @@ dependencies = [
"unicode-xid 0.1.0 (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 = "quote"
version = "0.3.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "quote" name = "quote"
version = "0.6.8" version = "0.6.8"
@ -598,6 +760,18 @@ dependencies = [
"redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "regex"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"aho-corasick 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"regex-syntax 0.5.6 (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.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "regex" name = "regex"
version = "1.0.5" version = "1.0.5"
@ -610,6 +784,14 @@ dependencies = [
"utf8-ranges 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "utf8-ranges 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "regex-syntax"
version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "regex-syntax" name = "regex-syntax"
version = "0.6.2" version = "0.6.2"
@ -898,9 +1080,12 @@ dependencies = [
"docopt 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "docopt 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"errno 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "errno 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
"error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
"field-offset 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"hashbrown 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
"indicatif 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)", "indicatif 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.44 (git+https://github.com/rust-lang/libc)", "libc 0.2.44 (git+https://github.com/rust-lang/libc)",
"libffi 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
"nix 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "nix 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
@ -912,10 +1097,58 @@ dependencies = [
"tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
"wabt 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "wabt 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
"wasmer-clif-backend 0.1.0",
"wasmer-emscripten 0.1.1",
"wasmer-runtime 0.1.0",
"wasmparser 0.23.0 (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)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "wasmer-clif-backend"
version = "0.1.0"
dependencies = [
"byteorder 1.2.7 (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.7 (registry+https://github.com/rust-lang/crates.io-index)",
"libffi 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
"nix 0.12.0 (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 0.1.0",
"wasmparser 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "wasmer-emscripten"
version = "0.1.1"
dependencies = [
"byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
"glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"hashbrown 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.44 (git+https://github.com/rust-lang/libc)",
"time 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
"wabt 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
"wasmer-clif-backend 0.1.0",
"wasmer-runtime 0.1.0",
]
[[package]]
name = "wasmer-runtime"
version = "0.1.0"
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.7 (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)",
"wabt 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
"wasmer-clif-backend 0.1.0",
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "wasmparser" name = "wasmparser"
version = "0.22.1" version = "0.22.1"
@ -926,6 +1159,19 @@ name = "wasmparser"
version = "0.23.0" version = "0.23.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "which"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.44 (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]] [[package]]
name = "winapi" name = "winapi"
version = "0.3.6" version = "0.3.6"
@ -935,6 +1181,11 @@ dependencies = [
"winapi-x86_64-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]] [[package]]
name = "winapi-i686-pc-windows-gnu" name = "winapi-i686-pc-windows-gnu"
version = "0.4.0" version = "0.4.0"
@ -946,17 +1197,21 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata] [metadata]
"checksum abort_on_panic 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9fa948f9ec9f095cc955efbe4fd00ac5774ef933cc2442562a8fe5a57c4ef919"
"checksum aho-corasick 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "68f56c7353e5a9547cbd76ed90f7bb5ffc3ba09d4ea9bd1d8c06c8b1142eeb5a" "checksum aho-corasick 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "68f56c7353e5a9547cbd76ed90f7bb5ffc3ba09d4ea9bd1d8c06c8b1142eeb5a"
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
"checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef" "checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef"
"checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652"
"checksum backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "89a47830402e9981c5c41223151efcced65a0510c13097c769cede7efb34782a" "checksum backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "89a47830402e9981c5c41223151efcced65a0510c13097c769cede7efb34782a"
"checksum backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "c66d56ac8dabd07f6aacdaf633f4b8262f5b3601a810a0dcddffd5c22c69daa0" "checksum backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "c66d56ac8dabd07f6aacdaf633f4b8262f5b3601a810a0dcddffd5c22c69daa0"
"checksum bindgen 0.31.3 (registry+https://github.com/rust-lang/crates.io-index)" = "57253399c086f4f29e57ffd3b5cdbc23a806a00292619351aa4cfa39cb49d4ea"
"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"
"checksum byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d" "checksum byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d"
"checksum cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "926013f2860c46252efceabb19f4a6b308197505082c609025aa6706c011d427" "checksum cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "926013f2860c46252efceabb19f4a6b308197505082c609025aa6706c011d427"
"checksum cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "f159dfd43363c4d08055a07703eb7a3406b0dac4d0584d96965a3262db3c9d16" "checksum cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "f159dfd43363c4d08055a07703eb7a3406b0dac4d0584d96965a3262db3c9d16"
"checksum cexpr 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "42aac45e9567d97474a834efdee3081b3c942b2205be932092f53354ce503d6c"
"checksum cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0c4e7bb64a8ebb0d856483e1e682ea3422f883c5f5615a90d51a2c82fe87fdd3" "checksum cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0c4e7bb64a8ebb0d856483e1e682ea3422f883c5f5615a90d51a2c82fe87fdd3"
"checksum clang-sys 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e414af9726e1d11660801e73ccc7fb81803fb5f49e5903a25b348b2b3b480d2e"
"checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e" "checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e"
"checksum clicolors-control 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "51872be694bb3bcbd1ea95c6dd467c2c46c6c64d287e1c9084ace7c3116ae9c0" "checksum clicolors-control 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "51872be694bb3bcbd1ea95c6dd467c2c46c6c64d287e1c9084ace7c3116ae9c0"
"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
@ -974,34 +1229,50 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9" "checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9"
"checksum docopt 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d60c92df70dfaaabecc14b409fd79f55ba0f247780529db1d73bfa601e1d3ac0" "checksum docopt 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d60c92df70dfaaabecc14b409fd79f55ba0f247780529db1d73bfa601e1d3ac0"
"checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0" "checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0"
"checksum env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3ddf21e73e016298f5cb37d6ef8e8da8e39f91f9ec8b0df44b7deb16a9f8cd5b"
"checksum errno 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c2a071601ed01b988f896ab14b95e67335d1eeb50190932a1320f7fe3cadc84e" "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 errno-dragonfly 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "14ca354e36190500e1e1fb267c647932382b54053c50b14970856c0b00a35067"
"checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02" "checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02"
"checksum failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6dd377bcc1b1b7ce911967e3ec24fa19c3224394ec05b54aa7b083d498341ac7" "checksum failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6dd377bcc1b1b7ce911967e3ec24fa19c3224394ec05b54aa7b083d498341ac7"
"checksum failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "64c2d913fe8ed3b6c6518eedf4538255b989945c14c2a7d5cbff62a5e2120596" "checksum failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "64c2d913fe8ed3b6c6518eedf4538255b989945c14c2a7d5cbff62a5e2120596"
"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 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-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
"checksum gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)" = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" "checksum gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)" = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2"
"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb"
"checksum hashbrown 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "64b7d419d0622ae02fe5da6b9a5e1964b610a65bb37923b976aeebb6dbb8f86e"
"checksum indicatif 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)" = "40ecd1e2ee08e6c255ce890f5a99d17000850e664e7acf119fb03b25b0575bfe" "checksum indicatif 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)" = "40ecd1e2ee08e6c255ce890f5a99d17000850e664e7acf119fb03b25b0575bfe"
"checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" "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 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73"
"checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1" "checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1"
"checksum libc 0.2.44 (git+https://github.com/rust-lang/libc)" = "<none>" "checksum libc 0.2.44 (git+https://github.com/rust-lang/libc)" = "<none>"
"checksum libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)" = "10923947f84a519a45c8fefb7dd1b3e8c08747993381adee176d7a82b4195311" "checksum libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)" = "10923947f84a519a45c8fefb7dd1b3e8c08747993381adee176d7a82b4195311"
"checksum libffi 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d8a9dac273181f514d742b6b858be5153570c5b80dd4d6020093c0fa584578b1"
"checksum libffi-sys 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4675d5d7fdbba34b66218fae3b0d528c2b29580a64ca2ccc5bbfc5af2324b373"
"checksum libloading 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fd38073de8f7965d0c17d30546d4bb6da311ab428d1c7a3fc71dff7f9d4979b9"
"checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c"
"checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b"
"checksum log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fcce5fa49cc693c312001daf1d13411c4a5283796bac1084299ea3e567113f" "checksum log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fcce5fa49cc693c312001daf1d13411c4a5283796bac1084299ea3e567113f"
"checksum mach 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2fd13ee2dd61cc82833ba05ade5a30bb3d63f7ced605ef827063c63078302de9" "checksum mach 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2fd13ee2dd61cc82833ba05ade5a30bb3d63f7ced605ef827063c63078302de9"
"checksum make-cmd 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a8ca8afbe8af1785e09636acb5a41e08a765f5f0340568716c18a8700ba3c0d3"
"checksum memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a"
"checksum memchr 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4b3629fe9fdbff6daa6c33b90f7c08355c1aca05a3d01fa8063b822fcf185f3b" "checksum memchr 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4b3629fe9fdbff6daa6c33b90f7c08355c1aca05a3d01fa8063b822fcf185f3b"
"checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" "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.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "921f61dc817b379d0834e45d5ec45beaacfae97082090a49c2cf30dcbc30206f"
"checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" "checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945"
"checksum nom 3.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05aec50c70fd288702bcd93284a8444607f3292dbdf2a30de5ea5dcdbe72287b"
"checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" "checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1"
"checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" "checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30"
"checksum number_prefix 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "dbf9993e59c894e3c08aa1c2712914e9e6bf1fcbfc6bef283e2183df345a4fee" "checksum number_prefix 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "dbf9993e59c894e3c08aa1c2712914e9e6bf1fcbfc6bef283e2183df345a4fee"
"checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" "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.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9723236a9525c757d9725b993511e3fc941e33f27751942232f0058298297edf" "checksum parking_lot 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9723236a9525c757d9725b993511e3fc941e33f27751942232f0058298297edf"
"checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" "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 pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c"
"checksum proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)" = "3d7b7eaaa90b4a90a932a9ea6666c95a389e424eff347f0f793979289429feee" "checksum proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)" = "3d7b7eaaa90b4a90a932a9ea6666c95a389e424eff347f0f793979289429feee"
"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
"checksum quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "dd636425967c33af890042c483632d33fa7a18f19ad1d7ea72e8998c6ef8dea5" "checksum quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "dd636425967c33af890042c483632d33fa7a18f19ad1d7ea72e8998c6ef8dea5"
"checksum rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8356f47b32624fef5b3301c1be97e5944ecdd595409cc5da11d05f211db6cfbd" "checksum rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8356f47b32624fef5b3301c1be97e5944ecdd595409cc5da11d05f211db6cfbd"
"checksum rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ae9d223d52ae411a33cf7e54ec6034ec165df296ccd23533d671a28252b6f66a" "checksum rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ae9d223d52ae411a33cf7e54ec6034ec165df296ccd23533d671a28252b6f66a"
@ -1016,7 +1287,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b055d1e92aba6877574d8fe604a63c8b5df60f60e5982bf7ccbb1338ea527356" "checksum rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b055d1e92aba6877574d8fe604a63c8b5df60f60e5982bf7ccbb1338ea527356"
"checksum redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "c214e91d3ecf43e9a4e41e578973adeb14b474f2bee858742d127af75a0112b1" "checksum redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "c214e91d3ecf43e9a4e41e578973adeb14b474f2bee858742d127af75a0112b1"
"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
"checksum regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9329abc99e39129fcceabd24cf5d85b4671ef7c29c50e972bc5afe32438ec384"
"checksum regex 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "2069749032ea3ec200ca51e4a31df41759190a88edca0d2d86ee8bedf7073341" "checksum regex 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "2069749032ea3ec200ca51e4a31df41759190a88edca0d2d86ee8bedf7073341"
"checksum regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7d707a4fa2637f2dca2ef9fd02225ec7661fe01a53623c1e6515b6916511f7a7"
"checksum regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "747ba3b235651f6e2f67dfa8bcdcd073ddb7c243cb21c442fc12395dfcac212d" "checksum regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "747ba3b235651f6e2f67dfa8bcdcd073ddb7c243cb21c442fc12395dfcac212d"
"checksum region 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3f9d3f2bb4b7085e6996e2765b56b783bd8f3a8a4ea5b95683063ca13cded993" "checksum region 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3f9d3f2bb4b7085e6996e2765b56b783bd8f3a8a4ea5b95683063ca13cded993"
"checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" "checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5"
@ -1055,6 +1328,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum wabt-sys 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0cc8982bfe0a923f152e96d991e50a6f97fe73ca4af6d9d84d76634f03051fa2" "checksum wabt-sys 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0cc8982bfe0a923f152e96d991e50a6f97fe73ca4af6d9d84d76634f03051fa2"
"checksum wasmparser 0.22.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f46e666ecb4a406483a59a49f9d0c17f327e70da53a128eccddae2eadb95865c" "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.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b5e01c420bc7d36e778bd242e1167b079562ba8b34087122cc9057187026d060"
"checksum which 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e84a603e7e0b1ce1aa1ee2b109c7be00155ce52df5081590d1ffb93f4f515cb2"
"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 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-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

View File

@ -1,13 +1,12 @@
[package] [package]
name = "wasmer" name = "wasmer"
version = "0.1.4" version = "0.1.4"
authors = ["Syrus Akbary <me@syrusakbary.com>"] authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"]
edition = "2018" edition = "2018"
repository = "https://github.com/wasmerio/wasmer" repository = "https://github.com/wasmerio/wasmer"
publish = true publish = true
description = "High-Performance WebAssembly JIT interpreter" description = "High-Performance WebAssembly JIT interpreter"
license = "MIT" license = "MIT"
build = "build/mod.rs"
include = [ include = [
"examples/**/*", "examples/**/*",
"src/**/*", "src/**/*",
@ -42,14 +41,22 @@ region = "0.3.0"
# spin = "0.4.10" # spin = "0.4.10"
log = "0.4.5" log = "0.4.5"
target-lexicon = "0.2.0" target-lexicon = "0.2.0"
# libc = "0.2"
libc = { git = "https://github.com/rust-lang/libc" }
nix = "0.12.0" nix = "0.12.0"
rayon = "1.0.3" rayon = "1.0.3"
byteorder = "1" byteorder = "1"
indicatif = "0.10" indicatif = "0.10"
console = "0.7.1" console = "0.7.1"
field-offset = "0.1.1"
hashbrown = "0.1"
libffi = "0.6.4"
time = "0.1.41" time = "0.1.41"
wasmer-clif-backend = { path = "lib/clif-backend" }
wasmer-runtime = { path = "lib/runtime" }
wasmer-emscripten = { path = "lib/emscripten" }
libc = { git = "https://github.com/rust-lang/libc" }
[workspace]
members = ["lib/clif-backend", "lib/runtime", "lib/emscripten"]
[build-dependencies] [build-dependencies]
wabt = "0.7.2" wabt = "0.7.2"

View File

@ -7,10 +7,10 @@ endif
# This will re-generate the Rust test files based on spectests/*.wast # This will re-generate the Rust test files based on spectests/*.wast
spectests: spectests:
WASM_GENERATE_SPECTESTS=1 cargo build WASMER_RUNTIME_GENERATE_SPECTESTS=1 cargo build -p wasmer-runtime
emtests: emtests:
WASM_GENERATE_EMTESTS=1 cargo build WASM_EMSCRIPTEN_GENERATE_EMTESTS=1 cargo build -p wasmer-emscripten
# clean: # clean:
# rm -rf artifacts # rm -rf artifacts
@ -21,14 +21,22 @@ build:
install: install:
cargo install --path . cargo install --path .
integration-tests: release
echo "Running Integration Tests"
# Commented for now until we fix emscripten
# ./integration_tests/nginx/test.sh
lint: lint:
cargo fmt -- --check cargo fmt --all -- --check
cargo clippy --all
precommit: lint test precommit: lint test
test: test:
# We use one thread so the emscripten stdouts doesn't collide # We use one thread so the emscripten stdouts doesn't collide
cargo test -- --test-threads=1 $(runargs) # cargo test --all -- --test-threads=1 $(runargs)
# cargo test --all --exclude wasmer-emscripten -- --test-threads=1 $(runargs)
cargo test -p wasmer-runtime -- --test-threads=1 $(runargs)
release: release:
# If you are in OS-X, you will need mingw-w64 for cross compiling to windows # If you are in OS-X, you will need mingw-w64 for cross compiling to windows

View File

@ -57,6 +57,13 @@ you can run:
make spectests make spectests
``` ```
You can also run integration tests with:
```sh
make integration-tests
```
## Roadmap ## 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. 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.

View File

@ -1,19 +0,0 @@
extern crate glob;
extern crate wabt;
use std::env;
mod emtests;
mod spectests;
static SPECTESTS_ENV_VAR: &str = "WASM_GENERATE_SPECTESTS";
static EMTESTS_ENV_VAR: &str = "WASM_GENERATE_EMTESTS";
fn main() {
if env::var(SPECTESTS_ENV_VAR).unwrap_or("0".to_string()) == "1" {
spectests::build();
}
if env::var(EMTESTS_ENV_VAR).unwrap_or("0".to_string()) == "1" {
emtests::build();
}
}

View File

@ -1,7 +1,5 @@
#! /bin/bash #! /bin/bash
# Build the release and run nginx
make release
nohup ./target/release/wasmer run examples/nginx/nginx.wasm -- -p integration_tests/nginx/ -c nginx.conf & nohup ./target/release/wasmer run examples/nginx/nginx.wasm -- -p integration_tests/nginx/ -c nginx.conf &
sleep 3s sleep 3s

1
lib/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
.Cargo.lock

View File

@ -0,0 +1,21 @@
[package]
name = "wasmer-clif-backend"
version = "0.1.0"
authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"]
edition = "2018"
[dependencies]
wasmer-runtime = { path = "../runtime" }
cranelift-native = "0.26.0"
cranelift-codegen = "0.26.0"
cranelift-entity = "0.26.0"
cranelift-wasm = "0.26.0"
hashbrown = "0.1"
target-lexicon = "0.2.0"
wasmparser = "0.23.0"
byteorder = "1"
nix = "0.12.0"
# We depend on libffi for now.
# This will be removed asap.
libffi = "0.6.4"

View File

@ -0,0 +1,138 @@
mod recovery;
mod sighandler;
pub use self::recovery::HandlerData;
use crate::call::recovery::call_protected;
use hashbrown::HashSet;
use libffi::high::{arg as libffi_arg, call as libffi_call, CodePtr};
use std::iter;
use wasmer_runtime::{
backend::{ProtectedCaller, Token},
error::RuntimeResult,
export::Context,
module::{ExportIndex, ModuleInner},
types::{FuncIndex, FuncSig, LocalOrImport, Type, Value},
vm::{self, ImportBacking},
};
pub struct Caller {
func_export_set: HashSet<FuncIndex>,
handler_data: HandlerData,
}
impl Caller {
pub fn new(module: &ModuleInner, handler_data: HandlerData) -> Self {
let mut func_export_set = HashSet::new();
for export_index in module.exports.values() {
if let ExportIndex::Func(func_index) = export_index {
func_export_set.insert(*func_index);
}
}
if let Some(start_func_index) = module.start_func {
func_export_set.insert(start_func_index);
}
Self {
func_export_set,
handler_data,
}
}
}
impl ProtectedCaller for Caller {
fn call(
&self,
module: &ModuleInner,
func_index: FuncIndex,
params: &[Value],
returns: &mut [Value],
import_backing: &ImportBacking,
vmctx: *mut vm::Ctx,
_: Token,
) -> RuntimeResult<()> {
let (func_ptr, ctx, signature) = get_func_from_index(&module, import_backing, func_index);
let vmctx_ptr = match ctx {
Context::External(external_vmctx) => external_vmctx,
Context::Internal => vmctx,
};
assert!(self.func_export_set.contains(&func_index));
assert!(
returns.len() == signature.returns.len() && signature.returns.len() <= 1,
"multi-value returns not yet supported"
);
assert!(signature.check_sig(params), "incorrect signature");
let libffi_args: Vec<_> = params
.iter()
.map(|val| match val {
Value::I32(ref x) => libffi_arg(x),
Value::I64(ref x) => libffi_arg(x),
Value::F32(ref x) => libffi_arg(x),
Value::F64(ref x) => libffi_arg(x),
})
.chain(iter::once(libffi_arg(&vmctx_ptr)))
.collect();
let code_ptr = CodePtr::from_ptr(func_ptr as _);
call_protected(&self.handler_data, || {
// Only supports zero or one return values for now.
// To support multiple returns, we will have to
// generate trampolines instead of using libffi.
match signature.returns.first() {
Some(ty) => {
let val = match ty {
Type::I32 => Value::I32(unsafe { libffi_call(code_ptr, &libffi_args) }),
Type::I64 => Value::I64(unsafe { libffi_call(code_ptr, &libffi_args) }),
Type::F32 => Value::F32(unsafe { libffi_call(code_ptr, &libffi_args) }),
Type::F64 => Value::F64(unsafe { libffi_call(code_ptr, &libffi_args) }),
};
returns[0] = val;
}
// call with no returns
None => unsafe {
libffi_call::<()>(code_ptr, &libffi_args);
},
}
})
}
}
fn get_func_from_index<'a>(
module: &'a ModuleInner,
import_backing: &ImportBacking,
func_index: FuncIndex,
) -> (*const vm::Func, Context, &'a FuncSig) {
let sig_index = *module
.func_assoc
.get(func_index)
.expect("broken invariant, incorrect func index");
let (func_ptr, ctx) = match func_index.local_or_import(module) {
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.sig_registry.lookup_func_sig(sig_index);
(func_ptr, ctx, signature)
}

View File

@ -0,0 +1,189 @@
//! When a WebAssembly module triggers any traps, we perform recovery here.
//!
//! This module uses TLS (thread-local storage) to track recovery information. Since the four signals we're handling
//! are very special, the async signal unsafety of Rust's TLS implementation generally does not affect the correctness here
//! unless you have memory unsafety elsewhere in your code.
use crate::call::sighandler::install_sighandler;
use crate::relocation::{TrapData, TrapSink};
use cranelift_codegen::ir::TrapCode;
use nix::libc::{c_void, siginfo_t};
use nix::sys::signal::{Signal, SIGBUS, SIGFPE, SIGILL, SIGSEGV};
use std::cell::{Cell, UnsafeCell};
use std::ptr;
use std::sync::Once;
use wasmer_runtime::{
error::{RuntimeError, RuntimeResult},
structures::TypedIndex,
types::{MemoryIndex, TableIndex},
};
extern "C" {
pub fn setjmp(env: *mut ::nix::libc::c_void) -> ::nix::libc::c_int;
fn longjmp(env: *mut ::nix::libc::c_void, val: ::nix::libc::c_int) -> !;
}
const SETJMP_BUFFER_LEN: usize = 27;
pub static SIGHANDLER_INIT: Once = Once::new();
thread_local! {
pub static SETJMP_BUFFER: UnsafeCell<[::nix::libc::c_int; SETJMP_BUFFER_LEN]> = UnsafeCell::new([0; SETJMP_BUFFER_LEN]);
pub static CAUGHT_ADDRESSES: Cell<(*const c_void, *const c_void)> = Cell::new((ptr::null(), ptr::null()));
pub static CURRENT_EXECUTABLE_BUFFER: Cell<*const c_void> = Cell::new(ptr::null());
}
pub struct HandlerData {
trap_data: TrapSink,
buffer_ptr: *const c_void,
buffer_size: usize,
}
impl HandlerData {
pub fn new(trap_data: TrapSink, buffer_ptr: *const c_void, buffer_size: usize) -> Self {
Self {
trap_data,
buffer_ptr,
buffer_size,
}
}
pub fn lookup(&self, ip: *const c_void) -> Option<TrapData> {
let ip = ip as usize;
let buffer_ptr = self.buffer_ptr as usize;
if buffer_ptr <= ip && ip < buffer_ptr + self.buffer_size {
let offset = ip - buffer_ptr;
self.trap_data.lookup(offset)
} else {
None
}
}
}
pub fn call_protected<T>(handler_data: &HandlerData, f: impl FnOnce() -> T) -> RuntimeResult<T> {
unsafe {
let jmp_buf = SETJMP_BUFFER.with(|buf| buf.get());
let prev_jmp_buf = *jmp_buf;
SIGHANDLER_INIT.call_once(|| {
install_sighandler();
});
let signum = setjmp(jmp_buf as *mut ::nix::libc::c_void);
if signum != 0 {
*jmp_buf = prev_jmp_buf;
let (faulting_addr, _) = CAUGHT_ADDRESSES.with(|cell| cell.get());
if let Some(TrapData {
trapcode,
srcloc: _,
}) = handler_data.lookup(faulting_addr)
{
Err(match Signal::from_c_int(signum) {
Ok(SIGILL) => match trapcode {
TrapCode::BadSignature => RuntimeError::IndirectCallSignature {
table: TableIndex::new(0),
},
TrapCode::IndirectCallToNull => RuntimeError::IndirectCallToNull {
table: TableIndex::new(0),
},
TrapCode::HeapOutOfBounds => {
let addr =
(faulting_addr as usize) - (handler_data.buffer_ptr as usize);
if addr <= handler_data.buffer_size {
// in the memory
RuntimeError::OutOfBoundsAccess {
memory: MemoryIndex::new(0),
addr: addr as u32,
}
} else {
// if there's an invalid access outside of the memory, including guard pages
// just kill the process.
panic!("invalid memory access, way out of bounds")
}
}
TrapCode::TableOutOfBounds => RuntimeError::TableOutOfBounds {
table: TableIndex::new(0),
},
_ => RuntimeError::Unknown {
msg: "unknown trap".to_string(),
},
},
Ok(SIGSEGV) | Ok(SIGBUS) => {
let addr = (faulting_addr as usize) - (handler_data.buffer_ptr as usize);
if addr <= handler_data.buffer_size {
// in the memory
RuntimeError::OutOfBoundsAccess {
memory: MemoryIndex::new(0),
addr: addr as u32,
}
} else {
// if there's an invalid access outside of the memory, including guard pages
// just kill the process.
panic!("invalid memory access, way out of bounds")
}
}
Ok(SIGFPE) => RuntimeError::IllegalArithmeticOperation,
_ => unimplemented!(),
}
.into())
} else {
let signal = match Signal::from_c_int(signum) {
Ok(SIGFPE) => "floating-point exception",
Ok(SIGILL) => "illegal instruction",
Ok(SIGSEGV) => "segmentation violation",
Ok(SIGBUS) => "bus error",
Err(_) => "error while getting the Signal",
_ => "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),
}
.into())
}
} else {
let ret = f(); // TODO: Switch stack?
*jmp_buf = prev_jmp_buf;
Ok(ret)
}
}
}
/// Unwinds to last protected_call.
pub unsafe fn do_unwind(signum: i32, siginfo: *mut siginfo_t, ucontext: *const c_void) -> ! {
// Since do_unwind is only expected to get called from WebAssembly code which doesn't hold any host resources (locks etc.)
// itself, accessing TLS here is safe. In case any other code calls this, it often indicates a memory safety bug and you should
// temporarily disable the signal handlers to debug it.
let jmp_buf = SETJMP_BUFFER.with(|buf| buf.get());
if *jmp_buf == [0; SETJMP_BUFFER_LEN] {
::std::process::abort();
}
CAUGHT_ADDRESSES.with(|cell| cell.set(get_faulting_addr_and_ip(siginfo, ucontext)));
longjmp(jmp_buf as *mut ::nix::libc::c_void, signum)
}
#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
unsafe fn get_faulting_addr_and_ip(
siginfo: *mut siginfo_t,
_ucontext: *const c_void,
) -> (*const c_void, *const c_void) {
(ptr::null(), ptr::null())
}
#[cfg(all(target_os = "macos", target_arch = "x86_64"))]
unsafe fn get_faulting_addr_and_ip(
siginfo: *mut siginfo_t,
_ucontext: *const c_void,
) -> (*const c_void, *const c_void) {
((*siginfo).si_addr, ptr::null())
}
#[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");

View File

@ -1,10 +1,8 @@
//! We install signal handlers to handle WebAssembly traps within //! Installing signal handlers allows us to handle traps and out-of-bounds memory
//! our Rust code. Otherwise we will have errors that stop the Rust process //! accesses that occur when runniing webassembly.
//! such as `process didn't exit successfully: ... (signal: 8, SIGFPE: erroneous arithmetic operation)`
//! //!
//! Please read more about this here: https://github.com/CraneStation/wasmtime/issues/15
//! This code is inspired by: https://github.com/pepyakin/wasmtime/commit/625a2b6c0815b21996e111da51b9664feb174622 //! This code is inspired by: https://github.com/pepyakin/wasmtime/commit/625a2b6c0815b21996e111da51b9664feb174622
use super::recovery; use crate::call::recovery;
use nix::libc::{c_void, siginfo_t}; use nix::libc::{c_void, siginfo_t};
use nix::sys::signal::{ use nix::sys::signal::{
sigaction, SaFlags, SigAction, SigHandler, SigSet, SIGBUS, SIGFPE, SIGILL, SIGSEGV, sigaction, SaFlags, SigAction, SigHandler, SigSet, SIGBUS, SIGFPE, SIGILL, SIGSEGV,
@ -25,9 +23,9 @@ pub unsafe fn install_sighandler() {
extern "C" fn signal_trap_handler( extern "C" fn signal_trap_handler(
signum: ::nix::libc::c_int, signum: ::nix::libc::c_int,
siginfo: *mut siginfo_t, siginfo: *mut siginfo_t,
_ucontext: *mut c_void, ucontext: *mut c_void,
) { ) {
unsafe { unsafe {
recovery::do_unwind(signum, siginfo); recovery::do_unwind(signum, siginfo, ucontext);
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,665 @@
use crate::{module::Converter, module_env::ModuleEnv};
use cranelift_codegen::{
cursor::FuncCursor,
ir::{self, InstBuilder},
isa,
};
use cranelift_wasm::{self, FuncEnvironment, ModuleEnvironment};
use wasmer_runtime::{
memory::LinearMemory,
structures::TypedIndex,
types::{FuncIndex, GlobalIndex, LocalOrImport, MemoryIndex, TableIndex},
vm,
};
pub struct FuncEnv<'env, 'module, 'isa> {
env: &'env ModuleEnv<'module, 'isa>,
}
impl<'env, 'module, 'isa> FuncEnv<'env, 'module, 'isa> {
pub fn new(env: &'env ModuleEnv<'module, 'isa>) -> Self {
Self { env }
}
/// Creates a signature with VMContext as the last param
pub fn generate_signature(&self, sig_index: cranelift_wasm::SignatureIndex) -> ir::Signature {
// Get signature
let mut signature = self.env.signatures[Converter(sig_index).into()].clone();
// Add the vmctx parameter type to it
signature.params.push(ir::AbiParam::special(
self.pointer_type(),
ir::ArgumentPurpose::VMContext,
));
// Return signature
signature
}
}
impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
/// Gets configuration information needed for compiling functions
fn target_config(&self) -> isa::TargetFrontendConfig {
self.env.target_config()
}
/// Gets native pointers types.
///
/// `I64` on 64-bit arch; `I32` on 32-bit arch.
fn pointer_type(&self) -> ir::Type {
ir::Type::int(u16::from(self.target_config().pointer_bits())).unwrap()
}
/// Gets the size of a native pointer in bytes.
fn pointer_bytes(&self) -> u8 {
self.target_config().pointer_bytes()
}
/// Sets up the necessary preamble definitions in `func` to access the global identified
/// by `index`.
///
/// The index space covers both imported and locally declared globals.
fn make_global(
&mut self,
func: &mut ir::Function,
clif_global_index: cranelift_wasm::GlobalIndex,
) -> cranelift_wasm::GlobalVariable {
let global_index: GlobalIndex = Converter(clif_global_index).into();
// Create VMContext value.
let vmctx = func.create_global_value(ir::GlobalValueData::VMContext);
let ptr_type = self.pointer_type();
match global_index.local_or_import(self.env.module) {
LocalOrImport::Local(local_global_index) => {
let globals_base_addr = func.create_global_value(ir::GlobalValueData::Load {
base: vmctx,
offset: (vm::Ctx::offset_globals() as i32).into(),
global_type: self.pointer_type(),
readonly: true,
});
let offset = local_global_index.index() * vm::LocalGlobal::size() as usize;
let local_global_addr = func.create_global_value(ir::GlobalValueData::IAddImm {
base: globals_base_addr,
offset: (offset as i64).into(),
global_type: ptr_type,
});
// Create global variable based on the data above.
cranelift_wasm::GlobalVariable::Memory {
gv: local_global_addr,
offset: (vm::LocalGlobal::offset_data() as i32).into(),
ty: self.env.get_global(clif_global_index).ty,
}
}
LocalOrImport::Import(imported_global_index) => {
let imported_globals_base_addr =
func.create_global_value(ir::GlobalValueData::Load {
base: vmctx,
offset: (vm::Ctx::offset_imported_globals() as i32).into(),
global_type: ptr_type,
readonly: true,
});
let offset = imported_global_index.index() * vm::ImportedGlobal::size() as usize;
let imported_global_addr = func.create_global_value(ir::GlobalValueData::IAddImm {
base: imported_globals_base_addr,
offset: (offset as i64).into(),
global_type: ptr_type,
});
let local_global_addr = func.create_global_value(ir::GlobalValueData::Load {
base: imported_global_addr,
offset: (vm::ImportedGlobal::offset_global() as i32).into(),
global_type: ptr_type,
readonly: true,
});
cranelift_wasm::GlobalVariable::Memory {
gv: local_global_addr,
offset: (vm::LocalGlobal::offset_data() as i32).into(),
ty: self.env.get_global(clif_global_index).ty,
}
}
}
}
/// Sets up the necessary preamble definitions in `func` to access the linear memory identified
/// by `index`.
///
/// The index space covers both imported and locally declared memories.
fn make_heap(
&mut self,
func: &mut ir::Function,
clif_mem_index: cranelift_wasm::MemoryIndex,
) -> ir::Heap {
let mem_index: MemoryIndex = Converter(clif_mem_index).into();
// Create VMContext value.
let vmctx = func.create_global_value(ir::GlobalValueData::VMContext);
let ptr_type = self.pointer_type();
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 memory_offset = local_mem_index.index() * vm::LocalMemory::size() as usize;
let memory_struct_addr = func.create_global_value(ir::GlobalValueData::IAddImm {
base: memories_base_addr,
offset: (memory_offset as i64).into(),
global_type: ptr_type,
});
let memory_base_addr = func.create_global_value(ir::GlobalValueData::Load {
base: memory_struct_addr,
offset: (vm::LocalMemory::offset_base() as i32).into(),
global_type: ptr_type,
readonly: true,
});
func.create_heap(ir::HeapData {
base: memory_base_addr,
min_size: (self.env.module.memories[local_mem_index].min as u64).into(),
offset_guard_size: (LinearMemory::DEFAULT_GUARD_SIZE as u64).into(),
style: ir::HeapStyle::Static {
bound: (LinearMemory::DEFAULT_HEAP_SIZE as u64).into(),
},
index_type: ir::types::I32,
})
}
LocalOrImport::Import(imported_mem_index) => {
let imported_memories_base = func.create_global_value(ir::GlobalValueData::Load {
base: vmctx,
offset: (vm::Ctx::offset_imported_memories() as i32).into(),
global_type: ptr_type,
readonly: true,
});
let imported_memory_offset =
imported_mem_index.index() * vm::ImportedMemory::size() as usize;
let imported_memory_struct_addr =
func.create_global_value(ir::GlobalValueData::IAddImm {
base: imported_memories_base,
offset: (imported_memory_offset as i64).into(),
global_type: ptr_type,
});
let local_memory_struct_addr =
func.create_global_value(ir::GlobalValueData::Load {
base: imported_memory_struct_addr,
offset: (vm::ImportedMemory::offset_memory() as i32).into(),
global_type: ptr_type,
readonly: true,
});
let local_memory_base = func.create_global_value(ir::GlobalValueData::Load {
base: local_memory_struct_addr,
offset: (vm::LocalMemory::offset_base() as i32).into(),
global_type: ptr_type,
readonly: true,
});
func.create_heap(ir::HeapData {
base: local_memory_base,
min_size: (self.env.module.imported_memories[imported_mem_index].1.min as u64)
.into(),
offset_guard_size: (LinearMemory::DEFAULT_GUARD_SIZE as u64).into(),
style: ir::HeapStyle::Static {
bound: (LinearMemory::DEFAULT_HEAP_SIZE as u64).into(),
},
index_type: ir::types::I32,
})
}
}
}
/// Sets up the necessary preamble definitions in `func` to access the table identified
/// by `index`.
///
/// The index space covers both imported and locally declared tables.
fn make_table(
&mut self,
func: &mut ir::Function,
clif_table_index: cranelift_wasm::TableIndex,
) -> ir::Table {
let table_index: TableIndex = Converter(clif_table_index).into();
// Create VMContext value.
let vmctx = func.create_global_value(ir::GlobalValueData::VMContext);
let ptr_type = self.pointer_type();
match table_index.local_or_import(self.env.module) {
LocalOrImport::Local(local_table_index) => {
let tables_base = func.create_global_value(ir::GlobalValueData::Load {
base: vmctx,
offset: (vm::Ctx::offset_tables() as i32).into(),
global_type: ptr_type,
readonly: true,
});
let table_struct_offset =
local_table_index.index() * vm::LocalTable::size() as usize;
let table_struct_addr = func.create_global_value(ir::GlobalValueData::IAddImm {
base: tables_base,
offset: (table_struct_offset as i64).into(),
global_type: ptr_type,
});
let table_base = func.create_global_value(ir::GlobalValueData::Load {
base: table_struct_addr,
offset: (vm::LocalTable::offset_base() as i32).into(),
global_type: ptr_type,
// we will support growing tables, so this cannot be readonly.
readonly: false,
});
let table_bound = func.create_global_value(ir::GlobalValueData::Load {
base: table_struct_addr,
offset: (vm::LocalTable::offset_current_elements() as i32).into(),
// the number of elements in a table will always fit in an `i32`.
global_type: ir::types::I32,
readonly: false,
});
func.create_table(ir::TableData {
base_gv: table_base,
min_size: (self.env.module.tables[local_table_index].min as u64).into(),
bound_gv: table_bound,
element_size: (vm::Anyfunc::size() as u64).into(),
index_type: ir::types::I32,
})
}
LocalOrImport::Import(imported_table_index) => {
let imported_tables_base = func.create_global_value(ir::GlobalValueData::Load {
base: vmctx,
offset: (vm::Ctx::offset_imported_tables() as i32).into(),
global_type: ptr_type,
readonly: true,
});
let imported_table_struct_offset =
imported_table_index.index() * vm::ImportedTable::size() as usize;
let imported_table_struct_addr =
func.create_global_value(ir::GlobalValueData::IAddImm {
base: imported_tables_base,
offset: (imported_table_struct_offset as i64).into(),
global_type: ptr_type,
});
let local_table_struct_addr = func.create_global_value(ir::GlobalValueData::Load {
base: imported_table_struct_addr,
offset: (vm::ImportedTable::offset_table() as i32).into(),
global_type: ptr_type,
readonly: true,
});
let local_table_base = func.create_global_value(ir::GlobalValueData::Load {
base: local_table_struct_addr,
offset: (vm::LocalTable::offset_base() as i32).into(),
global_type: ptr_type,
readonly: false,
});
let local_table_bound = func.create_global_value(ir::GlobalValueData::Load {
base: local_table_struct_addr,
offset: (vm::LocalTable::offset_current_elements() as i32).into(),
global_type: ir::types::I32,
readonly: false,
});
func.create_table(ir::TableData {
base_gv: local_table_base,
min_size: (self.env.module.imported_tables[imported_table_index].1.min as u64)
.into(),
bound_gv: local_table_bound,
element_size: (vm::Anyfunc::size() as u64).into(),
index_type: ir::types::I32,
})
}
}
}
/// Sets up a signature definition in `func`'s preamble.
///
/// Signature may contain additional argument, but arguments marked as ArgumentPurpose::Normal`
/// must correspond to the arguments in the wasm signature
fn make_indirect_sig(
&mut self,
func: &mut ir::Function,
index: cranelift_wasm::SignatureIndex,
) -> ir::SigRef {
// Create a signature reference out of specified signature (with VMContext param added).
func.import_signature(self.generate_signature(index))
}
/// Sets up an external function definition in the preamble of `func` that can be used to
/// directly call the function `index`.
///
/// The index space covers both imported functions and functions defined in the current module.
fn make_direct_func(
&mut self,
func: &mut ir::Function,
func_index: cranelift_wasm::FuncIndex,
) -> ir::FuncRef {
// Get signature of function.
let signature_index = self.env.get_func_type(func_index);
// Create a signature reference from specified signature (with VMContext param added).
let signature = func.import_signature(self.generate_signature(signature_index));
// Get name of function.
let name = ir::ExternalName::user(0, func_index.as_u32());
// Create function reference from fuction data.
func.import_function(ir::ExtFuncData {
name,
signature,
colocated: false,
})
}
/// Generates an indirect call IR with `callee` and `call_args`.
///
/// Inserts instructions at `pos` to the function `callee` in the table
/// `table_index` with WebAssembly signature `sig_index`
#[cfg_attr(feature = "cargo-clippy", allow(clippy::too_many_arguments))]
fn translate_call_indirect(
&mut self,
mut pos: FuncCursor,
_table_index: cranelift_wasm::TableIndex,
table: ir::Table,
sig_index: cranelift_wasm::SignatureIndex,
sig_ref: ir::SigRef,
callee: ir::Value,
call_args: &[ir::Value],
) -> cranelift_wasm::WasmResult<ir::Inst> {
// Get the pointer type based on machine's pointer size.
let ptr_type = self.pointer_type();
// The `callee` value is an index into a table of Anyfunc structures.
let entry_addr = pos.ins().table_addr(ptr_type, table, callee, 0);
let mflags = ir::MemFlags::trusted();
let func_ptr = pos.ins().load(
ptr_type,
mflags,
entry_addr,
vm::Anyfunc::offset_func() as i32,
);
let vmctx_ptr = pos.ins().load(
ptr_type,
mflags,
entry_addr,
vm::Anyfunc::offset_vmctx() as i32,
);
let found_sig = pos.ins().load(
ir::types::I32,
mflags,
entry_addr,
vm::Anyfunc::offset_sig_id() as i32,
);
pos.ins().trapz(func_ptr, ir::TrapCode::IndirectCallToNull);
let deduplicated_sig_index = self
.env
.module
.sig_registry
.lookup_deduplicated_sigindex(Converter(sig_index).into());
let expected_sig = pos
.ins()
.iconst(ir::types::I32, deduplicated_sig_index.index() as i64);
let not_equal_flags = pos.ins().ifcmp(found_sig, expected_sig);
pos.ins().trapif(
ir::condcodes::IntCC::NotEqual,
not_equal_flags,
ir::TrapCode::BadSignature,
);
// 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.extend(call_args.iter().cloned());
args.push(vmctx_ptr);
Ok(pos.ins().call_indirect(sig_ref, func_ptr, &args))
}
/// Generates a call IR with `callee` and `call_args` and inserts it at `pos`
/// TODO: add support for imported functions
fn translate_call(
&mut self,
mut pos: FuncCursor,
clif_callee_index: cranelift_wasm::FuncIndex,
callee: ir::FuncRef,
call_args: &[ir::Value],
) -> cranelift_wasm::WasmResult<ir::Inst> {
let callee_index: FuncIndex = Converter(clif_callee_index).into();
match callee_index.local_or_import(self.env.module) {
LocalOrImport::Local(_) => {
// this is an internal function
let vmctx = pos
.func
.special_param(ir::ArgumentPurpose::VMContext)
.expect("missing vmctx parameter");
let mut args = Vec::with_capacity(call_args.len() + 1);
args.extend(call_args.iter().cloned());
args.push(vmctx);
Ok(pos.ins().call(callee, &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);
let imported_funcs = pos.func.create_global_value(ir::GlobalValueData::Load {
base: vmctx,
offset: (vm::Ctx::offset_imported_funcs() as i32).into(),
global_type: ptr_type,
readonly: true,
});
let imported_func_offset =
imported_func_index.index() * vm::ImportedFunc::size() as usize;
let imported_func_struct_addr =
pos.func.create_global_value(ir::GlobalValueData::IAddImm {
base: imported_funcs,
offset: (imported_func_offset as i64).into(),
global_type: ptr_type,
});
let imported_func_addr = pos.func.create_global_value(ir::GlobalValueData::Load {
base: imported_func_struct_addr,
offset: (vm::ImportedFunc::offset_func() as i32).into(),
global_type: ptr_type,
readonly: true,
});
let imported_vmctx_addr = pos.func.create_global_value(ir::GlobalValueData::Load {
base: imported_func_struct_addr,
offset: (vm::ImportedFunc::offset_vmctx() as i32).into(),
global_type: ptr_type,
readonly: true,
});
let imported_func_addr = pos.ins().global_value(ptr_type, imported_func_addr);
let imported_vmctx_addr = pos.ins().global_value(ptr_type, imported_vmctx_addr);
let sig_ref = pos.func.dfg.ext_funcs[callee].signature;
let mut args = Vec::with_capacity(call_args.len() + 1);
args.extend(call_args.iter().cloned());
args.push(imported_vmctx_addr);
Ok(pos
.ins()
.call_indirect(sig_ref, imported_func_addr, &args[..]))
}
}
}
/// Generates code corresponding to wasm `memory.grow`.
///
/// `index` refers to the linear memory to query.
///
/// `heap` refers to the IR generated by `make_heap`.
///
/// `val` refers the value to grow the memory by.
fn translate_memory_grow(
&mut self,
mut pos: FuncCursor,
clif_mem_index: cranelift_wasm::MemoryIndex,
_heap: ir::Heap,
by_value: ir::Value,
) -> cranelift_wasm::WasmResult<ir::Value> {
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),
],
returns: vec![ir::AbiParam::new(ir::types::I32)],
});
let mem_index: MemoryIndex = Converter(clif_mem_index).into();
let (name, mem_index) = match mem_index.local_or_import(self.env.module) {
LocalOrImport::Local(local_mem_index) => {
(
// local_static_memory_grow
ir::ExternalName::user(1, 0),
local_mem_index.index(),
)
}
LocalOrImport::Import(imported_mem_index) => {
(
// imported_static_memory_grow
ir::ExternalName::user(1, 2),
imported_mem_index.index(),
)
}
};
let mem_grow_func = pos.func.import_function(ir::ExtFuncData {
name,
signature,
colocated: false,
});
let const_mem_index = pos.ins().iconst(ir::types::I32, mem_index as i64);
let vmctx = pos
.func
.special_param(ir::ArgumentPurpose::VMContext)
.expect("missing vmctx parameter");
let call_inst = pos
.ins()
.call(mem_grow_func, &[const_mem_index, by_value, vmctx]);
Ok(*pos.func.dfg.inst_results(call_inst).first().unwrap())
}
/// Generates code corresponding to wasm `memory.size`.
///
/// `index` refers to the linear memory to query.
///
/// `heap` refers to the IR generated by `make_heap`.
fn translate_memory_size(
&mut self,
mut pos: FuncCursor,
clif_mem_index: cranelift_wasm::MemoryIndex,
_heap: ir::Heap,
) -> cranelift_wasm::WasmResult<ir::Value> {
// 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),
// ],
// returns: vec![ir::AbiParam::new(ir::types::I32)],
// });
// let size_mem_func = pos.func.import_function(ir::ExtFuncData {
// // `ir::ExternalName` for static_grow_memory`
// name: ir::ExternalName::user(1, 1),
// signature,
// colocated: false,
// });
// // Create a memory index value.
// let memory_index = pos.ins().iconst(ir::types::I32, index.index() as i64);
// // Create a VMContext value.
// let vmctx = pos
// .func
// .special_param(ir::ArgumentPurpose::VMContext)
// .expect("missing vmctx parameter");
// // Insert call instructions for `grow_memory`.
// let call_inst = pos.ins().call(size_mem_func, &[memory_index, vmctx]);
// // Return value.
// Ok(*pos.func.dfg.inst_results(call_inst).first().unwrap())
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),
],
returns: vec![ir::AbiParam::new(ir::types::I32)],
});
let mem_index: MemoryIndex = Converter(clif_mem_index).into();
let (name, mem_index) = match mem_index.local_or_import(self.env.module) {
LocalOrImport::Local(local_mem_index) => {
(
// local_static_memory_size
ir::ExternalName::user(1, 1),
local_mem_index.index(),
)
}
LocalOrImport::Import(imported_mem_index) => {
(
// imported_static_memory_size
ir::ExternalName::user(1, 3),
imported_mem_index.index(),
)
}
};
let mem_grow_func = pos.func.import_function(ir::ExtFuncData {
name,
signature,
colocated: false,
});
let const_mem_index = pos.ins().iconst(ir::types::I32, mem_index as i64);
let vmctx = pos
.func
.special_param(ir::ArgumentPurpose::VMContext)
.expect("missing vmctx parameter");
let call_inst = pos.ins().call(mem_grow_func, &[const_mem_index, vmctx]);
Ok(*pos.func.dfg.inst_results(call_inst).first().unwrap())
}
}

View File

@ -0,0 +1,73 @@
// pub mod codegen;
mod call;
mod func_env;
mod libcalls;
mod module;
mod module_env;
mod relocation;
mod resolver;
use cranelift_codegen::{
isa,
settings::{self, Configurable},
};
use target_lexicon::Triple;
use wasmer_runtime::{
backend::{Compiler, Token},
error::{CompileError, CompileResult},
module::ModuleInner,
};
use wasmparser::{self, WasmDecoder};
pub struct CraneliftCompiler {}
impl CraneliftCompiler {
pub fn new() -> Self {
Self {}
}
}
impl Compiler for CraneliftCompiler {
// Compiles wasm binary to a wasmer module.
fn compile(&self, wasm: &[u8], _: Token) -> CompileResult<ModuleInner> {
validate(wasm)?;
let isa = get_isa();
let mut module = module::Module::empty();
let module_env = module_env::ModuleEnv::new(&mut module, &*isa);
let func_bodies = module_env.translate(wasm)?;
module.compile(&*isa, func_bodies)
}
}
fn get_isa() -> Box<isa::TargetIsa> {
let flags = {
let mut builder = settings::builder();
builder.set("opt_level", "best").unwrap();
if cfg!(not(test)) {
builder.set("enable_verifier", "false").unwrap();
}
let flags = settings::Flags::new(builder);
debug_assert_eq!(flags.opt_level(), settings::OptLevel::Best);
flags
};
isa::lookup(Triple::host()).unwrap().finish(flags)
}
fn validate(bytes: &[u8]) -> CompileResult<()> {
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(),
})?,
_ => {}
}
}
}

View File

@ -0,0 +1,83 @@
use std::{f32, f64};
// F32
pub extern "C" fn ceilf32(x: f32) -> f32 {
x.ceil()
}
pub extern "C" fn floorf32(x: f32) -> f32 {
x.floor()
}
pub extern "C" fn truncf32(x: f32) -> f32 {
x.trunc()
}
/// `f32.round()` doesn't have the correct behavior. Ideally, we'd use
/// "https://doc.rust-lang.org/std/intrinsics/fn.nearbyintf32.html" for this,
/// but support for stable compilers is necessary, so we must implement
/// this ourselves.
/// This is ported from "https://github.com/rust-lang/rust/issues/55107#issuecomment-431247454"
pub extern "C" fn nearbyintf32(x: f32) -> f32 {
#[inline]
fn copysign(x: f32, y: f32) -> f32 {
let bitmask = y.to_bits() & (1 << 31);
f32::from_bits(x.to_bits() | bitmask)
}
if x.is_nan() {
f32::from_bits(x.to_bits() | (1 << 22))
} else {
let k = f32::EPSILON.recip();
let a = x.abs();
if a < k {
copysign((a + k) - k, x)
} else {
x
}
}
}
// F64
pub extern "C" fn ceilf64(x: f64) -> f64 {
x.ceil()
}
pub extern "C" fn floorf64(x: f64) -> f64 {
x.floor()
}
pub extern "C" fn truncf64(x: f64) -> f64 {
x.trunc()
}
/// `f64.round()` doesn't have the correct behavior. Ideally, we'd use
/// "https://doc.rust-lang.org/std/intrinsics/fn.nearbyintf64.html" for this,
/// but support for stable compilers is necessary, so we must implement
/// this ourselves.
/// This is ported from "https://github.com/rust-lang/rust/issues/55007#issuecomment-431247454"
pub extern "C" fn nearbyintf64(x: f64) -> f64 {
#[inline]
fn copysign(x: f64, y: f64) -> f64 {
let bitmask = y.to_bits() & (1 << 63);
f64::from_bits(x.to_bits() | bitmask)
}
if x.is_nan() {
f64::from_bits(x.to_bits() | (1 << 51))
} else {
let k = f64::EPSILON.recip();
let a = x.abs();
if a < k {
copysign((a + k) - k, x)
} else {
x
}
}
}
/// A declaration for the stack probe function in Rust's standard library, for
/// catching callstack overflow.
extern "C" {
pub fn __rust_probestack();
}

View File

@ -0,0 +1,180 @@
use crate::{call::Caller, resolver::FuncResolverBuilder};
use cranelift_codegen::{ir, isa};
use cranelift_entity::EntityRef;
use cranelift_wasm;
use hashbrown::HashMap;
use std::{
ops::{Deref, DerefMut},
ptr::NonNull,
};
use wasmer_runtime::{
backend::SigRegistry,
backend::{FuncResolver, ProtectedCaller, Token},
error::{CompileResult, RuntimeResult},
module::ModuleInner,
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<NonNull<vm::Func>> {
None
}
}
impl ProtectedCaller for Placeholder {
fn call(
&self,
_module: &ModuleInner,
_func_index: FuncIndex,
_params: &[Value],
_returns: &mut [Value],
_import_backing: &ImportBacking,
_vmctx: *mut vm::Ctx,
_: Token,
) -> RuntimeResult<()> {
Ok(())
}
}
/// This contains all of the items in a `ModuleInner` except the `func_resolver`.
pub struct Module {
pub module: ModuleInner,
}
impl Module {
pub fn empty() -> Self {
Self {
module: ModuleInner {
// this is a placeholder
func_resolver: Box::new(Placeholder),
protected_caller: Box::new(Placeholder),
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: HashMap::new(),
data_initializers: Vec::new(),
elem_initializers: Vec::new(),
start_func: None,
func_assoc: Map::new(),
sig_registry: SigRegistry::new(),
},
}
}
pub fn compile(
mut self,
isa: &isa::TargetIsa,
functions: Map<LocalFuncIndex, ir::Function>,
) -> CompileResult<ModuleInner> {
// we have to deduplicate `module.func_assoc`
let func_assoc = &mut self.module.func_assoc;
let sig_registry = &self.module.sig_registry;
func_assoc.iter_mut().for_each(|(_, sig_index)| {
*sig_index = sig_registry.lookup_deduplicated_sigindex(*sig_index);
});
let (func_resolver_builder, handler_data) = FuncResolverBuilder::new(isa, functions)?;
self.module.func_resolver = Box::new(func_resolver_builder.finalize()?);
self.module.protected_caller = Box::new(Caller::new(&self.module, handler_data));
Ok(self.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<T>(pub T);
macro_rules! convert_clif_to_runtime_index {
($clif_index:ident, $runtime_index:ident) => {
impl From<Converter<cranelift_wasm::$clif_index>> for $runtime_index {
fn from(clif_index: Converter<cranelift_wasm::$clif_index>) -> Self {
$runtime_index::new(clif_index.0.index())
}
}
impl From<Converter<$runtime_index>> for cranelift_wasm::$clif_index {
fn from(runtime_index: Converter<$runtime_index>) -> Self {
cranelift_wasm::$clif_index::new(runtime_index.0.index())
}
}
};
($(($clif_index:ident: $runtime_index:ident),)*) => {
$(
convert_clif_to_runtime_index!($clif_index, $runtime_index);
)*
};
}
convert_clif_to_runtime_index![
(FuncIndex: FuncIndex),
(MemoryIndex: MemoryIndex),
(TableIndex: TableIndex),
(GlobalIndex: GlobalIndex),
(SignatureIndex: SigIndex),
];
impl<'a> From<Converter<&'a ir::Signature>> for FuncSig {
fn from(signature: Converter<&'a ir::Signature>) -> Self {
FuncSig {
params: signature
.0
.params
.iter()
.map(|param| Converter(param.value_type).into())
.collect(),
returns: signature
.0
.returns
.iter()
.map(|ret| Converter(ret.value_type).into())
.collect(),
}
}
}
impl From<Converter<ir::Type>> for Type {
fn from(ty: Converter<ir::Type>) -> Self {
match ty.0 {
ir::types::I32 => Type::I32,
ir::types::I64 => Type::I64,
ir::types::F32 => Type::F32,
ir::types::F64 => Type::F64,
_ => panic!("unsupported wasm type"),
}
}
}

View File

@ -0,0 +1,364 @@
use crate::{
func_env::FuncEnv,
module::{Converter, Module},
};
use cranelift_codegen::{ir, isa};
use cranelift_wasm::{self, translate_module, FuncTranslator, ModuleEnvironment};
use wasmer_runtime::{
error::{CompileError, CompileResult},
module::{DataInitializer, ExportIndex, ImportName, TableInitializer},
structures::{Map, TypedIndex},
types::{
ElementType, Global, GlobalDesc, GlobalIndex, Initializer, LocalFuncIndex, LocalOrImport,
Memory, SigIndex, Table, Value,
},
};
pub struct ModuleEnv<'module, 'isa> {
pub module: &'module mut Module,
isa: &'isa isa::TargetIsa,
pub signatures: Map<SigIndex, ir::Signature>,
globals: Map<GlobalIndex, cranelift_wasm::Global>,
func_bodies: Map<LocalFuncIndex, ir::Function>,
}
impl<'module, 'isa> ModuleEnv<'module, 'isa> {
pub fn new(module: &'module mut Module, isa: &'isa isa::TargetIsa) -> Self {
Self {
module,
isa,
signatures: Map::new(),
globals: Map::new(),
func_bodies: Map::new(),
}
}
pub fn translate(mut self, wasm: &[u8]) -> CompileResult<Map<LocalFuncIndex, ir::Function>> {
translate_module(wasm, &mut self)
.map_err(|e| CompileError::InternalError { msg: e.to_string() })?;
Ok(self.func_bodies)
}
}
impl<'module, 'isa, 'data> ModuleEnvironment<'data> for ModuleEnv<'module, 'isa> {
/// Get the information needed to produce Cranelift IR for the current target.
fn target_config(&self) -> isa::TargetFrontendConfig {
self.isa.frontend_config()
}
/// Declares a function signature to the environment.
fn declare_signature(&mut self, sig: &ir::Signature) {
self.signatures.push(sig.clone());
self.module.sig_registry.register(Converter(sig).into());
}
/// Return the signature with the given index.
fn get_signature(&self, sig_index: cranelift_wasm::SignatureIndex) -> &ir::Signature {
&self.signatures[Converter(sig_index).into()]
}
/// Declares a function import to the environment.
fn declare_func_import(
&mut self,
sig_index: cranelift_wasm::SignatureIndex,
namespace: &'data str,
name: &'data str,
) {
self.module.func_assoc.push(Converter(sig_index).into());
// Add import names to list of imported functions
self.module.imported_functions.push(ImportName {
namespace: namespace.to_string(),
name: name.to_string(),
});
}
/// Return the number of imported funcs.
fn get_num_func_imports(&self) -> usize {
self.module.imported_functions.len()
}
/// Declares the type (signature) of a local function in the module.
fn declare_func_type(&mut self, sig_index: cranelift_wasm::SignatureIndex) {
self.module.func_assoc.push(Converter(sig_index).into());
}
/// Return the signature index for the given function index.
fn get_func_type(
&self,
func_index: cranelift_wasm::FuncIndex,
) -> cranelift_wasm::SignatureIndex {
Converter(self.module.func_assoc[Converter(func_index).into()]).into()
}
/// Declares a global to the environment.
fn declare_global(&mut self, global: cranelift_wasm::Global) {
use cranelift_wasm::GlobalInit;
let desc = GlobalDesc {
mutable: global.mutability,
ty: Converter(global.ty).into(),
};
let init = match global.initializer {
GlobalInit::I32Const(x) => Initializer::Const(Value::I32(x)),
GlobalInit::I64Const(x) => Initializer::Const(Value::I64(x)),
GlobalInit::F32Const(x) => Initializer::Const(Value::F32(f32::from_bits(x))),
GlobalInit::F64Const(x) => Initializer::Const(Value::F64(f64::from_bits(x))),
GlobalInit::GetGlobal(global_index) => {
assert!(!desc.mutable);
let global_index: GlobalIndex = Converter(global_index).into();
let imported_global_index = global_index
.local_or_import(self.module)
.import()
.expect("invalid global initializer when declaring an imported global");
Initializer::GetGlobal(imported_global_index)
}
_ => panic!("invalid global initializer when declaring a local global"),
};
// Add global ir to the list of globals
self.module.globals.push(Global { desc, init });
self.globals.push(global);
}
/// Declares a global import to the environment.
fn declare_global_import(
&mut self,
global: cranelift_wasm::Global,
namespace: &'data str,
name: &'data str,
) {
assert!(match global.initializer {
cranelift_wasm::GlobalInit::Import => true,
_ => false,
});
let import_name = ImportName {
namespace: namespace.to_string(),
name: name.to_string(),
};
let desc = GlobalDesc {
mutable: global.mutability,
ty: Converter(global.ty).into(),
};
// Add global ir to the list of globals
self.module.imported_globals.push((import_name, desc));
self.globals.push(global);
}
/// Return the global for the given global index.
fn get_global(&self, global_index: cranelift_wasm::GlobalIndex) -> &cranelift_wasm::Global {
&self.globals[Converter(global_index).into()]
}
/// Declares a table to the environment.
fn declare_table(&mut self, table: cranelift_wasm::Table) {
use cranelift_wasm::TableElementType;
// Add table ir to the list of tables
self.module.tables.push(Table {
ty: match table.ty {
TableElementType::Func => ElementType::Anyfunc,
_ => unimplemented!(),
},
min: table.minimum,
max: table.maximum,
});
}
/// Declares a table import to the environment.
fn declare_table_import(
&mut self,
table: cranelift_wasm::Table,
namespace: &'data str,
name: &'data str,
) {
use cranelift_wasm::TableElementType;
let import_name = ImportName {
namespace: namespace.to_string(),
name: name.to_string(),
};
let imported_table = Table {
ty: match table.ty {
TableElementType::Func => ElementType::Anyfunc,
_ => unimplemented!(),
},
min: table.minimum,
max: table.maximum,
};
// Add import names to list of imported tables
self.module
.imported_tables
.push((import_name, imported_table));
}
/// Fills a declared table with references to functions in the module.
fn declare_table_elements(
&mut self,
table_index: cranelift_wasm::TableIndex,
base: Option<cranelift_wasm::GlobalIndex>,
offset: usize,
elements: Vec<cranelift_wasm::FuncIndex>,
) {
// Convert Cranelift GlobalIndex to wamser GlobalIndex
// let base = base.map(|index| WasmerGlobalIndex::new(index.index()));
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) {
LocalOrImport::Import(imported_global_index) => imported_global_index,
LocalOrImport::Local(_) => {
panic!("invalid global initializer when declaring an imported global")
}
})
}
None => Initializer::Const((offset as i32).into()),
};
// Add table initializer to list of table initializers
self.module.elem_initializers.push(TableInitializer {
table_index: Converter(table_index).into(),
base,
elements: elements
.iter()
.map(|&func_index| Converter(func_index).into())
.collect(),
});
}
/// Declares a memory to the environment
fn declare_memory(&mut self, memory: cranelift_wasm::Memory) {
self.module.memories.push(Memory {
min: memory.minimum,
max: memory.maximum,
shared: memory.shared,
});
}
/// Declares a memory import to the environment.
fn declare_memory_import(
&mut self,
memory: cranelift_wasm::Memory,
namespace: &'data str,
name: &'data str,
) {
let import_name = ImportName {
namespace: namespace.to_string(),
name: name.to_string(),
};
let memory = Memory {
min: memory.minimum,
max: memory.maximum,
shared: memory.shared,
};
// Add import names to list of imported memories
self.module.imported_memories.push((import_name, memory));
}
/// Fills a declared memory with bytes at module instantiation.
fn declare_data_initialization(
&mut self,
memory_index: cranelift_wasm::MemoryIndex,
base: Option<cranelift_wasm::GlobalIndex>,
offset: usize,
data: &'data [u8],
) {
// Convert Cranelift GlobalIndex to wamser GlobalIndex
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) {
LocalOrImport::Import(imported_global_index) => imported_global_index,
LocalOrImport::Local(_) => {
panic!("invalid global initializer when declaring an imported global")
}
})
}
None => Initializer::Const((offset as i32).into()),
};
// Add data initializer to list of data initializers
self.module.data_initializers.push(DataInitializer {
memory_index: Converter(memory_index).into(),
base,
data: data.to_vec(),
});
}
/// Declares a function export to the environment.
fn declare_func_export(&mut self, func_index: cranelift_wasm::FuncIndex, name: &'data str) {
self.module.exports.insert(
name.to_string(),
ExportIndex::Func(Converter(func_index).into()),
);
}
/// Declares a table export to the environment.
fn declare_table_export(&mut self, table_index: cranelift_wasm::TableIndex, name: &'data str) {
self.module.exports.insert(
name.to_string(),
ExportIndex::Table(Converter(table_index).into()),
);
}
/// Declares a memory export to the environment.
fn declare_memory_export(
&mut self,
memory_index: cranelift_wasm::MemoryIndex,
name: &'data str,
) {
self.module.exports.insert(
name.to_string(),
ExportIndex::Memory(Converter(memory_index).into()),
);
}
/// Declares a global export to the environment.
fn declare_global_export(
&mut self,
global_index: cranelift_wasm::GlobalIndex,
name: &'data str,
) {
self.module.exports.insert(
name.to_string(),
ExportIndex::Global(Converter(global_index).into()),
);
}
/// Declares a start function.
fn declare_start_func(&mut self, func_index: cranelift_wasm::FuncIndex) {
self.module.start_func = Some(Converter(func_index).into());
}
/// Provides the contents of a function body.
fn define_function_body(&mut self, body_bytes: &'data [u8]) -> cranelift_wasm::WasmResult<()> {
let mut func_translator = FuncTranslator::new();
let func_body = {
let mut func_env = FuncEnv::new(self);
let func_index = self.func_bodies.next_index();
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()),
);
let mut func = ir::Function::with_name_signature(name, sig);
func_translator.translate(body_bytes, &mut func, &mut func_env)?;
func
};
// Add function body to list of function bodies.
self.func_bodies.push(func_body);
Ok(())
}
}

View File

@ -3,9 +3,10 @@
//! any other calls that this function is doing, so we can "patch" the //! any other calls that this function is doing, so we can "patch" the
//! function addrs in runtime with the functions we need. //! function addrs in runtime with the functions we need.
use cranelift_codegen::binemit; use cranelift_codegen::binemit;
use cranelift_codegen::ir::{self, ExternalName, LibCall, SourceLoc, TrapCode};
pub use cranelift_codegen::binemit::Reloc; pub use cranelift_codegen::binemit::Reloc;
use cranelift_codegen::ir::{self, ExternalName, LibCall, SourceLoc, TrapCode};
use hashbrown::HashMap;
use wasmer_runtime::{structures::TypedIndex, types::LocalFuncIndex};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Relocation { pub struct Relocation {
@ -19,14 +20,21 @@ pub struct Relocation {
pub target: RelocationType, pub target: RelocationType,
} }
#[derive(Debug, Clone, Copy)]
pub enum VmCall {
LocalStaticMemoryGrow,
LocalStaticMemorySize,
ImportedStaticMemoryGrow,
ImportedStaticMemorySize,
}
/// Specify the type of relocation /// Specify the type of relocation
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum RelocationType { pub enum RelocationType {
Normal(u32), Normal(LocalFuncIndex),
Intrinsic(String), Intrinsic(String),
LibCall(LibCall), LibCall(LibCall),
GrowMemory, VmCall(VmCall),
CurrentMemory,
} }
/// Implementation of a relocation sink that just saves all the information for later /// Implementation of a relocation sink that just saves all the information for later
@ -61,22 +69,35 @@ impl binemit::RelocSink for RelocSink {
reloc, reloc,
offset, offset,
addend, addend,
target: RelocationType::Normal(index as _), target: RelocationType::Normal(LocalFuncIndex::new(index as usize)),
});
}
ExternalName::User {
namespace: 1,
index,
} => {
let target = RelocationType::VmCall(match index {
0 => VmCall::LocalStaticMemoryGrow,
1 => VmCall::LocalStaticMemorySize,
2 => VmCall::ImportedStaticMemoryGrow,
3 => VmCall::ImportedStaticMemorySize,
_ => unimplemented!(),
});
self.func_relocs.push(Relocation {
reloc,
offset,
addend,
target,
}); });
} }
ExternalName::TestCase { length, ascii } => { ExternalName::TestCase { length, ascii } => {
let (slice, _) = ascii.split_at(length as usize); let (slice, _) = ascii.split_at(length as usize);
let name = String::from_utf8(slice.to_vec()).unwrap(); let name = String::from_utf8(slice.to_vec()).unwrap();
let relocation_type = match name.as_str() {
"current_memory" => RelocationType::CurrentMemory,
"grow_memory" => RelocationType::GrowMemory,
_ => RelocationType::Intrinsic(name),
};
self.func_relocs.push(Relocation { self.func_relocs.push(Relocation {
reloc, reloc,
offset, offset,
addend, addend,
target: relocation_type, target: RelocationType::Intrinsic(name),
}); });
} }
ExternalName::LibCall(libcall) => { ExternalName::LibCall(libcall) => {
@ -112,32 +133,50 @@ impl RelocSink {
} }
} }
#[derive(Debug, Clone, Copy)]
pub struct TrapData { pub struct TrapData {
pub offset: usize, pub trapcode: TrapCode,
pub code: TrapCode, pub srcloc: SourceLoc,
} }
/// Simple implementation of a TrapSink /// Simple implementation of a TrapSink
/// that saves the info for later. /// that saves the info for later.
pub struct TrapSink { pub struct TrapSink {
current_func_offset: usize, trap_datas: HashMap<usize, TrapData>,
trap_datas: Vec<TrapData>,
} }
impl TrapSink { impl TrapSink {
pub fn new(current_func_offset: usize) -> TrapSink { pub fn new() -> TrapSink {
TrapSink { TrapSink {
current_func_offset, trap_datas: HashMap::new(),
trap_datas: Vec::new(),
}
} }
} }
impl binemit::TrapSink for TrapSink { pub fn lookup(&self, offset: usize) -> Option<TrapData> {
fn trap(&mut self, offset: u32, _: SourceLoc, code: TrapCode) { self.trap_datas.get(&offset).cloned()
self.trap_datas.push(TrapData { }
offset: self.current_func_offset + offset as usize,
code, pub fn drain_local(&mut self, current_func_offset: usize, local: &mut LocalTrapSink) {
local.trap_datas.drain(..).for_each(|(offset, trap_data)| {
self.trap_datas
.insert(current_func_offset + offset, trap_data);
}); });
} }
} }
pub struct LocalTrapSink {
trap_datas: Vec<(usize, TrapData)>,
}
impl LocalTrapSink {
pub fn new() -> Self {
LocalTrapSink { trap_datas: vec![] }
}
}
impl binemit::TrapSink for LocalTrapSink {
fn trap(&mut self, offset: u32, srcloc: SourceLoc, trapcode: TrapCode) {
self.trap_datas
.push((offset as usize, TrapData { trapcode, srcloc }));
}
}

View File

@ -0,0 +1,219 @@
use crate::call::HandlerData;
use crate::libcalls;
use crate::relocation::{
LocalTrapSink, Reloc, RelocSink, Relocation, RelocationType, TrapSink, VmCall,
};
use byteorder::{ByteOrder, LittleEndian};
use cranelift_codegen::{ir, isa, Context};
use std::mem;
use std::ptr::{write_unaligned, NonNull};
use wasmer_runtime::{
self,
backend::{
self,
sys::{Memory, Protect},
},
error::{CompileError, CompileResult},
structures::Map,
types::LocalFuncIndex,
vm, vmcalls,
};
#[allow(dead_code)]
pub struct FuncResolverBuilder {
resolver: FuncResolver,
relocations: Map<LocalFuncIndex, Vec<Relocation>>,
}
impl FuncResolverBuilder {
pub fn new(
isa: &isa::TargetIsa,
function_bodies: Map<LocalFuncIndex, ir::Function>,
) -> CompileResult<(Self, HandlerData)> {
let mut compiled_functions: Vec<Vec<u8>> = Vec::with_capacity(function_bodies.len());
let mut relocations = Map::with_capacity(function_bodies.len());
let mut trap_sink = TrapSink::new();
let mut local_trap_sink = LocalTrapSink::new();
let mut ctx = Context::new();
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();
// Clear the local trap sink and consolidate all trap info
// into a single location.
trap_sink.drain_local(total_size, &mut local_trap_sink);
// Round up each function's size to pointer alignment.
total_size += round_up(code_buf.len(), mem::size_of::<usize>());
compiled_functions.push(code_buf);
relocations.push(reloc_sink.func_relocs);
}
let mut memory = Memory::with_size(total_size)
.map_err(|e| CompileError::InternalError { msg: e.to_string() })?;
unsafe {
memory
.protect(0..memory.size(), Protect::ReadWrite)
.map_err(|e| CompileError::InternalError { msg: e.to_string() })?;
}
// Normally, excess memory due to alignment and page-rounding would
// be filled with null-bytes. On x86 (and x86_64),
// "\x00\x00" disassembles to "add byte ptr [eax],al".
//
// If the instruction pointer falls out of its designated area,
// it would be better if it would immediately crash instead of
// continuing on and causing non-local issues.
//
// "\xCC" disassembles to "int3", which will immediately cause
// an interrupt that we can catch if we want.
for i in unsafe { memory.as_slice_mut() } {
*i = 0xCC;
}
let mut map = Map::with_capacity(compiled_functions.len());
let mut previous_end = 0;
for compiled in compiled_functions.iter() {
let new_end = previous_end + round_up(compiled.len(), mem::size_of::<usize>());
unsafe {
memory.as_slice_mut()[previous_end..previous_end + compiled.len()]
.copy_from_slice(&compiled[..]);
}
map.push(previous_end);
previous_end = new_end;
}
let handler_data = HandlerData::new(trap_sink, memory.as_ptr() as _, memory.size());
Ok((
Self {
resolver: FuncResolver { map, memory },
relocations,
},
handler_data,
))
}
pub fn finalize(mut self) -> CompileResult<FuncResolver> {
for (index, relocs) in self.relocations.iter() {
for ref reloc in relocs {
let target_func_address: isize = match reloc.target {
RelocationType::Normal(local_func_index) => {
// This will always be an internal function
// because imported functions are not
// called in this way.
self.resolver.lookup(local_func_index).unwrap().as_ptr() as isize
}
RelocationType::LibCall(libcall) => match libcall {
ir::LibCall::CeilF32 => libcalls::ceilf32 as isize,
ir::LibCall::FloorF32 => libcalls::floorf32 as isize,
ir::LibCall::TruncF32 => libcalls::truncf32 as isize,
ir::LibCall::NearestF32 => libcalls::nearbyintf32 as isize,
ir::LibCall::CeilF64 => libcalls::ceilf64 as isize,
ir::LibCall::FloorF64 => libcalls::floorf64 as isize,
ir::LibCall::TruncF64 => libcalls::truncf64 as isize,
ir::LibCall::NearestF64 => libcalls::nearbyintf64 as isize,
ir::LibCall::Probestack => libcalls::__rust_probestack as isize,
_ => Err(CompileError::InternalError {
msg: format!("unexpected libcall: {}", libcall),
})?,
},
RelocationType::Intrinsic(ref name) => Err(CompileError::InternalError {
msg: format!("unexpected intrinsic: {}", name),
})?,
RelocationType::VmCall(vmcall) => match vmcall {
VmCall::LocalStaticMemoryGrow => vmcalls::local_static_memory_grow as _,
VmCall::LocalStaticMemorySize => vmcalls::local_static_memory_size as _,
VmCall::ImportedStaticMemoryGrow => {
vmcalls::imported_static_memory_grow as _
}
VmCall::ImportedStaticMemorySize => {
vmcalls::imported_static_memory_size as _
}
},
};
// We need the address of the current function
// because 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 => unsafe {
let reloc_address = func_addr.offset(reloc.offset as isize) as isize;
let reloc_addend = reloc.addend as isize;
// TODO: Handle overflow.
let reloc_delta_i32 =
(target_func_address - reloc_address + reloc_addend) as i32;
write_unaligned(reloc_address as *mut i32, reloc_delta_i32);
},
_ => Err(CompileError::InternalError {
msg: format!("unsupported reloc kind: {}", reloc.reloc),
})?,
}
}
}
unsafe {
self.resolver
.memory
.protect(0..self.resolver.memory.size(), Protect::ReadExec)
.map_err(|e| CompileError::InternalError { msg: e.to_string() })?;;
}
Ok(self.resolver)
}
}
/// Resolves a function index to a function address.
pub struct FuncResolver {
map: Map<LocalFuncIndex, usize>,
memory: Memory,
}
impl FuncResolver {
fn lookup(&self, local_func_index: LocalFuncIndex) -> Option<NonNull<vm::Func>> {
let offset = *self.map.get(local_func_index)?;
let ptr = unsafe { self.memory.as_ptr().add(offset) };
NonNull::new(ptr).map(|nonnull| nonnull.cast())
}
}
// Implements FuncResolver trait.
impl backend::FuncResolver for FuncResolver {
fn get(
&self,
_module: &wasmer_runtime::module::ModuleInner,
index: LocalFuncIndex,
) -> Option<NonNull<vm::Func>> {
self.lookup(index)
}
}
#[inline]
fn round_up(n: usize, multiple: usize) -> usize {
(n + multiple - 1) & !(multiple - 1)
}

20
lib/emscripten/Cargo.toml Normal file
View File

@ -0,0 +1,20 @@
[package]
name = "wasmer-emscripten"
version = "0.1.1"
authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"]
edition = "2018"
build = "build/mod.rs"
[dependencies]
hashbrown = "0.1"
wasmer-runtime = { path = "../runtime" }
libc = { git = "https://github.com/rust-lang/libc" }
byteorder = "1"
time = "0.1.41"
[dev-dependencies]
wasmer-clif-backend = { path = "../clif-backend" }
wabt = "0.7.2"
[build-dependencies]
glob = "0.2.11"

View File

@ -85,7 +85,7 @@ pub fn compile(file: &str, ignores: &Vec<String>) -> Option<String> {
let rs_module_name = module_name.to_lowercase(); let rs_module_name = module_name.to_lowercase();
let rust_test_filepath = format!( let rust_test_filepath = format!(
concat!(env!("CARGO_MANIFEST_DIR"), "/src/emtests/{}.rs"), concat!(env!("CARGO_MANIFEST_DIR"), "/tests/emtests/{}.rs"),
rs_module_name.as_str() rs_module_name.as_str()
); );
@ -138,7 +138,7 @@ fn test_{rs_module_name}() {{
} }
pub fn build() { pub fn build() {
let rust_test_modpath = concat!(env!("CARGO_MANIFEST_DIR"), "/src/emtests/mod.rs"); let rust_test_modpath = concat!(env!("CARGO_MANIFEST_DIR"), "/tests/emtests/mod.rs");
let mut modules: Vec<String> = Vec::new(); let mut modules: Vec<String> = Vec::new();
// modules.reserve_exact(TESTS.len()); // modules.reserve_exact(TESTS.len());

View File

@ -0,0 +1,11 @@
use std::env;
mod emtests;
static EMTESTS_ENV_VAR: &str = "WASM_EMSCRIPTEN_GENERATE_EMTESTS";
fn main() {
if env::var(EMTESTS_ENV_VAR).unwrap_or("0".to_string()) == "1" {
emtests::build();
}
}

Some files were not shown because too many files have changed in this diff Show More