Merge branch 'master' into wat

This commit is contained in:
Mark McCaskey
2019-12-04 17:17:00 -08:00
297 changed files with 24017 additions and 7556 deletions

View File

@ -1,78 +0,0 @@
version: "{build} ~ {branch}"
os: Visual Studio 2017
branches:
only:
- staging
- trying
- master
environment:
matrix:
- CHANNEL: stable
ARCH: x86_64
ABI: msvc
TARGET: x86_64-pc-windows-msvc
cache:
- 'C:\Users\appveyor\.cargo'
- target
install:
# Install LLVM
- mkdir C:\projects\deps
- cd C:\projects\deps
- appveyor DownloadFile https://github.com/wasmerio/windows-llvm-build/releases/download/v8.0.0/llvm-8.0.0-install.zip -FileName llvm-8.0.0-install.zip
- 7z x llvm-8.0.0-install.zip
- C:\projects\deps\llvm-8.0.0-install\bin\llvm-config.exe --version
- set "LLVM_SYS_80_PREFIX=C:\projects\deps\llvm-8.0.0-install"
- cd "%APPVEYOR_BUILD_FOLDER%"
# Install Rust
# uncomment these lines if the cache is cleared, or if we must re-install rust for some reason
- appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe
- rustup-init.exe -yv --default-host %target%
- set PATH=%PATH%;%USERPROFILE%\.cargo\bin
- rustup default stable-%target%
- rustup update
- rustc -vV
- cargo -vV
# Install InnoSetup
- appveyor-retry appveyor DownloadFile https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/2017-08-22-is.exe
- 2017-08-22-is.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /SP-
- set PATH="C:\Program Files (x86)\Inno Setup 5";%PATH%
# uncomment to RDP to appveyor
# - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
build_script:
- cargo build --release --verbose --features backend-llvm
- cargo build --release --manifest-path lib/runtime-c-api/Cargo.toml
test_script:
- cargo test --manifest-path lib/spectests/Cargo.toml --release --features clif -- --nocapture
before_deploy:
- appveyor PushArtifact target\release\wasmer_runtime_c_api.dll
- git submodule init
- git submodule update
- cargo build --release --manifest-path wapm-cli/Cargo.toml --features "telemetry update-notifications"
- cd ./src/installer
- iscc wasmer.iss
- copy /y .\WasmerInstaller.exe ..\..\WasmerInstaller-%APPVEYOR_REPO_TAG_NAME%.exe
- appveyor PushArtifact ..\..\WasmerInstaller-%APPVEYOR_REPO_TAG_NAME%.exe
- cd ..\..\
matrix:
fast_finish: true
deploy:
description: 'WasmerInstaller'
artifact: /.*\.exe/
auth_token:
secure: BbreGNDJy20922za7OhJG5TERzfX+dJSBQwttNTJkLvszbqMov6hhAtRb3P45hpf
provider: GitHub
on:
branch: master
appveyor_repo_tag: true

43
.azure/install-cmake.yml Normal file
View File

@ -0,0 +1,43 @@
# This template installs CMake (if doesn't exist in the systems)
steps:
- bash: |
set -ex
if [ -x "`command -v cmake`" ]; then
echo `command -v cmake` `cmake --version` installed
else
curl -O https://cmake.org/files/v3.4/cmake-3.4.1-Darwin-x86_64.tar.gz
tar xf cmake-3.4.1-Darwin-x86_64.tar.gz
export CMAKE_BIN_PATH="`pwd`/cmake-3.4.1-Darwin-x86_64/CMake.app/Contents/bin"
echo "##vso[task.prependpath]$CMAKE_BIN_PATH"
fi
displayName: "Install CMake (macOS)"
condition: eq(variables['Agent.OS'], 'Darwin')
- bash: |
set -ex
if [ -x "`command -v cmake`" ]; then
echo `command -v cmake` `cmake --version` installed
else
curl -O https://cmake.org/files/v3.4/cmake-3.4.1-Linux-x86_64.tar.gz
tar xf cmake-3.4.1-Linux-x86_64.tar.gz
export CMAKE_BIN_PATH="`pwd`/cmake-3.4.1-Linux-x86_64/CMake.app/Contents/bin"
echo "##vso[task.prependpath]$CMAKE_BIN_PATH"
fi
displayName: "Install CMake (Linux)"
condition: eq(variables['Agent.OS'], 'Linux')
- bash: |
set -ex
if [ -x "`command -v cmake`" ]; then
echo `command -v cmake` `cmake --version` installed
else
chocolatey install cmake --installargs 'ADD_CMAKE_TO_PATH=System'
fi
displayName: "Install CMake (Windows)"
condition: eq(variables['Agent.OS'], 'Windows_NT')
- bash: |
set -ex
cmake --version
displayName: CMake version

View File

@ -0,0 +1,18 @@
# This template installs InnoSetup
steps:
- bash: |
set -ex
if [ -x "`command -v iscc`" ]; then
echo `command -v iscc` `iscc -?` installed
else
choco install innosetup -y
fi
displayName: Install InnoSetup - Windows
condition: eq(variables['Agent.OS'], 'Windows_NT')
# - bash: |
# set -ex
# iscc
# displayName: InnoSetup
# condition: eq(variables['Agent.OS'], 'Windows_NT')

53
.azure/install-llvm.yml Normal file
View File

@ -0,0 +1,53 @@
# This template installs LLVM (if doesn't exist in the systems)
steps:
- bash: |
set -ex
if [ -x "`command -v llvm-config`" ]; then
echo `command -v llvm-config` `llvm-config --version` installed
else
curl -O https://releases.llvm.org/8.0.0/clang+llvm-8.0.0-x86_64-apple-darwin.tar.xz
tar xf clang+llvm-8.0.0-x86_64-apple-darwin.tar.xz
export LLVM_PATH="`pwd`/clang+llvm-8.0.0-x86_64-apple-darwin/"
echo "##vso[task.prependpath]$LLVM_PATH/bin"
echo "##vso[task.setvariable variable=LLVM_SYS_80_PREFIX]$LLVM_PATH"
fi
displayName: "Install LLVM (macOS)"
condition: eq(variables['Agent.OS'], 'Darwin')
- bash: |
set -ex
if [ -x "`command -v llvm-config`" ]; then
echo `command -v llvm-config` `llvm-config --version` installed
else
curl -O https://releases.llvm.org/8.0.0/clang+llvm-8.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz
tar xf clang+llvm-8.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz
export LLVM_PATH="`pwd`/clang+llvm-8.0.0-x86_64-linux-gnu-ubuntu-16.04/"
echo "##vso[task.prependpath]$LLVM_PATH/bin"
echo "##vso[task.setvariable variable=LLVM_SYS_80_PREFIX]$LLVM_PATH"
fi
displayName: "Install LLVM (Linux)"
condition: eq(variables['Agent.OS'], 'Linux')
- bash: |
set -ex
curl -OL https://github.com/wasmerio/windows-llvm-build/releases/download/v8.0.0/llvm-8.0.0-install.zip
7z x llvm-8.0.0-install.zip
llvm=`pwd`/llvm-8.0.0-install
echo "##vso[task.prependpath]$llvm/bin"
echo "##vso[task.setvariable variable=LLVM_SYS_80_PREFIX;]$llvm"
displayName: "Install LLVM (Windows)"
condition: eq(variables['Agent.OS'], 'Windows_NT')
# Just to make sure the paths and vars are set properly
- powershell: |
Write-Host "##vso[task.prependpath]$pwd/llvm-8.0.0-install/bin"
Write-Host "##vso[task.setvariable variable=LLVM_SYS_80_PREFIX;]$pwd/llvm-8.0.0-install/"
displayName: Install LLVM (Windows)
condition: eq(variables['Agent.OS'], 'Windows_NT')
- bash: |
set -ex
env
llvm-config --version
displayName: LLVM version

52
.azure/install-rust.yml Normal file
View File

@ -0,0 +1,52 @@
# This template installs Rust (if doesn't exist in the systems)
# Also installs the desired Rust toolchain
# Template inspired by Tokio and wasm-bindgen templates
# Tokio template: https://github.com/tokio-rs/tokio/blob/master/ci/azure-install-rust.yml
# Wasm-bindgen template: https://github.com/rustwasm/wasm-bindgen/blob/master/ci/azure-install-rust.yml
steps:
# - bash: |
# set -ex
# brew install openssl@1.1 curl
# brew link openssl@1.1 --force
# echo "##vso[task.prependpath]/usr/local/opt/openssl/bin"
# echo "##vso[task.setvariable variable=LDFLAGS;]-L/usr/local/opt/openssl/lib"
# echo "##vso[task.setvariable variable=CPPFLAGS;]-I/usr/local/opt/openssl/include"
# displayName: "Fix Cargo SSL (macOS)"
# condition: eq(variables['Agent.OS'], 'Darwin')
- bash: |
set -ex
if [ -x "`command -v rustup`" ]; then
echo `command -v rustup` `rustup -V` installed
else
curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain $RUST_TOOLCHAIN
echo "##vso[task.prependpath]$HOME/.cargo/bin"
fi
displayName: "Install Rust (Linux, macOS)"
condition: ne(variables['Agent.OS'], 'Windows_NT')
# - bash: |
# set -ex
# if [ -x "`command -v rustup`" ]; then
# echo `command -v rustup` `rustup -V` installed
# else
# choco install rust -y
# # curl -sSf -o rustup-init.exe https://win.rustup.rs
# # ./rustup-init.exe -y --default-toolchain $RUST_TOOLCHAIN
# # echo "##vso[task.prependpath]$USERPROFILE/.cargo/bin"
# fi
# displayName: "Install Rust (Windows)"
# condition: eq(variables['Agent.OS'], 'Windows_NT')
- bash: |
set -ex
rustup update --no-self-update $RUST_TOOLCHAIN
rustup default $RUST_TOOLCHAIN
rustc -Vv
cargo -V
displayName: Install Rust
- bash: echo "##vso[task.setvariable variable=RUSTC_VERSION;]`rustc --version`"
displayName: Set rustc version in env var

View File

@ -0,0 +1,57 @@
# This template installs sccache (Shared Compilation Cache)
# More info: https://github.com/mozilla/sccache
# Template originally from wasm-bindgen
# https://github.com/rustwasm/wasm-bindgen/blob/master/ci/azure-install-sccache.yml
steps:
- bash: |
set -ex
curl -L https://github.com/mozilla/sccache/releases/download/0.2.10/sccache-0.2.10-x86_64-unknown-linux-musl.tar.gz | tar xzf -
sccache=`pwd`/sccache-0.2.10-x86_64-unknown-linux-musl/sccache
echo "##vso[task.setvariable variable=RUSTC_WRAPPER;]$sccache"
displayName: Install sccache - Linux
condition: eq( variables['Agent.OS'], 'Linux' )
- bash: |
set -ex
brew install openssl@1.1
curl -L https://github.com/mozilla/sccache/releases/download/0.2.10/sccache-0.2.10-x86_64-apple-darwin.tar.gz | tar xzf -
sccache=`pwd`/sccache-0.2.10-x86_64-apple-darwin/sccache
echo "##vso[task.setvariable variable=RUSTC_WRAPPER;]$sccache"
displayName: Install sccache - Darwin
condition: eq( variables['Agent.OS'], 'Darwin' )
- powershell: |
Invoke-WebRequest https://github.com/mozilla/sccache/releases/download/0.2.10/sccache-0.2.10-x86_64-pc-windows-msvc.tar.gz -OutFile sccache.tar.gz
tar xzf sccache.tar.gz
Write-Host "##vso[task.setvariable variable=RUSTC_WRAPPER;]$pwd/sccache-0.2.10-x86_64-pc-windows-msvc/sccache.exe"
displayName: Install sccache - Windows
condition: eq( variables['Agent.OS'], 'Windows_NT' )
- bash: |
set -ex
env
SCCACHE_ERROR_LOG=`pwd`/sccache.log RUST_LOG=debug $RUSTC_WRAPPER --start-server
$RUSTC_WRAPPER -s
cat sccache.log
displayName: "start sccache"
condition: not(eq( variables['Agent.OS'], 'Windows_NT' ))
env:
SCCACHE_AZURE_CONNECTION_STRING: $(SCCACHE_AZURE_CONNECTION_STRING)
SCCACHE_AZURE_BLOB_CONTAINER: $(SCCACHE_AZURE_BLOB_CONTAINER)
# Only use Azure pipelines cache in Windows
- bash: |
set -ex
env
mkdir -p $SCCACHE_DIR
SCCACHE_ERROR_LOG=`pwd`/sccache.log RUST_LOG=debug $RUSTC_WRAPPER --start-server
$RUSTC_WRAPPER -s
cat sccache.log
displayName: "start sccache"
condition: eq( variables['Agent.OS'], 'Windows_NT' )
env:
SCCACHE_DIR: $(Pipeline.Workspace)/.sccache
- task: CacheBeta@0
inputs:
key: sccache | $(Agent.OS) | Cargo.lock
path: $(Pipeline.Workspace)/.sccache
displayName: Cache Cargo Target
condition: eq( variables['Agent.OS'], 'Windows_NT' )

View File

@ -1,442 +0,0 @@
run_with_build_env_vars: &run_with_build_env_vars
environment:
LLVM_SYS_80_PREFIX: /home/circleci/project/clang+llvm-8.0.0-x86_64-linux-gnu-ubuntu-16.04/
run_install_dependencies: &run_install_dependencies
run:
name: install dependencies
command: |
sudo apt-get install -y cmake
curl -O https://releases.llvm.org/8.0.0/clang+llvm-8.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz
tar xf clang+llvm-8.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz
version: 2
jobs:
changelog:
docker:
- image: docker:stable-git
steps:
- checkout
- run:
command: ! git diff --exit-code CHANGELOG.md
# Job used for testing
lint:
docker:
- image: circleci/rust:latest
<<: *run_with_build_env_vars
steps:
- checkout
- run:
name: "Pull Submodules"
command: |
git submodule update --init
- restore_cache:
keys:
- v8-lint-{{ arch }}-{{ checksum "Cargo.lock" }}
- <<: *run_install_dependencies
- run:
name: Install lint deps
command: |
git config --global --unset url."ssh://git@github.com".insteadOf || true
# rustup toolchain install nightly-2019-06-10
# rustup default nightly-2019-06-10
rustup component add rustfmt
rustup component add clippy || cargo install --git https://github.com/rust-lang/rust-clippy/ --force clippy
- run:
name: Execute lints
command: |
cargo fmt --all -- --check
- save_cache:
paths:
- /usr/local/cargo/registry
- target/debug/.fingerprint
- target/debug/build
- target/debug/deps
key: v8-lint-{{ arch }}-{{ checksum "Cargo.lock" }}
test-stable:
docker:
- image: circleci/rust:1.36
<<: *run_with_build_env_vars
steps:
- checkout
- run:
name: "Pull Submodules"
command: |
git submodule update --init
- restore_cache:
keys:
- v8-test-cargo-cache-linux-stable-{{ arch }}-{{ checksum "Cargo.lock" }}
- <<: *run_install_dependencies
- run:
name: Test everything (except singlepass)
command: |
make cranelift
make llvm
make test-rest
- run:
name: Integration Tests
command: make integration-tests
- save_cache:
paths:
- /usr/local/cargo/registry
- target/release/.fingerprint
- target/release/build
- target/release/deps
key: v8-test-cargo-cache-linux-stable-{{ arch }}-{{ checksum "Cargo.lock" }}
test:
docker:
- image: circleci/rust:latest
<<: *run_with_build_env_vars
steps:
- checkout
- run:
name: "Pull Submodules"
command: |
git submodule update --init
- restore_cache:
keys:
- v8-test-cargo-cache-linux-nightly-{{ arch }}-{{ checksum "Cargo.lock" }}
- <<: *run_install_dependencies
- run: rustup default nightly-2019-06-10
- run:
name: Tests
command: make test
- run:
name: Debug flag checked
command: |
cargo check --features "debug" --release
- run:
name: Check
command: |
make check
make compile-bench-singlepass
make compile-bench-llvm
# TODO: add compile-bench-clif when it works
- run:
name: Integration Tests
command: make integration-tests
- save_cache:
paths:
- /usr/local/cargo/registry
- target/release/.fingerprint
- target/release/build
- target/release/deps
key: v8-test-cargo-cache-linux-nightly-{{ arch }}-{{ checksum "Cargo.lock" }}
test-rust-example:
docker:
- image: circleci/rust:latest
<<: *run_with_build_env_vars
steps:
- checkout
- run:
name: "Check Wasmer Rust example"
command: |
git clone https://github.com/wasmerio/wasmer-rust-example
rustup default stable
rustup target add wasm32-unknown-unknown
cd wasmer-rust-example
cd wasm-sample-app
cargo build --release
cd ..
sed -i 's/wasmer-runtime.*/wasmer-runtime = \{ path = "..\/lib\/runtime" \}/g' Cargo.toml
cargo run
cargo test
test-macos:
macos:
xcode: "9.0"
steps:
- checkout
- run:
name: "Pull Submodules"
command: |
git submodule update --init
- restore_cache:
keys:
- v8-cargo-cache-darwin-nightly-{{ arch }}-{{ checksum "Cargo.lock" }}
- run:
name: Install crate dependencies
command: |
# Installing cmake outside of brew to improve speed
curl -O https://cmake.org/files/v3.4/cmake-3.4.1-Darwin-x86_64.tar.gz
tar xf cmake-3.4.1-Darwin-x86_64.tar.gz
export PATH="`pwd`/cmake-3.4.1-Darwin-x86_64/CMake.app/Contents/bin:$PATH"
# Installing LLVM outside of brew
curl -O https://releases.llvm.org/8.0.0/clang+llvm-8.0.0-x86_64-apple-darwin.tar.xz
tar xf clang+llvm-8.0.0-x86_64-apple-darwin.tar.xz
- run:
name: Install Rust
command: |
curl -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain nightly-2019-06-10
export PATH="$HOME/.cargo/bin:$PATH"
cargo --version
- run:
name: Tests
command: |
export PATH="$HOME/.cargo/bin:$PATH"
export PATH="`pwd`/cmake-3.4.1-Darwin-x86_64/CMake.app/Contents/bin:$PATH"
export LLVM_SYS_80_PREFIX="`pwd`/clang+llvm-8.0.0-x86_64-apple-darwin/"
# We increase the ulimit for fixing cargo unclosed files in mac
ulimit -n 8000
sudo sysctl -w kern.maxfiles=655360 kern.maxfilesperproc=327680
make test
- run:
name: Check
command: |
export PATH="$HOME/.cargo/bin:$PATH"
export LLVM_SYS_80_PREFIX="`pwd`/clang+llvm-8.0.0-x86_64-apple-darwin/"
make check
- run:
name: Integration Tests
command: |
export PATH="$HOME/.cargo/bin:$PATH"
export PATH="`pwd`/cmake-3.4.1-Darwin-x86_64/CMake.app/Contents/bin:$PATH"
export LLVM_SYS_80_PREFIX="`pwd`/clang+llvm-8.0.0-x86_64-apple-darwin/"
make integration-tests
- save_cache:
paths:
- ~/.cargo/registry/
- target/release/.fingerprint
- target/release/build
- target/release/deps
key: v8-cargo-cache-darwin-nightly-{{ arch }}-{{ checksum "Cargo.lock" }}
test-and-build:
docker:
- image: circleci/rust:latest
steps:
- checkout
- run:
name: "Pull Submodules"
command: |
git submodule update --init
- run:
name: "Pull dependencies"
command: |
git submodule init
git submodule update
- restore_cache:
keys:
- v8-cargo-cache-linux-nightly-{{ arch }}-{{ checksum "Cargo.lock" }}
- run:
name: Install dependencies
command: |
sudo apt-get install -y cmake
curl -O https://releases.llvm.org/8.0.0/clang+llvm-8.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz
tar xf clang+llvm-8.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz
- run: rustup default nightly-2019-06-10
- run:
name: Tests
command: |
export LLVM_SYS_80_PREFIX="`pwd`/clang+llvm-8.0.0-x86_64-linux-gnu-ubuntu-16.04/"
make test
- run:
name: Release Build
command: |
export LLVM_SYS_80_PREFIX="`pwd`/clang+llvm-8.0.0-x86_64-linux-gnu-ubuntu-16.04/"
make release
cargo build --release --manifest-path wapm-cli/Cargo.toml --features "telemetry update-notifications"
mkdir -p artifacts
VERSION=$(cargo pkgid | cut -d# -f2 | cut -d: -f2)
# GIT_VERSION=$(git describe --exact-match --tags)
echo "${VERSION}" >> artifacts/version
echo "${CIRCLE_TAG}" >> artifacts/git_version
make build-install
cp ./wasmer.tar.gz ./artifacts/$(./scripts/binary-name.sh)
- run:
name: Dynamic library
command: |
cargo build --release --manifest-path lib/runtime-c-api/Cargo.toml
cp target/release/libwasmer_runtime_c_api.so ./artifacts
- persist_to_workspace:
root: .
paths:
- artifacts
- save_cache:
paths:
- /usr/local/cargo/registry
- target/release/.fingerprint
- target/release/build
- target/release/deps
- wapm-cli/target/release/.fingerprint
- wapm-cli/target/release/build
- wapm-cli/target/release/deps
key: v8-cargo-cache-linux-nightly-{{ arch }}-{{ checksum "Cargo.lock" }}
test-and-build-macos:
macos:
xcode: "9.0"
steps:
- checkout
- run:
name: "Pull dependencies"
command: |
git submodule init
git submodule update
- restore_cache:
keys:
- v8-cargo-cache-darwin-nightly-{{ arch }}-{{ checksum "Cargo.lock" }}
- run:
name: Install crate dependencies
command: |
# Installing cmake outside of brew to improve speed
curl -O https://cmake.org/files/v3.4/cmake-3.4.1-Darwin-x86_64.tar.gz
tar xf cmake-3.4.1-Darwin-x86_64.tar.gz
export PATH="`pwd`/cmake-3.4.1-Darwin-x86_64/CMake.app/Contents/bin:$PATH"
# Installing LLVM outside of brew
curl -O https://releases.llvm.org/8.0.0/clang+llvm-8.0.0-x86_64-apple-darwin.tar.xz
tar xf clang+llvm-8.0.0-x86_64-apple-darwin.tar.xz
- run:
name: Install Rust
command: |
curl -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain nightly-2019-06-10
export PATH="$HOME/.cargo/bin:$PATH"
cargo --version
- run:
name: Tests
command: |
export PATH="`pwd`/cmake-3.4.1-Darwin-x86_64/CMake.app/Contents/bin:$PATH"
export PATH="$HOME/.cargo/bin:$PATH"
export LLVM_SYS_80_PREFIX="`pwd`/clang+llvm-8.0.0-x86_64-apple-darwin/"
# We increase the ulimit for fixing cargo unclosed files in mac
ulimit -n 8000
sudo sysctl -w kern.maxfiles=655360 kern.maxfilesperproc=327680
make test
- run:
name: Release Build
command: |
export PATH="`pwd`/cmake-3.4.1-Darwin-x86_64/CMake.app/Contents/bin:$PATH"
export PATH="$HOME/.cargo/bin:$PATH"
export LLVM_SYS_80_PREFIX="`pwd`/clang+llvm-8.0.0-x86_64-apple-darwin/"
make release
cargo build --release --manifest-path wapm-cli/Cargo.toml --features "telemetry update-notifications"
mkdir -p artifacts
make build-install
cp ./wasmer.tar.gz ./artifacts/$(./scripts/binary-name.sh)
# VERSION=$(cargo pkgid | cut -d# -f2 | cut -d: -f2)
# echo "${VERSION}" >> artifacts/version
- run:
name: Generate dynamic library for the runtime C API
command: |
export PATH="$HOME/.cargo/bin:$PATH"
cargo build --release --manifest-path lib/runtime-c-api/Cargo.toml
install_name_tool -id "@rpath/libwasmer_runtime_c_api.dylib" target/release/libwasmer_runtime_c_api.dylib
cp target/release/libwasmer_runtime_c_api.dylib ./artifacts
- persist_to_workspace:
root: .
paths:
- artifacts
- save_cache:
paths:
- ~/.cargo/registry/
- target/release/.fingerprint
- target/release/build
- target/release/deps
- wapm-cli/target/release/.fingerprint
- wapm-cli/target/release/build
- wapm-cli/target/release/deps
key: v8-cargo-cache-darwin-nightly-{{ arch }}-{{ checksum "Cargo.lock" }}
publish-github-release:
docker:
- image: cibuilds/github
steps:
- attach_workspace:
at: .
- run:
name: "Publish Release on GitHub"
command: |
# go get github.com/tcnksm/ghr
# VERSION=$(git log -1 --pretty=%B)
# VERSION=$(./artifacts/ --version)
VERSION=$(cat ./artifacts/version)
# VERSION_TAG=${CIRCLE_TAG}
VERSION_TAG=$(cat ./artifacts/git_version)
LATEST_VERSION_PUBLISHED_ON_CRATES=$(curl -s https://raw.githubusercontent.com/rust-lang/crates.io-index/master/wa/sm/wasmer-runtime | tail -n 1 | sed 's/.*"vers":"\([^"]*\)".*/\1/')
if ( [ $VERSION_TAG -ne $LATEST_VERSION_PUBLISHED_ON_CRATES ] ) then { echo "Could not detect version published to crates.io; make sure we've published the crates before publishing the Wasmer binary"; exit 1; } else { true; } fi
rm ./artifacts/version
rm ./artifacts/git_version
# VERSION_TAG=$(git describe --exact-match --tags)
#if [ "$VERSION" == "$VERSION_TAG" ]; then
# echo "Versions match, publishing to Github"
ghr -t ${GITHUB_TOKEN} -u ${CIRCLE_PROJECT_USERNAME} -r ${CIRCLE_PROJECT_REPONAME} -c ${CIRCLE_SHA1} ${VERSION} ./artifacts/ || true
#else
# echo "Versions don't match. Wasmer output version (wasmer --version) is ${VERSION} while Git tag is ${VERSION_TAG}"
# exit 1
#fi
trigger-benchmark-build:
docker:
- image: circleci/rust:latest
steps:
- run:
name: "Trigger Benchmark Build"
command: |
if [[ -z "${CIRCLE_API_USER_TOKEN}" ]]; then
echo "CIRCLE_API_USER_TOKEN environment variable not set"
exit 1
else
echo "Triggering benchmark build"
curl -u ${CIRCLE_API_USER_TOKEN} \
-d build_parameters[CIRCLE_JOB]=bench \
https://circleci.com/api/v1.1/project/github/wasmerio/wasmer-bench/tree/master
fi
workflows:
version: 2
main:
jobs:
- changelog
- lint
- test:
filters:
branches:
only:
- trying
- staging
- test-rust-example:
filters:
branches:
only:
- trying
- staging
- test-macos:
filters:
branches:
only:
- trying
- staging
- test-and-build:
filters:
branches:
only:
- master
- test-and-build-macos:
filters:
branches:
only:
- master
- test-stable:
filters:
branches:
only:
- trying
- staging
- publish-github-release:
requires:
- lint
- test-and-build
- test-and-build-macos
filters:
branches:
only: master
- trigger-benchmark-build:
requires:
- test-and-build
- lint
filters:
branches:
only: master

View File

@ -2,5 +2,6 @@
** **
!lib/** !lib/**
!src/** !src/**
!examples/**
!Cargo.toml !Cargo.toml
!Cargo.lock !Cargo.lock

1
.gitattributes vendored
View File

@ -1,2 +1,3 @@
lib/emscripten/emtests/* linguist-vendored lib/emscripten/emtests/* linguist-vendored
lib/spectests/spectests/* linguist-vendored lib/spectests/spectests/* linguist-vendored
CHANGELOG.md merge=union

1
.github/CODEOWNERS vendored
View File

@ -8,7 +8,6 @@ lib/llvm-backend @nlewycky @losfair
# Runtime # Runtime
lib/runtime-core @Hywan @bjfish lib/runtime-core @Hywan @bjfish
lib/runtime-abi @MarkMcCaskey
lib/runtime @MarkMcCaskey @Hywan @bjfish lib/runtime @MarkMcCaskey @Hywan @bjfish
lib/runtime-c-api @bjfish @Hywan lib/runtime-c-api @bjfish @Hywan
lib/win-exception-handler @bjfish @losfair lib/win-exception-handler @bjfish @losfair

View File

@ -7,37 +7,44 @@ assignees: ''
--- ---
Thanks for the bug report! <!-- Thanks for the bug report! -->
### Describe the bug ### Describe the bug
<!--
A clear and concise description of what the bug is. A clear and concise description of what the bug is.
Copy and paste the result of executing the following in your shell, so we can know the version of wasmer, Rust (if available) and architecture of your environment. Copy and paste the result of executing the following in your shell, so we can know the version of wasmer, Rust (if available) and architecture of your environment.
-->
```bash ```sh
echo "`wasmer -V` | `rustc -V` | `uname -m`" echo "`wasmer -V` | `rustc -V` | `uname -m`"
``` ```
### Steps to reproduce
### Steps to reproduce
<!--
Include steps that will help us recreate the issue.
For example,
1. Go to '…' 1. Go to '…'
2. Compile with '…' 2. Compile with '…'
3. Run '…' 3. Run '…'
4. See error 4. See error
If applicable, add a link to a test case (as a zip file or link to a repository we can clone). If applicable, add a link to a test case (as a zip file or link to a repository we can clone).
-->
### Expected behavior ### Expected behavior
<!-- A clear and concise description of what you expected to happen. -->
A clear and concise description of what you expected to happen.
### Actual behavior ### Actual behavior
<!--
A clear and concise description of what actually happened. A clear and concise description of what actually happened.
If applicable, add screenshots to help explain your problem. If applicable, add screenshots to help explain your problem.
-->
### Additional context ### Additional context
<!-- Add any other context about the problem here. -->
Add any other context about the problem here.

15
.github/pull_request_template.md vendored Normal file
View File

@ -0,0 +1,15 @@
<!--
Prior to submitting a PR, review the CONTRIBUTING.md document for recommendations on how to test:
https://github.com/wasmerio/wasmer/blob/master/CONTRIBUTING.md#pull-requests
-->
# Description
<!--
Provide details regarding the change including motivation,
links to related issues, and the context of the PR.
-->
# Review
- [ ] Add a short description of the the change to the CHANGELOG.md file

65
.travis.yml Normal file
View File

@ -0,0 +1,65 @@
arch:
- arm64
language: rust
rust:
- nightly-2019-08-15
cache:
directories:
- /home/travis/.sccache/
- /home/travis/.cargo/bin/
script:
# Sccache
# - curl -L https://github.com/mozilla/sccache/releases/download/0.2.10/sccache-0.2.10-x86_64-unknown-linux-musl.tar.gz | tar xzf -
# - export RUSTC_WRAPPER=`pwd`/sccache-0.2.10-x86_64-unknown-linux-musl/sccache
- test -f /home/travis/.cargo/bin/sccache || cargo install sccache
- export RUSTC_WRAPPER=/home/travis/.cargo/bin/sccache
- mkdir -p /home/travis/.sccache/
- export SCCACHE_DIR="/home/travis/.sccache/"
- SCCACHE_ERROR_LOG=`pwd`/sccache.log RUST_LOG=debug $RUSTC_WRAPPER --start-server
- $RUSTC_WRAPPER -s
# Tests
- make spectests-singlepass
before_deploy:
# Release
- make release-singlepass
- make wapm
- make build-install
- mkdir -p artifacts
- cp ./wasmer.tar.gz ./artifacts/$(./scripts/binary-name.sh)
# before_deploy:
# # Set up git user name and tag this commit
# - git config --local user.name "Syrus Akbary"
# - git config --local user.email "syrus@wasmer.io"
# - export TRAVIS_TAG="0.10.2"
# # - git tag $TRAVIS_TAG
deploy:
provider: releases
file_glob: true
file: artifacts/*
api_key: $GITHUB_OAUTH_TOKEN
# This is set to the previous artifacts are not deleted by travis
skip_cleanup: true
on:
tags: true
# branch: feature/singlepass-aarch64
addons:
apt:
packages:
- cmake
branches:
only:
- master
- staging
- trying
# Making sure Travis runs on new Tags
- /^\d+\.\d+(\.\d+)?(-\S*)?$/
- /^v\d+\.\d+(\.\d+)?(-\S*)?$/

View File

@ -1,13 +1,113 @@
# Changelog # Changelog
All PRs to the Wasmer repository must add to this file.
Blocks of changes will separated by version increments.
## **[Unreleased]** ## **[Unreleased]**
- [#1029](https://github.com/wasmerio/wasmer/pull/1029) Add the “floating” `WasiVersion::Latest` version.
- [#1006](https://github.com/wasmerio/wasmer/pull/1006) Fix minor panic issue when `wasmer::compile_with` called with llvm backend
- [#1009](https://github.com/wasmerio/wasmer/pull/1009) Enable LLVM verifier for all tests, add new llvm-backend-tests crate.
- [#1022](https://github.com/wasmerio/wasmer/pull/1022) Add caching support for Singlepass backend.
- [#1004](https://github.com/wasmerio/wasmer/pull/1004) Add the Auto backend to enable to adapt backend usage depending on wasm file executed.
## 0.11.0 - 2019-11-22
- [#713](https://github.com/wasmerio/wasmer/pull/713) Add AArch64 support for singlepass.
- [#995](https://github.com/wasmerio/wasmer/pull/995) Detect when a global is read without being initialized (emit a proper error instead of panicking)
- [#996](https://github.com/wasmerio/wasmer/pull/997) Refactored spectests, emtests and wasitests to use default compiler logic
- [#992](https://github.com/wasmerio/wasmer/pull/992) Updates WAPM version to 0.4.1, fix arguments issue introduced in #990
- [#990](https://github.com/wasmerio/wasmer/pull/990) Default wasmer CLI to `run`. Wasmer will now attempt to parse unrecognized command line options as if they were applied to the run command: `wasmer mywasm.wasm --dir=.` now works!
- [#987](https://github.com/wasmerio/wasmer/pull/987) Fix `runtime-c-api` header files when compiled by gnuc.
- [#957](https://github.com/wasmerio/wasmer/pull/957) Change the meaning of `wasmer_wasi::is_wasi_module` to detect any type of WASI module, add support for new wasi snapshot_preview1
- [#934](https://github.com/wasmerio/wasmer/pull/934) Simplify float expressions in the LLVM backend.
## 0.10.2 - 2019-11-18
- [#968](https://github.com/wasmerio/wasmer/pull/968) Added `--invoke` option to the command
- [#964](https://github.com/wasmerio/wasmer/pull/964) Enable cross-compilation for specific target
- [#971](https://github.com/wasmerio/wasmer/pull/971) In LLVM backend, use unaligned loads and stores for non-atomic accesses to wasmer memory.
- [#960](https://github.com/wasmerio/wasmer/pull/960) Fix `runtime-c-api` header files when compiled by clang.
- [#925](https://github.com/wasmerio/wasmer/pull/925) Host functions can be closures with a captured environment.
- [#917](https://github.com/wasmerio/wasmer/pull/917) Host functions (aka imported functions) may not have `&mut vm::Ctx` as first argument, i.e. the presence of the `&mut vm::Ctx` argument is optional.
- [#915](https://github.com/wasmerio/wasmer/pull/915) All backends share the same definition of `Trampoline` (defined in `wasmer-runtime-core`).
## 0.10.1 - 2019-11-11
- [#952](https://github.com/wasmerio/wasmer/pull/952) Use C preprocessor to properly hide trampoline functions on Windows and non-x86_64 targets.
## 0.10.0 - 2019-11-11
Special thanks to [@newpavlov](https://github.com/newpavlov) and [@Maxgy](https://github.com/Maxgy) for their contributions!
- [#942](https://github.com/wasmerio/wasmer/pull/942) Deny missing docs in runtime core and add missing docs
- [#939](https://github.com/wasmerio/wasmer/pull/939) Fix bug causing attempts to append to files with WASI to delete the contents of the file
- [#940](https://github.com/wasmerio/wasmer/pull/940) Update supported Rust version to 1.38+
- [#923](https://github.com/wasmerio/wasmer/pull/923) Fix memory leak in the C API caused by an incorrect cast in `wasmer_trampoline_buffer_destroy`
- [#921](https://github.com/wasmerio/wasmer/pull/921) In LLVM backend, annotate all memory accesses with TBAA metadata.
- [#883](https://github.com/wasmerio/wasmer/pull/883) Allow floating point operations to have arbitrary inputs, even including SNaNs.
- [#856](https://github.com/wasmerio/wasmer/pull/856) Expose methods in the runtime C API to get a WASI import object
## 0.9.0 - 2019-10-23
Special thanks to @alocquet for their contributions!
- [#898](https://github.com/wasmerio/wasmer/pull/898) State tracking is now disabled by default in the LLVM backend. It can be enabled with `--track-state`.
- [#861](https://github.com/wasmerio/wasmer/pull/861) Add descriptions to `unimplemented!` macro in various places
- [#897](https://github.com/wasmerio/wasmer/pull/897) Removes special casing of stdin, stdout, and stderr in WASI. Closing these files now works. Removes `stdin`, `stdout`, and `stderr` from `WasiFS`, replaced by the methods `stdout`, `stdout_mut`, and so on.
- [#863](https://github.com/wasmerio/wasmer/pull/863) Fix min and max for cases involving NaN and negative zero when using the LLVM backend.
## 0.8.0 - 2019-10-02
Special thanks to @jdanford for their contributions!
- [#850](https://github.com/wasmerio/wasmer/pull/850) New `WasiStateBuilder` API. small, add misc. breaking changes to existing API (for example, changing the preopen dirs arg on `wasi::generate_import_object` from `Vec<String>` to `Vec<Pathbuf>`)
- [#852](https://github.com/wasmerio/wasmer/pull/852) Make minor grammar/capitalization fixes to README.md
- [#841](https://github.com/wasmerio/wasmer/pull/841) Slightly improve rustdoc documentation and small updates to outdated info in readme files
- [#836](https://github.com/wasmerio/wasmer/pull/836) Update Cranelift fork version to `0.44.0`
- [#839](https://github.com/wasmerio/wasmer/pull/839) Change supported version to stable Rust 1.37+
- [#834](https://github.com/wasmerio/wasmer/pull/834) Fix panic when unwraping `wasmer` arguments
- [#835](https://github.com/wasmerio/wasmer/pull/835) Add parallel execution example (independent instances created from the same `ImportObject` and `Module` run with rayon)
- [#834](https://github.com/wasmerio/wasmer/pull/834) Fix panic when parsing numerical arguments for no-ABI targets run with the wasmer binary
- [#833](https://github.com/wasmerio/wasmer/pull/833) Add doc example of using ImportObject's new `maybe_with_namespace` method
- [#832](https://github.com/wasmerio/wasmer/pull/832) Delete unused runtime ABI
- [#809](https://github.com/wasmerio/wasmer/pull/809) Fix bugs leading to panics in `LocalBacking`.
- [#831](https://github.com/wasmerio/wasmer/pull/831) Add support for atomic operations, excluding wait and notify, to singlepass.
- [#822](https://github.com/wasmerio/wasmer/pull/822) Update Cranelift fork version to `0.43.1`
- [#829](https://github.com/wasmerio/wasmer/pull/829) Fix deps on `make bench-*` commands; benchmarks don't compile other backends now
- [#807](https://github.com/wasmerio/wasmer/pull/807) Implement Send for `Instance`, breaking change on `ImportObject`, remove method `get_namespace` replaced with `with_namespace` and `maybe_with_namespace`
- [#817](https://github.com/wasmerio/wasmer/pull/817) Add document for tracking features across backends and language integrations, [docs/feature_matrix.md]
- [#823](https://github.com/wasmerio/wasmer/issues/823) Improved Emscripten / WASI integration
- [#821](https://github.com/wasmerio/wasmer/issues/821) Remove patch version on most deps Cargo manifests. This gives Wasmer library users more control over which versions of the deps they use.
- [#820](https://github.com/wasmerio/wasmer/issues/820) Remove null-pointer checks in `WasmPtr` from runtime-core, re-add them in Emscripten
- [#803](https://github.com/wasmerio/wasmer/issues/803) Add method to `Ctx` to invoke functions by their `TableIndex`
- [#790](https://github.com/wasmerio/wasmer/pull/790) Fix flaky test failure with LLVM, switch to large code model.
- [#788](https://github.com/wasmerio/wasmer/pull/788) Use union merge on the changelog file.
- [#785](https://github.com/wasmerio/wasmer/pull/785) Include Apache license file for spectests.
- [#786](https://github.com/wasmerio/wasmer/pull/786) In the LLVM backend, lower atomic wasm operations to atomic machine instructions.
- [#784](https://github.com/wasmerio/wasmer/pull/784) Fix help string for wasmer run.
## 0.7.0 - 2019-09-12
Special thanks to @YaronWittenstein @penberg for their contributions. Special thanks to @YaronWittenstein @penberg for their contributions.
- [#776](https://github.com/wasmerio/wasmer/issues/776) Allow WASI preopened fds to be closed
- [#774](https://github.com/wasmerio/wasmer/issues/774) Add more methods to the `WasiFile` trait
- [#772](https://github.com/wasmerio/wasmer/issues/772) [#770](https://github.com/wasmerio/wasmer/issues/770) Handle more internal failures by passing back errors
- [#756](https://github.com/wasmerio/wasmer/issues/756) Allow NULL parameter and 0 arity in `wasmer_export_func_call` C API
- [#747](https://github.com/wasmerio/wasmer/issues/747) Return error instead of panicking on traps when using the Wasmer binary
- [#741](https://github.com/wasmerio/wasmer/issues/741) Add validate Wasm fuzz target
- [#733](https://github.com/wasmerio/wasmer/issues/733) Remove dependency on compiler backends for `middleware-common`
- [#732](https://github.com/wasmerio/wasmer/issues/732) [#731](https://github.com/wasmerio/wasmer/issues/731) WASI bug fixes and improvements
- [#726](https://github.com/wasmerio/wasmer/issues/726) Add serialization and deserialization for Wasi State
- [#716](https://github.com/wasmerio/wasmer/issues/716) Improve portability of install script
- [#714](https://github.com/wasmerio/wasmer/issues/714) Add Code of Conduct
- [#708](https://github.com/wasmerio/wasmer/issues/708) Remove unconditional dependency on Cranelift in the C API
- [#703](https://github.com/wasmerio/wasmer/issues/703) Fix compilation on AArch64 Linux
- [#702](https://github.com/wasmerio/wasmer/issues/702) Add SharedMemory to Wasmer. Add `--enable-threads` flag, add partial implementation of atomics to LLVM backend.
- [#698](https://github.com/wasmerio/wasmer/issues/698) [#690](https://github.com/wasmerio/wasmer/issues/690) [#687](https://github.com/wasmerio/wasmer/issues/690) Fix panics in Emscripten
- [#689](https://github.com/wasmerio/wasmer/issues/689) Replace `wasmer_runtime_code::memory::Atomic` with `std::sync::atomic` atomics, changing its interface
- [#680](https://github.com/wasmerio/wasmer/issues/680) [#673](https://github.com/wasmerio/wasmer/issues/673) [#669](https://github.com/wasmerio/wasmer/issues/669) [#660](https://github.com/wasmerio/wasmer/issues/660) [#659](https://github.com/wasmerio/wasmer/issues/659) Misc. runtime and singlepass fixes
- [#677](https://github.com/wasmerio/wasmer/issues/677) [#675](https://github.com/wasmerio/wasmer/issues/675) [#674](https://github.com/wasmerio/wasmer/issues/674) LLVM backend fixes and improvements
- [#671](https://github.com/wasmerio/wasmer/issues/671) Implement fs polling in `wasi::poll_oneoff` for Unix-like platforms
- [#656](https://github.com/wasmerio/wasmer/issues/656) Move CI to Azure Pipelines
- [#650](https://github.com/wasmerio/wasmer/issues/650) Implement `wasi::path_rename`, improve WASI FS public api, and allow open files to exist even when the underlying file is deleted - [#650](https://github.com/wasmerio/wasmer/issues/650) Implement `wasi::path_rename`, improve WASI FS public api, and allow open files to exist even when the underlying file is deleted
- [#643](https://github.com/wasmerio/wasmer/issues/643) Implement `wasi::path_symlink` and improve WASI FS public api IO error reporting - [#643](https://github.com/wasmerio/wasmer/issues/643) Implement `wasi::path_symlink` and improve WASI FS public api IO error reporting
- [#608](https://github.com/wasmerio/wasmer/issues/608) Implement wasi syscalls `fd_allocate`, `fd_sync`, `fd_pread`, `path_link`, `path_filestat_set_times`; update WASI fs API in a WIP way; reduce coupling of WASI code to host filesystem; make debug messages from WASI more readable; improve rights-checking when calling syscalls; implement reference counting on inodes; misc bug fixes and improvements - [#608](https://github.com/wasmerio/wasmer/issues/608) Implement wasi syscalls `fd_allocate`, `fd_sync`, `fd_pread`, `path_link`, `path_filestat_set_times`; update WASI fs API in a WIP way; reduce coupling of WASI code to host filesystem; make debug messages from WASI more readable; improve rights-checking when calling syscalls; implement reference counting on inodes; misc bug fixes and improvements

View File

@ -3,12 +3,15 @@
Thank you for your interest in contributing to Wasmer. This document outlines some recommendations on how to contribute. Thank you for your interest in contributing to Wasmer. This document outlines some recommendations on how to contribute.
## Issues & Feature Requests ## Issues & Feature Requests
Please use the issue template and provide a failing example if possible to help us recreate the issue. Please use the issue template and provide a failing example if possible to help us recreate the issue.
## Pull Requests ## Pull Requests
For large changes, please try reaching the Wasmer using Github Issues or Spectrum Chat to ensure we can accept the change once it is ready.
For large changes, please try reaching communicating with the Wasmer maintainers via GitHub Issues or Spectrum Chat to ensure we can accept the change once it is ready.
We recommend trying the following commands before sending a pull request to ensure code quality: We recommend trying the following commands before sending a pull request to ensure code quality:
- `cargo fmt --all` Ensures all code is correctly formatted. - `cargo fmt --all` Ensures all code is correctly formatted.
- Run `cargo test` in the crates that you are modifying. - Run `cargo test` in the crates that you are modifying.
- Run `cargo build --all` (nightly) or `cargo build --all --exclude wasmer-singlepass-backend` - Run `cargo build --all` (nightly) or `cargo build --all --exclude wasmer-singlepass-backend`
@ -17,17 +20,14 @@ A comprehensive CI test suite will be run by a Wasmer team member after the PR h
### Common Build Issues ### Common Build Issues
**LLVM Dependency** #### LLVM Dependency
The LLVM backend requires LLVM to be installed to compile. `Didn't find usable system-wide LLVM`
So, you may run into the following error: Building Wasmer with the LLVM backend requires LLVM to be installed
```
Didn't find usable system-wide LLVM.
No suitable version of LLVM was found system-wide or pointed
```
**Singlepass Nightly Only** #### Singlepass Nightly Only
The singlepass crate depends on nightly so you may need to add the `+nightly` cargo flag to compile this crate.
`error[E0554]: #![feature] may not be used on the stable release channel` `error[E0554]: #![feature] may not be used on the stable release channel`
Building Wasmer with the singlepass backend requires the nightly version of Rust

1561
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,12 +1,13 @@
[package] [package]
name = "wasmer" name = "wasmer"
version = "0.6.0" version = "0.11.0"
authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"] 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"
default-run = "wasmer"
include = [ include = [
"examples/**/*", "examples/**/*",
"src/**/*", "src/**/*",
@ -19,15 +20,14 @@ include = [
] ]
[dependencies] [dependencies]
byteorder = "1.3.2" byteorder = "1.3"
errno = "0.2.4" errno = "0.2"
structopt = "0.2.18" structopt = "0.3"
wabt = "0.9.1" wabt = "0.9.1"
wasmer-clif-backend = { path = "lib/clif-backend" } wasmer-clif-backend = { path = "lib/clif-backend", optional = true }
wasmer-singlepass-backend = { path = "lib/singlepass-backend", optional = true } wasmer-singlepass-backend = { path = "lib/singlepass-backend", optional = true }
wasmer-middleware-common = { path = "lib/middleware-common" } wasmer-middleware-common = { path = "lib/middleware-common" }
wasmer-runtime = { path = "lib/runtime" } wasmer-runtime = { path = "lib/runtime" }
# wasmer-runtime-abi = { path = "lib/runtime-abi", optional = true }
wasmer-runtime-core = { path = "lib/runtime-core" } wasmer-runtime-core = { path = "lib/runtime-core" }
wasmer-emscripten = { path = "lib/emscripten" } wasmer-emscripten = { path = "lib/emscripten" }
wasmer-llvm-backend = { path = "lib/llvm-backend", optional = true } wasmer-llvm-backend = { path = "lib/llvm-backend", optional = true }
@ -35,6 +35,7 @@ wasmer-wasi = { path = "lib/wasi", optional = true }
wasmer-kernel-loader = { path = "lib/kernel-loader", optional = true } wasmer-kernel-loader = { path = "lib/kernel-loader", optional = true }
wasmer-dev-utils = { path = "lib/dev-utils", optional = true } wasmer-dev-utils = { path = "lib/dev-utils", optional = true }
wasmer-wasi-tests = { path = "lib/wasi-tests", optional = true } wasmer-wasi-tests = { path = "lib/wasi-tests", optional = true }
wasmer-middleware-common-tests = { path = "lib/middleware-common-tests", optional = true }
wasmer-emscripten-tests = { path = "lib/emscripten-tests", optional = true } wasmer-emscripten-tests = { path = "lib/emscripten-tests", optional = true }
wasmer-wasi-framebuffer = { path = "lib/wasi-framebuffer", optional = true } wasmer-wasi-framebuffer = { path = "lib/wasi-framebuffer", optional = true }
@ -43,13 +44,14 @@ members = [
"lib/clif-backend", "lib/clif-backend",
"lib/singlepass-backend", "lib/singlepass-backend",
"lib/runtime", "lib/runtime",
# "lib/runtime-abi",
"lib/runtime-core", "lib/runtime-core",
"lib/runtime-core-tests",
"lib/emscripten", "lib/emscripten",
"lib/spectests", "lib/spectests",
"lib/win-exception-handler", "lib/win-exception-handler",
"lib/runtime-c-api", "lib/runtime-c-api",
"lib/llvm-backend", "lib/llvm-backend",
"lib/llvm-backend-tests",
"lib/wasi", "lib/wasi",
"lib/middleware-common", "lib/middleware-common",
"lib/kernel-loader", "lib/kernel-loader",
@ -58,43 +60,56 @@ members = [
"lib/wasi-framebuffer", "lib/wasi-framebuffer",
"lib/wasi-tests", "lib/wasi-tests",
"lib/emscripten-tests", "lib/emscripten-tests",
"examples/plugin-for-example" "lib/middleware-common-tests",
"examples/parallel",
"examples/plugin-for-example",
"examples/parallel-guest",
] ]
[build-dependencies] [build-dependencies]
wabt = "0.9.1" wabt = "0.9.1"
glob = "0.3.0" glob = "0.3"
rustc_version = "0.2.3" rustc_version = "0.2"
[dev-dependencies]
serde = { version = "1", features = ["derive"] } # used by the plugin example
typetag = "0.1" # used by the plugin example
[features] [features]
default = ["fast-tests", "wasi", "backend-cranelift"] default = ["fast-tests", "wasi"]
"loader-kernel" = ["wasmer-kernel-loader"] "loader-kernel" = ["wasmer-kernel-loader"]
debug = ["wasmer-runtime-core/debug"] debug = ["wasmer-runtime-core/debug"]
trace = ["wasmer-runtime-core/trace"] trace = ["wasmer-runtime-core/trace"]
docs = ["wasmer-runtime/docs"]
extra-debug = ["wasmer-clif-backend/debug", "wasmer-runtime-core/debug"] extra-debug = ["wasmer-clif-backend/debug", "wasmer-runtime-core/debug"]
# This feature will allow cargo test to run much faster # This feature will allow cargo test to run much faster
fast-tests = [] fast-tests = []
backend-cranelift = [ backend-cranelift = [
"wasmer-clif-backend",
"wasmer-runtime-core/backend-cranelift", "wasmer-runtime-core/backend-cranelift",
"wasmer-runtime/cranelift", "wasmer-runtime/cranelift",
"wasmer-middleware-common/clif" "wasmer-middleware-common-tests/clif",
] ]
backend-llvm = [ backend-llvm = [
"wasmer-llvm-backend", "wasmer-llvm-backend",
"wasmer-runtime-core/backend-llvm", "wasmer-runtime-core/backend-llvm",
"wasmer-runtime/llvm", "wasmer-runtime/llvm",
"wasmer-middleware-common/llvm" "wasmer-middleware-common-tests/llvm",
] ]
backend-singlepass = [ backend-singlepass = [
"wasmer-singlepass-backend", "wasmer-singlepass-backend",
"wasmer-runtime-core/backend-singlepass", "wasmer-runtime-core/backend-singlepass",
"wasmer-runtime/singlepass", "wasmer-runtime/singlepass",
"wasmer-middleware-common/singlepass" "wasmer-middleware-common-tests/singlepass",
] ]
wasi = ["wasmer-wasi"] wasi = ["wasmer-wasi"]
# vfs = ["wasmer-runtime-abi"]
experimental-framebuffer = ["wasmer-wasi-framebuffer"] experimental-framebuffer = ["wasmer-wasi-framebuffer"]
managed = ["backend-singlepass", "wasmer-runtime-core/managed"]
[[example]] [[example]]
name = "plugin" name = "plugin"
crate-type = ["bin"] crate-type = ["bin"]
[[example]]
name = "callback"
crate-type = ["bin"]

View File

@ -1,4 +1,4 @@
FROM circleci/rust:1.33.0-stretch as wasmer-build-env FROM circleci/rust:1.38.0-stretch as wasmer-build-env
RUN sudo apt-get update && \ RUN sudo apt-get update && \
sudo apt-get install -y --no-install-recommends \ sudo apt-get install -y --no-install-recommends \
cmake \ cmake \
@ -17,7 +17,7 @@ FROM wasmer-build-env AS wasmer-build
WORKDIR /home/circleci/wasmer WORKDIR /home/circleci/wasmer
COPY . /home/circleci/wasmer COPY . /home/circleci/wasmer
RUN sudo chmod -R 777 . RUN sudo chmod -R 777 .
RUN cargo build --release RUN cargo build --release --features backend-cranelift
FROM debian:stretch AS wasmer FROM debian:stretch AS wasmer
WORKDIR /root/ WORKDIR /root/

155
Makefile
View File

@ -1,11 +1,15 @@
.PHONY: spectests emtests clean build install lint precommit .PHONY: spectests emtests clean build install lint precommit docs examples
# Generate files # Generate files
generate-spectests: generate-spectests:
WASMER_RUNTIME_GENERATE_SPECTESTS=1 cargo build -p wasmer-runtime-core --release WASMER_RUNTIME_GENERATE_SPECTESTS=1 cargo build -p wasmer-runtime-core --release \
&& echo "formatting" \
&& cargo fmt
generate-emtests: generate-emtests:
WASM_EMSCRIPTEN_GENERATE_EMTESTS=1 cargo build -p wasmer-emscripten-tests --release WASM_EMSCRIPTEN_GENERATE_EMTESTS=1 cargo build -p wasmer-emscripten-tests --release \
&& echo "formatting" \
&& cargo fmt
generate-wasitests: wasitests-setup generate-wasitests: wasitests-setup
WASM_WASI_GENERATE_WASITESTS=1 cargo build -p wasmer-wasi-tests --release -vv \ WASM_WASI_GENERATE_WASITESTS=1 cargo build -p wasmer-wasi-tests --release -vv \
@ -21,7 +25,7 @@ generate: generate-spectests generate-emtests generate-wasitests
# Spectests # Spectests
spectests-singlepass: spectests-singlepass:
cargo test --manifest-path lib/spectests/Cargo.toml --release --features singlepass -- --nocapture cargo test --manifest-path lib/spectests/Cargo.toml --release --features singlepass -- --nocapture --test-threads 1
spectests-cranelift: spectests-cranelift:
cargo test --manifest-path lib/spectests/Cargo.toml --release --features clif -- --nocapture cargo test --manifest-path lib/spectests/Cargo.toml --release --features clif -- --nocapture
@ -50,13 +54,13 @@ emtests: emtests-unit emtests-singlepass emtests-cranelift emtests-llvm
# Middleware tests # Middleware tests
middleware-singlepass: middleware-singlepass:
cargo test --manifest-path lib/middleware-common/Cargo.toml --release --features singlepass cargo test --manifest-path lib/middleware-common-tests/Cargo.toml --release --features singlepass
middleware-cranelift: middleware-cranelift:
cargo test --manifest-path lib/middleware-common/Cargo.toml --release --features clif cargo test --manifest-path lib/middleware-common-tests/Cargo.toml --release --features clif
middleware-llvm: middleware-llvm:
cargo test --manifest-path lib/middleware-common/Cargo.toml --release --features llvm cargo test --manifest-path lib/middleware-common-tests/Cargo.toml --release --features llvm
middleware: middleware-singlepass middleware-cranelift middleware-llvm middleware: middleware-singlepass middleware-cranelift middleware-llvm
@ -70,12 +74,13 @@ wasitests-singlepass: wasitests-setup
cargo test --manifest-path lib/wasi-tests/Cargo.toml --release --features singlepass -- --test-threads=1 cargo test --manifest-path lib/wasi-tests/Cargo.toml --release --features singlepass -- --test-threads=1
wasitests-cranelift: wasitests-setup wasitests-cranelift: wasitests-setup
cargo test --manifest-path lib/wasi-tests/Cargo.toml --release --features clif -- --test-threads=1 cargo test --manifest-path lib/wasi-tests/Cargo.toml --release --features clif -- --test-threads=1 --nocapture
wasitests-llvm: wasitests-setup wasitests-llvm: wasitests-setup
cargo test --manifest-path lib/wasi-tests/Cargo.toml --release --features llvm -- --test-threads=1 cargo test --manifest-path lib/wasi-tests/Cargo.toml --release --features llvm -- --test-threads=1
wasitests-unit: wasitests-unit: wasitests-setup
cargo test --manifest-path lib/wasi-tests/Cargo.toml --release --features clif -- --test-threads=1 --nocapture
cargo test --manifest-path lib/wasi/Cargo.toml --release cargo test --manifest-path lib/wasi/Cargo.toml --release
wasitests: wasitests-unit wasitests-singlepass wasitests-cranelift wasitests-llvm wasitests: wasitests-unit wasitests-singlepass wasitests-cranelift wasitests-llvm
@ -84,22 +89,43 @@ wasitests: wasitests-unit wasitests-singlepass wasitests-cranelift wasitests-llv
# Backends # Backends
singlepass: spectests-singlepass emtests-singlepass middleware-singlepass wasitests-singlepass singlepass: spectests-singlepass emtests-singlepass middleware-singlepass wasitests-singlepass
cargo test -p wasmer-singlepass-backend --release cargo test -p wasmer-singlepass-backend --release
cargo test -p wasmer-runtime-core-tests --release --no-default-features --features backend-singlepass
cranelift: spectests-cranelift emtests-cranelift middleware-cranelift wasitests-cranelift cranelift: spectests-cranelift emtests-cranelift middleware-cranelift wasitests-cranelift
cargo test -p wasmer-clif-backend --release cargo test -p wasmer-clif-backend --release
cargo test -p wasmer-runtime-core-tests --release
llvm: spectests-llvm emtests-llvm wasitests-llvm llvm: spectests-llvm emtests-llvm wasitests-llvm
cargo test -p wasmer-llvm-backend --release cargo test -p wasmer-llvm-backend --release
cargo test -p wasmer-llvm-backend-tests --release
cargo test -p wasmer-runtime-core-tests --release --no-default-features --features backend-llvm
# All tests # All tests
capi: capi:
cargo build --release cargo build --release --features backend-cranelift
cargo build -p wasmer-runtime-c-api --release cargo build -p wasmer-runtime-c-api --release
test-capi: capi
cargo test -p wasmer-runtime-c-api --release cargo test -p wasmer-runtime-c-api --release
test-rest: capi capi-test: test-capi
cargo test --release --all --exclude wasmer-runtime-c-api --exclude wasmer-emscripten --exclude wasmer-spectests --exclude wasmer-wasi --exclude wasmer-middleware-common --exclude wasmer-singlepass-backend --exclude wasmer-clif-backend --exclude wasmer-llvm-backend --exclude wasmer-wasi-tests --exclude wasmer-emscripten-tests
test-rest:
cargo test --release \
--all \
--exclude wasmer-runtime-c-api \
--exclude wasmer-emscripten \
--exclude wasmer-spectests \
--exclude wasmer-wasi \
--exclude wasmer-middleware-common \
--exclude wasmer-middleware-common-tests \
--exclude wasmer-singlepass-backend \
--exclude wasmer-clif-backend \
--exclude wasmer-llvm-backend \
--exclude wasmer-wasi-tests \
--exclude wasmer-emscripten-tests \
--exclude wasmer-runtime-core-tests
circleci-clean: circleci-clean:
@if [ ! -z "${CIRCLE_JOB}" ]; then rm -f /home/circleci/project/target/debug/deps/libcranelift_wasm* && rm -f /Users/distiller/project/target/debug/deps/libcranelift_wasm*; fi; @if [ ! -z "${CIRCLE_JOB}" ]; then rm -f /home/circleci/project/target/debug/deps/libcranelift_wasm* && rm -f /Users/distiller/project/target/debug/deps/libcranelift_wasm*; fi;
@ -108,12 +134,16 @@ test: spectests emtests middleware wasitests circleci-clean test-rest
# Integration tests # Integration tests
integration-tests: release-clif integration-tests: release-clif examples
echo "Running Integration Tests" echo "Running Integration Tests"
./integration_tests/lua/test.sh ./integration_tests/lua/test.sh
./integration_tests/nginx/test.sh ./integration_tests/nginx/test.sh
./integration_tests/cowsay/test.sh ./integration_tests/cowsay/test.sh
examples:
cargo run --example plugin
cargo run --example callback
# Utils # Utils
lint: lint:
@ -122,22 +152,82 @@ lint:
precommit: lint test precommit: lint test
debug: debug:
cargo build --release --features backend-singlepass,debug,trace cargo build --release --features backend-cranelift,backend-singlepass,debug,trace
install: install:
cargo install --path . cargo install --path .
check: # Checks
cargo check --release --features backend-singlepass,backend-llvm,loader-kernel check-bench-singlepass:
cargo check --benches --all --no-default-features --features "backend-singlepass" \
--exclude wasmer-clif-backend --exclude wasmer-llvm-backend --exclude wasmer-kernel-loader
check-bench-clif:
cargo check --benches --all --no-default-features --features "backend-cranelift" \
--exclude wasmer-singlepass-backend --exclude wasmer-llvm-backend --exclude wasmer-kernel-loader \
--exclude wasmer-middleware-common-tests
check-bench-llvm:
cargo check --benches --all --no-default-features --features "backend-llvm" \
--exclude wasmer-singlepass-backend --exclude wasmer-clif-backend --exclude wasmer-kernel-loader
check-bench: check-bench-singlepass check-bench-llvm
# TODO: We wanted `--workspace --exclude wasmer-runtime`, but can't due
# to https://github.com/rust-lang/cargo/issues/6745 .
NOT_RUNTIME_CRATES = -p wasmer-clif-backend -p wasmer-singlepass-backend -p wasmer-middleware-common -p wasmer-runtime-core -p wasmer-emscripten -p wasmer-llvm-backend -p wasmer-wasi -p wasmer-kernel-loader -p wasmer-dev-utils -p wasmer-wasi-tests -p wasmer-middleware-common-tests -p wasmer-emscripten-tests
RUNTIME_CHECK = cargo check --manifest-path lib/runtime/Cargo.toml --no-default-features
check: check-bench
cargo check $(NOT_RUNTIME_CRATES)
cargo check --release $(NOT_RUNTIME_CRATES)
cargo check --all-features $(NOT_RUNTIME_CRATES)
cargo check --release --all-features $(NOT_RUNTIME_CRATES)
# wasmer-runtime doesn't work with all backends enabled at once.
#
# We test using manifest-path directly so as to disable the default.
# `--no-default-features` only disables the default features in the
# current package, not the package specified by `-p`. This is
# intentional.
#
# Test default features, test 'debug' feature only in non-release
# builds, test as many combined features as possible with each backend
# as default, and test a minimal set of features with only one backend
# at a time.
cargo check --manifest-path lib/runtime/Cargo.toml
cargo check --release --manifest-path lib/runtime/Cargo.toml
$(RUNTIME_CHECK) \
--features=cranelift,cache,debug,llvm,singlepass,default-backend-singlepass
$(RUNTIME_CHECK) --release \
--features=cranelift,cache,llvm,singlepass,default-backend-singlepass
$(RUNTIME_CHECK) \
--features=cranelift,cache,debug,llvm,singlepass,default-backend-cranelift
$(RUNTIME_CHECK) --release \
--features=cranelift,cache,llvm,singlepass,default-backend-cranelift
$(RUNTIME_CHECK) \
--features=cranelift,cache,debug,llvm,singlepass,default-backend-llvm
$(RUNTIME_CHECK) --release \
--features=cranelift,cache,llvm,singlepass,default-backend-llvm
$(RUNTIME_CHECK) \
--features=singlepass,default-backend-singlepass,debug
$(RUNTIME_CHECK) --release \
--features=singlepass,default-backend-singlepass
$(RUNTIME_CHECK) \
--features=cranelift,default-backend-cranelift,debug
$(RUNTIME_CHECK) --release \
--features=cranelift,default-backend-cranelift
$(RUNTIME_CHECK) \
--features=llvm,default-backend-llvm,debug
$(RUNTIME_CHECK) --release \
--features=llvm,default-backend-llvm
# Release
release: release:
cargo build --release --features backend-singlepass,backend-llvm,loader-kernel cargo build --release --features backend-singlepass,backend-cranelift,backend-llvm,loader-kernel
# Only one backend (cranelift) # Only one backend (cranelift)
release-clif: release-clif:
# If you are in OS-X, you will need mingw-w64 for cross compiling to windows # If you are on macOS, you will need mingw-w64 for cross compiling to Windows
# brew install mingw-w64 # brew install mingw-w64
cargo build --release cargo build --release --features backend-cranelift
release-singlepass: release-singlepass:
cargo build --release --features backend-singlepass cargo build --release --features backend-singlepass
@ -146,20 +236,15 @@ release-llvm:
cargo build --release --features backend-llvm cargo build --release --features backend-llvm
bench-singlepass: bench-singlepass:
cargo bench --all --no-default-features --features "backend-singlepass" cargo bench --all --no-default-features --features "backend-singlepass" \
--exclude wasmer-clif-backend --exclude wasmer-llvm-backend --exclude wasmer-kernel-loader
bench-clif: bench-clif:
cargo bench --all --no-default-features --features "backend-cranelift" cargo bench --all --no-default-features --features "backend-cranelift" \
--exclude wasmer-singlepass-backend --exclude wasmer-llvm-backend --exclude wasmer-kernel-loader \
--exclude wasmer-middleware-common-tests
bench-llvm: bench-llvm:
cargo bench --all --no-default-features --features "backend-llvm" cargo bench --all --no-default-features --features "backend-llvm" \
--exclude wasmer-singlepass-backend --exclude wasmer-clif-backend --exclude wasmer-kernel-loader
# compile but don't run the benchmarks
compile-bench-singlepass:
cargo bench --all --no-run --no-default-features --features "backend-singlepass"
compile-bench-clif:
cargo bench --all --no-run --no-default-features --features "backend-cranelift"
compile-bench-llvm:
cargo bench --all --no-run --no-default-features --features "backend-llvm"
# Build utils # Build utils
build-install: build-install:
@ -178,4 +263,10 @@ publish-release:
# cargo install cargo-deps # cargo install cargo-deps
# must install graphviz for `dot` # must install graphviz for `dot`
dep-graph: dep-graph:
cargo deps --optional-deps --filter wasmer-wasi wasmer-wasi-tests wasmer-kernel-loader wasmer-dev-utils wasmer-llvm-backend wasmer-emscripten wasmer-emscripten-tests wasmer-runtime-core wasmer-runtime wasmer-middleware-common wasmer-singlepass-backend wasmer-clif-backend wasmer --manifest-path Cargo.toml | dot -Tpng > wasmer_depgraph.png cargo deps --optional-deps --filter wasmer-wasi wasmer-wasi-tests wasmer-kernel-loader wasmer-dev-utils wasmer-llvm-backend wasmer-emscripten wasmer-emscripten-tests wasmer-runtime-core wasmer-runtime wasmer-middleware-common wasmer-middleware-common-tests wasmer-singlepass-backend wasmer-clif-backend wasmer --manifest-path Cargo.toml | dot -Tpng > wasmer_depgraph.png
docs:
cargo doc --features=backend-singlepass,backend-cranelift,backend-llvm,docs,wasi,managed
wapm:
cargo build --release --manifest-path wapm-cli/Cargo.toml --features "telemetry update-notifications"

View File

@ -5,42 +5,53 @@
</p> </p>
<p align="center"> <p align="center">
<a href="https://circleci.com/gh/wasmerio/wasmer/"> <a href="https://dev.azure.com/wasmerio/wasmer/_build/latest?definitionId=3&branchName=master">
<img src="https://img.shields.io/circleci/project/github/wasmerio/wasmer/master.svg" alt="Build Status"> <img src="https://img.shields.io/azure-devops/build/wasmerio/wasmer/3.svg?style=flat-square" alt="Build Status">
</a>
<a href="https://docs.wasmer.io">
<img src="https://img.shields.io/badge/Docs-docs.wasmer.io-blue?style=flat-square" alt="Documentation">
</a> </a>
<a href="https://github.com/wasmerio/wasmer/blob/master/LICENSE"> <a href="https://github.com/wasmerio/wasmer/blob/master/LICENSE">
<img src="https://img.shields.io/github/license/wasmerio/wasmer.svg" alt="License"> <img src="https://img.shields.io/github/license/wasmerio/wasmer.svg?style=flat-square" alt="License">
</a> </a>
<a href="https://spectrum.chat/wasmer"> <a href="https://spectrum.chat/wasmer">
<img src="https://withspectrum.github.io/badge/badge.svg" alt="Join the Wasmer Community"> <img src="https://withspectrum.github.io/badge/badge.svg" alt="Join the Wasmer Community">
</a> </a>
<a href="https://twitter.com/wasmerio"> <a href="https://twitter.com/wasmerio">
<img alt="Follow @wasmerio on Twitter" src="https://img.shields.io/twitter/follow/wasmerio?label=%40wasmerio&style=social"> <img alt="Follow @wasmerio on Twitter" src="https://img.shields.io/twitter/follow/wasmerio?label=%40wasmerio&style=flat-square">
</a> </a>
</p> </p>
## Introduction ## Introduction
[Wasmer](https://wasmer.io/) is a standalone JIT WebAssembly runtime, aiming to be fully compatible with [WASI](https://github.com/WebAssembly/WASI) and [Emscripten](https://emscripten.org/). [Wasmer](https://wasmer.io/) is a standalone WebAssembly runtime for running WebAssembly [outside of the browser](https://webassembly.org/docs/non-web/), supporting [WASI](https://github.com/WebAssembly/WASI) and [Emscripten](https://emscripten.org/). Wasmer can be used standalone (via the CLI) and embedded in different languages, running in x86 and [ARM devices](https://medium.com/wasmer/running-webassembly-on-arm-7d365ed0e50c).
Install Wasmer with: Install the Wasmer and [WAPM](https://wapm.io) cli with:
```sh ```sh
curl https://get.wasmer.io -sSfL | sh curl https://get.wasmer.io -sSfL | sh
``` ```
> Note: *Wasmer is also available on Windows. Download the [`WasmerInstaller.exe` from the Github Releases](https://github.com/wasmerio/wasmer/releases) page.* > Note: *Wasmer is also [available on Windows](https://github.com/wasmerio/wasmer/releases)*
Wasmer runtime can also be embedded in different languages, so you can use WebAssembly anywhere ✨: ### Languages
* [**🦀 Rust**](https://github.com/wasmerio/wasmer-rust-example) Wasmer runtime can be used as a library embedded in different languages, so you can use WebAssembly anywhere:
* [**🔗 C/C++**](https://github.com/wasmerio/wasmer-c-api)
* [**#️⃣ C#**](https://github.com/migueldeicaza/WasmerSharp) | &nbsp; | Language | Author(s) | Maintenance | Release | Stars |
* [**🐘 PHP**](https://github.com/wasmerio/php-ext-wasm) |-|-|-|-|-|-|
* [**🐍 Python**](https://github.com/wasmerio/python-ext-wasm) | ![Rust logo](./docs/assets/languages/rust.svg) | [**Rust**](https://github.com/wasmerio/wasmer-rust-example) | Wasmer | actively developed | <a href="https://crates.io/crates/wasmer-runtime/" target="_blank">![last release](https://img.shields.io/crates/v/wasmer-runtime?style=flat-square)</a> | ![number of Github stars](https://img.shields.io/github/stars/wasmerio/wasmer?style=flat-square) |
* [**💎 Ruby**](https://github.com/wasmerio/ruby-ext-wasm) | ![C logo](./docs/assets/languages/c.svg) | [**C/C++**](https://github.com/wasmerio/wasmer-c-api) | Wasmer | actively developed | <a href="https://github.com/wasmerio/wasmer-c-api/" target="_blank">![last release](https://img.shields.io/github/v/release/wasmerio/wasmer?style=flat-square)</a> | ![number of Github stars](https://img.shields.io/github/stars/wasmerio/wasmer?style=flat-square) |
* [**🐹 Go**](https://github.com/wasmerio/go-ext-wasm) | ![Python logo](./docs/assets/languages/python.svg) | [**Python**](https://github.com/wasmerio/python-ext-wasm) | Wasmer | actively developed | <a href="https://pypi.org/project/wasmer/" target="_blank">![last release](https://img.shields.io/pypi/v/wasmer?style=flat-square)</a> | ![number of Github stars](https://img.shields.io/github/stars/wasmerio/python-ext-wasm?style=flat-square) |
* [**R**](https://github.com/dirkschumacher/wasmr) | ![Go logo](./docs/assets/languages/go.svg) | [**Go**](https://github.com/wasmerio/go-ext-wasm) | Wasmer | actively developed | <a href="https://github.com/wasmerio/go-ext-wasm" target="_blank">![last release](https://img.shields.io/github/v/release/wasmerio/go-ext-wasm?style=flat-square)</a> | ![number of Github stars](https://img.shields.io/github/stars/wasmerio/go-ext-wasm?style=flat-square) |
| ![PHP logo](./docs/assets/languages/php.svg) | [**PHP**](https://github.com/wasmerio/php-ext-wasm) | Wasmer | actively developed | <a href="https://pecl.php.net/package/wasm" target="_blank">![last release](https://img.shields.io/github/v/release/wasmerio/php-ext-wasm?style=flat-square)</a> | ![number of Github stars](https://img.shields.io/github/stars/wasmerio/php-ext-wasm?style=flat-square) |
| ![Ruby logo](./docs/assets/languages/ruby.svg) | [**Ruby**](https://github.com/wasmerio/ruby-ext-wasm) | Wasmer | actively developed | <a href="https://rubygems.org/gems/wasmer" target="_blank">![last release](https://img.shields.io/gem/v/wasmer?style=flat-square)</a> | ![number of Github stars](https://img.shields.io/github/stars/wasmerio/ruby-ext-wasm?style=flat-square) |
| ![Postgres logo](./docs/assets/languages/postgres.svg) | [**Postgres**](https://github.com/wasmerio/postgres-ext-wasm) | Wasmer | actively developed | <a href="https://github.com/wasmerio/postgres-ext-wasm" target="_blank">![last release](https://img.shields.io/github/v/release/wasmerio/postgres-ext-wasm?style=flat-square)</a> | ![number of Github stars](https://img.shields.io/github/stars/wasmerio/postgres-ext-wasm?style=flat-square) |
| ![JS Logo](./docs/assets/languages/js.svg) | [**JavaScript**](https://github.com/wasmerio/wasmer-js) | Wasmer | actively developed | <a href="https://www.npmjs.com/package/@wasmer/wasi" target="_blank">![last release](https://img.shields.io/npm/v/@wasmer/wasi?style=flat-square)</a> | ![number of Github stars](https://img.shields.io/github/stars/wasmerio/wasmer-js?style=flat-square) |
| ![C# logo](./docs/assets/languages/csharp.svg) | [**C#/.Net**](https://github.com/migueldeicaza/WasmerSharp) | [Miguel de Icaza](https://github.com/migueldeicaza) | actively developed | <a href="https://www.nuget.org/packages/WasmerSharp/" target="_blank">![last release](https://img.shields.io/nuget/v/WasmerSharp?style=flat-square)</a> | ![number of Github stars](https://img.shields.io/github/stars/migueldeicaza/WasmerSharp?style=flat-square) |
| ![R logo](./docs/assets/languages/r.svg) | [**R**](https://github.com/dirkschumacher/wasmr) | [Dirk Schumacher](https://github.com/dirkschumacher) | actively developed | | ![number of Github stars](https://img.shields.io/github/stars/dirkschumacher/wasmr?style=flat-square) |
| ![Swift logo](./docs/assets/languages/swift.svg) | [**Swift**](https://github.com/markmals/swift-ext-wasm) | [Mark Malström](https://github.com/markmals/) | passively maintained | | ![number of Github stars](https://img.shields.io/github/stars/markmals/swift-ext-wasm?style=flat-square) |
| ❓ | [your language is missing?](https://github.com/wasmerio/wasmer/issues/new?assignees=&labels=%F0%9F%8E%89+enhancement&template=---feature-request.md&title=) | | | |
### Usage ### Usage
@ -51,28 +62,15 @@ Once installed, you will be able to run any WebAssembly files (_including Lua, P
```sh ```sh
# Run Lua # Run Lua
wasmer run examples/lua.wasm wasmer examples/lua.wasm
``` ```
*You can find more `wasm/wat` examples in the [examples](./examples) directory.* *You can find more `wasm/wat` examples in the [examples](./examples) directory.*
#### With WAPM ### Docs
Installing Wasmer through `wasmer.io` includes Wasmer documentation lives on [docs.wasmer.io](https://docs.wasmer.io).
[`wapm`](https://github.com/wasmerio/wapm-cli), the [WebAssembly Package Manager](https://wapm.io/).
Wapm allows you to easily download, run, and distribute WebAssembly binaries.
```sh
# Install cowsay globally
wapm install -g cowsay
# Run cowsay
wapm run cowsay "Hello, world!"
```
For more information about wapm, check out the [website](https://www.wapm.io)
and this [example program](https://github.com/wapm-packages/rust-wasi-example).
## Code Structure ## Code Structure
@ -80,7 +78,7 @@ Wasmer is structured into different directories:
- [`src`](./src): code related to the Wasmer executable itself - [`src`](./src): code related to the Wasmer executable itself
- [`lib`](./lib): modularized libraries that Wasmer uses under the hood - [`lib`](./lib): modularized libraries that Wasmer uses under the hood
- [`examples`](./examples): some useful examples to getting started with Wasmer - [`examples`](./examples): some useful examples for getting started with Wasmer
## Dependencies ## Dependencies
@ -111,7 +109,7 @@ If you have [Homebrew](https://brew.sh/) installed:
brew install cmake brew install cmake
``` ```
Or, in case you have [MacPorts](https://www.macports.org/install.php): Or, if you have [MacPorts](https://www.macports.org/install.php):
```sh ```sh
sudo port install cmake sudo port install cmake
@ -129,6 +127,7 @@ sudo port install cmake
```sh ```sh
sudo apt install cmake pkg-config libssl-dev sudo apt install cmake pkg-config libssl-dev
``` ```
</p> </p>
</details> </details>
@ -141,6 +140,7 @@ sudo apt install cmake pkg-config libssl-dev
```sh ```sh
pkg install cmake pkg install cmake
``` ```
</p> </p>
</details> </details>
@ -150,40 +150,40 @@ pkg install cmake
#### Windows (MSVC) #### Windows (MSVC)
Windows support is _experimental_. WASI is fully supported, but Emscripten support is on the works (this means Windows support is _experimental_. WASI is fully supported, but Emscripten support is in the works (this means
nginx and Lua do not work on Windows - you can track the progress on [this issue](https://github.com/wasmerio/wasmer/issues/176)). nginx and Lua do not work on Windows - you can track the progress on [this issue](https://github.com/wasmerio/wasmer/issues/176)).
1. Install [Visual Studio](https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/?sku=Community&rel=15) 1. Install [Visual Studio](https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/?sku=Community&rel=15)
2. Install [Rust for Windows](https://win.rustup.rs) 2. Install [Rust for Windows](https://win.rustup.rs)
3. Install [Python for Windows](https://www.python.org/downloads/release/python-2714/). The Windows x86-64 MSI installer is fine. 3. Install [Git for Windows](https://git-scm.com/download/win). Allow it to add `git.exe` to your PATH (default
Make sure to enable "Add python.exe to Path" during installation.
4. Install [Git for Windows](https://git-scm.com/download/win). Allow it to add `git.exe` to your PATH (default
settings for the installer are fine). settings for the installer are fine).
5. Install [CMake](https://cmake.org/download/). Ensure CMake is in your PATH. 4. Install [CMake](https://cmake.org/download/). Ensure CMake is in your PATH.
6. Install [LLVM 8.0](https://prereleases.llvm.org/win-snapshots/LLVM-8.0.0-r351033-win64.exe) 5. Install [LLVM 8.0](https://prereleases.llvm.org/win-snapshots/LLVM-8.0.0-r351033-win64.exe)
</p> </p>
</details> </details>
## Building ## Building
[![Rustc Version 1.36+](https://img.shields.io/badge/rustc-1.36+-red.svg)](https://blog.rust-lang.org/2019/07/04/Rust-1.36.0.html)
[![Rustc Version 1.38+](https://img.shields.io/badge/rustc-1.37+-red.svg?style=flat-square)](https://blog.rust-lang.org/2019/09/26/Rust-1.38.0.html)
Wasmer is built with [Cargo](https://crates.io/), the Rust package manager. Wasmer is built with [Cargo](https://crates.io/), the Rust package manager.
The Singlepass backend requires nightly, so if you want to use it, The Singlepass backend requires nightly, so if you want to use it,
Set Rust Nightly: Set Rust Nightly:
``` ```
rustup default nightly rustup default nightly
``` ```
Otherwise an up to date (see badge above) verison of stable Rust will work. Otherwise an up to date (see badge above) version of stable Rust will work.
And install Wasmer And install Wasmer
```sh ```sh
# checkout code # checkout code
git clone https://github.com/wasmerio/wasmer.git git clone https://github.com/wasmerio/wasmer.git
@ -225,11 +225,10 @@ Each integration can be tested separately:
* Spec tests: `make spectests` * Spec tests: `make spectests`
* Emscripten: `make emtests` * Emscripten: `make emtests`
* WASI: `make wasi` * WASI: `make wasitests`
* Middleware: `make middleware` * Middleware: `make middleware`
* C API: `make capi` * C API: `make capi`
## Benchmarking ## Benchmarking
Benchmarks can be run with: Benchmarks can be run with:
@ -250,8 +249,8 @@ Below are some of the goals of this project (in order of priority):
- [x] It should be 100% compatible with the [WebAssembly spec tests](https://github.com/wasmerio/wasmer/tree/master/lib/spectests/spectests) - [x] It should be 100% compatible with the [WebAssembly spec tests](https://github.com/wasmerio/wasmer/tree/master/lib/spectests/spectests)
- [x] It should be fast _(partially achieved)_ - [x] It should be fast _(partially achieved)_
- [x] Support WASI - released in [0.3.0](https://github.com/wasmerio/wasmer/releases/tag/0.3.0) - [x] Support WASI - released in [0.3.0](https://github.com/wasmerio/wasmer/releases/tag/0.3.0)
- [x] Support Emscripten calls _(in the works)_ - [x] Support Emscripten calls
- [ ] Support Go js ABI calls - [ ] Support Go JS ABI calls _(in the works)_
## Architecture ## Architecture

271
azure-pipelines.yml Normal file
View File

@ -0,0 +1,271 @@
name: $(Build.SourceBranch)-$(date:yyyyMMdd)$(rev:.r)
# The Different jobs (lint, test, build to run)
jobs:
- job: changelog
steps:
- bash: |
git --no-pager diff --name-only HEAD $(git merge-base HEAD master) --exit-code CHANGELOG.md
displayName: Changelog Updated
- job: lint
pool:
vmImage: "macos-10.14"
steps:
- checkout: self
submodules: true
- template: .azure/install-rust.yml
- script: |
rustup component add rustfmt
rustup component add clippy || cargo install --git https://github.com/rust-lang/rust-clippy/ --force clippy
displayName: Lint dependencies
- script: cargo fmt --all -- --check
displayName: Lint
variables:
rust_toolchain: '1.38.0'
- job: Test
strategy:
matrix:
linux:
imageName: "ubuntu-16.04"
rust_toolchain: nightly-2019-08-15
mac:
imageName: "macos-10.14"
rust_toolchain: nightly-2019-08-15
# By default schannel checks revocation of certificates unlike some other SSL
# backends, but we've historically had problems on CI where a revocation
# server goes down presumably. See #43333 for more info
CARGO_HTTP_CHECK_REVOKE: false
windows:
imageName: "vs2017-win2016"
rust_toolchain: '1.38.0'
pool:
vmImage: $(imageName)
condition: in(variables['Build.SourceBranch'], 'refs/heads/master', 'refs/heads/staging', 'refs/heads/trying')
steps:
- checkout: self
submodules: true
- template: .azure/install-rust.yml
- template: .azure/install-llvm.yml
- template: .azure/install-sccache.yml
- template: .azure/install-cmake.yml
- bash: |
hostname
uname -a
displayName: System info (*nix)
condition: and(succeeded(), not(eq(variables['Agent.OS'], 'Windows_NT')))
- bash: |
cat /proc/cpuinfo
cat /proc/meminfo
displayName: System info - Extended (Linux)
condition: and(succeeded(), eq(variables['Agent.OS'], 'Linux'))
- bash: |
sysctl -a | grep machdep.cpu
displayName: System info - Extended (Mac)
condition: and(succeeded(), eq(variables['Agent.OS'], 'Darwin'))
- bash: make test
displayName: Tests (*nix)
condition: and(succeeded(), not(eq(variables['Agent.OS'], 'Windows_NT')))
- bash: make spectests-cranelift
displayName: Tests (Windows)
condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT'))
- job: Check
pool:
vmImage: "ubuntu-16.04"
variables:
rust_toolchain: nightly-2019-08-15
condition: in(variables['Build.SourceBranch'], 'refs/heads/master', 'refs/heads/staging', 'refs/heads/trying')
steps:
- checkout: self
submodules: true
- template: .azure/install-rust.yml
- template: .azure/install-llvm.yml
- template: .azure/install-sccache.yml
- template: .azure/install-cmake.yml
- bash: make check
displayName: Check with Flags
condition: and(succeeded(), not(eq(variables['Agent.OS'], 'Windows_NT')))
- job: Build_CLI
strategy:
matrix:
linux:
imageName: "ubuntu-16.04"
rust_toolchain: nightly-2019-08-15
mac:
imageName: "macos-10.14"
rust_toolchain: nightly-2019-08-15
MACOSX_DEPLOYMENT_TARGET: 10.10
windows:
imageName: "vs2017-win2016"
rust_toolchain: '1.38.0'
# RUSTFLAGS: -Ctarget-feature=+crt-static
pool:
vmImage: $(imageName)
condition: |
or(
in(variables['Build.SourceBranch'], 'refs/heads/master', 'refs/heads/staging', 'refs/heads/trying'),
startsWith(variables['Build.SourceBranch'], 'refs/tags')
)
steps:
- checkout: self
submodules: true
- template: .azure/install-rust.yml
- template: .azure/install-llvm.yml
- template: .azure/install-sccache.yml
- template: .azure/install-cmake.yml
- template: .azure/install-innosetup.yml
- bash: |
mkdir -p artifacts
displayName: Create Artifacts Dir
- bash: make release
displayName: Build (*nix)
condition: and(succeeded(), not(eq(variables['Agent.OS'], 'Windows_NT')))
- bash: make release-llvm
displayName: Build (Windows)
condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT'))
- bash: |
make wapm
displayName: Build WAPM
condition: |
startsWith(variables['Build.SourceBranch'], 'refs/tags')
- bash: |
make build-install
cp ./wasmer.tar.gz ./artifacts/$(./scripts/binary-name.sh)
displayName: Build Distribution (*nix)
condition: |
and(
succeeded(),
startsWith(variables['Build.SourceBranch'], 'refs/tags'),
not(eq(variables['Agent.OS'], 'Windows_NT'))
)
- bash: |
cd ./src/installer
iscc wasmer.iss
cp WasmerInstaller.exe ../../artifacts/wasmer-windows.exe
displayName: Build Distribution (Windows)
condition: |
and(
succeeded(),
startsWith(variables['Build.SourceBranch'], 'refs/tags'),
eq(variables['Agent.OS'], 'Windows_NT')
)
- publish: $(System.DefaultWorkingDirectory)/artifacts
artifact: cli-$(Agent.OS)
- job: Build_Library
strategy:
matrix:
linux:
imageName: "ubuntu-16.04"
rust_toolchain: nightly-2019-08-15
mac:
imageName: "macos-10.14"
rust_toolchain: nightly-2019-08-15
MACOSX_DEPLOYMENT_TARGET: 10.10
windows:
imageName: "vs2017-win2016"
rust_toolchain: '1.38.0'
# RUSTFLAGS: -Ctarget-feature=+crt-static
pool:
vmImage: $(imageName)
condition: |
or(
in(variables['Build.SourceBranch'], 'refs/heads/master', 'refs/heads/staging', 'refs/heads/trying'),
startsWith(variables['Build.SourceBranch'], 'refs/tags')
)
steps:
- checkout: self
submodules: true
- template: .azure/install-rust.yml
# - template: .azure/install-llvm.yml
- template: .azure/install-sccache.yml
- template: .azure/install-cmake.yml
- bash: |
mkdir -p artifacts
displayName: Create Artifacts Dir
- bash: |
make capi
make test-capi
cp target/release/libwasmer_runtime_c_api.so ./artifacts
displayName: Build c-api (Linux)
condition: and(succeeded(), eq(variables['Agent.OS'], 'Linux'))
- bash: |
make capi
make test-capi
install_name_tool -id "@rpath/libwasmer_runtime_c_api.dylib" target/release/libwasmer_runtime_c_api.dylib
cp target/release/libwasmer_runtime_c_api.dylib ./artifacts
displayName: Build c-api (Darwin)
condition: and(succeeded(), eq(variables['Agent.OS'], 'Darwin'))
- bash: |
make capi
# Tests are failing on Windows, comment for now
# make test-capi
cp target/release/wasmer_runtime_c_api.dll ./artifacts
displayName: Build c-api (Windows)
condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT'))
- publish: $(System.DefaultWorkingDirectory)/artifacts
artifact: library-$(Agent.OS)
- job: Publish
dependsOn:
- Build_CLI
- Build_Library
condition: |
startsWith(variables['Build.SourceBranch'], 'refs/tags')
steps:
# - download: current
- task: DownloadPipelineArtifact@1
inputs:
targetPath: $(Build.ArtifactStagingDirectory)
- bash: |
ls $ARTIFACT_STAGING_DIRECTORY
displayName: List Artifacts
env:
ARTIFACT_STAGING_DIRECTORY: $(Build.ArtifactStagingDirectory)
- script: VERSION_TAG=`git describe --tags` && echo "##vso[task.setvariable variable=VERSION_TAG]$VERSION_TAG"
displayName: Set the tag name as an environment variable
- task: GithubRelease@0
displayName: "Create GitHub Release"
condition: and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/tags'))
inputs:
gitHubConnection: 'wasmer'
repositoryName: 'wasmerio/wasmer'
action: 'create'
target: '$(Build.SourceVersion)'
title: '$(VERSION_TAG)'
addChangeLog: false
tagSource: 'auto'
# TODO: automate it all by getting the release notes from somewhere else and using the `releaseNotesFile` key
isDraft: false
isPreRelease: false
assets: '$(Build.ArtifactStagingDirectory)/**'
- job: Docs
pool:
vmImage: "ubuntu-16.04"
variables:
rust_toolchain: nightly-2019-08-15
steps:
- checkout: self
submodules: true
- template: .azure/install-rust.yml
- template: .azure/install-llvm.yml
- template: .azure/install-sccache.yml
- template: .azure/install-cmake.yml
- bash: |
make docs
displayName: Build documentation
# We only run the pipelines on PRs to Master
pr:
- master
# Otherwise, we test in any of this branches (master or bors related)
trigger:
- master
- staging
- trying
- refs/tags/*

View File

@ -1,10 +1,5 @@
status = [ status = [
"ci/circleci: lint", "wasmerio.wasmer"
"ci/circleci: test",
"ci/circleci: test-macos",
"ci/circleci: test-stable",
"ci/circleci: test-rust-example",
"continuous-integration/appveyor/branch"
] ]
required_approvals = 1 required_approvals = 1
timeout_sec = 7200 timeout_sec = 7200

1
docs/assets/languages/c.svg Executable file
View File

@ -0,0 +1 @@
<svg width="20" height="22" id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 22"><defs><style>.cls-1{fill:#7f8b99;}.cls-2{fill:#a9b9cb;}.cls-3{fill:#fff;}</style></defs><title>c-logo-colored</title><path class="cls-1" d="M1,17.22l2.19,1.24L16.79,3.54,11,.26a2,2,0,0,0-2,0L1,4.78A2,2,0,0,0,0,6.52v9A2,2,0,0,0,1,17.22Z"/><path class="cls-2" d="M19,4.78,16.79,3.54,3.21,18.46,9,21.74a2,2,0,0,0,2,0l8-4.52a2,2,0,0,0,1-1.74v-9A2,2,0,0,0,19,4.78Z"/><path class="cls-3" d="M12.07,9.58l3.11,0A4.84,4.84,0,0,0,10.1,5.25,5.42,5.42,0,0,0,4.48,11a5.31,5.31,0,0,0,5.62,5.66c4,0,4.94-2.86,4.94-4.38h-3a1.73,1.73,0,0,1-2,1.75c-1.91,0-2.22-2.27-2.22-3,0-1.18.42-3,2.22-3A1.86,1.86,0,0,1,12.07,9.58Z"/></svg>

After

Width:  |  Height:  |  Size: 726 B

1
docs/assets/languages/cpp.svg Executable file
View File

@ -0,0 +1 @@
<svg width="20" height="22" id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 22"><defs><style>.cls-1{fill:#659ad2;}.cls-2{fill:#0e4580;}.cls-3{fill:#035a9d;}.cls-4{fill:#fff;}</style></defs><title>c++-logo-colored</title><path class="cls-1" d="M19.72,5.5A2,2,0,0,0,19,4.77L11,.25a2,2,0,0,0-2,0L1,4.77A2,2,0,0,0,0,6.52v9a2,2,0,0,0,.28,1Z"/><path class="cls-2" d="M.28,16.5a2,2,0,0,0,.74.73l8,4.52a2,2,0,0,0,2,0l8-4.52a2,2,0,0,0,.74-.73L10,11Z"/><path class="cls-3" d="M20,6.52a2,2,0,0,0-.28-1L10,11l9.72,5.5a2,2,0,0,0,.28-1Z"/><path class="cls-4" d="M16.67,10.69h-.74V10h-.75v.73h-.74v.73h.74v.72h.75v-.72h.74Z"/><path class="cls-4" d="M19.44,10.69H18.7V10H18v.73h-.74v.73H18v.72h.74v-.72h.74Z"/><path class="cls-4" d="M12.86,12.62a3.3,3.3,0,1,1,0-3.24l2.8-1.58a6.5,6.5,0,1,0,0,6.4Z"/></svg>

After

Width:  |  Height:  |  Size: 825 B

View File

@ -0,0 +1 @@
<svg width="20" height="20" id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><defs><style>.cls-1{fill:#0c9438;}.cls-2{fill:#219e38;opacity:0.85;}.cls-3{opacity:0.1;isolation:isolate;}.cls-4{fill:#fff;}</style></defs><title>csharp-logo-colored</title><path class="cls-1" d="M17.07,2.93a10,10,0,0,0-14.14,0L17.07,17.07A10,10,0,0,0,17.07,2.93Z"/><path class="cls-2" d="M2.93,2.93A10,10,0,0,0,17.07,17.07Z"/><path class="cls-3" d="M1,10.23a.76.76,0,0,1,0-.15c0,.15,0,.3,0,.45Z"/><path class="cls-4" d="M9.51,13.64a4.6,4.6,0,0,1-2.19.46,3.46,3.46,0,0,1-1.46-.25A3.66,3.66,0,0,1,4.63,13a4.05,4.05,0,0,1-1-2.84,4.34,4.34,0,0,1,.26-1.64,4.2,4.2,0,0,1,.88-1.41,4,4,0,0,1,1.32-.94A3.81,3.81,0,0,1,7.65,6a4.42,4.42,0,0,1,1.84.25v1A3.72,3.72,0,0,0,7.64,6.8,2.9,2.9,0,0,0,6.44,7a2.81,2.81,0,0,0-1,.69,3.4,3.4,0,0,0-.85,2.42,3.24,3.24,0,0,0,.79,2.29,2.68,2.68,0,0,0,.94.66,2.9,2.9,0,0,0,1.13.2,4,4,0,0,0,2.05-.53Z"/><path class="cls-4" d="M16.49,8.3l-.13.58H14.93l-.35,1.65h1.55l-.15.58H14.47L14,13.3h-.69l.47-2.19H12.39l-.46,2.19h-.68l.46-2.19H10.26l.11-.58h1.46l.33-1.65H10.64l.12-.58h1.52l.46-2.21h.69L13,8.3l1.38,0,.47-2.17h.66L15.05,8.3Zm-2.24.58H12.86l-.36,1.65h1.4Z"/></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

1
docs/assets/languages/go.svg Executable file
View File

@ -0,0 +1 @@
<svg width="32" height="12" id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 12"><defs><style>.cls-1{fill:#38b6ac;}</style></defs><title>go-logo-colored</title><path class="cls-1" d="M2.4,3.62s-.07,0,0-.09l.33-.42A.25.25,0,0,1,2.86,3H8.43c.05,0,.08,0,0,.09l-.25.4a.24.24,0,0,1-.17.09Z"/><path class="cls-1" d="M.06,5.06C0,5.06,0,5,0,5l.32-.42a.3.3,0,0,1,.17-.08H7.62a.08.08,0,0,1,.08.1L7.57,5a.15.15,0,0,1-.14.1Z"/><path class="cls-1" d="M3.84,6.49c-.06,0-.09,0-.06-.09L4,6a.2.2,0,0,1,.16-.09H7.28A.09.09,0,0,1,7.37,6l0,.37a.13.13,0,0,1-.12.11Z"/><path class="cls-1" d="M31.94,4.55a4.86,4.86,0,0,0-2.2-3.49A5.72,5.72,0,0,0,25.31.25,6.56,6.56,0,0,0,21,2.87a6.74,6.74,0,0,0-1.08,2.05h-5a.43.43,0,0,0-.38.25c-.22.41-.6,1.24-.8,1.71-.11.27,0,.47.29.47h3c-.16.22-.28.41-.43.58a2.88,2.88,0,0,1-2.65,1A2.45,2.45,0,0,1,11.8,6.49a3.36,3.36,0,0,1,1.6-3,2.69,2.69,0,0,1,2.81-.23,2,2,0,0,1,.73.6c.2.23.22.21.45.15,1-.25,1.64-.45,2.62-.69.18,0,.24-.12.18-.25A5,5,0,0,0,18.39.87,5.48,5.48,0,0,0,14.26.11,6.88,6.88,0,0,0,9.9,2.82,6.12,6.12,0,0,0,8.58,7.41a4.93,4.93,0,0,0,2,3.47,5.49,5.49,0,0,0,4.18,1,6.45,6.45,0,0,0,4.44-2.66,6.88,6.88,0,0,0,.64-1.07,5,5,0,0,0,1.54,2.43A5.77,5.77,0,0,0,25.16,12c.41-.05.78-.06,1.19-.14a7.21,7.21,0,0,0,3.79-2A6.07,6.07,0,0,0,31.94,4.55Zm-5,4.1a2.83,2.83,0,0,1-2.55.09,2.58,2.58,0,0,1-1.42-2.95,3.37,3.37,0,0,1,2.72-2.73,2.58,2.58,0,0,1,3.18,2.09c0,.16,0,.32.05.52A3.44,3.44,0,0,1,26.9,8.65Z"/></svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

8
docs/assets/languages/js.svg Executable file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<svg width="20" height="20" viewBox="0 0 256 256" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid">
<g>
<path d="M0,0 L256,0 L256,256 L0,256 L0,0 Z" fill="#F7DF1E"></path>
<path d="M67.311746,213.932292 L86.902654,202.076241 C90.6821079,208.777346 94.1202286,214.447137 102.367086,214.447137 C110.272203,214.447137 115.256076,211.354819 115.256076,199.326883 L115.256076,117.528787 L139.313575,117.528787 L139.313575,199.666997 C139.313575,224.58433 124.707759,235.925943 103.3984,235.925943 C84.1532952,235.925943 72.9819429,225.958603 67.3113397,213.93026" fill="#000000"></path>
<path d="M152.380952,211.354413 L171.969422,200.0128 C177.125994,208.433981 183.827911,214.619835 195.684368,214.619835 C205.652521,214.619835 212.009041,209.635962 212.009041,202.762159 C212.009041,194.513676 205.479416,191.592025 194.481168,186.78207 L188.468419,184.202565 C171.111213,176.81473 159.597308,167.53534 159.597308,147.944838 C159.597308,129.901308 173.344508,116.153295 194.825752,116.153295 C210.119924,116.153295 221.117765,121.48094 229.021663,135.400432 L210.29059,147.428775 C206.166146,140.040127 201.699556,137.119289 194.826159,137.119289 C187.78047,137.119289 183.312254,141.587098 183.312254,147.428775 C183.312254,154.646349 187.78047,157.568406 198.089956,162.036622 L204.103924,164.614095 C224.553448,173.378641 236.067352,182.313448 236.067352,202.418387 C236.067352,224.071924 219.055137,235.927975 196.200432,235.927975 C173.860978,235.927975 159.425829,225.274311 152.381359,211.354413" fill="#000000"></path>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

1
docs/assets/languages/php.svg Executable file
View File

@ -0,0 +1 @@
<svg width="27" height="14" id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 27 14"><title>php-logo</title><path d="M2.14,2.94h4A3.05,3.05,0,0,1,8.69,4a3.59,3.59,0,0,1,.53,2.82,5.59,5.59,0,0,1-.47,1.61,4.6,4.6,0,0,1-1,1.42,3.31,3.31,0,0,1-1.6,1,6.9,6.9,0,0,1-1.76.22H2.64L2.08,14H0ZM3.88,4.7,3,9.33h.39a7.55,7.55,0,0,0,2.39-.29c.63-.22,1.06-1,1.28-2.25.18-1.08,0-1.7-.54-1.87a6.6,6.6,0,0,0-2-.23l-.35,0H3.87Z"/><path d="M11.59,0h2.06l-.59,2.94h1.86a3.72,3.72,0,0,1,2.27.65c.51.41.66,1.19.45,2.35l-1,5.13h-2.1l1-4.9a1.44,1.44,0,0,0-.09-1.1,1.26,1.26,0,0,0-1-.32l-1.66,0L11.5,11.07H9.43Z"/><path d="M19.85,2.94h4A3.08,3.08,0,0,1,26.41,4a3.59,3.59,0,0,1,.52,2.82,5.56,5.56,0,0,1-.46,1.61,4.81,4.81,0,0,1-1,1.42,3.31,3.31,0,0,1-1.6,1,6.79,6.79,0,0,1-1.76.22H20.36L19.79,14H17.71ZM21.6,4.7l-.9,4.63h.39a7.51,7.51,0,0,0,2.39-.29q1-.33,1.29-2.25c.17-1.08,0-1.7-.54-1.87a6.67,6.67,0,0,0-2-.23l-.34,0h-.32Z"/></svg>

After

Width:  |  Height:  |  Size: 938 B

View File

@ -0,0 +1,22 @@
<?xml version="1.0"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="21px" height="22px" viewBox="0 0 432.071 445.383" xml:space="preserve" xmlns="http://www.w3.org/2000/svg">
<g id="orginal" style="fill-rule:nonzero;clip-rule:nonzero;stroke:#000000;stroke-miterlimit:4;">
</g>
<g id="Layer_x0020_3" style="fill-rule:nonzero;clip-rule:nonzero;fill:none;stroke:#FFFFFF;stroke-width:12.4651;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;">
<path style="fill:#000000;stroke:#000000;stroke-width:37.3953;stroke-linecap:butt;stroke-linejoin:miter;" d="M323.205,324.227c2.833-23.601,1.984-27.062,19.563-23.239l4.463,0.392c13.517,0.615,31.199-2.174,41.587-7c22.362-10.376,35.622-27.7,13.572-23.148c-50.297,10.376-53.755-6.655-53.755-6.655c53.111-78.803,75.313-178.836,56.149-203.322 C352.514-5.534,262.036,26.049,260.522,26.869l-0.482,0.089c-9.938-2.062-21.06-3.294-33.554-3.496c-22.761-0.374-40.032,5.967-53.133,15.904c0,0-161.408-66.498-153.899,83.628c1.597,31.936,45.777,241.655,98.47,178.31 c19.259-23.163,37.871-42.748,37.871-42.748c9.242,6.14,20.307,9.272,31.912,8.147l0.897-0.765c-0.281,2.876-0.157,5.689,0.359,9.019c-13.572,15.167-9.584,17.83-36.723,23.416c-27.457,5.659-11.326,15.734-0.797,18.367c12.768,3.193,42.305,7.716,62.268-20.224 l-0.795,3.188c5.325,4.26,4.965,30.619,5.72,49.452c0.756,18.834,2.017,36.409,5.856,46.771c3.839,10.36,8.369,37.05,44.036,29.406c29.809-6.388,52.6-15.582,54.677-101.107"/>
<path style="fill:#336791;stroke:none;" d="M402.395,271.23c-50.302,10.376-53.76-6.655-53.76-6.655c53.111-78.808,75.313-178.843,56.153-203.326c-52.27-66.785-142.752-35.2-144.262-34.38l-0.486,0.087c-9.938-2.063-21.06-3.292-33.56-3.496c-22.761-0.373-40.026,5.967-53.127,15.902 c0,0-161.411-66.495-153.904,83.63c1.597,31.938,45.776,241.657,98.471,178.312c19.26-23.163,37.869-42.748,37.869-42.748c9.243,6.14,20.308,9.272,31.908,8.147l0.901-0.765c-0.28,2.876-0.152,5.689,0.361,9.019c-13.575,15.167-9.586,17.83-36.723,23.416 c-27.459,5.659-11.328,15.734-0.796,18.367c12.768,3.193,42.307,7.716,62.266-20.224l-0.796,3.188c5.319,4.26,9.054,27.711,8.428,48.969c-0.626,21.259-1.044,35.854,3.147,47.254c4.191,11.4,8.368,37.05,44.042,29.406c29.809-6.388,45.256-22.942,47.405-50.555 c1.525-19.631,4.976-16.729,5.194-34.28l2.768-8.309c3.192-26.611,0.507-35.196,18.872-31.203l4.463,0.392c13.517,0.615,31.208-2.174,41.591-7c22.358-10.376,35.618-27.7,13.573-23.148z"/>
<path d="M215.866,286.484c-1.385,49.516,0.348,99.377,5.193,111.495c4.848,12.118,15.223,35.688,50.9,28.045c29.806-6.39,40.651-18.756,45.357-46.051c3.466-20.082,10.148-75.854,11.005-87.281"/>
<path d="M173.104,38.256c0,0-161.521-66.016-154.012,84.109c1.597,31.938,45.779,241.664,98.473,178.316c19.256-23.166,36.671-41.335,36.671-41.335"/>
<path d="M260.349,26.207c-5.591,1.753,89.848-34.889,144.087,34.417c19.159,24.484-3.043,124.519-56.153,203.329"/>
<path style="stroke-linejoin:bevel;" d="M348.282,263.953c0,0,3.461,17.036,53.764,6.653c22.04-4.552,8.776,12.774-13.577,23.155c-18.345,8.514-59.474,10.696-60.146-1.069c-1.729-30.355,21.647-21.133,19.96-28.739c-1.525-6.85-11.979-13.573-18.894-30.338 c-6.037-14.633-82.796-126.849,21.287-110.183c3.813-0.789-27.146-99.002-124.553-100.599c-97.385-1.597-94.19,119.762-94.19,119.762"/>
<path d="M188.604,274.334c-13.577,15.166-9.584,17.829-36.723,23.417c-27.459,5.66-11.326,15.733-0.797,18.365c12.768,3.195,42.307,7.718,62.266-20.229c6.078-8.509-0.036-22.086-8.385-25.547c-4.034-1.671-9.428-3.765-16.361,3.994z"/>
<path d="M187.715,274.069c-1.368-8.917,2.93-19.528,7.536-31.942c6.922-18.626,22.893-37.255,10.117-96.339c-9.523-44.029-73.396-9.163-73.436-3.193c-0.039,5.968,2.889,30.26-1.067,58.548c-5.162,36.913,23.488,68.132,56.479,64.938"/>
<path style="fill:#FFFFFF;stroke-width:4.155;stroke-linecap:butt;stroke-linejoin:miter;" d="M172.517,141.7c-0.288,2.039,3.733,7.48,8.976,8.207c5.234,0.73,9.714-3.522,9.998-5.559c0.284-2.039-3.732-4.285-8.977-5.015c-5.237-0.731-9.719,0.333-9.996,2.367z"/>
<path style="fill:#FFFFFF;stroke-width:2.0775;stroke-linecap:butt;stroke-linejoin:miter;" d="M331.941,137.543c0.284,2.039-3.732,7.48-8.976,8.207c-5.238,0.73-9.718-3.522-10.005-5.559c-0.277-2.039,3.74-4.285,8.979-5.015c5.239-0.73,9.718,0.333,10.002,2.368z"/>
<path d="M350.676,123.432c0.863,15.994-3.445,26.888-3.988,43.914c-0.804,24.748,11.799,53.074-7.191,81.435"/>
<path style="stroke-width:3;" d="M0,60.232"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

@ -0,0 +1 @@
<svg width="20" height="20" id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><defs><style>.cls-1{fill:#387ab0;}.cls-2{fill:#feca3d;}</style></defs><title>python-logo-colored</title><path class="cls-1" d="M9.93,0C4.87,0,5.18,2.21,5.18,2.21V4.5H10v.7H3.25S0,4.82,0,10s2.84,5,2.84,5H4.53V12.56A2.71,2.71,0,0,1,7.32,9.7h4.79A2.58,2.58,0,0,0,14.8,7.08V2.67S15.23,0,9.93,0ZM7.26,1.53a.88.88,0,1,1-.87.88A.88.88,0,0,1,7.26,1.53Z"/><path class="cls-2" d="M10.07,20c5.06,0,4.75-2.21,4.75-2.21V15.5H10v-.7h6.76S20,15.18,20,10s-2.84-5-2.84-5H15.47V7.44a2.71,2.71,0,0,1-2.79,2.86H7.89A2.58,2.58,0,0,0,5.2,12.92v4.41S4.77,20,10.07,20Zm2.67-1.53a.88.88,0,1,1,.87-.88A.88.88,0,0,1,12.74,18.47Z"/></svg>

After

Width:  |  Height:  |  Size: 726 B

View File

@ -0,0 +1,14 @@
<svg width="24" height="18" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid" viewBox="0 0 724 561">
<defs>
<linearGradient id="gradientFill-1" x1="0" x2="1" y1="0" y2="1" gradientUnits="objectBoundingBox" spreadMethod="pad">
<stop offset="0" stop-color="rgb(203,206,208)" stop-opacity="1"/>
<stop offset="1" stop-color="rgb(132,131,139)" stop-opacity="1"/>
</linearGradient>
<linearGradient id="gradientFill-2" x1="0" x2="1" y1="0" y2="1" gradientUnits="objectBoundingBox" spreadMethod="pad">
<stop offset="0" stop-color="rgb(39,109,195)" stop-opacity="1"/>
<stop offset="1" stop-color="rgb(22,92,170)" stop-opacity="1"/>
</linearGradient>
</defs>
<path d="M361.453,485.937 C162.329,485.937 0.906,377.828 0.906,244.469 C0.906,111.109 162.329,3.000 361.453,3.000 C560.578,3.000 722.000,111.109 722.000,244.469 C722.000,377.828 560.578,485.937 361.453,485.937 ZM416.641,97.406 C265.289,97.406 142.594,171.314 142.594,262.484 C142.594,353.654 265.289,427.562 416.641,427.562 C567.992,427.562 679.687,377.033 679.687,262.484 C679.687,147.971 567.992,97.406 416.641,97.406 Z" fill="url(#gradientFill-1)" fill-rule="evenodd"/>
<path d="M550.000,377.000 C550.000,377.000 571.822,383.585 584.500,390.000 C588.899,392.226 596.510,396.668 602.000,402.500 C607.378,408.212 610.000,414.000 610.000,414.000 L696.000,559.000 L557.000,559.062 L492.000,437.000 C492.000,437.000 478.690,414.131 470.500,407.500 C463.668,401.969 460.755,400.000 454.000,400.000 C449.298,400.000 420.974,400.000 420.974,400.000 L421.000,558.974 L298.000,559.026 L298.000,152.938 L545.000,152.938 C545.000,152.938 657.500,154.967 657.500,262.000 C657.500,369.033 550.000,377.000 550.000,377.000 ZM496.500,241.024 L422.037,240.976 L422.000,310.026 L496.500,310.002 C496.500,310.002 531.000,309.895 531.000,274.877 C531.000,239.155 496.500,241.024 496.500,241.024 Z" fill="url(#gradientFill-2)" fill-rule="evenodd"/>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

1
docs/assets/languages/ruby.svg Executable file
View File

@ -0,0 +1 @@
<svg width="20" height="20" id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><defs><style>.cls-1{fill:#b11917;}</style></defs><title>ruby-logo-colored</title><path class="cls-1" d="M2,12.84l-.42-1C1.21,11,.86,10.15.51,9.3a.08.08,0,0,1,0-.1C1.23,8,2,6.73,2.67,5.49a.61.61,0,0,1,.12-.16l3.9-3.65a.74.74,0,0,1,.21-.13L10.2.33a.11.11,0,0,1,.1,0l2.77,2s0,0,0,.09c-.47,1.48-.93,3-1.4,4.44a.41.41,0,0,1,0,.09L6.39,11.82l-.09,0L2,12.83Z"/><path class="cls-1" d="M5.12,19.94Q6,16.38,6.9,12.83l6.78,2.63-.07,0A22.89,22.89,0,0,1,11,17.58a14.7,14.7,0,0,1-4.29,2,13.17,13.17,0,0,1-1.54.33Z"/><path class="cls-1" d="M12.68,7.55l6.67-.15c-.08.19-.14.37-.22.55a18.59,18.59,0,0,1-2.54,4.3c-.54.7-1.11,1.35-1.69,2l0,0Z"/><path class="cls-1" d="M7.39,12.08l4.48-4.19,2.21,6.79Z"/><path class="cls-1" d="M15.29,15.19l0,0,.05-.05c.59-.64,1.17-1.29,1.71-2A21.07,21.07,0,0,0,19.43,9.4L19.64,9h0q-.37,4.79-.73,9.55"/><path class="cls-1" d="M19.73,6.08l-5.34-3.9,0,0L17.61.38a.06.06,0,0,1,.06,0,3.5,3.5,0,0,1,2,2A4.49,4.49,0,0,1,20,3.54a6.5,6.5,0,0,1-.12,1.92C19.81,5.66,19.77,5.86,19.73,6.08Z"/><path class="cls-1" d="M18.46,19.09,9,19.74a21.13,21.13,0,0,0,5.66-4l.42.38"/><path class="cls-1" d="M12.66,6.67c.4-1.27.8-2.53,1.19-3.8l5,3.65h0Z"/><path class="cls-1" d="M4.32,19.48c-.67-1.94-1.43-3.87-2.11-5.81L6,12.83c-.56,2.23-1.12,4.44-1.67,6.65Z"/><path class="cls-1" d="M1.64,14.4c.64,1.87,1.29,3.73,1.94,5.6l-.3,0A4.44,4.44,0,0,1,2,19.53,3.32,3.32,0,0,1,.54,18.1,4.57,4.57,0,0,1,.15,17a.19.19,0,0,1,0-.08l1.45-2.49Z"/><path class="cls-1" d="M11.33,0h5.15l0,0L13.67,1.58s-.06,0-.09,0L11.36,0Z"/><path class="cls-1" d="M0,15.47V10.35l0,.08c.39.94.79,1.89,1.18,2.84a.08.08,0,0,1,0,.1L0,15.42A.13.13,0,0,1,0,15.47Z"/></svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

1
docs/assets/languages/rust.svg Executable file
View File

@ -0,0 +1 @@
<svg width="22" height="22" id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 22 22"><title>rust-logo</title><path d="M21.85,10.73l-.92-.57,0-.27.79-.74a.34.34,0,0,0,.1-.3.33.33,0,0,0-.2-.23l-1-.38A2,2,0,0,0,20.49,8l.64-.88a.34.34,0,0,0,0-.31.31.31,0,0,0-.24-.19l-1.07-.18c0-.08-.08-.16-.13-.24l.45-1a.31.31,0,0,0-.3-.45l-1.08,0-.18-.21.25-1.06a.31.31,0,0,0-.38-.38l-1.06.25a1.73,1.73,0,0,0-.21-.17l0-1.09a.32.32,0,0,0-.14-.28.31.31,0,0,0-.31,0l-1,.45-.24-.13L15.4,1.08a.31.31,0,0,0-.19-.24.34.34,0,0,0-.31,0L14,1.51l-.26-.08-.38-1a.33.33,0,0,0-.23-.2.34.34,0,0,0-.3.1l-.74.79-.27,0L11.27.15a.32.32,0,0,0-.54,0l-.57.92-.27,0L9.15.31a.32.32,0,0,0-.53.1l-.38,1L8,1.51,7.1.87a.32.32,0,0,0-.5.21L6.42,2.15l-.24.13-1-.45a.31.31,0,0,0-.31,0,.32.32,0,0,0-.14.28l0,1.09-.21.17L3.52,3.14a.31.31,0,0,0-.38.38l.25,1.06-.17.21-1.09,0a.32.32,0,0,0-.28.14.31.31,0,0,0,0,.31l.45,1-.13.24L1.08,6.6a.31.31,0,0,0-.24.19.34.34,0,0,0,0,.31L1.51,8a2,2,0,0,0-.08.26l-1,.38a.33.33,0,0,0-.2.23.34.34,0,0,0,.1.3l.79.74,0,.27-.92.57a.32.32,0,0,0,0,.54l.92.57,0,.27-.79.74a.34.34,0,0,0-.1.3.33.33,0,0,0,.2.23l1,.38a2,2,0,0,0,.08.26l-.64.88a.34.34,0,0,0,0,.31.31.31,0,0,0,.24.19l1.07.18.13.24-.45,1a.31.31,0,0,0,0,.31.32.32,0,0,0,.28.14l1.09,0a1.73,1.73,0,0,0,.17.21l-.25,1.06a.31.31,0,0,0,.38.38l1.06-.25.21.17,0,1.09a.32.32,0,0,0,.14.28.31.31,0,0,0,.31,0l1-.45.24.13.18,1.07a.31.31,0,0,0,.19.24.34.34,0,0,0,.31,0L8,20.49l.26.08.38,1a.33.33,0,0,0,.23.2.34.34,0,0,0,.3-.1l.74-.79.27,0,.57.92a.32.32,0,0,0,.54,0l.57-.92.27,0,.74.79a.34.34,0,0,0,.3.1.33.33,0,0,0,.23-.2l.38-1,.26-.08.88.64a.34.34,0,0,0,.31,0,.31.31,0,0,0,.19-.24l.18-1.07.24-.13,1,.45a.31.31,0,0,0,.31,0,.32.32,0,0,0,.14-.28l0-1.09a1.73,1.73,0,0,0,.21-.17l1.06.25a.31.31,0,0,0,.38-.38l-.25-1.06.18-.21,1.08,0a.31.31,0,0,0,.3-.45l-.45-1c.05-.08.09-.16.13-.24l1.07-.18a.31.31,0,0,0,.24-.19.34.34,0,0,0,0-.31L20.49,14a2,2,0,0,0,.08-.26l1-.38a.33.33,0,0,0,.2-.23.34.34,0,0,0-.1-.3l-.79-.74,0-.27.92-.57a.32.32,0,0,0,0-.54Zm-6.18,7.66a.65.65,0,0,1,.27-1.28.66.66,0,0,1,.5.78A.64.64,0,0,1,15.67,18.39Zm-.32-2.12a.59.59,0,0,0-.7.46l-.33,1.53A8,8,0,0,1,11,19a8.16,8.16,0,0,1-3.39-.74L7.28,16.7a.58.58,0,0,0-.7-.46l-1.35.29a7.88,7.88,0,0,1-.7-.83H11.1c.08,0,.12,0,.12-.08V13.3c0-.07,0-.08-.12-.08H9.18V11.74h2.08a1.32,1.32,0,0,1,1.28,1.11c.08.33.26,1.38.38,1.72s.63,1.13,1.17,1.13h3.39a10.43,10.43,0,0,1-.74.88ZM6.26,18.36a.64.64,0,0,1-.77-.5.65.65,0,0,1,.5-.78.65.65,0,0,1,.27,1.28ZM3.77,8.25a.65.65,0,1,1-.86-.33A.64.64,0,0,1,3.77,8.25ZM3,10.07l1.41-.63a.59.59,0,0,0,.3-.79L4.42,8H5.56v5.14H3.26A8.54,8.54,0,0,1,3,10.07Zm6.18-.5V8.05h2.71c.14,0,1,.16,1,.8s-.65.72-1.18.72ZM19,10.93c0,.2,0,.4,0,.6H18.2c-.09,0-.12.05-.12.13V12c0,.89-.5,1.09-.94,1.14s-.89-.18-.95-.44a2.81,2.81,0,0,0-1.31-2.2,3,3,0,0,0,1.65-2.29,2.59,2.59,0,0,0-1.26-2.12,3.63,3.63,0,0,0-1.73-.57H5A8.07,8.07,0,0,1,9.51,3l1,1.06a.6.6,0,0,0,.85,0L12.48,3A8.07,8.07,0,0,1,18,6.94l-.77,1.74a.59.59,0,0,0,.3.79l1.48.66A7,7,0,0,1,19,10.93Zm-8.53-8.8a.66.66,0,0,1,.93,0,.65.65,0,0,1,0,.92.66.66,0,0,1-.93,0A.65.65,0,0,1,10.51,2.13Zm7.65,6.15A.65.65,0,0,1,19,8a.65.65,0,1,1-.86.33Z"/></svg>

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="20px" height="18px" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 36" version="1.1">
<defs>
<linearGradient id="a" x2="50%" x1="50%" y2="100%">
<stop stop-color="#F88A36" offset="0"/>
<stop stop-color="#FD2020" offset="1"/>
</linearGradient>
</defs>
<path d="m29.885 33.047c-4.667 2.696-11.084 2.973-17.54 0.206-5.2273-2.224-9.5646-6.117-12.345-10.565 1.3346 1.112 2.8916 2.002 4.5598 2.78 6.6672 3.125 13.333 2.911 18.024 0.008-0.003-0.003-0.005-0.005-0.007-0.008-6.673-5.116-12.345-11.789-16.571-17.238-0.8901-0.8898-1.5574-2.002-2.2247-3.0029 5.1159 4.671 13.235 10.565 16.126 12.234-6.116-6.451-11.566-14.458-11.344-14.236 9.676 9.787 18.685 15.348 18.685 15.348 0.298 0.168 0.528 0.308 0.713 0.433 0.195-0.496 0.366-1.011 0.51-1.545 1.557-5.672-0.222-12.123-4.115-17.461 9.008 5.4495 14.347 15.681 12.122 24.245-0.058 0.231-0.121 0.459-0.189 0.683 0.026 0.031 0.052 0.063 0.078 0.096 4.448 5.561 3.225 11.455 2.669 10.343-2.413-4.722-6.88-3.278-9.151-2.32z" fill="url(#a)"/>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

50
docs/debugging.md Normal file
View File

@ -0,0 +1,50 @@
# Debugging Wasmer
## When is this document useful?
If you're developing wasmer or running into issues, this document will explain to useful techniques and common errors.
## Tracing syscalls
To trace syscalls, compile with the `debug` feature (`cargo build --features "debug"`). For even more verbose messages, use the `trace` flag.
## Tracing calls
TODO: did we disable tracing calls? if not talk about how to enable it
TODO: someone with more context on the backends mention which backends this works for
If you'd like to see all calls and you're using emscripten, you can use a symbol map to get better error output with the `em-symbol-map` flag.
## Common things that can go wrong
### Missing imports
If, when attempting to run a wasm module, you get an error about missing imports there are a number of things that could be going wrong.
The most likely is that we haven't implemented those imports for your ABI. If you're targeting emscripten, this is probably the issue.
However if that's not the case, then there's a chance that you're using an unsupported ABI (let us know!) or that the wasm is invalid for the detected ABI. (TODO: link to wasm contracts or something)
### Hitting `undefined`
If this happens it's because wasmer does not have full support for whatever feature you tried to use. Running with tracing on can help clarify the issue if it's not clear from the message.
To fix this, file an issue letting us know that wasmer is missing a feature that's important to you. If you'd like, you can try to implement it yourself and send us a PR.
### No output
If you're seeing no output from running the wasm module then it may be that:
- this is the intended behavior of the wasm module
- or it's very slow to compile (try compiling with a faster backend like cranelift (the default) or singlepass (requires nightly))
### Segfault
If you're seeing a segfault while developing wasmer, chances are that it's a cache issue. We reset the cache on every version bump, but if you're running it from source then the cache may become invalid, which can lead to segfaults.
To fix this delete the cache with `wasmer cache clean` or run the command with the `disable-cache` flag (`wasmer run some.wasm --disable-cache`)
If you're seeing a segfault with a released version of wasmer, please file an issue so we can ship an updated version as soon as possible.
### Something else
If none of this has helped with your issue, let us know and we'll do our best to help.

42
docs/feature_matrix.md Normal file
View File

@ -0,0 +1,42 @@
# Feature Table
## Compiler Backend
| &nbsp; | Singlepass | Cranelift | LLVM |
| - | :-: | :-: | :-: |
| Caching | ✅ | ✅ | ✅ |
| Emscripten | ✅ | ✅ | ✅ |
| Metering | ✅ | ⬜ | ✅ |
| Multi-value return | ⬜ | ⬜ | ⬜ |
| OSR | 🔄 | ⬜ | 🔄 |
| SIMD | ⬜ | ⬜ | ✅ |
| WASI | ✅ | ✅ | ✅ |
| WASMER_BACKTRACE | ✅ | ⬜ | ⬜ |
## Operating System
| &nbsp; | GNU Linux | Mac OSX | Windows NT |
| - | :-: | :-: | :-: |
| Cranelift Backend | ✅ | ✅ | ✅ |
| LLVM Backend | ✅ | ✅ | ✅ |
| Singlepass Backend | ✅ | ✅ | [#347](https://github.com/wasmerio/wasmer/issues/347) |
| WASI | ✅ | ✅ | ✅* |
* `poll_fd` is not fully implemented for Windows yet
## Language integration
TODO: define a set of features that are relevant and mark them here
Current ideas:
- Callbacks
- Metering
- Caching
> TODO: expand this table, it's focused on new features that we haven't implemented yet and doesn't list all language integrations
| &nbsp; | Rust | C / C++ | Go | Python | Ruby |
| - | :-: | :-: | :-: | :-: | :-: |
| Terminate in host call | ✅ | ⬜ | ⬜ | ⬜ | ⬜ |
| WASI | ✅ | ✅ | 🔄 | ⬜ | ⬜ |
| WASI FS API | ✅ | ⬜ | ⬜ | ⬜ | ⬜ |

View File

@ -0,0 +1,5 @@
# Call back guest
This is part of the `callback` example. This Wasm module passes host imports and its own functions to the Wasm host to execute.
See `examples/callback.rs` for the host

View File

@ -0,0 +1,24 @@
extern "C" {
fn call_guest_fn(f: u32) -> u32;
fn call_guest_fn2(f: u32) -> u32;
fn host_callback() -> u32;
}
#[no_mangle]
fn test_callback() -> u32 {
42
}
#[no_mangle]
fn test_callback2() -> u32 {
45
}
fn main() {
unsafe { call_guest_fn(test_callback as usize as u32) };
unsafe { call_guest_fn(host_callback as usize as u32) };
unsafe { call_guest_fn(test_callback2 as usize as u32) };
unsafe { call_guest_fn2(test_callback2 as usize as u32) };
unsafe { call_guest_fn2(test_callback as usize as u32) };
unsafe { call_guest_fn2(host_callback as usize as u32) };
}

Binary file not shown.

46
examples/callback.rs Normal file
View File

@ -0,0 +1,46 @@
/// This example demonstrates the use of callbacks: calling functions (Host and Wasm)
/// passed to us from the Wasm via hostcall
use wasmer_runtime::{compile_with, compiler_for_backend, func, imports, Backend, Ctx};
use wasmer_runtime_core::{structures::TypedIndex, types::TableIndex};
static WASM: &'static str = "examples/callback-guest/callback-guest.wasm";
/// This function matches our arbitrarily decided callback signature
/// in this example we'll only call functions that take no arguments and return one value
fn host_callback(_ctx: &mut Ctx) -> u32 {
55
}
fn call_guest_fn(ctx: &mut Ctx, guest_fn: u32) -> u32 {
// We get a TableIndex from our raw value passed in
let guest_fn_typed = TableIndex::new(guest_fn as usize);
// and use it to call the corresponding function
let result = ctx.call_with_table_index(guest_fn_typed, &[]).unwrap();
println!("Guest fn {} returned {:?}", guest_fn, result);
0
}
fn main() {
let wasm_bytes =
std::fs::read(WASM).expect(&format!("Could not read in WASM plugin at {}", WASM));
let imports = imports! {
"env" => {
"call_guest_fn" => func!(call_guest_fn),
"call_guest_fn2" => func!(call_guest_fn),
"host_callback" => func!(host_callback),
},
};
let compiler = compiler_for_backend(Backend::default()).unwrap();
let module = compile_with(&wasm_bytes[..], compiler.as_ref()).unwrap();
let instance = module
.instantiate(&imports)
.expect("failed to instantiate wasm module");
let entry_point = instance.func::<(u32, u32), u32>("main").unwrap();
entry_point.call(0, 0).expect("START");
}

20
examples/fib.wat Normal file
View File

@ -0,0 +1,20 @@
(module
(func $main (result i32)
(call $fib (i32.const 40))
)
(func $fib (param $n i32) (result i32)
(if (i32.eq (get_local $n) (i32.const 0))
(then (return (i32.const 1)))
)
(if (i32.eq (get_local $n) (i32.const 1))
(then (return (i32.const 1)))
)
(i32.add
(call $fib (i32.sub (get_local $n) (i32.const 1)))
(call $fib (i32.sub (get_local $n) (i32.const 2)))
)
)
(export "main" (func $main))
)

View File

@ -0,0 +1,9 @@
[package]
name = "hello_world"
version = "0.1.0"
authors = ["losfair <zhy20000919@hotmail.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

View File

@ -0,0 +1,7 @@
fn main() {
for i in 0..8 {
let s = format!("Hello, {}", i);
println!("{}", s);
}
panic!("OK");
}

View File

@ -1,7 +1,13 @@
use blake2::{Blake2b, Digest}; use blake2::{Blake2b, Digest};
use std::time::{Duration, SystemTime};
fn main() { fn main() {
let mut data: Vec<u8> = b"test".to_vec(); let mut data: Vec<u8> = b"test".to_vec();
let now = SystemTime::now();
let mut last_millis: u128 = 0;
let mut round_count: usize = 0;
let mut record_count: usize = 0;
for i in 0.. { for i in 0.. {
let mut hasher = Blake2b::new(); let mut hasher = Blake2b::new();
@ -9,8 +15,15 @@ fn main() {
let out = hasher.result(); let out = hasher.result();
data = out.to_vec(); data = out.to_vec();
if i % 1000000 == 0 { if i != 0 && i % 1000 == 0 {
println!("Round {}: {:?}", i, data); let millis = now.elapsed().unwrap().as_millis();
let diff = millis - last_millis;
if diff >= 100 {
record_count += 1;
println!("{}", ((i - round_count) as u128) * 1000000 / diff );
last_millis = millis;
round_count = i;
}
} }
} }
} }

57
examples/many_params.wat Normal file
View File

@ -0,0 +1,57 @@
;; Test case for correctness of reading state with the presence of parameters passed on (machine) stack.
;; Usage: Run with a backend with support for OSR. Interrupt execution randomly.
;; Should see the stack frame for `$foo` to have locals `[0] = 1, [1] = 2, [2] = 3, [3] = 4, [4] = 5, [5] = 6, [6] = 7, [7] = 8` with high probability.
;; If the logic for reading stack parameters is broken, it's likely to see `[0] = 1, [1] = 2, [2] = 3, [3] = 4, [4] = 5, [5] = ?, [6] = ?, [7] = ?`.
(module
(import "wasi_unstable" "proc_exit" (func $__wasi_proc_exit (param i32)))
(func $long_running
(local $count i32)
(loop
(if (i32.eq (get_local $count) (i32.const 1000000)) (then (return)))
(set_local $count (i32.add (i32.const 1) (get_local $count)))
(br 0)
)
(unreachable)
)
(func $foo (param i32) (param i64) (param i32) (param i32) (param i32) (param i64) (param i64) (param i64) (result i32)
(set_local 2 (i32.const 3))
(call $long_running)
(i32.add
(i32.mul (i32.const 2) (get_local 0))
(i32.add
(i32.mul (i32.const 3) (i32.wrap/i64 (get_local 1)))
(i32.add
(i32.mul (i32.const 5) (get_local 2))
(i32.add
(i32.mul (i32.const 7) (get_local 3))
(i32.add
(i32.mul (i32.const 11) (get_local 4))
(i32.add
(i32.mul (i32.const 13) (i32.wrap/i64 (get_local 5)))
(i32.add
(i32.mul (i32.const 17) (i32.wrap/i64 (get_local 6)))
(i32.mul (i32.const 19) (i32.wrap/i64 (get_local 7)))
)
)
)
)
)
)
)
)
(func $_start (export "_start")
(local $count i32)
(loop
(if (i32.eq (get_local $count) (i32.const 10000)) (then (return)))
(set_local $count (i32.add (i32.const 1) (get_local $count)))
(call $foo (i32.const 1) (i64.const 2) (i32.const 30) (i32.const 4) (i32.const 5) (i64.const 6) (i64.const 7) (i64.const 8))
(if (i32.ne (i32.const 455))
(then unreachable)
)
(br 0)
)
(unreachable)
)
)

BIN
examples/parallel-guest.wasm Executable file

Binary file not shown.

View File

@ -0,0 +1,11 @@
[package]
name = "parallel-guest"
version = "0.1.0"
authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"]
license = "MIT"
edition = "2018"
publish = false
[dependencies]
md5 = "0.6"
lazy_static = "1"

View File

@ -0,0 +1,82 @@
#[macro_use]
extern crate lazy_static;
extern "C" {
fn get_hashed_password(ptr: u32, len: u32) -> u32;
fn print_char(c: u32);
}
fn print_str(s: &str) {
for c in s.chars() {
unsafe { print_char(c as u32) };
}
unsafe { print_char(b'\n' as u32) };
}
fn load_hashed_password() -> Option<String> {
let mut buffer = String::with_capacity(32);
for _ in 0..32 {
buffer.push(0 as char);
}
let result =
unsafe { get_hashed_password(buffer.as_mut_ptr() as u32, buffer.capacity() as u32) };
if result == 0 {
Some(buffer)
} else {
None
}
}
lazy_static! {
static ref HASHED_PASSWORD: String = load_hashed_password().unwrap();
}
static PASSWORD_CHARS: &'static [u8] = b"abcdefghijklmnopqrstuvwxyz0123456789";
// for simplicty we define a scheme for mapping numbers onto passwords
fn num_to_password(mut num: u64) -> String {
let mut extra_zero = num == 0;
let mut out = String::new();
while num > 0 {
out.push(PASSWORD_CHARS[num as usize % PASSWORD_CHARS.len()] as char);
extra_zero = extra_zero || num == PASSWORD_CHARS.len() as u64;
num /= PASSWORD_CHARS.len() as u64;
}
if extra_zero {
out.push(PASSWORD_CHARS[0] as char);
}
out
}
#[repr(C)]
struct RetStr {
ptr: u32,
len: u32,
}
// returns a (pointer, len) to the password or null
#[no_mangle]
fn check_password(from: u64, to: u64) -> u64 {
for i in from..to {
let password = num_to_password(i);
let digest = md5::compute(&password);
let hash_as_str = format!("{:x}", digest);
if hash_as_str == *HASHED_PASSWORD {
let ret = RetStr {
ptr: password.as_ptr() as usize as u32,
len: password.len() as u32,
};
// leak the data so ending the function doesn't corrupt it, if we cared the host could free it after
std::mem::forget(password);
return unsafe { std::mem::transmute(ret) };
}
}
return 0;
}
fn main() {}

View File

@ -0,0 +1,14 @@
[package]
name = "parallel"
version = "0.1.0"
authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"]
edition = "2018"
repository = "https://github.com/wasmerio/wasmer"
publish = false
license = "MIT"
[dependencies]
rayon = "1.2"
time = "0.1"
wasmer-runtime = { path = "../../lib/runtime" }
wasmer-runtime-core = { path = "../../lib/runtime-core" }

View File

@ -0,0 +1,5 @@
# Parallel Wasmer example
This example shows executing independent code from multiple threads on an "embarassingly parallel" problem
This is a toy example of cracking md5 hashes. This is not a benchmark. This example is not optimized, it will compare poorly to an implementation that is.

View File

@ -0,0 +1,137 @@
use rayon::prelude::*;
use wasmer_runtime::{compile_with, compiler_for_backend, func, imports, instantiate, Backend};
use wasmer_runtime_core::{
memory::ptr::{Array, WasmPtr},
vm::Ctx,
};
static PLUGIN_LOCATION: &'static str = "../parallel-guest.wasm";
fn get_hashed_password(ctx: &mut Ctx, ptr: WasmPtr<u8, Array>, len: u32) -> u32 {
// "hard" password - 7 characters
//let password = b"2ab96390c7dbe3439de74d0c9b0b1767";
// "easy" password - 5 characters
let password = b"ab56b4d92b40713acc5af89985d4b786";
let memory = ctx.memory(0);
if let Some(writer) = ptr.deref(memory, 0, len) {
for (i, byte) in password.iter().enumerate() {
writer[i].set(*byte)
}
0
} else {
u32::max_value()
}
}
#[repr(C)]
struct RetStr {
ptr: u32,
len: u32,
}
fn print_char(_cxt: &mut Ctx, c: u32) {
print!("{}", c as u8 as char);
}
fn main() {
let wasm_bytes = std::fs::read(PLUGIN_LOCATION).expect(&format!(
"Could not read in WASM plugin at {}",
PLUGIN_LOCATION
));
let imports = imports! {
"env" => {
"get_hashed_password" => func!(get_hashed_password),
"print_char" => func!(print_char),
},
};
let compiler = compiler_for_backend(Backend::default()).unwrap();
let module = compile_with(&wasm_bytes[..], compiler.as_ref()).unwrap();
println!("Parallel");
let start_ts = time::SteadyTime::now();
for outer in 0..1000u64 {
let start = outer * 1000;
let end = start + 1000;
let out = (start..=end)
.into_par_iter()
.filter_map(|i| {
let instance = module
.clone()
.instantiate(&imports)
.expect("failed to instantiate wasm module");
let check_password = instance.func::<(u64, u64), u64>("check_password").unwrap();
let j = i * 10000;
let result = check_password.call(j, j + 10000).unwrap();
print!(".");
use std::io::Write;
std::io::stdout().flush().unwrap();
if result != 0 {
let res: RetStr = unsafe { std::mem::transmute(result) };
let ctx = instance.context();
let memory = ctx.memory(0);
let wasm_ptr: WasmPtr<u8, Array> = WasmPtr::new(res.ptr);
let password_str = wasm_ptr
.get_utf8_string(memory, res.len)
.unwrap()
.to_string();
Some(password_str)
} else {
None
}
})
.find_first(|_: &String| true);
if out.is_some() {
let end_ts = time::SteadyTime::now();
let delta = end_ts - start_ts;
println!(
"Password cracked: \"{}\" in {}.{:03}",
out.unwrap(),
delta.num_seconds(),
(delta.num_milliseconds() % 1000),
);
break;
}
}
println!("Serial:");
let start_ts = time::SteadyTime::now();
let instance =
instantiate(&wasm_bytes[..], &imports).expect("failed to instantiate wasm module");
let check_password = instance.func::<(u64, u64), u64>("check_password").unwrap();
let mut out: Option<RetStr> = None;
for i in (0..=u64::max_value()).step_by(10000) {
let result = check_password.call(i, i + 10000).unwrap();
print!(".");
use std::io::Write;
std::io::stdout().flush().unwrap();
if result != 0 {
out = Some(unsafe { std::mem::transmute(result) });
break;
}
}
println!("");
if let Some(res) = out {
let ctx = instance.context();
let memory = ctx.memory(0);
let wasm_ptr: WasmPtr<u8, Array> = WasmPtr::new(res.ptr);
let password_str = wasm_ptr.get_utf8_string(memory, res.len).unwrap();
let end_ts = time::SteadyTime::now();
let delta = end_ts - start_ts;
println!(
"Password cracked: \"{}\" in {}.{:03}",
password_str,
delta.num_seconds(),
(delta.num_milliseconds() % 1000),
);
} else {
println!("Password not found!");
}
}

View File

@ -1,8 +1,9 @@
use serde::{Deserialize, Serialize};
use wasmer_runtime::{func, imports, instantiate}; use wasmer_runtime::{func, imports, instantiate};
use wasmer_runtime_core::vm::Ctx; use wasmer_runtime_core::vm::Ctx;
use wasmer_wasi::{ use wasmer_wasi::{
generate_import_object, generate_import_object,
state::{self, WasiFile}, state::{self, WasiFile, WasiFsError},
types, types,
}; };
@ -13,7 +14,7 @@ fn it_works(_ctx: &mut Ctx) -> i32 {
5 5
} }
#[derive(Debug)] #[derive(Debug, Serialize, Deserialize)]
pub struct LoggingWrapper { pub struct LoggingWrapper {
pub wasm_module_name: String, pub wasm_module_name: String,
} }
@ -86,6 +87,8 @@ impl std::io::Write for LoggingWrapper {
} }
// the WasiFile methods aren't relevant for a write-only Stdout-like implementation // the WasiFile methods aren't relevant for a write-only Stdout-like implementation
// we must use typetag and serde so that our trait objects can be safely Serialized and Deserialized
#[typetag::serde]
impl WasiFile for LoggingWrapper { impl WasiFile for LoggingWrapper {
fn last_accessed(&self) -> u64 { fn last_accessed(&self) -> u64 {
0 0
@ -99,6 +102,16 @@ impl WasiFile for LoggingWrapper {
fn size(&self) -> u64 { fn size(&self) -> u64 {
0 0
} }
fn set_len(&mut self, _len: u64) -> Result<(), WasiFsError> {
Ok(())
}
fn unlink(&mut self) -> Result<(), WasiFsError> {
Ok(())
}
fn bytes_available(&self) -> Result<usize, WasiFsError> {
// return an arbitrary amount
Ok(1024)
}
} }
/// Called by the program when it wants to set itself up /// Called by the program when it wants to set itself up

View File

@ -10,6 +10,10 @@ cargo-fuzz = true
[dependencies] [dependencies]
wasmer-runtime = { path = "../lib/runtime" } wasmer-runtime = { path = "../lib/runtime" }
wasmer-runtime-core = { path = "../lib/runtime-core" }
wasmer = { path = "../" }
wasmer-llvm-backend = { path = "../lib/llvm-backend" }
wasmer-singlepass-backend = { path = "../lib/singlepass-backend" }
libfuzzer-sys = { git = "https://github.com/rust-fuzz/libfuzzer-sys.git" } libfuzzer-sys = { git = "https://github.com/rust-fuzz/libfuzzer-sys.git" }
# Prevent this from interfering with workspaces # Prevent this from interfering with workspaces
@ -19,3 +23,11 @@ members = ["."]
[[bin]] [[bin]]
name = "simple_instantiate" name = "simple_instantiate"
path = "fuzz_targets/simple_instantiate.rs" path = "fuzz_targets/simple_instantiate.rs"
[[bin]]
name = "validate_wasm"
path = "fuzz_targets/validate_wasm.rs"
[[bin]]
name = "compile_wasm"
path = "fuzz_targets/compile_wasm.rs"

View File

@ -10,12 +10,20 @@ $ cargo install cargo-fuzz
`cargo-fuzz` is documented in the [Rust Fuzz Book](https://rust-fuzz.github.io/book/cargo-fuzz.html). `cargo-fuzz` is documented in the [Rust Fuzz Book](https://rust-fuzz.github.io/book/cargo-fuzz.html).
## Running a fuzzer ## Running a fuzzer (simple_instantiate, validate_wasm, compile_wasm)
Once `cargo-fuzz` is installed, you can run the `simple_instantiate` fuzzer with Once `cargo-fuzz` is installed, you can run the `simple_instantiate` fuzzer with
```sh ```sh
cargo fuzz run simple_instantiate cargo fuzz run simple_instantiate
``` ```
or the `validate_wasm` fuzzer
```sh
cargo fuzz run validate_wasm
```
or the `compile_wasm` fuzzer
```sh
cargo fuzz run compile_wasm
```
You should see output that looks something like this: You should see output that looks something like this:
@ -39,7 +47,7 @@ The fuzzer works best when it has examples of small Wasm files to start with. Us
```sh ```sh
mkdir spec-test-corpus mkdir spec-test-corpus
for i in lib/spectests/spectests/*.wast; do wast2json $i -o spec-test-corpus/$(basename $i).json; done for i in lib/spectests/spectests/*.wast; do wast2json --enable-all $i -o spec-test-corpus/$(basename $i).json; done
mv spec-test-corpus/*.wasm fuzz/corpus/simple_instantiate/ mv spec-test-corpus/*.wasm fuzz/corpus/simple_instantiate/
rm -r spec-test-corpus rm -r spec-test-corpus
``` ```

View File

@ -0,0 +1,25 @@
#![no_main]
#[macro_use]
extern crate libfuzzer_sys;
extern crate wasmer_runtime;
extern crate wasmer_runtime_core;
extern crate wasmer_llvm_backend;
extern crate wasmer_singlepass_backend;
use wasmer_runtime::{compile, compile_with};
use wasmer_runtime_core::backend::Compiler;
fn get_llvm_compiler() -> impl Compiler {
use wasmer_llvm_backend::LLVMCompiler;
LLVMCompiler::new()
}
fn get_singlepass_compiler() -> impl Compiler {
use wasmer_singlepass_backend::SinglePassCompiler;
SinglePassCompiler::new()
}
fuzz_target!(|data: &[u8]| {
let _ = compile_with(data, &get_llvm_compiler());
let _ = compile(data);
let _ = compile_with(data, &get_singlepass_compiler());
});

View File

@ -1,11 +1,9 @@
#![no_main] #![no_main]
#[macro_use] extern crate libfuzzer_sys; #[macro_use]
extern crate libfuzzer_sys;
extern crate wasmer_runtime; extern crate wasmer_runtime;
use wasmer_runtime::{ use wasmer_runtime::{imports, instantiate};
instantiate,
imports,
};
fuzz_target!(|data: &[u8]| { fuzz_target!(|data: &[u8]| {
let import_object = imports! {}; let import_object = imports! {};

View File

@ -0,0 +1,20 @@
#![no_main]
#[macro_use]
extern crate libfuzzer_sys;
extern crate wasmer;
extern crate wasmer_runtime_core;
use wasmer_runtime_core::backend::Features;
fuzz_target!(|data: &[u8]| {
let _ = wasmer::utils::is_wasm_binary(data);
let _ = wasmer_runtime_core::validate_and_report_errors_with_features(
&data,
Features {
// Modify these values to explore additional parts of wasmer.
simd: false,
threads: false,
},
);
});

View File

@ -1,8 +1,8 @@
#!/bin/sh #!/bin/sh
# This install script is intended to download and install the latest available # This install script is intended to download and install the latest available
# release of the wasmer. # release of Wasmer.
# Installer script inspired from: # Installer script inspired by:
# 1) https://raw.githubusercontent.com/golang/dep/master/install.sh # 1) https://raw.githubusercontent.com/golang/dep/master/install.sh
# 2) https://sh.rustup.rs # 2) https://sh.rustup.rs
# 3) https://yarnpkg.com/install.sh # 3) https://yarnpkg.com/install.sh
@ -22,7 +22,6 @@
set -e set -e
reset="\033[0m" reset="\033[0m"
red="\033[31m" red="\033[31m"
green="\033[32m" green="\033[32m"
@ -209,9 +208,11 @@ initArch() {
printf "$cyan> Using WASMER_ARCH ($WASMER_ARCH).$reset\n" printf "$cyan> Using WASMER_ARCH ($WASMER_ARCH).$reset\n"
ARCH="$WASMER_ARCH" ARCH="$WASMER_ARCH"
fi fi
# If you modify this list, please also modify scripts/binary-name.sh
case $ARCH in case $ARCH in
amd64) ARCH="amd64";; amd64) ARCH="amd64";;
x86_64) ARCH="amd64";; x86_64) ARCH="amd64";;
aarch64) ARCH="arm64";;
# i386) ARCH="386";; # i386) ARCH="386";;
*) printf "$red> The system architecture (${ARCH}) is not supported by this installation script.$reset\n"; exit 1;; *) printf "$red> The system architecture (${ARCH}) is not supported by this installation script.$reset\n"; exit 1;;
esac esac

View File

@ -1,9 +1,8 @@
# `cowsay` integration test # `cowsay` integration test
This starts Wasmer with the Cowsay WASI Wasm file. The test makes assertions on This starts Wasmer with the Cowsay WASI Wasm file. The test makes assertions on
the output of Wasmer. Run test with: the output of Wasmer. Run test with:
```bash ```sh
./integration_tests/cowsay/test.sh ./integration_tests/cowsay/test.sh
``` ```

View File

@ -1,41 +1,43 @@
[package] [package]
name = "wasmer-clif-backend" name = "wasmer-clif-backend"
version = "0.6.0" version = "0.11.0"
description = "Wasmer runtime Cranelift compiler backend" description = "Wasmer runtime Cranelift compiler backend"
license = "MIT" license = "MIT"
authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"] authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"]
repository = "https://github.com/wasmerio/wasmer" repository = "https://github.com/wasmerio/wasmer"
keywords = ["wasm", "webassembly", "compiler", "JIT", "AOT"]
categories = ["wasm"]
edition = "2018" edition = "2018"
readme = "README.md" readme = "README.md"
[dependencies] [dependencies]
wasmer-runtime-core = { path = "../runtime-core", version = "0.6.0" } wasmer-runtime-core = { path = "../runtime-core", version = "0.11.0" }
cranelift-native = { version = "0.31" } cranelift-native = "0.44.0"
cranelift-codegen = { version = "0.31" } cranelift-codegen = "0.44.0"
cranelift-entity = { version = "0.31" } cranelift-entity = "0.44.0"
cranelift-frontend = { package = "wasmer-clif-fork-frontend", version = "0.33" } cranelift-frontend = { package = "wasmer-clif-fork-frontend", version = "0.44.0" }
cranelift-wasm = { package = "wasmer-clif-fork-wasm", version = "0.33" } cranelift-wasm = { package = "wasmer-clif-fork-wasm", version = "0.44.0" }
target-lexicon = "0.4.0" target-lexicon = "0.8.1"
wasmparser = "0.35.1" wasmparser = "0.39.1"
byteorder = "1.3.2" byteorder = "1.3.2"
nix = "0.15.0" nix = "0.15.0"
libc = "0.2.60" libc = "0.2.60"
rayon = "1.1.0" rayon = "1.1"
# Dependencies for caching. # Dependencies for caching.
[dependencies.serde] [dependencies.serde]
version = "1.0.99" version = "1.0"
features = ["rc"] features = ["rc"]
[dependencies.serde_derive] [dependencies.serde_derive]
version = "1.0.98" version = "1.0"
[dependencies.serde_bytes] [dependencies.serde_bytes]
version = "0.11.2" version = "0.11"
[dependencies.serde-bench] [dependencies.serde-bench]
version = "0.0.7" version = "0.0.7"
[target.'cfg(windows)'.dependencies] [target.'cfg(windows)'.dependencies]
winapi = { version = "0.3.7", features = ["errhandlingapi", "minwindef", "minwinbase", "winnt"] } winapi = { version = "0.3", features = ["errhandlingapi", "minwindef", "minwinbase", "winnt"] }
wasmer-win-exception-handler = { path = "../win-exception-handler", version = "0.6.0" } wasmer-win-exception-handler = { path = "../win-exception-handler", version = "0.11.0" }
[features] [features]
debug = ["wasmer-runtime-core/debug"] debug = ["wasmer-runtime-core/debug"]

View File

@ -1,21 +1,21 @@
<p align="center"> <p align="center">
<a href="https://wasmer.io" target="_blank" rel="noopener noreferrer"> <a href="https://wasmer.io" target="_blank" rel="noopener noreferrer">
<img width="400" src="https://raw.githubusercontent.com/wasmerio/wasmer/master/logo.png" alt="Wasmer logo"> <img width="300" src="https://raw.githubusercontent.com/wasmerio/wasmer/master/logo.png" alt="Wasmer logo">
</a> </a>
</p> </p>
<p align="center"> <p align="center">
<a href="https://circleci.com/gh/wasmerio/wasmer/"> <a href="https://dev.azure.com/wasmerio/wasmer/_build/latest?definitionId=3&branchName=master">
<img src="https://img.shields.io/circleci/project/github/wasmerio/wasmer/master.svg" alt="Build Status"> <img src="https://img.shields.io/azure-devops/build/wasmerio/wasmer/3.svg?style=flat-square" alt="Build Status">
</a> </a>
<a href="https://github.com/wasmerio/wasmer/blob/master/LICENSE"> <a href="https://github.com/wasmerio/wasmer/blob/master/LICENSE">
<img src="https://img.shields.io/github/license/wasmerio/wasmer.svg" alt="License"> <img src="https://img.shields.io/github/license/wasmerio/wasmer.svg?style=flat-square" alt="License">
</a> </a>
<a href="https://spectrum.chat/wasmer"> <a href="https://spectrum.chat/wasmer">
<img src="https://withspectrum.github.io/badge/badge.svg" alt="Join the Wasmer Community"> <img src="https://withspectrum.github.io/badge/badge.svg" alt="Join the Wasmer Community">
</a> </a>
<a href="https://crates.io/crates/wasmer-clif-backend"> <a href="https://crates.io/crates/wasmer-clif-backend">
<img src="https://img.shields.io/crates/d/wasmer-clif-backend.svg" alt="Number of downloads from crates.io"> <img src="https://img.shields.io/crates/d/wasmer-clif-backend.svg?style=flat-square" alt="Number of downloads from crates.io">
</a> </a>
<a href="https://docs.rs/wasmer-clif-backend"> <a href="https://docs.rs/wasmer-clif-backend">
<img src="https://docs.rs/wasmer-clif-backend/badge.svg" alt="Read our API documentation"> <img src="https://docs.rs/wasmer-clif-backend/badge.svg" alt="Read our API documentation">
@ -36,7 +36,7 @@ This crate represents the Cranelift backend integration for Wasmer.
If you are using the `wasmer` CLI, you can specify the backend with: If you are using the `wasmer` CLI, you can specify the backend with:
```bash ```sh
wasmer run program.wasm --backend=cranelift wasmer run program.wasm --backend=cranelift
``` ```

View File

@ -54,6 +54,10 @@ impl ModuleCodeGenerator<CraneliftFunctionCodeGenerator, Caller, CodegenError>
} }
} }
fn new_with_target(_: Option<String>, _: Option<String>, _: Option<String>) -> Self {
unimplemented!("cross compilation is not available for clif backend")
}
fn backend_id() -> Backend { fn backend_id() -> Backend {
Backend::Cranelift Backend::Cranelift
} }
@ -128,166 +132,6 @@ impl ModuleCodeGenerator<CraneliftFunctionCodeGenerator, Caller, CodegenError>
.state .state
.initialize(&builder.func.signature, exit_block); .initialize(&builder.func.signature, exit_block);
#[cfg(feature = "debug")]
{
use cranelift_codegen::cursor::{Cursor, FuncCursor};
use cranelift_codegen::ir::InstBuilder;
let entry_ebb = func.layout.entry_block().unwrap();
let ebb = func.dfg.make_ebb();
func.layout.insert_ebb(ebb, entry_ebb);
let mut pos = FuncCursor::new(&mut func).at_first_insertion_point(ebb);
let params = pos.func.dfg.ebb_params(entry_ebb).to_vec();
let new_ebb_params: Vec<_> = params
.iter()
.map(|&param| {
pos.func
.dfg
.append_ebb_param(ebb, pos.func.dfg.value_type(param))
})
.collect();
let start_debug = {
let signature = pos.func.import_signature(ir::Signature {
call_conv: self.target_config().default_call_conv,
params: vec![
ir::AbiParam::special(ir::types::I64, ir::ArgumentPurpose::VMContext),
ir::AbiParam::new(ir::types::I32),
],
returns: vec![],
});
let name = ir::ExternalName::testcase("strtdbug");
pos.func.import_function(ir::ExtFuncData {
name,
signature,
colocated: false,
})
};
let end_debug = {
let signature = pos.func.import_signature(ir::Signature {
call_conv: self.target_config().default_call_conv,
params: vec![ir::AbiParam::special(
ir::types::I64,
ir::ArgumentPurpose::VMContext,
)],
returns: vec![],
});
let name = ir::ExternalName::testcase("enddbug");
pos.func.import_function(ir::ExtFuncData {
name,
signature,
colocated: false,
})
};
let i32_print = {
let signature = pos.func.import_signature(ir::Signature {
call_conv: self.target_config().default_call_conv,
params: vec![
ir::AbiParam::special(ir::types::I64, ir::ArgumentPurpose::VMContext),
ir::AbiParam::new(ir::types::I32),
],
returns: vec![],
});
let name = ir::ExternalName::testcase("i32print");
pos.func.import_function(ir::ExtFuncData {
name,
signature,
colocated: false,
})
};
let i64_print = {
let signature = pos.func.import_signature(ir::Signature {
call_conv: self.target_config().default_call_conv,
params: vec![
ir::AbiParam::special(ir::types::I64, ir::ArgumentPurpose::VMContext),
ir::AbiParam::new(ir::types::I64),
],
returns: vec![],
});
let name = ir::ExternalName::testcase("i64print");
pos.func.import_function(ir::ExtFuncData {
name,
signature,
colocated: false,
})
};
let f32_print = {
let signature = pos.func.import_signature(ir::Signature {
call_conv: self.target_config().default_call_conv,
params: vec![
ir::AbiParam::special(ir::types::I64, ir::ArgumentPurpose::VMContext),
ir::AbiParam::new(ir::types::F32),
],
returns: vec![],
});
let name = ir::ExternalName::testcase("f32print");
pos.func.import_function(ir::ExtFuncData {
name,
signature,
colocated: false,
})
};
let f64_print = {
let signature = pos.func.import_signature(ir::Signature {
call_conv: self.target_config().default_call_conv,
params: vec![
ir::AbiParam::special(ir::types::I64, ir::ArgumentPurpose::VMContext),
ir::AbiParam::new(ir::types::F64),
],
returns: vec![],
});
let name = ir::ExternalName::testcase("f64print");
pos.func.import_function(ir::ExtFuncData {
name,
signature,
colocated: false,
})
};
let vmctx = pos
.func
.special_param(ir::ArgumentPurpose::VMContext)
.expect("missing vmctx parameter");
let func_index = pos.ins().iconst(
ir::types::I32,
func_index.index() as i64 + self.module.info.imported_functions.len() as i64,
);
pos.ins().call(start_debug, &[vmctx, func_index]);
for param in new_ebb_params.iter().cloned() {
match pos.func.dfg.value_type(param) {
ir::types::I32 => pos.ins().call(i32_print, &[vmctx, param]),
ir::types::I64 => pos.ins().call(i64_print, &[vmctx, param]),
ir::types::F32 => pos.ins().call(f32_print, &[vmctx, param]),
ir::types::F64 => pos.ins().call(f64_print, &[vmctx, param]),
_ => unimplemented!(),
};
}
pos.ins().call(end_debug, &[vmctx]);
pos.ins().jump(entry_ebb, new_ebb_params.as_slice());
}
self.functions.push(func_env); self.functions.push(func_env);
Ok(self.functions.last_mut().unwrap()) Ok(self.functions.last_mut().unwrap())
} }
@ -851,7 +695,9 @@ impl FuncEnvironment for FunctionEnvironment {
} }
/// Generates a call IR with `callee` and `call_args` and inserts it at `pos` /// Generates a call IR with `callee` and `call_args` and inserts it at `pos`
/// TODO: add support for imported functions ///
/// It's about generating code that calls a local or imported function; in
/// WebAssembly: `(call $foo)`.
fn translate_call( fn translate_call(
&mut self, &mut self,
mut pos: FuncCursor, mut pos: FuncCursor,
@ -923,20 +769,31 @@ impl FuncEnvironment for FunctionEnvironment {
readonly: true, readonly: true,
}); });
let imported_vmctx_addr = pos.func.create_global_value(ir::GlobalValueData::Load { let imported_func_ctx_addr =
base: imported_func_struct_addr, pos.func.create_global_value(ir::GlobalValueData::Load {
offset: (vm::ImportedFunc::offset_vmctx() as i32).into(), base: imported_func_struct_addr,
global_type: ptr_type, offset: (vm::ImportedFunc::offset_func_ctx() as i32).into(),
readonly: true, global_type: ptr_type,
}); readonly: true,
});
let imported_func_ctx_vmctx_addr =
pos.func.create_global_value(ir::GlobalValueData::Load {
base: imported_func_ctx_addr,
offset: (vm::FuncCtx::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_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 imported_func_ctx_vmctx_addr = pos
.ins()
.global_value(ptr_type, imported_func_ctx_vmctx_addr);
let sig_ref = pos.func.dfg.ext_funcs[callee].signature; let sig_ref = pos.func.dfg.ext_funcs[callee].signature;
let mut args = Vec::with_capacity(call_args.len() + 1); let mut args = Vec::with_capacity(call_args.len() + 1);
args.push(imported_vmctx_addr); args.push(imported_func_ctx_vmctx_addr);
args.extend(call_args.iter().cloned()); args.extend(call_args.iter().cloned());
Ok(pos Ok(pos
@ -1117,7 +974,18 @@ impl FunctionCodeGenerator<CodegenError> for CraneliftFunctionCodeGenerator {
fn feed_local(&mut self, ty: WpType, n: usize) -> Result<(), CodegenError> { fn feed_local(&mut self, ty: WpType, n: usize) -> Result<(), CodegenError> {
let mut next_local = self.next_local; let mut next_local = self.next_local;
cranelift_wasm::declare_locals(&mut self.builder(), n as u32, ty, &mut next_local)?; let mut builder = FunctionBuilder::new(
&mut self.func,
&mut self.func_translator.func_ctx,
&mut self.position,
);
cranelift_wasm::declare_locals(
&mut builder,
n as u32,
ty,
&mut next_local,
&mut self.func_env,
)?;
self.next_local = next_local; self.next_local = next_local;
Ok(()) Ok(())
} }

View File

@ -1,5 +1,10 @@
//! The Wasmer Cranelift Backend crate is used to compile wasm binary code via parse events from the
//! Wasmer runtime common parser code into machine code.
//!
#![deny( #![deny(
dead_code, dead_code,
missing_docs,
nonstandard_style, nonstandard_style,
unused_imports, unused_imports,
unused_mut, unused_mut,
@ -7,6 +12,9 @@
unused_unsafe, unused_unsafe,
unreachable_patterns unreachable_patterns
)] )]
#![doc(html_favicon_url = "https://wasmer.io/static/icons/favicon.ico")]
#![doc(html_logo_url = "https://avatars3.githubusercontent.com/u/44205449?s=200&v=4")]
mod cache; mod cache;
mod code; mod code;
mod libcalls; mod libcalls;
@ -31,7 +39,7 @@ extern crate serde;
fn get_isa() -> Box<dyn isa::TargetIsa> { fn get_isa() -> Box<dyn isa::TargetIsa> {
let flags = { let flags = {
let mut builder = settings::builder(); let mut builder = settings::builder();
builder.set("opt_level", "best").unwrap(); builder.set("opt_level", "speed_and_size").unwrap();
builder.set("jump_tables_enabled", "false").unwrap(); builder.set("jump_tables_enabled", "false").unwrap();
if cfg!(not(test)) { if cfg!(not(test)) {
@ -39,7 +47,7 @@ fn get_isa() -> Box<dyn isa::TargetIsa> {
} }
let flags = settings::Flags::new(builder); let flags = settings::Flags::new(builder);
debug_assert_eq!(flags.opt_level(), settings::OptLevel::Best); debug_assert_eq!(flags.opt_level(), settings::OptLevel::SpeedAndSize);
flags flags
}; };
isa::lookup(Triple::host()).unwrap().finish(flags) isa::lookup(Triple::host()).unwrap().finish(flags)
@ -50,6 +58,8 @@ pub const VERSION: &str = env!("CARGO_PKG_VERSION");
use wasmer_runtime_core::codegen::SimpleStreamingCompilerGen; use wasmer_runtime_core::codegen::SimpleStreamingCompilerGen;
/// Streaming compiler implementation for the Cranelift backed. Compiles web assembly binary into
/// machine code.
pub type CraneliftCompiler = SimpleStreamingCompilerGen< pub type CraneliftCompiler = SimpleStreamingCompilerGen<
code::CraneliftModuleCodeGenerator, code::CraneliftModuleCodeGenerator,
code::CraneliftFunctionCodeGenerator, code::CraneliftFunctionCodeGenerator,

View File

@ -105,7 +105,7 @@ impl binemit::RelocSink for RelocSink {
_ebb_offset: binemit::CodeOffset, _ebb_offset: binemit::CodeOffset,
) { ) {
// This should use the `offsets` field of `ir::Function`. // This should use the `offsets` field of `ir::Function`.
unimplemented!(); unimplemented!("RelocSink::reloc_ebb");
} }
fn reloc_external( fn reloc_external(
&mut self, &mut self,
@ -146,7 +146,7 @@ impl binemit::RelocSink for RelocSink {
DYNAMIC_MEM_GROW => VmCallKind::DynamicMemoryGrow, DYNAMIC_MEM_GROW => VmCallKind::DynamicMemoryGrow,
DYNAMIC_MEM_SIZE => VmCallKind::DynamicMemorySize, DYNAMIC_MEM_SIZE => VmCallKind::DynamicMemorySize,
_ => unimplemented!(), _ => unimplemented!("reloc_external VmCall::Local {}", index),
})), })),
IMPORT_NAMESPACE => RelocationType::VmCall(VmCall::Import(match index { IMPORT_NAMESPACE => RelocationType::VmCall(VmCall::Import(match index {
STATIC_MEM_GROW => VmCallKind::StaticMemoryGrow, STATIC_MEM_GROW => VmCallKind::StaticMemoryGrow,
@ -157,10 +157,10 @@ impl binemit::RelocSink for RelocSink {
DYNAMIC_MEM_GROW => VmCallKind::DynamicMemoryGrow, DYNAMIC_MEM_GROW => VmCallKind::DynamicMemoryGrow,
DYNAMIC_MEM_SIZE => VmCallKind::DynamicMemorySize, DYNAMIC_MEM_SIZE => VmCallKind::DynamicMemorySize,
_ => unimplemented!(), _ => unimplemented!("reloc_external VmCall::Import {}", index),
})), })),
SIG_NAMESPACE => RelocationType::Signature(SigIndex::new(index as usize)), SIG_NAMESPACE => RelocationType::Signature(SigIndex::new(index as usize)),
_ => unimplemented!(), _ => unimplemented!("reloc_external SigIndex {}", index),
}; };
self.external_relocs.push(ExternalRelocation { self.external_relocs.push(ExternalRelocation {
reloc, reloc,
@ -202,13 +202,18 @@ impl binemit::RelocSink for RelocSink {
} }
} }
} }
fn reloc_constant(&mut self, _: u32, _: cranelift_codegen::binemit::Reloc, _: u32) {
unimplemented!("RelocSink::reloc_constant")
}
fn reloc_jt( fn reloc_jt(
&mut self, &mut self,
_offset: binemit::CodeOffset, _offset: binemit::CodeOffset,
_reloc: binemit::Reloc, _reloc: binemit::Reloc,
_jt: ir::JumpTable, _jt: ir::JumpTable,
) { ) {
unimplemented!(); unimplemented!("RelocSink::reloc_jt");
} }
} }

View File

@ -1,29 +1,31 @@
use crate::{cache::BackendCache, trampoline::Trampolines};
use crate::{ use crate::{
cache::BackendCache,
libcalls, libcalls,
relocation::{ relocation::{
ExternalRelocation, LibCall, LocalRelocation, LocalTrapSink, Reloc, RelocSink, ExternalRelocation, LibCall, LocalRelocation, LocalTrapSink, Reloc, RelocSink,
RelocationType, TrapSink, VmCall, VmCallKind, RelocationType, TrapSink, VmCall, VmCallKind,
}, },
signal::HandlerData, signal::HandlerData,
trampoline::Trampolines,
};
use byteorder::{ByteOrder, LittleEndian};
use cranelift_codegen::{
binemit::{Stackmap, StackmapSink},
ir, isa, Context,
}; };
use rayon::prelude::*; use rayon::prelude::*;
use byteorder::{ByteOrder, LittleEndian};
use cranelift_codegen::{ir, isa, Context};
use std::{ use std::{
mem, mem,
ptr::{write_unaligned, NonNull}, ptr::{write_unaligned, NonNull},
sync::Arc, sync::Arc,
}; };
use wasmer_runtime_core::cache::Error as CacheError;
use wasmer_runtime_core::{ use wasmer_runtime_core::{
self, self,
backend::{ backend::{
sys::{Memory, Protect}, sys::{Memory, Protect},
SigRegistry, SigRegistry,
}, },
cache::Error as CacheError,
error::{CompileError, CompileResult}, error::{CompileError, CompileResult},
module::ModuleInfo, module::ModuleInfo,
structures::{Map, SliceMap, TypedIndex}, structures::{Map, SliceMap, TypedIndex},
@ -58,6 +60,11 @@ pub struct FuncResolverBuilder {
import_len: usize, import_len: usize,
} }
pub struct NoopStackmapSink {}
impl StackmapSink for NoopStackmapSink {
fn add_stackmap(&mut self, _: u32, _: Stackmap) {}
}
impl FuncResolverBuilder { impl FuncResolverBuilder {
pub fn new_from_backend_cache( pub fn new_from_backend_cache(
backend_cache: BackendCache, backend_cache: BackendCache,
@ -109,12 +116,13 @@ impl FuncResolverBuilder {
ctx.func = func.to_owned(); ctx.func = func.to_owned();
let mut reloc_sink = RelocSink::new(); let mut reloc_sink = RelocSink::new();
let mut local_trap_sink = LocalTrapSink::new(); let mut local_trap_sink = LocalTrapSink::new();
let mut stackmap_sink = NoopStackmapSink {};
ctx.compile_and_emit( ctx.compile_and_emit(
isa, isa,
&mut code_buf, &mut code_buf,
&mut reloc_sink, &mut reloc_sink,
&mut local_trap_sink, &mut local_trap_sink,
&mut stackmap_sink,
) )
.map_err(|e| CompileError::InternalError { msg: e.to_string() })?; .map_err(|e| CompileError::InternalError { msg: e.to_string() })?;
ctx.clear(); ctx.clear();
@ -241,25 +249,17 @@ impl FuncResolverBuilder {
#[cfg(not(target_os = "windows"))] #[cfg(not(target_os = "windows"))]
LibCall::Probestack => __rust_probestack as isize, LibCall::Probestack => __rust_probestack as isize,
}, },
RelocationType::Intrinsic(ref name) => match name.as_str() { RelocationType::Intrinsic(ref name) => Err(CompileError::InternalError {
"i32print" => i32_print as isize, msg: format!("unexpected intrinsic: {}", name),
"i64print" => i64_print as isize, })?,
"f32print" => f32_print as isize,
"f64print" => f64_print as isize,
"strtdbug" => start_debug as isize,
"enddbug" => end_debug as isize,
_ => Err(CompileError::InternalError {
msg: format!("unexpected intrinsic: {}", name),
})?,
},
RelocationType::VmCall(vmcall) => match vmcall { RelocationType::VmCall(vmcall) => match vmcall {
VmCall::Local(kind) => match kind { VmCall::Local(kind) => match kind {
VmCallKind::StaticMemoryGrow => vmcalls::local_static_memory_grow as _, VmCallKind::StaticMemoryGrow | VmCallKind::SharedStaticMemoryGrow => {
VmCallKind::StaticMemorySize => vmcalls::local_static_memory_size as _, vmcalls::local_static_memory_grow as _
}
VmCallKind::SharedStaticMemoryGrow => unimplemented!(), VmCallKind::StaticMemorySize | VmCallKind::SharedStaticMemorySize => {
VmCallKind::SharedStaticMemorySize => unimplemented!(), vmcalls::local_static_memory_size as _
}
VmCallKind::DynamicMemoryGrow => { VmCallKind::DynamicMemoryGrow => {
vmcalls::local_dynamic_memory_grow as _ vmcalls::local_dynamic_memory_grow as _
} }
@ -268,16 +268,12 @@ impl FuncResolverBuilder {
} }
}, },
VmCall::Import(kind) => match kind { VmCall::Import(kind) => match kind {
VmCallKind::StaticMemoryGrow => { VmCallKind::StaticMemoryGrow | VmCallKind::SharedStaticMemoryGrow => {
vmcalls::imported_static_memory_grow as _ vmcalls::imported_static_memory_grow as _
} }
VmCallKind::StaticMemorySize => { VmCallKind::StaticMemorySize | VmCallKind::SharedStaticMemorySize => {
vmcalls::imported_static_memory_size as _ vmcalls::imported_static_memory_size as _
} }
VmCallKind::SharedStaticMemoryGrow => unimplemented!(),
VmCallKind::SharedStaticMemorySize => unimplemented!(),
VmCallKind::DynamicMemoryGrow => { VmCallKind::DynamicMemoryGrow => {
vmcalls::imported_dynamic_memory_grow as _ vmcalls::imported_dynamic_memory_grow as _
} }
@ -366,28 +362,3 @@ impl FuncResolver {
fn round_up(n: usize, multiple: usize) -> usize { fn round_up(n: usize, multiple: usize) -> usize {
(n + multiple - 1) & !(multiple - 1) (n + multiple - 1) & !(multiple - 1)
} }
extern "C" fn i32_print(_ctx: &mut vm::Ctx, n: i32) {
eprint!(" i32: {},", n);
}
extern "C" fn i64_print(_ctx: &mut vm::Ctx, n: i64) {
eprint!(" i64: {},", n);
}
extern "C" fn f32_print(_ctx: &mut vm::Ctx, n: f32) {
eprint!(" f32: {},", n);
}
extern "C" fn f64_print(_ctx: &mut vm::Ctx, n: f64) {
eprint!(" f64: {},", n);
}
extern "C" fn start_debug(ctx: &mut vm::Ctx, func_index: u32) {
if let Some(symbol_map) = unsafe { ctx.borrow_symbol_map() } {
if let Some(fn_name) = symbol_map.get(&func_index) {
eprint!("func ({} ({})), args: [", fn_name, func_index);
return;
}
}
eprint!("func ({}), args: [", func_index);
}
extern "C" fn end_debug(_ctx: &mut vm::Ctx) {
eprintln!(" ]");
}

View File

@ -1,12 +1,14 @@
use crate::relocation::{TrapData, TrapSink}; use crate::{
use crate::resolver::FuncResolver; relocation::{TrapData, TrapSink},
use crate::trampoline::Trampolines; resolver::FuncResolver,
trampoline::Trampolines,
};
use libc::c_void; use libc::c_void;
use std::{any::Any, cell::Cell, ptr::NonNull, sync::Arc}; use std::{any::Any, cell::Cell, ptr::NonNull, sync::Arc};
use wasmer_runtime_core::{ use wasmer_runtime_core::{
backend::RunnableModule, backend::RunnableModule,
module::ModuleInfo, module::ModuleInfo,
typed_func::{Wasm, WasmTrapInfo}, typed_func::{Trampoline, Wasm, WasmTrapInfo},
types::{LocalFuncIndex, SigIndex}, types::{LocalFuncIndex, SigIndex},
vm, vm,
}; };
@ -59,7 +61,7 @@ impl RunnableModule for Caller {
fn get_trampoline(&self, _: &ModuleInfo, sig_index: SigIndex) -> Option<Wasm> { fn get_trampoline(&self, _: &ModuleInfo, sig_index: SigIndex) -> Option<Wasm> {
unsafe extern "C" fn invoke( unsafe extern "C" fn invoke(
trampoline: unsafe extern "C" fn(*mut vm::Ctx, NonNull<vm::Func>, *const u64, *mut u64), trampoline: Trampoline,
ctx: *mut vm::Ctx, ctx: *mut vm::Ctx,
func: NonNull<vm::Func>, func: NonNull<vm::Func>,
args: *const u64, args: *const u64,

View File

@ -98,7 +98,10 @@ pub fn call_protected<T>(
}, },
Ok(SIGSEGV) | Ok(SIGBUS) => WasmTrapInfo::MemoryOutOfBounds, Ok(SIGSEGV) | Ok(SIGBUS) => WasmTrapInfo::MemoryOutOfBounds,
Ok(SIGFPE) => WasmTrapInfo::IllegalArithmetic, Ok(SIGFPE) => WasmTrapInfo::IllegalArithmetic,
_ => unimplemented!(), _ => unimplemented!(
"WasmTrapInfo::Unknown signal:{:?}",
Signal::from_c_int(signum)
),
})) }))
} else { } else {
let signal = match Signal::from_c_int(signum) { let signal = match Signal::from_c_int(signum) {

View File

@ -1,24 +1,30 @@
use crate::relocation::{TrapCode, TrapData}; use crate::{
use crate::signal::{CallProtError, HandlerData}; relocation::{TrapCode, TrapData},
use crate::trampoline::Trampoline; signal::{CallProtError, HandlerData},
use std::cell::Cell; };
use std::ffi::c_void; use std::{
use std::ptr::{self, NonNull}; cell::Cell,
use wasmer_runtime_core::typed_func::WasmTrapInfo; ffi::c_void,
use wasmer_runtime_core::vm::Ctx; ptr::{self, NonNull},
use wasmer_runtime_core::vm::Func; };
use wasmer_runtime_core::{
typed_func::{Trampoline, WasmTrapInfo},
vm::{Ctx, Func},
};
use wasmer_win_exception_handler::CallProtectedData; use wasmer_win_exception_handler::CallProtectedData;
pub use wasmer_win_exception_handler::_call_protected; pub use wasmer_win_exception_handler::_call_protected;
use winapi::shared::minwindef::DWORD; use winapi::{
use winapi::um::minwinbase::{ shared::minwindef::DWORD,
EXCEPTION_ACCESS_VIOLATION, EXCEPTION_ARRAY_BOUNDS_EXCEEDED, EXCEPTION_BREAKPOINT, um::minwinbase::{
EXCEPTION_DATATYPE_MISALIGNMENT, EXCEPTION_FLT_DENORMAL_OPERAND, EXCEPTION_FLT_DIVIDE_BY_ZERO, EXCEPTION_ACCESS_VIOLATION, EXCEPTION_ARRAY_BOUNDS_EXCEEDED, EXCEPTION_BREAKPOINT,
EXCEPTION_FLT_INEXACT_RESULT, EXCEPTION_FLT_INVALID_OPERATION, EXCEPTION_FLT_OVERFLOW, EXCEPTION_DATATYPE_MISALIGNMENT, EXCEPTION_FLT_DENORMAL_OPERAND,
EXCEPTION_FLT_STACK_CHECK, EXCEPTION_FLT_UNDERFLOW, EXCEPTION_GUARD_PAGE, EXCEPTION_FLT_DIVIDE_BY_ZERO, EXCEPTION_FLT_INEXACT_RESULT,
EXCEPTION_ILLEGAL_INSTRUCTION, EXCEPTION_INT_DIVIDE_BY_ZERO, EXCEPTION_INT_OVERFLOW, EXCEPTION_FLT_INVALID_OPERATION, EXCEPTION_FLT_OVERFLOW, EXCEPTION_FLT_STACK_CHECK,
EXCEPTION_INVALID_HANDLE, EXCEPTION_IN_PAGE_ERROR, EXCEPTION_NONCONTINUABLE_EXCEPTION, EXCEPTION_FLT_UNDERFLOW, EXCEPTION_GUARD_PAGE, EXCEPTION_ILLEGAL_INSTRUCTION,
EXCEPTION_POSSIBLE_DEADLOCK, EXCEPTION_PRIV_INSTRUCTION, EXCEPTION_SINGLE_STEP, EXCEPTION_INT_DIVIDE_BY_ZERO, EXCEPTION_INT_OVERFLOW, EXCEPTION_INVALID_HANDLE,
EXCEPTION_STACK_OVERFLOW, EXCEPTION_IN_PAGE_ERROR, EXCEPTION_NONCONTINUABLE_EXCEPTION, EXCEPTION_POSSIBLE_DEADLOCK,
EXCEPTION_PRIV_INSTRUCTION, EXCEPTION_SINGLE_STEP, EXCEPTION_STACK_OVERFLOW,
},
}; };
thread_local! { thread_local! {
@ -110,5 +116,5 @@ pub fn call_protected(
pub unsafe fn trigger_trap() -> ! { pub unsafe fn trigger_trap() -> ! {
// TODO // TODO
unimplemented!(); unimplemented!("windows::trigger_trap");
} }

View File

@ -1,17 +1,16 @@
use crate::cache::TrampolineCache; use crate::{cache::TrampolineCache, resolver::NoopStackmapSink};
use cranelift_codegen::{ use cranelift_codegen::{
binemit::{NullTrapSink, Reloc, RelocSink}, binemit::{NullTrapSink, Reloc, RelocSink},
cursor::{Cursor, FuncCursor}, cursor::{Cursor, FuncCursor},
ir::{self, InstBuilder}, ir::{self, InstBuilder},
isa, Context, isa, Context,
}; };
use std::collections::HashMap; use std::{collections::HashMap, iter, mem};
use std::{iter, mem, ptr::NonNull};
use wasmer_runtime_core::{ use wasmer_runtime_core::{
backend::sys::{Memory, Protect}, backend::sys::{Memory, Protect},
module::{ExportIndex, ModuleInfo}, module::{ExportIndex, ModuleInfo},
typed_func::Trampoline,
types::{FuncSig, SigIndex, Type}, types::{FuncSig, SigIndex, Type},
vm,
}; };
struct NullRelocSink {} struct NullRelocSink {}
@ -19,11 +18,14 @@ struct NullRelocSink {}
impl RelocSink for NullRelocSink { impl RelocSink for NullRelocSink {
fn reloc_ebb(&mut self, _: u32, _: Reloc, _: u32) {} fn reloc_ebb(&mut self, _: u32, _: Reloc, _: u32) {}
fn reloc_external(&mut self, _: u32, _: Reloc, _: &ir::ExternalName, _: i64) {} fn reloc_external(&mut self, _: u32, _: Reloc, _: &ir::ExternalName, _: i64) {}
fn reloc_constant(&mut self, _: u32, _: Reloc, _: u32) {
unimplemented!("RelocSink::reloc_constant")
}
fn reloc_jt(&mut self, _: u32, _: Reloc, _: ir::JumpTable) {} fn reloc_jt(&mut self, _: u32, _: Reloc, _: ir::JumpTable) {}
} }
pub type Trampoline = unsafe extern "C" fn(*mut vm::Ctx, NonNull<vm::Func>, *const u64, *mut u64);
pub struct Trampolines { pub struct Trampolines {
memory: Memory, memory: Memory,
offsets: HashMap<SigIndex, usize>, offsets: HashMap<SigIndex, usize>,
@ -89,12 +91,13 @@ impl Trampolines {
ctx.func = trampoline_func; ctx.func = trampoline_func;
let mut code_buf = Vec::new(); let mut code_buf = Vec::new();
let mut stackmap_sink = NoopStackmapSink {};
ctx.compile_and_emit( ctx.compile_and_emit(
isa, isa,
&mut code_buf, &mut code_buf,
&mut NullRelocSink {}, &mut NullRelocSink {},
&mut NullTrapSink {}, &mut NullTrapSink {},
&mut stackmap_sink,
) )
.expect("unable to compile trampolines"); .expect("unable to compile trampolines");
ctx.clear(); ctx.clear();

View File

@ -1,11 +1,12 @@
[package] [package]
name = "wasmer-dev-utils" name = "wasmer-dev-utils"
version = "0.6.0" version = "0.11.0"
description = "Wasmer runtime core library" description = "Wasmer runtime core library"
license = "MIT" license = "MIT"
authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"] 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 = false
[dependencies] [dependencies]
libc = "0.2.60" libc = "0.2.60"

View File

@ -1,2 +1,5 @@
#![doc(html_favicon_url = "https://wasmer.io/static/icons/favicon.ico")]
#![doc(html_logo_url = "https://avatars3.githubusercontent.com/u/44205449?s=200&v=4")]
pub mod file_descriptor; pub mod file_descriptor;
pub mod stdio; pub mod stdio;

View File

@ -1,6 +1,6 @@
[package] [package]
name = "wasmer-emscripten-tests" name = "wasmer-emscripten-tests"
version = "0.6.0" version = "0.11.0"
description = "Tests for our Emscripten implementation" description = "Tests for our Emscripten implementation"
license = "MIT" license = "MIT"
authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"] authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"]
@ -9,20 +9,20 @@ publish = false
build = "build/mod.rs" build = "build/mod.rs"
[dependencies] [dependencies]
wasmer-emscripten = { path = "../emscripten", version = "0.6.0" } wasmer-emscripten = { path = "../emscripten", version = "0.11.0" }
wasmer-runtime-core = { path = "../runtime-core", version = "0.6.0" } wasmer-runtime = { path = "../runtime", version = "0.11.0", default-features = false }
wasmer-clif-backend = { path = "../clif-backend", version = "0.6.0" } wasmer-clif-backend = { path = "../clif-backend", version = "0.11.0", optional = true}
wasmer-llvm-backend = { path = "../llvm-backend", version = "0.6.0", optional = true } wasmer-llvm-backend = { path = "../llvm-backend", version = "0.11.0", optional = true, features = ["test"] }
wasmer-singlepass-backend = { path = "../singlepass-backend", version = "0.6.0", optional = true } wasmer-singlepass-backend = { path = "../singlepass-backend", version = "0.11.0", optional = true }
[dev-dependencies] [dev-dependencies]
wabt = "0.9.1" wabt = "0.9.1"
wasmer-dev-utils = { path = "../dev-utils", version = "0.6.0"} wasmer-dev-utils = { path = "../dev-utils", version = "0.11.0"}
[build-dependencies] [build-dependencies]
glob = "0.3.0" glob = "0.3"
[features] [features]
clif = [] clif = ["wasmer-clif-backend", "wasmer-runtime/default-backend-cranelift"]
llvm = ["wasmer-llvm-backend"] singlepass = ["wasmer-singlepass-backend", "wasmer-runtime/default-backend-singlepass"]
singlepass = ["wasmer-singlepass-backend"] llvm = ["wasmer-llvm-backend", "wasmer-runtime/default-backend-llvm"]

View File

@ -29,6 +29,7 @@ test_i16_emcc_intrinsic
test_i64 test_i64
test_i64_7z test_i64_7z
test_i64_varargs test_i64_varargs
test_indirectbr_many
test_llvm_intrinsics test_llvm_intrinsics
test_longjmp_exc test_longjmp_exc
test_lower_intrinsics test_lower_intrinsics

View File

@ -3,40 +3,13 @@ mod tests {
use std::sync::Arc; use std::sync::Arc;
use wabt::wat2wasm; use wabt::wat2wasm;
use wasmer_emscripten::is_emscripten_module; use wasmer_emscripten::is_emscripten_module;
use wasmer_runtime_core::backend::Compiler; use wasmer_runtime::compile;
use wasmer_runtime_core::compile_with;
#[cfg(feature = "clif")]
fn get_compiler() -> impl Compiler {
use wasmer_clif_backend::CraneliftCompiler;
CraneliftCompiler::new()
}
#[cfg(feature = "llvm")]
fn get_compiler() -> impl Compiler {
use wasmer_llvm_backend::LLVMCompiler;
LLVMCompiler::new()
}
#[cfg(feature = "singlepass")]
fn get_compiler() -> impl Compiler {
use wasmer_singlepass_backend::SinglePassCompiler;
SinglePassCompiler::new()
}
#[cfg(not(any(feature = "llvm", feature = "clif", feature = "singlepass")))]
fn get_compiler() -> impl Compiler {
panic!("compiler not specified, activate a compiler via features");
use wasmer_clif_backend::CraneliftCompiler;
CraneliftCompiler::new()
}
#[test] #[test]
fn should_detect_emscripten_files() { fn should_detect_emscripten_files() {
const WAST_BYTES: &[u8] = include_bytes!("tests/is_emscripten_true.wast"); const WAST_BYTES: &[u8] = include_bytes!("tests/is_emscripten_true.wast");
let wasm_binary = wat2wasm(WAST_BYTES.to_vec()).expect("Can't convert to wasm"); let wasm_binary = wat2wasm(WAST_BYTES.to_vec()).expect("Can't convert to wasm");
let module = let module = compile(&wasm_binary[..]).expect("WASM can't be compiled");
compile_with(&wasm_binary[..], &get_compiler()).expect("WASM can't be compiled");
let module = Arc::new(module); let module = Arc::new(module);
assert!(is_emscripten_module(&module)); assert!(is_emscripten_module(&module));
} }
@ -45,8 +18,7 @@ mod tests {
fn should_detect_non_emscripten_files() { fn should_detect_non_emscripten_files() {
const WAST_BYTES: &[u8] = include_bytes!("tests/is_emscripten_false.wast"); const WAST_BYTES: &[u8] = include_bytes!("tests/is_emscripten_false.wast");
let wasm_binary = wat2wasm(WAST_BYTES.to_vec()).expect("Can't convert to wasm"); let wasm_binary = wat2wasm(WAST_BYTES.to_vec()).expect("Can't convert to wasm");
let module = let module = compile(&wasm_binary[..]).expect("WASM can't be compiled");
compile_with(&wasm_binary[..], &get_compiler()).expect("WASM can't be compiled");
let module = Arc::new(module); let module = Arc::new(module);
assert!(!is_emscripten_module(&module)); assert!(!is_emscripten_module(&module));
} }

View File

@ -5,39 +5,12 @@ macro_rules! assert_emscripten_output {
EmscriptenGlobals, EmscriptenGlobals,
generate_emscripten_env, generate_emscripten_env,
}; };
use wasmer_runtime_core::{ use wasmer_runtime::compile;
backend::Compiler,
};
use wasmer_dev_utils::stdio::StdioCapturer; use wasmer_dev_utils::stdio::StdioCapturer;
#[cfg(feature = "clif")]
fn get_compiler() -> impl Compiler {
use wasmer_clif_backend::CraneliftCompiler;
CraneliftCompiler::new()
}
#[cfg(feature = "llvm")]
fn get_compiler() -> impl Compiler {
use wasmer_llvm_backend::LLVMCompiler;
LLVMCompiler::new()
}
#[cfg(feature = "singlepass")]
fn get_compiler() -> impl Compiler {
use wasmer_singlepass_backend::SinglePassCompiler;
SinglePassCompiler::new()
}
#[cfg(not(any(feature = "llvm", feature = "clif", feature = "singlepass")))]
fn get_compiler() -> impl Compiler {
panic!("compiler not specified, activate a compiler via features");
use wasmer_clif_backend::CraneliftCompiler;
CraneliftCompiler::new()
}
let wasm_bytes = include_bytes!($file); let wasm_bytes = include_bytes!($file);
let module = wasmer_runtime_core::compile_with(&wasm_bytes[..], &get_compiler()) let module = compile(&wasm_bytes[..])
.expect("WASM can't be compiled"); .expect("WASM can't be compiled");
// let module = compile(&wasm_bytes[..]) // let module = compile(&wasm_bytes[..])

View File

@ -1,4 +1,5 @@
#[test] #[test]
#[ignore]
fn test_test_indirectbr_many() { fn test_test_indirectbr_many() {
assert_emscripten_output!( assert_emscripten_output!(
"../../emtests/test_indirectbr_many.wasm", "../../emtests/test_indirectbr_many.wasm",

View File

@ -1,21 +1,23 @@
[package] [package]
name = "wasmer-emscripten" name = "wasmer-emscripten"
version = "0.6.0" version = "0.11.0"
description = "Wasmer runtime emscripten implementation library" description = "Wasmer runtime emscripten implementation library"
license = "MIT" license = "MIT"
authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"] authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"]
repository = "https://github.com/wasmerio/wasmer" repository = "https://github.com/wasmerio/wasmer"
keywords = ["wasm", "webassembly", "ABI", "emscripten", "posix"]
categories = ["wasm"]
edition = "2018" edition = "2018"
[dependencies] [dependencies]
byteorder = "1.3.2" byteorder = "1.3"
lazy_static = "1.3.0" lazy_static = "1.4"
libc = "0.2.60" libc = "0.2.60"
time = "0.1.42" time = "0.1"
wasmer-runtime-core = { path = "../runtime-core", version = "0.6.0" } wasmer-runtime-core = { path = "../runtime-core", version = "0.11.0" }
[target.'cfg(windows)'.dependencies] [target.'cfg(windows)'.dependencies]
rand = "0.7.0" getrandom = "0.1"
[features] [features]
debug = ["wasmer-runtime-core/debug"] debug = ["wasmer-runtime-core/debug"]

View File

@ -12,14 +12,14 @@ pub use self::windows::*;
use libc::c_char; use libc::c_char;
use crate::{allocate_on_stack, EmscriptenData}; use crate::{
allocate_on_stack,
ptr::{Array, WasmPtr},
EmscriptenData,
};
use std::os::raw::c_int; use std::os::raw::c_int;
use wasmer_runtime_core::{ use wasmer_runtime_core::{types::ValueType, vm::Ctx};
memory::ptr::{Array, WasmPtr},
types::ValueType,
vm::Ctx,
};
pub fn call_malloc(ctx: &mut Ctx, size: u32) -> u32 { pub fn call_malloc(ctx: &mut Ctx, size: u32) -> u32 {
get_emscripten_data(ctx) get_emscripten_data(ctx)

View File

@ -9,11 +9,9 @@ use std::mem;
use std::os::raw::c_char; use std::os::raw::c_char;
use crate::env::{call_malloc, call_malloc_with_cast, EmAddrInfo, EmSockAddr}; use crate::env::{call_malloc, call_malloc_with_cast, EmAddrInfo, EmSockAddr};
use crate::ptr::{Array, WasmPtr};
use crate::utils::{copy_cstr_into_wasm, copy_terminated_array_of_cstrs}; use crate::utils::{copy_cstr_into_wasm, copy_terminated_array_of_cstrs};
use wasmer_runtime_core::{ use wasmer_runtime_core::vm::Ctx;
memory::ptr::{Array, WasmPtr},
vm::Ctx,
};
// #[no_mangle] // #[no_mangle]
/// emscripten: _getenv // (name: *const char) -> *const c_char; /// emscripten: _getenv // (name: *const char) -> *const c_char;

View File

@ -6,8 +6,9 @@ use std::mem;
use std::os::raw::c_char; use std::os::raw::c_char;
use crate::env::{call_malloc, EmAddrInfo}; use crate::env::{call_malloc, EmAddrInfo};
use crate::ptr::WasmPtr;
use crate::utils::{copy_cstr_into_wasm, read_string_from_wasm}; use crate::utils::{copy_cstr_into_wasm, read_string_from_wasm};
use wasmer_runtime_core::{memory::ptr::WasmPtr, vm::Ctx}; use wasmer_runtime_core::vm::Ctx;
extern "C" { extern "C" {
#[link_name = "_putenv"] #[link_name = "_putenv"]

View File

@ -10,22 +10,22 @@ pub fn ___cxa_allocate_exception(ctx: &mut Ctx, size: u32) -> u32 {
pub fn ___cxa_current_primary_exception(_ctx: &mut Ctx) -> u32 { pub fn ___cxa_current_primary_exception(_ctx: &mut Ctx) -> u32 {
debug!("emscripten::___cxa_current_primary_exception"); debug!("emscripten::___cxa_current_primary_exception");
unimplemented!() unimplemented!("emscripten::___cxa_current_primary_exception")
} }
pub fn ___cxa_decrement_exception_refcount(_ctx: &mut Ctx, _a: u32) { pub fn ___cxa_decrement_exception_refcount(_ctx: &mut Ctx, _a: u32) {
debug!("emscripten::___cxa_decrement_exception_refcount({})", _a); debug!("emscripten::___cxa_decrement_exception_refcount({})", _a);
unimplemented!() unimplemented!("emscripten::___cxa_decrement_exception_refcount({})", _a)
} }
pub fn ___cxa_increment_exception_refcount(_ctx: &mut Ctx, _a: u32) { pub fn ___cxa_increment_exception_refcount(_ctx: &mut Ctx, _a: u32) {
debug!("emscripten::___cxa_increment_exception_refcount({})", _a); debug!("emscripten::___cxa_increment_exception_refcount({})", _a);
unimplemented!() unimplemented!("emscripten::___cxa_increment_exception_refcount({})", _a)
} }
pub fn ___cxa_rethrow_primary_exception(_ctx: &mut Ctx, _a: u32) { pub fn ___cxa_rethrow_primary_exception(_ctx: &mut Ctx, _a: u32) {
debug!("emscripten::___cxa_rethrow_primary_exception({})", _a); debug!("emscripten::___cxa_rethrow_primary_exception({})", _a);
unimplemented!() unimplemented!("emscripten::___cxa_rethrow_primary_exception({})", _a)
} }
/// emscripten: ___cxa_throw /// emscripten: ___cxa_throw

View File

@ -15,13 +15,13 @@ use wasmer_runtime_core::vm::Ctx;
/// getprotobyname /// getprotobyname
pub fn getprotobyname(_ctx: &mut Ctx, _name_ptr: i32) -> i32 { pub fn getprotobyname(_ctx: &mut Ctx, _name_ptr: i32) -> i32 {
debug!("emscripten::getprotobyname"); debug!("emscripten::getprotobyname");
unimplemented!() unimplemented!("emscripten::getprotobyname")
} }
/// getprotobynumber /// getprotobynumber
pub fn getprotobynumber(_ctx: &mut Ctx, _one: i32) -> i32 { pub fn getprotobynumber(_ctx: &mut Ctx, _one: i32) -> i32 {
debug!("emscripten::getprotobynumber"); debug!("emscripten::getprotobynumber");
unimplemented!() unimplemented!("emscripten::getprotobynumber")
} }
/// sigdelset /// sigdelset
@ -53,11 +53,11 @@ pub fn sigfillset(ctx: &mut Ctx, set: i32) -> i32 {
/// tzset /// tzset
pub fn tzset(_ctx: &mut Ctx) { pub fn tzset(_ctx: &mut Ctx) {
debug!("emscripten::tzset - stub"); debug!("emscripten::tzset - stub");
//unimplemented!() //unimplemented!("emscripten::tzset - stub")
} }
/// strptime /// strptime
pub fn strptime(_ctx: &mut Ctx, _one: i32, _two: i32, _three: i32) -> i32 { pub fn strptime(_ctx: &mut Ctx, _one: i32, _two: i32, _three: i32) -> i32 {
debug!("emscripten::strptime"); debug!("emscripten::strptime");
unimplemented!() unimplemented!("emscripten::strptime")
} }

View File

@ -36,11 +36,11 @@ pub fn printf(_ctx: &mut Ctx, memory_offset: i32, extra: i32) -> i32 {
/// chroot /// chroot
pub fn chroot(_ctx: &mut Ctx, _name_ptr: i32) -> i32 { pub fn chroot(_ctx: &mut Ctx, _name_ptr: i32) -> i32 {
debug!("emscripten::chroot"); debug!("emscripten::chroot");
unimplemented!() unimplemented!("emscripten::chroot")
} }
/// getpwuid /// getpwuid
pub fn getpwuid(_ctx: &mut Ctx, _uid: i32) -> i32 { pub fn getpwuid(_ctx: &mut Ctx, _uid: i32) -> i32 {
debug!("emscripten::getpwuid"); debug!("emscripten::getpwuid");
unimplemented!() unimplemented!("emscripten::getpwuid")
} }

View File

@ -7,6 +7,9 @@
unused_unsafe, unused_unsafe,
unreachable_patterns unreachable_patterns
)] )]
#![doc(html_favicon_url = "https://wasmer.io/static/icons/favicon.ico")]
#![doc(html_logo_url = "https://avatars3.githubusercontent.com/u/44205449?s=200&v=4")]
#[macro_use] #[macro_use]
extern crate wasmer_runtime_core; extern crate wasmer_runtime_core;
@ -59,6 +62,7 @@ mod math;
mod memory; mod memory;
mod process; mod process;
mod pthread; mod pthread;
mod ptr;
mod signal; mod signal;
mod storage; mod storage;
mod syscalls; mod syscalls;
@ -107,7 +111,7 @@ pub struct EmscriptenData<'a> {
pub dyn_call_iii: Option<Func<'a, (i32, i32, i32), i32>>, pub dyn_call_iii: Option<Func<'a, (i32, i32, i32), i32>>,
pub dyn_call_iiii: Option<Func<'a, (i32, i32, i32, i32), i32>>, pub dyn_call_iiii: Option<Func<'a, (i32, i32, i32, i32), i32>>,
pub dyn_call_iifi: Option<Func<'a, (i32, i32, f64, i32), i32>>, pub dyn_call_iifi: Option<Func<'a, (i32, i32, f64, i32), i32>>,
pub dyn_call_v: Option<Func<'a, (i32)>>, pub dyn_call_v: Option<Func<'a, i32>>,
pub dyn_call_vi: Option<Func<'a, (i32, i32)>>, pub dyn_call_vi: Option<Func<'a, (i32, i32)>>,
pub dyn_call_vii: Option<Func<'a, (i32, i32, i32)>>, pub dyn_call_vii: Option<Func<'a, (i32, i32, i32)>>,
pub dyn_call_viii: Option<Func<'a, (i32, i32, i32, i32)>>, pub dyn_call_viii: Option<Func<'a, (i32, i32, i32, i32)>>,
@ -164,7 +168,7 @@ pub struct EmscriptenData<'a> {
pub temp_ret_0: i32, pub temp_ret_0: i32,
pub stack_save: Option<Func<'a, (), i32>>, pub stack_save: Option<Func<'a, (), i32>>,
pub stack_restore: Option<Func<'a, (i32)>>, pub stack_restore: Option<Func<'a, i32>>,
pub set_threw: Option<Func<'a, (i32, i32)>>, pub set_threw: Option<Func<'a, (i32, i32)>>,
pub mapped_dirs: HashMap<String, PathBuf>, pub mapped_dirs: HashMap<String, PathBuf>,
} }
@ -470,11 +474,7 @@ impl EmscriptenGlobals {
let (memory_min, memory_max, shared) = get_emscripten_memory_size(&module)?; let (memory_min, memory_max, shared) = get_emscripten_memory_size(&module)?;
// Memory initialization // Memory initialization
let memory_type = MemoryDescriptor { let memory_type = MemoryDescriptor::new(memory_min, memory_max, shared)?;
minimum: memory_min,
maximum: memory_max,
shared: shared,
};
let memory = Memory::new(memory_type).unwrap(); let memory = Memory::new(memory_type).unwrap();
let table_type = TableDescriptor { let table_type = TableDescriptor {
@ -731,8 +731,9 @@ pub fn generate_emscripten_env(globals: &mut EmscriptenGlobals) -> ImportObject
"___syscall345" => func!(crate::syscalls::___syscall345), "___syscall345" => func!(crate::syscalls::___syscall345),
// Process // Process
"abort" => func!(crate::process::em_abort), "abort" => func!(crate::process::_abort),
"_abort" => func!(crate::process::_abort), "_abort" => func!(crate::process::_abort),
"_prctl" => func!(crate::process::_prctl),
"abortStackOverflow" => func!(crate::process::abort_stack_overflow), "abortStackOverflow" => func!(crate::process::abort_stack_overflow),
"_llvm_trap" => func!(crate::process::_llvm_trap), "_llvm_trap" => func!(crate::process::_llvm_trap),
"_fork" => func!(crate::process::_fork), "_fork" => func!(crate::process::_fork),
@ -825,6 +826,9 @@ pub fn generate_emscripten_env(globals: &mut EmscriptenGlobals) -> ImportObject
"_gmtime" => func!(crate::time::_gmtime), "_gmtime" => func!(crate::time::_gmtime),
// Math // Math
"sqrt" => func!(crate::math::sqrt),
"floor" => func!(crate::math::floor),
"fabs" => func!(crate::math::fabs),
"f64-rem" => func!(crate::math::f64_rem), "f64-rem" => func!(crate::math::f64_rem),
"_llvm_copysign_f32" => func!(crate::math::_llvm_copysign_f32), "_llvm_copysign_f32" => func!(crate::math::_llvm_copysign_f32),
"_llvm_copysign_f64" => func!(crate::math::_llvm_copysign_f64), "_llvm_copysign_f64" => func!(crate::math::_llvm_copysign_f64),

View File

@ -88,6 +88,21 @@ pub fn log(_ctx: &mut Ctx, value: f64) -> f64 {
value.ln() value.ln()
} }
// emscripten: global.Math sqrt
pub fn sqrt(_ctx: &mut Ctx, value: f64) -> f64 {
value.sqrt()
}
// emscripten: global.Math floor
pub fn floor(_ctx: &mut Ctx, value: f64) -> f64 {
value.floor()
}
// emscripten: global.Math fabs
pub fn fabs(_ctx: &mut Ctx, value: f64) -> f64 {
value.abs()
}
// emscripten: asm2wasm.f64-to-int // emscripten: asm2wasm.f64-to-int
pub fn f64_to_int(_ctx: &mut Ctx, value: f64) -> i32 { pub fn f64_to_int(_ctx: &mut Ctx, value: f64) -> i32 {
debug!("emscripten::f64_to_int {}", value); debug!("emscripten::f64_to_int {}", value);

View File

@ -1,11 +1,10 @@
use libc::{abort, c_char, c_int, exit, EAGAIN}; use libc::{abort, c_int, exit, EAGAIN};
#[cfg(not(target_os = "windows"))] #[cfg(not(target_os = "windows"))]
type PidT = libc::pid_t; type PidT = libc::pid_t;
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
type PidT = c_int; type PidT = c_int;
use std::ffi::CStr;
use wasmer_runtime_core::vm::Ctx; use wasmer_runtime_core::vm::Ctx;
pub fn abort_with_message(ctx: &mut Ctx, message: &str) { pub fn abort_with_message(ctx: &mut Ctx, message: &str) {
@ -21,6 +20,12 @@ pub fn _abort(_ctx: &mut Ctx) {
} }
} }
pub fn _prctl(ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
debug!("emscripten::_prctl");
abort_with_message(ctx, "missing function: prctl");
-1
}
pub fn _fork(_ctx: &mut Ctx) -> PidT { pub fn _fork(_ctx: &mut Ctx) -> PidT {
debug!("emscripten::_fork"); debug!("emscripten::_fork");
// unsafe { // unsafe {
@ -45,18 +50,6 @@ pub fn _exit(_ctx: &mut Ctx, status: c_int) {
unsafe { exit(status) } unsafe { exit(status) }
} }
pub fn em_abort(ctx: &mut Ctx, message: u32) {
debug!("emscripten::em_abort {}", message);
let message_addr = emscripten_memory_pointer!(ctx.memory(0), message) as *mut c_char;
unsafe {
let message = CStr::from_ptr(message_addr)
.to_str()
.unwrap_or("Unexpected abort");
abort_with_message(ctx, message);
}
}
pub fn _kill(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { pub fn _kill(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
debug!("emscripten::_kill"); debug!("emscripten::_kill");
-1 -1

116
lib/emscripten/src/ptr.rs Normal file
View File

@ -0,0 +1,116 @@
//! This is a wrapper around the `WasmPtr` abstraction that does not allow deref of address 0
//! This is a common assumption in Emscripten code
// this is a wrapper with extra logic around the runtime-core `WasmPtr`, so we
// don't want to warn about unusued code here
#![allow(dead_code)]
use std::{cell::Cell, fmt};
pub use wasmer_runtime_core::memory::ptr::Array;
use wasmer_runtime_core::{
memory::{ptr, Memory},
types::{ValueType, WasmExternType},
};
#[repr(transparent)]
pub struct WasmPtr<T: Copy, Ty = ptr::Item>(ptr::WasmPtr<T, Ty>);
unsafe impl<T: Copy, Ty> ValueType for WasmPtr<T, Ty> {}
impl<T: Copy, Ty> Copy for WasmPtr<T, Ty> {}
impl<T: Copy, Ty> Clone for WasmPtr<T, Ty> {
fn clone(&self) -> Self {
Self(self.0.clone())
}
}
impl<T: Copy, Ty> fmt::Debug for WasmPtr<T, Ty> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?}", self.0)
}
}
unsafe impl<T: Copy, Ty> WasmExternType for WasmPtr<T, Ty> {
type Native = <ptr::WasmPtr<T, Ty> as WasmExternType>::Native;
fn to_native(self) -> Self::Native {
self.0.to_native()
}
fn from_native(n: Self::Native) -> Self {
Self(ptr::WasmPtr::from_native(n))
}
}
impl<T: Copy, Ty> PartialEq for WasmPtr<T, Ty> {
fn eq(&self, other: &Self) -> bool {
self.0 == other.0
}
}
impl<T: Copy, Ty> Eq for WasmPtr<T, Ty> {}
impl<T: Copy, Ty> WasmPtr<T, Ty> {
#[inline(always)]
pub fn new(offset: u32) -> Self {
Self(ptr::WasmPtr::new(offset))
}
#[inline(always)]
pub fn offset(self) -> u32 {
self.0.offset()
}
}
impl<T: Copy + ValueType> WasmPtr<T, ptr::Item> {
#[inline(always)]
pub fn deref<'a>(self, memory: &'a Memory) -> Option<&'a Cell<T>> {
if self.0.offset() == 0 {
None
} else {
self.0.deref(memory)
}
}
#[inline(always)]
pub unsafe fn deref_mut<'a>(self, memory: &'a Memory) -> Option<&'a mut Cell<T>> {
if self.0.offset() == 0 {
None
} else {
self.0.deref_mut(memory)
}
}
}
impl<T: Copy + ValueType> WasmPtr<T, ptr::Array> {
#[inline(always)]
pub fn deref<'a>(self, memory: &'a Memory, index: u32, length: u32) -> Option<&'a [Cell<T>]> {
if self.0.offset() == 0 {
None
} else {
self.0.deref(memory, index, length)
}
}
#[inline]
pub unsafe fn deref_mut<'a>(
self,
memory: &'a Memory,
index: u32,
length: u32,
) -> Option<&'a mut [Cell<T>]> {
if self.0.offset() == 0 {
None
} else {
self.0.deref_mut(memory, index, length)
}
}
#[inline(always)]
pub fn get_utf8_string<'a>(self, memory: &'a Memory, str_len: u32) -> Option<&'a str> {
if self.0.offset() == 0 {
None
} else {
self.0.get_utf8_string(memory, str_len)
}
}
}

View File

@ -10,7 +10,10 @@ pub use self::unix::*;
#[cfg(windows)] #[cfg(windows)]
pub use self::windows::*; pub use self::windows::*;
use crate::utils::{copy_stat_into_wasm, get_cstr_path, get_current_directory}; use crate::{
ptr::{Array, WasmPtr},
utils::{copy_stat_into_wasm, get_cstr_path, get_current_directory},
};
use super::varargs::VarArgs; use super::varargs::VarArgs;
use byteorder::{ByteOrder, LittleEndian}; use byteorder::{ByteOrder, LittleEndian};
@ -40,10 +43,7 @@ use libc::{
write, write,
// ENOTTY, // ENOTTY,
}; };
use wasmer_runtime_core::{ use wasmer_runtime_core::vm::Ctx;
memory::ptr::{Array, WasmPtr},
vm::Ctx,
};
use super::env; use super::env;
use std::cell::Cell; use std::cell::Cell;

View File

@ -1,4 +1,4 @@
use crate::varargs::VarArgs; use crate::{ptr::WasmPtr, varargs::VarArgs};
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
use libc::size_t; use libc::size_t;
/// NOTE: TODO: These syscalls only support wasm_32 for now because they assume offsets are u32 /// NOTE: TODO: These syscalls only support wasm_32 for now because they assume offsets are u32
@ -7,6 +7,7 @@ use libc::{
accept, accept,
access, access,
bind, bind,
c_char,
c_int, c_int,
c_ulong, c_ulong,
c_void, c_void,
@ -111,7 +112,7 @@ fn translate_ioctl(wasm_ioctl: u32) -> c_ulong {
#[allow(unused_imports)] #[allow(unused_imports)]
use std::ffi::CStr; use std::ffi::CStr;
use wasmer_runtime_core::{memory::ptr::WasmPtr, vm::Ctx}; use wasmer_runtime_core::vm::Ctx;
use crate::env::EmSockAddr; use crate::env::EmSockAddr;
use crate::utils::{self, get_cstr_path}; use crate::utils::{self, get_cstr_path};
@ -259,7 +260,7 @@ pub fn ___syscall194(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in
ftruncate64(_fd, _length) ftruncate64(_fd, _length)
} }
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
unimplemented!() unimplemented!("emscripten::___syscall194 (ftruncate64) {}", _which)
} }
/// lchown /// lchown
@ -1063,14 +1064,14 @@ pub fn ___syscall220(ctx: &mut Ctx, _which: i32, mut varargs: VarArgs) -> i32 {
let upper_bound = std::cmp::min((*dirent).d_reclen, 255) as usize; let upper_bound = std::cmp::min((*dirent).d_reclen, 255) as usize;
let mut i = 0; let mut i = 0;
while i < upper_bound { while i < upper_bound {
*(dirp.add(pos + 11 + i) as *mut i8) = (*dirent).d_name[i] as _; *(dirp.add(pos + 11 + i) as *mut c_char) = (*dirent).d_name[i] as c_char;
i += 1; i += 1;
} }
// We set the termination string char // We set the termination string char
*(dirp.add(pos + 11 + i) as *mut i8) = 0 as i8; *(dirp.add(pos + 11 + i) as *mut c_char) = 0 as c_char;
debug!( debug!(
" => file {}", " => file {}",
CStr::from_ptr(dirp.add(pos + 11) as *const i8) CStr::from_ptr(dirp.add(pos + 11) as *const c_char)
.to_str() .to_str()
.unwrap() .unwrap()
); );
@ -1111,6 +1112,6 @@ pub fn ___syscall324(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in
} }
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
{ {
unimplemented!() unimplemented!("emscripten::___syscall324 (fallocate) {}", _which)
} }
} }

View File

@ -2,7 +2,6 @@ use crate::utils::{copy_cstr_into_wasm, get_cstr_path};
use crate::varargs::VarArgs; use crate::varargs::VarArgs;
use libc::mkdir; use libc::mkdir;
use libc::open; use libc::open;
use rand::Rng;
use std::env; use std::env;
use std::ffi::CString; use std::ffi::CString;
use std::fs::File; use std::fs::File;
@ -39,7 +38,8 @@ pub fn ___syscall5(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
let ptr = tmp_dir_c_str.as_ptr() as *const i8; let ptr = tmp_dir_c_str.as_ptr() as *const i8;
let mut urandom_file = File::create(tmp_dir).unwrap(); let mut urandom_file = File::create(tmp_dir).unwrap();
// create some random bytes and put them into the file // create some random bytes and put them into the file
let random_bytes = rand::thread_rng().gen::<[u8; 32]>(); let mut random_bytes = [0u8; 32];
getrandom::getrandom(&mut random_bytes).unwrap();
let _ = urandom_file.write_all(&random_bytes).unwrap(); let _ = urandom_file.write_all(&random_bytes).unwrap();
// put the file path string into wasm memory // put the file path string into wasm memory
let urandom_file_offset = unsafe { copy_cstr_into_wasm(ctx, ptr) }; let urandom_file_offset = unsafe { copy_cstr_into_wasm(ctx, ptr) };
@ -66,13 +66,13 @@ pub fn ___syscall5(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
/// link /// link
pub fn ___syscall9(_ctx: &mut Ctx, _which: c_int, mut _varargs: VarArgs) -> c_int { pub fn ___syscall9(_ctx: &mut Ctx, _which: c_int, mut _varargs: VarArgs) -> c_int {
debug!("emscripten::___syscall9 (link) {}", _which); debug!("emscripten::___syscall9 (link) {}", _which);
unimplemented!() unimplemented!("emscripten::___syscall9 (link) {}", _which);
} }
/// ftruncate64 /// ftruncate64
pub fn ___syscall194(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { pub fn ___syscall194(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
debug!("emscripten::___syscall194 - stub"); debug!("emscripten::___syscall194 - stub");
unimplemented!() unimplemented!("emscripten::___syscall194 - stub")
} }
// chown // chown
@ -86,13 +86,13 @@ pub fn ___syscall212(_ctx: &mut Ctx, which: c_int, mut _varargs: VarArgs) -> c_i
/// access /// access
pub fn ___syscall33(_ctx: &mut Ctx, _which: c_int, mut _varargs: VarArgs) -> c_int { pub fn ___syscall33(_ctx: &mut Ctx, _which: c_int, mut _varargs: VarArgs) -> c_int {
debug!("emscripten::___syscall33 (access) {}", _which); debug!("emscripten::___syscall33 (access) {}", _which);
unimplemented!() unimplemented!("emscripten::___syscall33 (access) {}", _which);
} }
/// nice /// nice
pub fn ___syscall34(_ctx: &mut Ctx, _which: c_int, mut _varargs: VarArgs) -> c_int { pub fn ___syscall34(_ctx: &mut Ctx, _which: c_int, mut _varargs: VarArgs) -> c_int {
debug!("emscripten::___syscall34 (nice) {}", _which); debug!("emscripten::___syscall34 (nice) {}", _which);
unimplemented!() unimplemented!("emscripten::___syscall34 (nice) {}", _which);
} }
// mkdir // mkdir
@ -113,19 +113,19 @@ pub fn ___syscall39(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int
/// dup /// dup
pub fn ___syscall41(_ctx: &mut Ctx, _which: c_int, _varargs: VarArgs) -> c_int { pub fn ___syscall41(_ctx: &mut Ctx, _which: c_int, _varargs: VarArgs) -> c_int {
debug!("emscripten::___syscall41 (dup) {}", _which); debug!("emscripten::___syscall41 (dup) {}", _which);
unimplemented!() unimplemented!("emscripten::___syscall41 (dup) {}", _which);
} }
/// getrusage /// getrusage
pub fn ___syscall77(_ctx: &mut Ctx, _which: c_int, _varargs: VarArgs) -> c_int { pub fn ___syscall77(_ctx: &mut Ctx, _which: c_int, _varargs: VarArgs) -> c_int {
debug!("emscripten::___syscall77 (getrusage) {}", _which); debug!("emscripten::___syscall77 (getrusage) {}", _which);
unimplemented!() unimplemented!("emscripten::___syscall77 (getrusage) {}", _which);
} }
/// symlink /// symlink
pub fn ___syscall83(_ctx: &mut Ctx, _which: c_int, _varargs: VarArgs) -> c_int { pub fn ___syscall83(_ctx: &mut Ctx, _which: c_int, _varargs: VarArgs) -> c_int {
debug!("emscripten::___syscall83 (symlink) {}", _which); debug!("emscripten::___syscall83 (symlink) {}", _which);
unimplemented!() unimplemented!("emscripten::___syscall83 (symlink) {}", _which);
} }
/// readlink /// readlink
@ -143,38 +143,38 @@ pub fn ___syscall132(_ctx: &mut Ctx, _which: c_int, mut _varargs: VarArgs) -> c_
/// lchown /// lchown
pub fn ___syscall198(_ctx: &mut Ctx, _which: c_int, _varargs: VarArgs) -> c_int { pub fn ___syscall198(_ctx: &mut Ctx, _which: c_int, _varargs: VarArgs) -> c_int {
debug!("emscripten::___syscall198 (lchown) {}", _which); debug!("emscripten::___syscall198 (lchown) {}", _which);
unimplemented!() unimplemented!("emscripten::___syscall198 (lchown) {}", _which);
} }
/// getgid32 /// getgid32
pub fn ___syscall200(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { pub fn ___syscall200(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
debug!("emscripten::___syscall200 (getgid32)"); debug!("emscripten::___syscall200 (getgid32)");
unimplemented!(); unimplemented!("emscripten::___syscall200 (getgid32)");
} }
// geteuid32 // geteuid32
pub fn ___syscall201(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { pub fn ___syscall201(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
debug!("emscripten::___syscall201 (geteuid32)"); debug!("emscripten::___syscall201 (geteuid32)");
unimplemented!(); unimplemented!("emscripten::___syscall201 (geteuid32)");
} }
// getegid32 // getegid32
pub fn ___syscall202(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { pub fn ___syscall202(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
// gid_t // gid_t
debug!("emscripten::___syscall202 (getegid32)"); debug!("emscripten::___syscall202 (getegid32)");
unimplemented!(); unimplemented!("emscripten::___syscall202 (getegid32)");
} }
/// getgroups /// getgroups
pub fn ___syscall205(_ctx: &mut Ctx, _which: c_int, _varargs: VarArgs) -> c_int { pub fn ___syscall205(_ctx: &mut Ctx, _which: c_int, _varargs: VarArgs) -> c_int {
debug!("emscripten::___syscall205 (getgroups) {}", _which); debug!("emscripten::___syscall205 (getgroups) {}", _which);
unimplemented!() unimplemented!("emscripten::___syscall205 (getgroups) {}", _which);
} }
/// madvise /// madvise
pub fn ___syscall219(_ctx: &mut Ctx, _which: c_int, _varargs: VarArgs) -> c_int { pub fn ___syscall219(_ctx: &mut Ctx, _which: c_int, _varargs: VarArgs) -> c_int {
debug!("emscripten::___syscall212 (chown) {}", _which); debug!("emscripten::___syscall212 (chown) {}", _which);
unimplemented!() unimplemented!("emscripten::___syscall212 (chown) {}", _which);
} }
/// dup3 /// dup3
@ -194,7 +194,7 @@ pub fn ___syscall54(_ctx: &mut Ctx, which: c_int, mut _varargs: VarArgs) -> c_in
/// fchmod /// fchmod
pub fn ___syscall94(_ctx: &mut Ctx, _which: c_int, _varargs: VarArgs) -> c_int { pub fn ___syscall94(_ctx: &mut Ctx, _which: c_int, _varargs: VarArgs) -> c_int {
debug!("emscripten::___syscall118 (fchmod) {}", _which); debug!("emscripten::___syscall118 (fchmod) {}", _which);
unimplemented!() unimplemented!("emscripten::___syscall118 (fchmod) {}", _which);
} }
// socketcall // socketcall
@ -209,7 +209,7 @@ pub fn ___syscall102(_ctx: &mut Ctx, which: c_int, mut _varargs: VarArgs) -> c_i
/// fsync /// fsync
pub fn ___syscall118(_ctx: &mut Ctx, _which: c_int, _varargs: VarArgs) -> c_int { pub fn ___syscall118(_ctx: &mut Ctx, _which: c_int, _varargs: VarArgs) -> c_int {
debug!("emscripten::___syscall118 (fsync) {}", _which); debug!("emscripten::___syscall118 (fsync) {}", _which);
unimplemented!() unimplemented!("emscripten::___syscall118 (fsync) {}", _which);
} }
// pread // pread
@ -247,7 +247,7 @@ pub fn ___syscall142(_ctx: &mut Ctx, which: c_int, mut _varargs: VarArgs) -> c_i
/// fdatasync /// fdatasync
pub fn ___syscall148(_ctx: &mut Ctx, _which: c_int, _varargs: VarArgs) -> c_int { pub fn ___syscall148(_ctx: &mut Ctx, _which: c_int, _varargs: VarArgs) -> c_int {
debug!("emscripten::___syscall148 (fdatasync) {}", _which); debug!("emscripten::___syscall148 (fdatasync) {}", _which);
unimplemented!(); unimplemented!("emscripten::___syscall148 (fdatasync) {}", _which);
} }
// setpgid // setpgid
@ -300,11 +300,11 @@ pub fn ___syscall221(_ctx: &mut Ctx, _which: c_int, mut _varargs: VarArgs) -> c_
/// fchown /// fchown
pub fn ___syscall207(_ctx: &mut Ctx, _which: c_int, _varargs: VarArgs) -> c_int { pub fn ___syscall207(_ctx: &mut Ctx, _which: c_int, _varargs: VarArgs) -> c_int {
debug!("emscripten::___syscall207 (fchown) {}", _which); debug!("emscripten::___syscall207 (fchown) {}", _which);
unimplemented!() unimplemented!("emscripten::___syscall207 (fchown) {}", _which)
} }
/// fallocate /// fallocate
pub fn ___syscall324(_ctx: &mut Ctx, _which: c_int, _varargs: VarArgs) -> c_int { pub fn ___syscall324(_ctx: &mut Ctx, _which: c_int, _varargs: VarArgs) -> c_int {
debug!("emscripten::___syscall324 (fallocate) {}", _which); debug!("emscripten::___syscall324 (fallocate) {}", _which);
unimplemented!() unimplemented!("emscripten::___syscall324 (fallocate) {}", _which)
} }

View File

@ -24,7 +24,9 @@ pub fn is_emscripten_module(module: &Module) -> bool {
.namespace_table .namespace_table
.get(import_name.namespace_index); .get(import_name.namespace_index);
let field = module.info().name_table.get(import_name.name_index); let field = module.info().name_table.get(import_name.name_index);
if (field == "_emscripten_memcpy_big" || field == "emscripten_memcpy_big") if (field == "_emscripten_memcpy_big"
|| field == "emscripten_memcpy_big"
|| field == "__map_file")
&& namespace == "env" && namespace == "env"
{ {
return true; return true;

View File

@ -1,3 +1,6 @@
#![doc(html_favicon_url = "https://wasmer.io/static/icons/favicon.ico")]
#![doc(html_logo_url = "https://avatars3.githubusercontent.com/u/44205449?s=200&v=4")]
pub mod service; pub mod service;
use service::{ImportInfo, LoadProfile, RunProfile, ServiceContext, TableEntryRequest}; use service::{ImportInfo, LoadProfile, RunProfile, ServiceContext, TableEntryRequest};

View File

@ -1,5 +1,7 @@
#![cfg(all(target_arch = "wasm32", target_os = "wasi"))] #![cfg(all(target_arch = "wasm32", target_os = "wasi"))]
#![feature(wasi_ext)] #![feature(wasi_ext)]
#![doc(html_favicon_url = "https://wasmer.io/static/icons/favicon.ico")]
#![doc(html_logo_url = "https://avatars3.githubusercontent.com/u/44205449?s=200&v=4")]
use std::cell::RefCell; use std::cell::RefCell;
use std::fs::File; use std::fs::File;

View File

@ -0,0 +1,15 @@
[package]
name = "wasmer-llvm-backend-tests"
version = "0.10.2"
authors = ["Nick Lewycky <nick@wasmer.io>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
wabt = "0.9.1"
wasmer-runtime-core = { path = "../runtime-core", version = "0.11.0" }
wasmer-runtime = { path = "../runtime", version = "0.11.0" }
wasmer-llvm-backend = { path = "../llvm-backend", version = "0.11.0", features = ["test"] }
[features]

View File

@ -0,0 +1,7 @@
pub use wabt::wat2wasm;
use wasmer_llvm_backend::LLVMCompiler;
use wasmer_runtime_core::backend::Compiler;
pub fn get_compiler() -> impl Compiler {
LLVMCompiler::new()
}

View File

@ -0,0 +1,40 @@
use wasmer_llvm_backend_tests::{get_compiler, wat2wasm};
use wasmer_runtime::imports;
use wasmer_runtime_core::compile_with;
#[test]
fn crash_return_with_float_on_stack() {
const MODULE: &str = r#"
(module
(type (;0;) (func))
(type (;1;) (func (param f64) (result f64)))
(func $_start (type 0))
(func $fmod (type 1) (param f64) (result f64)
local.get 0
f64.const 0x0p+0 (;=0;)
f64.mul
return)
)
"#;
let wasm_binary = wat2wasm(MODULE.as_bytes()).expect("WAST not valid or malformed");
let module = compile_with(&wasm_binary, &get_compiler()).unwrap();
module.instantiate(&imports! {}).unwrap();
}
#[test]
fn crash_select_with_mismatched_pending() {
const MODULE: &str = r#"
(module
(func (param f64)
f64.const 0x0p+0 (;=0;)
local.get 0
f64.add
f64.const 0x0p+0 (;=0;)
i32.const 0
select
drop))
"#;
let wasm_binary = wat2wasm(MODULE.as_bytes()).expect("WAST not valid or malformed");
let module = compile_with(&wasm_binary, &get_compiler()).unwrap();
module.instantiate(&imports! {}).unwrap();
}

View File

@ -1,40 +1,44 @@
[package] [package]
name = "wasmer-llvm-backend" name = "wasmer-llvm-backend"
version = "0.6.0" version = "0.11.0"
license = "MIT"
authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"] authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"]
repository = "https://github.com/wasmerio/wasmer"
keywords = ["wasm", "webassembly", "compiler", "JIT", "llvm"]
categories = ["wasm"]
edition = "2018" edition = "2018"
readme = "README.md" readme = "README.md"
[dependencies] [dependencies]
wasmer-runtime-core = { path = "../runtime-core", version = "0.6.0" } wasmer-runtime-core = { path = "../runtime-core", version = "0.11.0" }
wasmparser = "0.35.1" wasmparser = "0.39.1"
smallvec = "0.6.10" smallvec = "0.6"
goblin = "0.0.24" goblin = "0.0.24"
libc = "0.2.60" libc = "0.2.60"
capstone = { version = "0.6.0", optional = true } byteorder = "1"
[dependencies.inkwell] [dependencies.inkwell]
git = "https://github.com/wasmerio/inkwell" git = "https://github.com/TheDan64/inkwell"
branch = "llvm8-0" rev = "781620e9fa30e51a6e03bd0d49b5f5bb7a782520"
default-features = false default-features = false
features = ["llvm8-0", "target-x86"] features = ["llvm8-0", "target-x86"]
[target.'cfg(unix)'.dependencies] [target.'cfg(unix)'.dependencies]
nix = "0.15.0" nix = "0.15"
[target.'cfg(windows)'.dependencies] [target.'cfg(windows)'.dependencies]
winapi = { version = "0.3.7", features = ["memoryapi"] } winapi = { version = "0.3", features = ["memoryapi"] }
[build-dependencies] [build-dependencies]
cc = "1.0" cc = "1.0"
lazy_static = "1.3.0" lazy_static = "1.4"
regex = "1.2.1" regex = "1.2"
semver = "0.9" semver = "0.9"
rustc_version = "0.2.3" rustc_version = "0.2"
[dev-dependencies] [dev-dependencies]
wabt = "0.9.1" wabt = "0.9.1"
[features] [features]
debug = ["wasmer-runtime-core/debug"] debug = ["wasmer-runtime-core/debug"]
disasm = ["capstone"] test = []

View File

@ -1,21 +1,21 @@
<p align="center"> <p align="center">
<a href="https://wasmer.io" target="_blank" rel="noopener noreferrer"> <a href="https://wasmer.io" target="_blank" rel="noopener noreferrer">
<img width="400" src="https://raw.githubusercontent.com/wasmerio/wasmer/master/logo.png" alt="Wasmer logo"> <img width="300" src="https://raw.githubusercontent.com/wasmerio/wasmer/master/logo.png" alt="Wasmer logo">
</a> </a>
</p> </p>
<p align="center"> <p align="center">
<a href="https://circleci.com/gh/wasmerio/wasmer/"> <a href="https://dev.azure.com/wasmerio/wasmer/_build/latest?definitionId=3&branchName=master">
<img src="https://img.shields.io/circleci/project/github/wasmerio/wasmer/master.svg" alt="Build Status"> <img src="https://img.shields.io/azure-devops/build/wasmerio/wasmer/3.svg?style=flat-square" alt="Build Status">
</a> </a>
<a href="https://github.com/wasmerio/wasmer/blob/master/LICENSE"> <a href="https://github.com/wasmerio/wasmer/blob/master/LICENSE">
<img src="https://img.shields.io/github/license/wasmerio/wasmer.svg" alt="License"> <img src="https://img.shields.io/github/license/wasmerio/wasmer.svg?style=flat-square" alt="License">
</a> </a>
<a href="https://spectrum.chat/wasmer"> <a href="https://spectrum.chat/wasmer">
<img src="https://withspectrum.github.io/badge/badge.svg" alt="Join the Wasmer Community"> <img src="https://withspectrum.github.io/badge/badge.svg" alt="Join the Wasmer Community">
</a> </a>
<a href="https://crates.io/crates/wasmer-llvm-backend"> <a href="https://crates.io/crates/wasmer-llvm-backend">
<img src="https://img.shields.io/crates/d/wasmer-llvm-backend.svg" alt="Number of downloads from crates.io"> <img src="https://img.shields.io/crates/d/wasmer-llvm-backend.svg?style=flat-square" alt="Number of downloads from crates.io">
</a> </a>
<a href="https://docs.rs/wasmer-llvm-backend"> <a href="https://docs.rs/wasmer-llvm-backend">
<img src="https://docs.rs/wasmer-llvm-backend/badge.svg" alt="Read our API documentation"> <img src="https://docs.rs/wasmer-llvm-backend/badge.svg" alt="Read our API documentation">
@ -36,7 +36,7 @@ This crate represents the LLVM backend integration for Wasmer.
If you are using the `wasmer` CLI, you can specify the backend with: If you are using the `wasmer` CLI, you can specify the backend with:
```bash ```sh
wasmer run program.wasm --backend=llvm wasmer run program.wasm --backend=llvm
``` ```

View File

@ -1,161 +1,196 @@
#include "object_loader.hh" #include "object_loader.hh"
#include <iostream> #include <iostream>
#include <memory> #include <memory>
#include <setjmp.h>
extern "C" void __register_frame(uint8_t *); extern "C" void __register_frame(uint8_t *);
extern "C" void __deregister_frame(uint8_t *); extern "C" void __deregister_frame(uint8_t *);
struct MemoryManager : llvm::RuntimeDyld::MemoryManager { MemoryManager::~MemoryManager() {
public: deregisterEHFrames();
MemoryManager(callbacks_t callbacks) : callbacks(callbacks) {} // Deallocate all of the allocated memory.
callbacks.dealloc_memory(code_section.base, code_section.size);
callbacks.dealloc_memory(read_section.base, read_section.size);
callbacks.dealloc_memory(readwrite_section.base, readwrite_section.size);
}
void unwinding_setjmp(jmp_buf stack_out, void (*func)(void *), void *userdata) {
if (setjmp(stack_out)) {
virtual ~MemoryManager() override { } else {
deregisterEHFrames(); func(userdata);
// Deallocate all of the allocated memory.
callbacks.dealloc_memory(code_section.base, code_section.size);
callbacks.dealloc_memory(read_section.base, read_section.size);
callbacks.dealloc_memory(readwrite_section.base, readwrite_section.size);
} }
}
virtual uint8_t *allocateCodeSection(uintptr_t size, unsigned alignment, [[noreturn]] void unwinding_longjmp(jmp_buf stack_in) { longjmp(stack_in, 42); }
unsigned section_id,
llvm::StringRef section_name) override { struct UnwindPoint {
return allocate_bump(code_section, code_bump_ptr, size, alignment); UnwindPoint *prev;
jmp_buf stack;
std::function<void()> *f;
std::unique_ptr<WasmException> exception;
};
static thread_local UnwindPoint *unwind_state = nullptr;
static void unwind_payload(void *_point) {
UnwindPoint *point = (UnwindPoint *)_point;
(*point->f)();
}
void catch_unwind(std::function<void()> &&f) {
UnwindPoint current;
current.prev = unwind_state;
current.f = &f;
unwind_state = &current;
unwinding_setjmp(current.stack, unwind_payload, (void *)&current);
unwind_state = current.prev;
if (current.exception) {
throw std::move(current.exception);
} }
}
virtual uint8_t *allocateDataSection(uintptr_t size, unsigned alignment, void unsafe_unwind(WasmException *exception) {
unsigned section_id, UnwindPoint *state = unwind_state;
llvm::StringRef section_name, if (state) {
bool read_only) override { state->exception.reset(exception);
// Allocate from the read-only section or the read-write section, depending unwinding_longjmp(state->stack);
// on if this allocation should be read-only or not. } else {
if (read_only) { abort();
return allocate_bump(read_section, read_bump_ptr, size, alignment); }
} else { }
return allocate_bump(readwrite_section, readwrite_bump_ptr, size,
alignment); uint8_t *MemoryManager::allocateCodeSection(uintptr_t size, unsigned alignment,
unsigned section_id,
llvm::StringRef section_name) {
return allocate_bump(code_section, code_bump_ptr, size, alignment);
}
uint8_t *MemoryManager::allocateDataSection(uintptr_t size, unsigned alignment,
unsigned section_id,
llvm::StringRef section_name,
bool read_only) {
// Allocate from the read-only section or the read-write section, depending
// on if this allocation should be read-only or not.
uint8_t *ret;
if (read_only) {
ret = allocate_bump(read_section, read_bump_ptr, size, alignment);
} else {
ret = allocate_bump(readwrite_section, readwrite_bump_ptr, size, alignment);
}
if (section_name.equals(llvm::StringRef("__llvm_stackmaps")) ||
section_name.equals(llvm::StringRef(".llvm_stackmaps"))) {
stack_map_ptr = ret;
stack_map_size = size;
}
return ret;
}
void MemoryManager::reserveAllocationSpace(uintptr_t code_size,
uint32_t code_align,
uintptr_t read_data_size,
uint32_t read_data_align,
uintptr_t read_write_data_size,
uint32_t read_write_data_align) {
auto aligner = [](uintptr_t ptr, size_t align) {
if (ptr == 0) {
return align;
} }
} return (ptr + align - 1) & ~(align - 1);
};
uint8_t *code_ptr_out = nullptr;
size_t code_size_out = 0;
auto code_result =
callbacks.alloc_memory(aligner(code_size, 4096), PROTECT_READ_WRITE,
&code_ptr_out, &code_size_out);
assert(code_result == RESULT_OK);
code_section = Section{code_ptr_out, code_size_out};
code_bump_ptr = (uintptr_t)code_ptr_out;
code_start_ptr = (uintptr_t)code_ptr_out;
this->code_size = code_size;
virtual void reserveAllocationSpace(uintptr_t code_size, uint32_t code_align, uint8_t *read_ptr_out = nullptr;
uintptr_t read_data_size, size_t read_size_out = 0;
uint32_t read_data_align, auto read_result =
uintptr_t read_write_data_size, callbacks.alloc_memory(aligner(read_data_size, 4096), PROTECT_READ_WRITE,
uint32_t read_write_data_align) override { &read_ptr_out, &read_size_out);
auto aligner = [](uintptr_t ptr, size_t align) { assert(read_result == RESULT_OK);
if (ptr == 0) { read_section = Section{read_ptr_out, read_size_out};
return align; read_bump_ptr = (uintptr_t)read_ptr_out;
}
return (ptr + align - 1) & ~(align - 1);
};
uint8_t *code_ptr_out = nullptr; uint8_t *readwrite_ptr_out = nullptr;
size_t code_size_out = 0; size_t readwrite_size_out = 0;
auto code_result = auto readwrite_result = callbacks.alloc_memory(
callbacks.alloc_memory(aligner(code_size, 4096), PROTECT_READ_WRITE, aligner(read_write_data_size, 4096), PROTECT_READ_WRITE,
&code_ptr_out, &code_size_out); &readwrite_ptr_out, &readwrite_size_out);
assert(code_result == RESULT_OK); assert(readwrite_result == RESULT_OK);
code_section = Section{code_ptr_out, code_size_out}; readwrite_section = Section{readwrite_ptr_out, readwrite_size_out};
code_bump_ptr = (uintptr_t)code_ptr_out; readwrite_bump_ptr = (uintptr_t)readwrite_ptr_out;
}
uint8_t *read_ptr_out = nullptr; bool MemoryManager::needsToReserveAllocationSpace() { return true; }
size_t read_size_out = 0;
auto read_result = callbacks.alloc_memory(aligner(read_data_size, 4096),
PROTECT_READ_WRITE, &read_ptr_out,
&read_size_out);
assert(read_result == RESULT_OK);
read_section = Section{read_ptr_out, read_size_out};
read_bump_ptr = (uintptr_t)read_ptr_out;
uint8_t *readwrite_ptr_out = nullptr; void MemoryManager::registerEHFrames(uint8_t *addr, uint64_t LoadAddr,
size_t readwrite_size_out = 0; size_t size) {
auto readwrite_result = callbacks.alloc_memory(
aligner(read_write_data_size, 4096), PROTECT_READ_WRITE,
&readwrite_ptr_out, &readwrite_size_out);
assert(readwrite_result == RESULT_OK);
readwrite_section = Section{readwrite_ptr_out, readwrite_size_out};
readwrite_bump_ptr = (uintptr_t)readwrite_ptr_out;
}
/* Turn on the `reserveAllocationSpace` callback. */
virtual bool needsToReserveAllocationSpace() override { return true; }
virtual void registerEHFrames(uint8_t *addr, uint64_t LoadAddr,
size_t size) override {
// We don't know yet how to do this on Windows, so we hide this on compilation // We don't know yet how to do this on Windows, so we hide this on compilation
// so we can compile and pass spectests on unix systems // so we can compile and pass spectests on unix systems
#ifndef _WIN32 #ifndef _WIN32
eh_frame_ptr = addr; eh_frame_ptr = addr;
eh_frame_size = size; eh_frame_size = size;
eh_frames_registered = true; eh_frames_registered = true;
callbacks.visit_fde(addr, size, __register_frame); callbacks.visit_fde(addr, size, __register_frame);
#endif #endif
} }
virtual void deregisterEHFrames() override { void MemoryManager::deregisterEHFrames() {
// We don't know yet how to do this on Windows, so we hide this on compilation // We don't know yet how to do this on Windows, so we hide this on compilation
// so we can compile and pass spectests on unix systems // so we can compile and pass spectests on unix systems
#ifndef _WIN32 #ifndef _WIN32
if (eh_frames_registered) { if (eh_frames_registered) {
callbacks.visit_fde(eh_frame_ptr, eh_frame_size, __deregister_frame); callbacks.visit_fde(eh_frame_ptr, eh_frame_size, __deregister_frame);
}
#endif
} }
#endif
}
virtual bool finalizeMemory(std::string *ErrMsg = nullptr) override { bool MemoryManager::finalizeMemory(std::string *ErrMsg) {
auto code_result = auto code_result =
callbacks.protect_memory(code_section.base, code_section.size, callbacks.protect_memory(code_section.base, code_section.size,
mem_protect_t::PROTECT_READ_EXECUTE); mem_protect_t::PROTECT_READ_EXECUTE);
if (code_result != RESULT_OK) { if (code_result != RESULT_OK) {
return false;
}
auto read_result = callbacks.protect_memory(
read_section.base, read_section.size, mem_protect_t::PROTECT_READ);
if (read_result != RESULT_OK) {
return false;
}
// The readwrite section is already mapped as read-write.
return false; return false;
} }
virtual void auto read_result = callbacks.protect_memory(
notifyObjectLoaded(llvm::RuntimeDyld &RTDyld, read_section.base, read_section.size, mem_protect_t::PROTECT_READ);
const llvm::object::ObjectFile &Obj) override {} if (read_result != RESULT_OK) {
return false;
private:
struct Section {
uint8_t *base;
size_t size;
};
uint8_t *allocate_bump(Section &section, uintptr_t &bump_ptr, size_t size,
size_t align) {
auto aligner = [](uintptr_t &ptr, size_t align) {
ptr = (ptr + align - 1) & ~(align - 1);
};
// Align the bump pointer to the requires alignment.
aligner(bump_ptr, align);
auto ret_ptr = bump_ptr;
bump_ptr += size;
assert(bump_ptr <= (uintptr_t)section.base + section.size);
return (uint8_t *)ret_ptr;
} }
Section code_section, read_section, readwrite_section; // The readwrite section is already mapped as read-write.
uintptr_t code_bump_ptr, read_bump_ptr, readwrite_bump_ptr;
uint8_t *eh_frame_ptr;
size_t eh_frame_size;
bool eh_frames_registered = false;
callbacks_t callbacks; return false;
}; }
void MemoryManager::notifyObjectLoaded(llvm::RuntimeDyld &RTDyld,
const llvm::object::ObjectFile &Obj) {}
uint8_t *MemoryManager::allocate_bump(Section &section, uintptr_t &bump_ptr,
size_t size, size_t align) {
auto aligner = [](uintptr_t &ptr, size_t align) {
ptr = (ptr + align - 1) & ~(align - 1);
};
// Align the bump pointer to the requires alignment.
aligner(bump_ptr, align);
auto ret_ptr = bump_ptr;
bump_ptr += size;
assert(bump_ptr <= (uintptr_t)section.base + section.size);
return (uint8_t *)ret_ptr;
}
struct SymbolLookup : llvm::JITSymbolResolver { struct SymbolLookup : llvm::JITSymbolResolver {
public: public:
@ -218,3 +253,19 @@ void *WasmModule::get_func(llvm::StringRef name) const {
auto symbol = runtime_dyld->getSymbol(name); auto symbol = runtime_dyld->getSymbol(name);
return (void *)symbol.getAddress(); return (void *)symbol.getAddress();
} }
uint8_t *WasmModule::get_stack_map_ptr() const {
return memory_manager->get_stack_map_ptr();
}
size_t WasmModule::get_stack_map_size() const {
return memory_manager->get_stack_map_size();
}
uint8_t *WasmModule::get_code_ptr() const {
return memory_manager->get_code_ptr();
}
size_t WasmModule::get_code_size() const {
return memory_manager->get_code_size();
}

View File

@ -1,7 +1,12 @@
#pragma once
#include <cstddef> #include <cstddef>
#include <cstdint> #include <cstdint>
#include <exception> #include <exception>
#include <functional>
#include <iostream> #include <iostream>
#include <memory>
#include <setjmp.h>
#include <sstream> #include <sstream>
#include <llvm/ExecutionEngine/RuntimeDyld.h> #include <llvm/ExecutionEngine/RuntimeDyld.h>
@ -48,11 +53,92 @@ typedef struct {
size_t data, vtable; size_t data, vtable;
} box_any_t; } box_any_t;
struct WasmException { enum WasmTrapType {
public: Unreachable = 0,
virtual std::string description() const noexcept = 0; IncorrectCallIndirectSignature = 1,
MemoryOutOfBounds = 2,
CallIndirectOOB = 3,
IllegalArithmetic = 4,
Unknown,
}; };
extern "C" void callback_trampoline(void *, void *);
struct MemoryManager : llvm::RuntimeDyld::MemoryManager {
public:
MemoryManager(callbacks_t callbacks) : callbacks(callbacks) {}
virtual ~MemoryManager() override;
inline uint8_t *get_stack_map_ptr() const { return stack_map_ptr; }
inline size_t get_stack_map_size() const { return stack_map_size; }
inline uint8_t *get_code_ptr() const { return (uint8_t *)code_start_ptr; }
inline size_t get_code_size() const { return code_size; }
virtual uint8_t *allocateCodeSection(uintptr_t size, unsigned alignment,
unsigned section_id,
llvm::StringRef section_name) override;
virtual uint8_t *allocateDataSection(uintptr_t size, unsigned alignment,
unsigned section_id,
llvm::StringRef section_name,
bool read_only) override;
virtual void reserveAllocationSpace(uintptr_t code_size, uint32_t code_align,
uintptr_t read_data_size,
uint32_t read_data_align,
uintptr_t read_write_data_size,
uint32_t read_write_data_align) override;
/* Turn on the `reserveAllocationSpace` callback. */
virtual bool needsToReserveAllocationSpace() override;
virtual void registerEHFrames(uint8_t *addr, uint64_t LoadAddr,
size_t size) override;
virtual void deregisterEHFrames() override;
virtual bool finalizeMemory(std::string *ErrMsg = nullptr) override;
virtual void notifyObjectLoaded(llvm::RuntimeDyld &RTDyld,
const llvm::object::ObjectFile &Obj) override;
private:
struct Section {
uint8_t *base;
size_t size;
};
uint8_t *allocate_bump(Section &section, uintptr_t &bump_ptr, size_t size,
size_t align);
Section code_section, read_section, readwrite_section;
uintptr_t code_start_ptr;
size_t code_size;
uintptr_t code_bump_ptr, read_bump_ptr, readwrite_bump_ptr;
uint8_t *eh_frame_ptr;
size_t eh_frame_size;
bool eh_frames_registered = false;
callbacks_t callbacks;
uint8_t *stack_map_ptr = nullptr;
size_t stack_map_size = 0;
};
struct WasmErrorSink {
WasmTrapType *trap_out;
box_any_t *user_error;
};
struct WasmException : std::exception {
public:
virtual std::string description() const noexcept { return "unknown"; }
virtual const char *what() const noexcept override {
return "wasm exception";
}
virtual void write_error(WasmErrorSink &out) const noexcept {
*out.trap_out = WasmTrapType::Unknown;
}
};
void catch_unwind(std::function<void()> &&f);
[[noreturn]] void unsafe_unwind(WasmException *exception);
struct UncatchableException : WasmException { struct UncatchableException : WasmException {
public: public:
virtual std::string description() const noexcept override { virtual std::string description() const noexcept override {
@ -70,6 +156,10 @@ public:
// The parts of a `Box<dyn Any>`. // The parts of a `Box<dyn Any>`.
box_any_t error_data; box_any_t error_data;
virtual void write_error(WasmErrorSink &out) const noexcept override {
*out.user_error = error_data;
}
}; };
struct BreakpointException : UncatchableException { struct BreakpointException : UncatchableException {
@ -81,20 +171,35 @@ public:
} }
uintptr_t callback; uintptr_t callback;
virtual void write_error(WasmErrorSink &out) const noexcept override {
puts("CB TRAMPOLINE");
callback_trampoline(out.user_error, (void *)callback);
}
};
struct WasmModule {
public:
WasmModule(const uint8_t *object_start, size_t object_size,
callbacks_t callbacks);
void *get_func(llvm::StringRef name) const;
uint8_t *get_stack_map_ptr() const;
size_t get_stack_map_size() const;
uint8_t *get_code_ptr() const;
size_t get_code_size() const;
bool _init_failed = false;
private:
std::unique_ptr<MemoryManager> memory_manager;
std::unique_ptr<llvm::object::ObjectFile> object_file;
std::unique_ptr<llvm::RuntimeDyld> runtime_dyld;
}; };
struct WasmTrap : UncatchableException { struct WasmTrap : UncatchableException {
public: public:
enum Type { WasmTrap(WasmTrapType type) : type(type) {}
Unreachable = 0,
IncorrectCallIndirectSignature = 1,
MemoryOutOfBounds = 2,
CallIndirectOOB = 3,
IllegalArithmetic = 4,
Unknown,
};
WasmTrap(Type type) : type(type) {}
virtual std::string description() const noexcept override { virtual std::string description() const noexcept override {
std::ostringstream ss; std::ostringstream ss;
@ -103,27 +208,31 @@ public:
return ss.str(); return ss.str();
} }
Type type; WasmTrapType type;
virtual void write_error(WasmErrorSink &out) const noexcept override {
*out.trap_out = type;
}
private: private:
friend std::ostream &operator<<(std::ostream &out, const Type &ty) { friend std::ostream &operator<<(std::ostream &out, const WasmTrapType &ty) {
switch (ty) { switch (ty) {
case Type::Unreachable: case WasmTrapType::Unreachable:
out << "unreachable"; out << "unreachable";
break; break;
case Type::IncorrectCallIndirectSignature: case WasmTrapType::IncorrectCallIndirectSignature:
out << "incorrect call_indirect signature"; out << "incorrect call_indirect signature";
break; break;
case Type::MemoryOutOfBounds: case WasmTrapType::MemoryOutOfBounds:
out << "memory access out-of-bounds"; out << "memory access out-of-bounds";
break; break;
case Type::CallIndirectOOB: case WasmTrapType::CallIndirectOOB:
out << "call_indirect out-of-bounds"; out << "call_indirect out-of-bounds";
break; break;
case Type::IllegalArithmetic: case WasmTrapType::IllegalArithmetic:
out << "illegal arithmetic operation"; out << "illegal arithmetic operation";
break; break;
case Type::Unknown: case WasmTrapType::Unknown:
default: default:
out << "unknown"; out << "unknown";
break; break;
@ -145,23 +254,7 @@ public:
uint64_t values[1]; uint64_t values[1];
}; };
struct WasmModule {
public:
WasmModule(const uint8_t *object_start, size_t object_size,
callbacks_t callbacks);
void *get_func(llvm::StringRef name) const;
bool _init_failed = false;
private:
std::unique_ptr<llvm::RuntimeDyld::MemoryManager> memory_manager;
std::unique_ptr<llvm::object::ObjectFile> object_file;
std::unique_ptr<llvm::RuntimeDyld> runtime_dyld;
};
extern "C" { extern "C" {
void callback_trampoline(void *, void *);
result_t module_load(const uint8_t *mem_ptr, size_t mem_size, result_t module_load(const uint8_t *mem_ptr, size_t mem_size,
callbacks_t callbacks, WasmModule **module_out) { callbacks_t callbacks, WasmModule **module_out) {
@ -174,42 +267,40 @@ result_t module_load(const uint8_t *mem_ptr, size_t mem_size,
return RESULT_OK; return RESULT_OK;
} }
[[noreturn]] void throw_trap(WasmTrap::Type ty) { throw WasmTrap(ty); } [[noreturn]] void throw_trap(WasmTrapType ty) {
unsafe_unwind(new WasmTrap(ty));
}
void module_delete(WasmModule *module) { delete module; } void module_delete(WasmModule *module) { delete module; }
// Throw a fat pointer that's assumed to be `*mut dyn Any` on the rust // Throw a fat pointer that's assumed to be `*mut dyn Any` on the rust
// side. // side.
[[noreturn]] void throw_any(size_t data, size_t vtable) { [[noreturn]] void throw_any(size_t data, size_t vtable) {
throw UserException(data, vtable); unsafe_unwind(new UserException(data, vtable));
} }
// Throw a pointer that's assumed to be codegen::BreakpointHandler on the // Throw a pointer that's assumed to be codegen::BreakpointHandler on the
// rust side. // rust side.
[[noreturn]] void throw_breakpoint(uintptr_t callback) { [[noreturn]] void throw_breakpoint(uintptr_t callback) {
throw BreakpointException(callback); unsafe_unwind(new BreakpointException(callback));
} }
bool invoke_trampoline(trampoline_t trampoline, void *ctx, void *func, bool invoke_trampoline(trampoline_t trampoline, void *ctx, void *func,
void *params, void *results, WasmTrap::Type *trap_out, void *params, void *results, WasmTrapType *trap_out,
box_any_t *user_error, void *invoke_env) noexcept { box_any_t *user_error, void *invoke_env) noexcept {
try { try {
trampoline(ctx, func, params, results); catch_unwind([trampoline, ctx, func, params, results]() {
trampoline(ctx, func, params, results);
});
return true; return true;
} catch (const WasmTrap &e) { } catch (std::unique_ptr<WasmException> &e) {
*trap_out = e.type; WasmErrorSink sink;
return false; sink.trap_out = trap_out;
} catch (const UserException &e) { sink.user_error = user_error;
*user_error = e.error_data; e->write_error(sink);
return false;
} catch (const BreakpointException &e) {
callback_trampoline(user_error, (void *)e.callback);
return false;
} catch (const WasmException &e) {
*trap_out = WasmTrap::Type::Unknown;
return false; return false;
} catch (...) { } catch (...) {
*trap_out = WasmTrap::Type::Unknown; *trap_out = WasmTrapType::Unknown;
return false; return false;
} }
} }
@ -217,4 +308,20 @@ bool invoke_trampoline(trampoline_t trampoline, void *ctx, void *func,
void *get_func_symbol(WasmModule *module, const char *name) { void *get_func_symbol(WasmModule *module, const char *name) {
return module->get_func(llvm::StringRef(name)); return module->get_func(llvm::StringRef(name));
} }
const uint8_t *llvm_backend_get_stack_map_ptr(const WasmModule *module) {
return module->get_stack_map_ptr();
}
size_t llvm_backend_get_stack_map_size(const WasmModule *module) {
return module->get_stack_map_size();
}
const uint8_t *llvm_backend_get_code_ptr(const WasmModule *module) {
return module->get_code_ptr();
}
size_t llvm_backend_get_code_size(const WasmModule *module) {
return module->get_code_size();
}
} }

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