mirror of
https://github.com/fluencelabs/wasmer
synced 2024-12-13 06:15:33 +00:00
Merge branch 'master' into feature/golang
This commit is contained in:
commit
f146cf1479
@ -2,8 +2,10 @@ version: "{build} ~ {branch}"
|
|||||||
|
|
||||||
os: Visual Studio 2017
|
os: Visual Studio 2017
|
||||||
|
|
||||||
# Do not build feature branch with open Pull Requests
|
branches:
|
||||||
skip_branch_with_pr: true
|
only:
|
||||||
|
- staging
|
||||||
|
- trying
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
matrix:
|
matrix:
|
||||||
@ -14,30 +16,51 @@ environment:
|
|||||||
|
|
||||||
cache:
|
cache:
|
||||||
- 'C:\Users\appveyor\.cargo'
|
- 'C:\Users\appveyor\.cargo'
|
||||||
|
- target
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe
|
# # Install LLVM
|
||||||
- rustup-init.exe -yv --default-host %target%
|
# - mkdir C:\projects\deps
|
||||||
- set PATH=%PATH%;%USERPROFILE%\.cargo\bin
|
# - cd C:\projects\deps
|
||||||
|
# - appveyor DownloadFile http://prereleases.llvm.org/win-snapshots/LLVM-7.0.0-r336178-win64.exe -FileName llvm.exe
|
||||||
|
# - 7z x llvm.exe -oC:\projects\deps\llvm
|
||||||
|
# # - set "PATH=%PATH%;C:\projects\deps\llvm\bin"
|
||||||
|
# - set "LLD_LINK=C:\projects\deps\llvm\bin\lld-link.exe"
|
||||||
|
# - set "LLVM_SYS_70_PREFIX=C:\projects\deps\llvm"
|
||||||
|
# - cd "%APPVEYOR_BUILD_FOLDER%"
|
||||||
|
|
||||||
|
# Install Rust
|
||||||
|
# uncomment these lines if the cache is cleared, or if we must re-install rust for some reason
|
||||||
|
# - appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe
|
||||||
|
# - rustup-init.exe -yv --default-host %target%
|
||||||
|
- set PATH=%PATH%;C:\\Libraries\\llvm-5.0.0\\bin;%USERPROFILE%\.cargo\bin
|
||||||
|
- rustup default stable-%target%
|
||||||
|
- rustup update
|
||||||
- rustc -vV
|
- rustc -vV
|
||||||
- cargo -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:
|
build_script:
|
||||||
- cargo build --verbose
|
- cargo build --release --verbose
|
||||||
|
|
||||||
test_script:
|
test_script:
|
||||||
- set RUST_BACKTRACE=1
|
- cargo test --manifest-path lib/spectests/Cargo.toml --features clif
|
||||||
- cd ./lib/spectests && cargo test -- --test-threads 1 && cd ../..
|
|
||||||
|
|
||||||
before_deploy:
|
before_deploy:
|
||||||
- cd ./src/installer
|
- cd ./src/installer
|
||||||
- iscc wasmer.iss
|
- iscc wasmer.iss
|
||||||
- copy /y .\WasmerInstaller.exe ..\..\WasmerInstaller-%APPVEYOR_REPO_TAG_NAME%.exe
|
- copy /y .\WasmerInstaller.exe ..\..\WasmerInstaller-%APPVEYOR_REPO_TAG_NAME%.exe
|
||||||
- appveyor PushArtifact WasmerInstaller-%APPVEYOR_REPO_TAG_NAME%.exe
|
- appveyor PushArtifact ..\..\WasmerInstaller-%APPVEYOR_REPO_TAG_NAME%.exe
|
||||||
|
- cd ..\..\
|
||||||
|
|
||||||
artifacts:
|
matrix:
|
||||||
- path: WasmerInstaller-%APPVEYOR_REPO_TAG_NAME%.exe
|
fast_finish: true
|
||||||
name: WasmerInstaller.exe
|
|
||||||
|
|
||||||
deploy:
|
deploy:
|
||||||
description: 'WasmerInstaller'
|
description: 'WasmerInstaller'
|
||||||
|
@ -1,55 +1,85 @@
|
|||||||
|
run_with_build_env_vars: &run_with_build_env_vars
|
||||||
|
environment:
|
||||||
|
LLVM_SYS_70_PREFIX: /home/circleci/project/clang+llvm-7.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/7.0.0/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz
|
||||||
|
tar xf clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz
|
||||||
|
|
||||||
version: 2
|
version: 2
|
||||||
jobs:
|
jobs:
|
||||||
|
changelog:
|
||||||
|
docker:
|
||||||
|
- image: docker:stable-git
|
||||||
|
steps:
|
||||||
|
- checkout
|
||||||
|
- run:
|
||||||
|
command: ! git diff --exit-code CHANGELOG.md
|
||||||
|
|
||||||
# Job used for testing
|
# Job used for testing
|
||||||
lint:
|
lint:
|
||||||
docker:
|
docker:
|
||||||
- image: circleci/rust:latest
|
- image: circleci/rust:latest
|
||||||
|
<<: *run_with_build_env_vars
|
||||||
steps:
|
steps:
|
||||||
- checkout
|
- checkout
|
||||||
- restore_cache:
|
- restore_cache:
|
||||||
keys:
|
keys:
|
||||||
- v6-lint-{{ arch }}-{{ checksum "Cargo.lock" }}
|
- v8-lint-{{ arch }}-{{ checksum "Cargo.lock" }}
|
||||||
- run:
|
- v8-lint-{{ arch }}
|
||||||
name: Install dependencies
|
- <<: *run_install_dependencies
|
||||||
command: |
|
|
||||||
sudo apt-get install -y cmake
|
|
||||||
- run:
|
- run:
|
||||||
name: Install lint deps
|
name: Install lint deps
|
||||||
command: |
|
command: |
|
||||||
|
git config --global --unset url."ssh://git@github.com".insteadOf || true
|
||||||
|
rustup toolchain install nightly-2019-02-27
|
||||||
rustup component add rustfmt
|
rustup component add rustfmt
|
||||||
rustup component add clippy
|
rustup component add clippy --toolchain=nightly-2019-02-27 || cargo +nightly-2019-02-27 install --git https://github.com/rust-lang/rust-clippy/ --force clippy
|
||||||
- run:
|
- run:
|
||||||
name: Execute lints
|
name: Execute lints
|
||||||
command: make lint
|
command: |
|
||||||
|
make lint
|
||||||
- save_cache:
|
- save_cache:
|
||||||
paths:
|
paths:
|
||||||
- /usr/local/cargo/registry
|
- /usr/local/cargo/registry
|
||||||
- target/debug/.fingerprint
|
- target/debug/.fingerprint
|
||||||
- target/debug/build
|
- target/debug/build
|
||||||
- target/debug/deps
|
- target/debug/deps
|
||||||
key: v6-lint-{{ arch }}-{{ checksum "Cargo.lock" }}
|
key: v8-lint-{{ arch }}-{{ checksum "Cargo.lock" }}
|
||||||
|
|
||||||
test:
|
test:
|
||||||
docker:
|
docker:
|
||||||
- image: circleci/rust:latest
|
- image: circleci/rust:latest
|
||||||
|
<<: *run_with_build_env_vars
|
||||||
steps:
|
steps:
|
||||||
- checkout
|
- checkout
|
||||||
- restore_cache:
|
- restore_cache:
|
||||||
keys:
|
keys:
|
||||||
- v6-test-cargo-cache-linux-{{ arch }}-{{ checksum "Cargo.lock" }}
|
- v8-test-cargo-cache-linux-stable-{{ arch }}-{{ checksum "Cargo.lock" }}
|
||||||
|
- v8-test-cargo-cache-linux-stable-{{ arch }}
|
||||||
|
- <<: *run_install_dependencies
|
||||||
- run:
|
- run:
|
||||||
name: Install dependencies
|
name: Tests
|
||||||
|
command: make test
|
||||||
|
- run:
|
||||||
|
name: Emscripten Tests
|
||||||
command: |
|
command: |
|
||||||
sudo apt-get install -y cmake
|
make test-emscripten-clif
|
||||||
- run: make test
|
make test-emscripten-llvm
|
||||||
- run: make integration-tests
|
- run:
|
||||||
|
name: Integration Tests
|
||||||
|
command: make integration-tests
|
||||||
- save_cache:
|
- save_cache:
|
||||||
paths:
|
paths:
|
||||||
- /usr/local/cargo/registry
|
- /usr/local/cargo/registry
|
||||||
- target/debug/.fingerprint
|
- target/debug/.fingerprint
|
||||||
- target/debug/build
|
- target/debug/build
|
||||||
- target/debug/deps
|
- target/debug/deps
|
||||||
key: v6-test-cargo-cache-linux-{{ arch }}-{{ checksum "Cargo.lock" }}
|
key: v8-test-cargo-cache-linux-stable-{{ arch }}-{{ checksum "Cargo.lock" }}
|
||||||
|
|
||||||
test-macos:
|
test-macos:
|
||||||
macos:
|
macos:
|
||||||
@ -58,7 +88,8 @@ jobs:
|
|||||||
- checkout
|
- checkout
|
||||||
- restore_cache:
|
- restore_cache:
|
||||||
keys:
|
keys:
|
||||||
- v6-cargo-cache-darwin-{{ arch }}-{{ checksum "Cargo.lock" }}
|
- v8-cargo-cache-darwin-stable-{{ arch }}-{{ checksum "Cargo.lock" }}
|
||||||
|
- v8-cargo-cache-darwin-stable-{{ arch }}
|
||||||
- run:
|
- run:
|
||||||
name: Install crate dependencies
|
name: Install crate dependencies
|
||||||
command: |
|
command: |
|
||||||
@ -66,6 +97,9 @@ jobs:
|
|||||||
curl -O https://cmake.org/files/v3.4/cmake-3.4.1-Darwin-x86_64.tar.gz
|
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
|
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"
|
export PATH="`pwd`/cmake-3.4.1-Darwin-x86_64/CMake.app/Contents/bin:$PATH"
|
||||||
|
# Installing LLVM outside of brew
|
||||||
|
curl -O https://releases.llvm.org/7.0.0/clang+llvm-7.0.0-x86_64-apple-darwin.tar.xz
|
||||||
|
tar xf clang+llvm-7.0.0-x86_64-apple-darwin.tar.xz
|
||||||
- run:
|
- run:
|
||||||
name: Install Rust
|
name: Install Rust
|
||||||
command: |
|
command: |
|
||||||
@ -73,19 +107,32 @@ jobs:
|
|||||||
export PATH="$HOME/.cargo/bin:$PATH"
|
export PATH="$HOME/.cargo/bin:$PATH"
|
||||||
cargo --version
|
cargo --version
|
||||||
- run:
|
- run:
|
||||||
name: Execute tests
|
name: Tests
|
||||||
command: |
|
command: |
|
||||||
export PATH="$HOME/.cargo/bin:$PATH"
|
export PATH="$HOME/.cargo/bin:$PATH"
|
||||||
export PATH="`pwd`/cmake-3.4.1-Darwin-x86_64/CMake.app/Contents/bin:$PATH"
|
export PATH="`pwd`/cmake-3.4.1-Darwin-x86_64/CMake.app/Contents/bin:$PATH"
|
||||||
|
export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-apple-darwin/"
|
||||||
# We increase the ulimit for fixing cargo unclosed files in mac
|
# We increase the ulimit for fixing cargo unclosed files in mac
|
||||||
ulimit -n 8000
|
ulimit -n 8000
|
||||||
sudo sysctl -w kern.maxfiles=655360 kern.maxfilesperproc=327680
|
sudo sysctl -w kern.maxfiles=655360 kern.maxfilesperproc=327680
|
||||||
make test
|
make test
|
||||||
- run:
|
- run:
|
||||||
name: Execute integration tests
|
name: Emscripten Tests
|
||||||
command: |
|
command: |
|
||||||
export PATH="$HOME/.cargo/bin:$PATH"
|
export PATH="$HOME/.cargo/bin:$PATH"
|
||||||
export PATH="`pwd`/cmake-3.4.1-Darwin-x86_64/CMake.app/Contents/bin:$PATH"
|
export PATH="`pwd`/cmake-3.4.1-Darwin-x86_64/CMake.app/Contents/bin:$PATH"
|
||||||
|
export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-apple-darwin/"
|
||||||
|
# We increase the ulimit for fixing cargo unclosed files in mac
|
||||||
|
ulimit -n 8000
|
||||||
|
sudo sysctl -w kern.maxfiles=655360 kern.maxfilesperproc=327680
|
||||||
|
make test-emscripten-clif
|
||||||
|
make test-emscripten-llvm
|
||||||
|
- 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_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-apple-darwin/"
|
||||||
make integration-tests
|
make integration-tests
|
||||||
- save_cache:
|
- save_cache:
|
||||||
paths:
|
paths:
|
||||||
@ -96,7 +143,7 @@ jobs:
|
|||||||
- target/release/.fingerprint
|
- target/release/.fingerprint
|
||||||
- target/release/build
|
- target/release/build
|
||||||
- target/release/deps
|
- target/release/deps
|
||||||
key: v6-cargo-cache-darwin-{{ arch }}-{{ checksum "Cargo.lock" }}
|
key: v8-cargo-cache-darwin-stable-{{ arch }}-{{ checksum "Cargo.lock" }}
|
||||||
|
|
||||||
test-and-build:
|
test-and-build:
|
||||||
docker:
|
docker:
|
||||||
@ -105,24 +152,43 @@ jobs:
|
|||||||
- checkout
|
- checkout
|
||||||
- restore_cache:
|
- restore_cache:
|
||||||
keys:
|
keys:
|
||||||
- v6-cargo-cache-linux-{{ arch }}-{{ checksum "Cargo.lock" }}
|
- v8-cargo-cache-linux-nightly-{{ arch }}-{{ checksum "Cargo.lock" }}
|
||||||
|
- v8-cargo-cache-linux-nightly-{{ arch }}
|
||||||
- run:
|
- run:
|
||||||
name: Install dependencies
|
name: Install dependencies
|
||||||
command: |
|
command: |
|
||||||
sudo apt-get install -y cmake
|
sudo apt-get install -y cmake
|
||||||
|
curl -O https://releases.llvm.org/7.0.0/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz
|
||||||
|
tar xf clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz
|
||||||
|
# Use rust nightly (for singlepass, for now)
|
||||||
|
- run: rustup default nightly-2019-04-11
|
||||||
- run:
|
- run:
|
||||||
name: Execute tests
|
name: Tests
|
||||||
command: make test
|
|
||||||
- run:
|
|
||||||
name: Make release build
|
|
||||||
command: |
|
command: |
|
||||||
make release
|
export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/"
|
||||||
|
make test
|
||||||
|
- run:
|
||||||
|
name: Emscripten Tests
|
||||||
|
command: |
|
||||||
|
export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/"
|
||||||
|
make test-emscripten-clif
|
||||||
|
make test-emscripten-llvm
|
||||||
|
- run:
|
||||||
|
name: Release Build
|
||||||
|
command: |
|
||||||
|
export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/"
|
||||||
|
make production-release
|
||||||
mkdir -p artifacts
|
mkdir -p artifacts
|
||||||
VERSION=$(cargo pkgid | cut -d# -f2 | cut -d: -f2)
|
VERSION=$(cargo pkgid | cut -d# -f2 | cut -d: -f2)
|
||||||
# GIT_VERSION=$(git describe --exact-match --tags)
|
# GIT_VERSION=$(git describe --exact-match --tags)
|
||||||
echo "${VERSION}" >> artifacts/version
|
echo "${VERSION}" >> artifacts/version
|
||||||
echo "${CIRCLE_TAG}" >> artifacts/git_version
|
echo "${CIRCLE_TAG}" >> artifacts/git_version
|
||||||
cp ./target/release/wasmer ./artifacts/$(./binary-name.sh)
|
make build-install
|
||||||
|
cp ./wasmer.tar.gz ./artifacts/$(./binary-name.sh)
|
||||||
|
- run:
|
||||||
|
name: Debug flag checked
|
||||||
|
command: |
|
||||||
|
cargo check --features "debug"
|
||||||
- persist_to_workspace:
|
- persist_to_workspace:
|
||||||
root: .
|
root: .
|
||||||
paths:
|
paths:
|
||||||
@ -136,7 +202,7 @@ jobs:
|
|||||||
- target/release/.fingerprint
|
- target/release/.fingerprint
|
||||||
- target/release/build
|
- target/release/build
|
||||||
- target/release/deps
|
- target/release/deps
|
||||||
key: v6-cargo-cache-linux-{{ arch }}-{{ checksum "Cargo.lock" }}
|
key: v8-cargo-cache-linux-nightly-{{ arch }}-{{ checksum "Cargo.lock" }}
|
||||||
|
|
||||||
test-and-build-macos:
|
test-and-build-macos:
|
||||||
macos:
|
macos:
|
||||||
@ -145,7 +211,8 @@ jobs:
|
|||||||
- checkout
|
- checkout
|
||||||
- restore_cache:
|
- restore_cache:
|
||||||
keys:
|
keys:
|
||||||
- v6-cargo-cache-darwin-{{ arch }}-{{ checksum "Cargo.lock" }}
|
- v8-cargo-cache-darwin-nightly-{{ arch }}-{{ checksum "Cargo.lock" }}
|
||||||
|
- v8-cargo-cache-darwin-nightly-{{ arch }}
|
||||||
- run:
|
- run:
|
||||||
name: Install crate dependencies
|
name: Install crate dependencies
|
||||||
command: |
|
command: |
|
||||||
@ -153,31 +220,54 @@ jobs:
|
|||||||
curl -O https://cmake.org/files/v3.4/cmake-3.4.1-Darwin-x86_64.tar.gz
|
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
|
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"
|
export PATH="`pwd`/cmake-3.4.1-Darwin-x86_64/CMake.app/Contents/bin:$PATH"
|
||||||
|
# Installing LLVM outside of brew
|
||||||
|
curl -O https://releases.llvm.org/7.0.0/clang+llvm-7.0.0-x86_64-apple-darwin.tar.xz
|
||||||
|
tar xf clang+llvm-7.0.0-x86_64-apple-darwin.tar.xz
|
||||||
- run:
|
- run:
|
||||||
name: Install Rust
|
name: Install Rust
|
||||||
command: |
|
command: |
|
||||||
curl https://sh.rustup.rs -sSf | sh -s -- -y
|
curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain nightly-2019-04-11
|
||||||
export PATH="$HOME/.cargo/bin:$PATH"
|
export PATH="$HOME/.cargo/bin:$PATH"
|
||||||
cargo --version
|
cargo --version
|
||||||
|
# Use rust nightly (for singlepass, for now)
|
||||||
|
# - run:
|
||||||
|
# name: Install Rust nightly
|
||||||
|
# command: |
|
||||||
|
# export PATH="$HOME/.rustup/bin:$PATH"
|
||||||
|
# rustup default nightly-2019-04-11
|
||||||
- run:
|
- run:
|
||||||
name: Execute tests
|
name: Tests
|
||||||
command: |
|
command: |
|
||||||
export PATH="`pwd`/cmake-3.4.1-Darwin-x86_64/CMake.app/Contents/bin:$PATH"
|
export PATH="`pwd`/cmake-3.4.1-Darwin-x86_64/CMake.app/Contents/bin:$PATH"
|
||||||
export PATH="$HOME/.cargo/bin:$PATH"
|
export PATH="$HOME/.cargo/bin:$PATH"
|
||||||
|
export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-apple-darwin/"
|
||||||
# We increase the ulimit for fixing cargo unclosed files in mac
|
# We increase the ulimit for fixing cargo unclosed files in mac
|
||||||
ulimit -n 8000
|
ulimit -n 8000
|
||||||
sudo sysctl -w kern.maxfiles=655360 kern.maxfilesperproc=327680
|
sudo sysctl -w kern.maxfiles=655360 kern.maxfilesperproc=327680
|
||||||
make test
|
make test
|
||||||
- run:
|
- run:
|
||||||
name: Make release build
|
name: Emscripten Tests
|
||||||
command: |
|
command: |
|
||||||
export PATH="`pwd`/cmake-3.4.1-Darwin-x86_64/CMake.app/Contents/bin:$PATH"
|
export PATH="`pwd`/cmake-3.4.1-Darwin-x86_64/CMake.app/Contents/bin:$PATH"
|
||||||
export PATH="$HOME/.cargo/bin:$PATH"
|
export PATH="$HOME/.cargo/bin:$PATH"
|
||||||
make release
|
export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-apple-darwin/"
|
||||||
|
# We increase the ulimit for fixing cargo unclosed files in mac
|
||||||
|
ulimit -n 8000
|
||||||
|
sudo sysctl -w kern.maxfiles=655360 kern.maxfilesperproc=327680
|
||||||
|
make test-emscripten-clif
|
||||||
|
make test-emscripten-singlepass
|
||||||
|
- 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_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-apple-darwin/"
|
||||||
|
make production-release
|
||||||
mkdir -p artifacts
|
mkdir -p artifacts
|
||||||
|
make build-install
|
||||||
|
cp ./wasmer.tar.gz ./artifacts/$(./binary-name.sh)
|
||||||
# VERSION=$(cargo pkgid | cut -d# -f2 | cut -d: -f2)
|
# VERSION=$(cargo pkgid | cut -d# -f2 | cut -d: -f2)
|
||||||
# echo "${VERSION}" >> artifacts/version
|
# echo "${VERSION}" >> artifacts/version
|
||||||
cp ./target/release/wasmer ./artifacts/$(./binary-name.sh)
|
|
||||||
- persist_to_workspace:
|
- persist_to_workspace:
|
||||||
root: .
|
root: .
|
||||||
paths:
|
paths:
|
||||||
@ -191,7 +281,7 @@ jobs:
|
|||||||
- target/release/.fingerprint
|
- target/release/.fingerprint
|
||||||
- target/release/build
|
- target/release/build
|
||||||
- target/release/deps
|
- target/release/deps
|
||||||
key: v6-cargo-cache-darwin-{{ arch }}-{{ checksum "Cargo.lock" }}
|
key: v8-cargo-cache-darwin-nightly-{ arch }}-{{ checksum "Cargo.lock" }}
|
||||||
|
|
||||||
test-rust-nightly:
|
test-rust-nightly:
|
||||||
docker:
|
docker:
|
||||||
@ -200,20 +290,28 @@ jobs:
|
|||||||
- checkout
|
- checkout
|
||||||
- restore_cache:
|
- restore_cache:
|
||||||
keys:
|
keys:
|
||||||
- v6-test-cargo-cache-linux-{{ arch }}-{{ checksum "Cargo.lock" }}-nightly
|
- v8-cargo-cache-linux-nightly-{{ arch }}-{{ checksum "Cargo.lock" }}
|
||||||
|
- v8-cargo-cache-linux-nightly-{{ arch }}
|
||||||
- run:
|
- run:
|
||||||
name: Install dependencies
|
name: Install dependencies
|
||||||
command: |
|
command: |
|
||||||
sudo apt-get install -y cmake
|
sudo apt-get install -y cmake
|
||||||
- run: rustup default nightly
|
curl -O https://releases.llvm.org/7.0.0/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz
|
||||||
- run: make test
|
tar xf clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz
|
||||||
|
- run: rustup default nightly-2019-04-11
|
||||||
|
- run: |
|
||||||
|
export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/"
|
||||||
|
make test
|
||||||
|
make test-singlepass
|
||||||
|
make test-emscripten-clif
|
||||||
|
make test-emscripten-singlepass
|
||||||
- save_cache:
|
- save_cache:
|
||||||
paths:
|
paths:
|
||||||
- /usr/local/cargo/registry
|
- /usr/local/cargo/registry
|
||||||
- target/debug/.fingerprint
|
- target/debug/.fingerprint
|
||||||
- target/debug/build
|
- target/debug/build
|
||||||
- target/debug/deps
|
- target/debug/deps
|
||||||
key: v6-test-cargo-cache-linux-{{ arch }}-{{ checksum "Cargo.lock" }}-nightly
|
key: v8-cargo-cache-linux-nightly-{{ arch }}-{{ checksum "Cargo.lock" }}-nightly
|
||||||
|
|
||||||
publish-github-release:
|
publish-github-release:
|
||||||
docker:
|
docker:
|
||||||
@ -240,32 +338,57 @@ jobs:
|
|||||||
# echo "Versions don't match. Wasmer output version (wasmer --version) is ${VERSION} while Git tag is ${VERSION_TAG}"
|
# echo "Versions don't match. Wasmer output version (wasmer --version) is ${VERSION} while Git tag is ${VERSION_TAG}"
|
||||||
# exit 1
|
# exit 1
|
||||||
#fi
|
#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:
|
workflows:
|
||||||
version: 2
|
version: 2
|
||||||
main:
|
main:
|
||||||
jobs:
|
jobs:
|
||||||
|
- changelog
|
||||||
- lint
|
- lint
|
||||||
- test:
|
- test:
|
||||||
filters:
|
filters:
|
||||||
branches:
|
branches:
|
||||||
ignore: master
|
only:
|
||||||
|
- trying
|
||||||
|
- staging
|
||||||
- test-macos:
|
- test-macos:
|
||||||
filters:
|
filters:
|
||||||
branches:
|
branches:
|
||||||
ignore: master
|
only:
|
||||||
|
- trying
|
||||||
|
- staging
|
||||||
- test-and-build:
|
- test-and-build:
|
||||||
filters:
|
filters:
|
||||||
branches:
|
branches:
|
||||||
only: master
|
only:
|
||||||
|
- master
|
||||||
- test-and-build-macos:
|
- test-and-build-macos:
|
||||||
filters:
|
filters:
|
||||||
branches:
|
branches:
|
||||||
only: master
|
only:
|
||||||
|
- master
|
||||||
- test-rust-nightly:
|
- test-rust-nightly:
|
||||||
filters:
|
filters:
|
||||||
branches:
|
branches:
|
||||||
only: master
|
only:
|
||||||
|
- trying
|
||||||
|
- staging
|
||||||
- publish-github-release:
|
- publish-github-release:
|
||||||
requires:
|
requires:
|
||||||
- lint
|
- lint
|
||||||
@ -274,3 +397,10 @@ workflows:
|
|||||||
filters:
|
filters:
|
||||||
branches:
|
branches:
|
||||||
only: master
|
only: master
|
||||||
|
- trigger-benchmark-build:
|
||||||
|
requires:
|
||||||
|
- test-and-build
|
||||||
|
- lint
|
||||||
|
filters:
|
||||||
|
branches:
|
||||||
|
only: master
|
||||||
|
6
.dockerignore
Normal file
6
.dockerignore
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
# Ignore everything
|
||||||
|
**
|
||||||
|
!lib/**
|
||||||
|
!src/**
|
||||||
|
!Cargo.toml
|
||||||
|
!Cargo.lock
|
43
.github/ISSUE_TEMPLATE/---bug-report.md
vendored
Normal file
43
.github/ISSUE_TEMPLATE/---bug-report.md
vendored
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
---
|
||||||
|
name: "\U0001F41E Bug report"
|
||||||
|
about: Create a report to help us improve
|
||||||
|
title: ''
|
||||||
|
labels: "\U0001F41E bug"
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Thanks for the bug report!
|
||||||
|
|
||||||
|
### Describe the bug
|
||||||
|
|
||||||
|
A clear and concise description of what the bug is.
|
||||||
|
|
||||||
|
Copy and paste the result of executing the following in your shell, so we can know the version of wasmer, Rust (if available) and architecture of your environment.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
echo "`wasmer -V` | `rustc -V` | `uname -m`"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Steps to reproduce
|
||||||
|
|
||||||
|
1. Go to '…'
|
||||||
|
2. Compile with '…'
|
||||||
|
3. Run '…'
|
||||||
|
4. See error
|
||||||
|
|
||||||
|
If applicable, add a link to a test case (as a zip file or link to a repository we can clone).
|
||||||
|
|
||||||
|
### Expected behavior
|
||||||
|
|
||||||
|
A clear and concise description of what you expected to happen.
|
||||||
|
|
||||||
|
### Actual behavior
|
||||||
|
|
||||||
|
A clear and concise description of what actually happened.
|
||||||
|
|
||||||
|
If applicable, add screenshots to help explain your problem.
|
||||||
|
|
||||||
|
### Additional context
|
||||||
|
|
||||||
|
Add any other context about the problem here.
|
26
.github/ISSUE_TEMPLATE/---feature-request.md
vendored
Normal file
26
.github/ISSUE_TEMPLATE/---feature-request.md
vendored
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
---
|
||||||
|
name: "\U0001F389 Feature request"
|
||||||
|
about: Suggest an idea for this project
|
||||||
|
title: ''
|
||||||
|
labels: "\U0001F389 enhancement"
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Thanks for proposing a new feature!
|
||||||
|
|
||||||
|
### Motivation
|
||||||
|
|
||||||
|
A clear and concise description of what the motivation for the new feature is, and what problem it is solving.
|
||||||
|
|
||||||
|
### Proposed solution
|
||||||
|
|
||||||
|
A clear and concise description of the feature you would like to add, and how it solves the motivating problem.
|
||||||
|
|
||||||
|
### Alternatives
|
||||||
|
|
||||||
|
A clear and concise description of any alternative solutions or features you've considered, and why you're proposed solution is better.
|
||||||
|
|
||||||
|
### Additional context
|
||||||
|
|
||||||
|
Add any other context or screenshots about the feature request here.
|
16
.github/ISSUE_TEMPLATE/--question.md
vendored
Normal file
16
.github/ISSUE_TEMPLATE/--question.md
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
---
|
||||||
|
name: "❓ Question"
|
||||||
|
about: Ask a question about this project
|
||||||
|
title: ''
|
||||||
|
labels: "❓ question"
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Summary
|
||||||
|
|
||||||
|
A clear and concise summary of your question.
|
||||||
|
|
||||||
|
### Additional details
|
||||||
|
|
||||||
|
Provide any additional details here.
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -3,3 +3,5 @@
|
|||||||
/artifacts
|
/artifacts
|
||||||
.DS_Store
|
.DS_Store
|
||||||
.idea
|
.idea
|
||||||
|
**/.vscode
|
||||||
|
install/
|
||||||
|
18
CHANGELOG.md
Normal file
18
CHANGELOG.md
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
All PRs to the Wasmer repository must add to this file.
|
||||||
|
|
||||||
|
Blocks of changes will separated by version increments.
|
||||||
|
|
||||||
|
## **[Unreleased]**
|
||||||
|
- [#371](https://github.com/wasmerio/wasmer/pull/371) Add more Debug impl for WASI types
|
||||||
|
- [#368](https://github.com/wasmerio/wasmer/pull/368) Fix issue with write buffering
|
||||||
|
- [#343](https://github.com/wasmerio/wasmer/pull/343) Implement preopened files for WASI and fix aligment issue when accessing WASI memory
|
||||||
|
- [#367](https://github.com/wasmerio/wasmer/pull/367) Add caching support to the LLVM backend.
|
||||||
|
- [#366](https://github.com/wasmerio/wasmer/pull/366) Remove `UserTrapper` trait to fix [#365](https://github.com/wasmerio/wasmer/issues/365).
|
||||||
|
- [#348](https://github.com/wasmerio/wasmer/pull/348) Refactor internal runtime ↔️ backend abstraction.
|
||||||
|
- [#355](https://github.com/wasmerio/wasmer/pull/355) Misc changes to `Cargo.toml`s for publishing
|
||||||
|
- [#352](https://github.com/wasmerio/wasmer/pull/352) Bump version numbers to 0.3.0
|
||||||
|
- [#351](https://github.com/wasmerio/wasmer/pull/351) Add hidden option to specify wasm program name (can be used to improve error messages)
|
||||||
|
- [#350](https://github.com/wasmerio/wasmer/pull/350) Enforce that CHANGELOG.md is updated through CI.
|
||||||
|
- [#349](https://github.com/wasmerio/wasmer/pull/349) Add [CHANGELOG.md](https://github.com/wasmerio/wasmer/blob/master/CHANGELOG.md).
|
1892
Cargo.lock
generated
1892
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
21
Cargo.toml
21
Cargo.toml
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "wasmer"
|
name = "wasmer"
|
||||||
version = "0.2.0"
|
version = "0.3.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"
|
||||||
@ -19,24 +19,33 @@ include = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
errno = "0.2.4"
|
||||||
structopt = "0.2.11"
|
structopt = "0.2.11"
|
||||||
wabt = "0.7.2"
|
wabt = "0.7.2"
|
||||||
|
hashbrown = "0.1.8"
|
||||||
wasmer-clif-backend = { path = "lib/clif-backend" }
|
wasmer-clif-backend = { path = "lib/clif-backend" }
|
||||||
|
wasmer-singlepass-backend = { path = "lib/singlepass-backend", optional = true }
|
||||||
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-golang = { path = "lib/golang" }
|
wasmer-llvm-backend = { path = "lib/llvm-backend", optional = true }
|
||||||
|
wasmer-wasi = { path = "lib/wasi", optional = true }
|
||||||
|
|
||||||
[workspace]
|
[workspace]
|
||||||
members = ["lib/clif-backend", "lib/runtime", "lib/runtime-core", "lib/emscripten", "lib/spectests", "lib/win-exception-handler", "lib/runtime-c-api", "lib/golang"]
|
members = ["lib/clif-backend", "lib/singlepass-backend", "lib/runtime", "lib/runtime-abi", "lib/runtime-core", "lib/emscripten", "lib/spectests", "lib/win-exception-handler", "lib/runtime-c-api", "lib/llvm-backend", "lib/wasi"]
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
wabt = "0.7.2"
|
wabt = "0.7.2"
|
||||||
glob = "0.2.11"
|
glob = "0.2.11"
|
||||||
|
rustc_version = "0.2.3"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["fast-tests"]
|
default = ["fast-tests", "wasi"]
|
||||||
|
debug = ["wasmer-clif-backend/debug", "wasmer-runtime-core/debug"]
|
||||||
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:llvm" = ["wasmer-llvm-backend"]
|
||||||
|
"backend:singlepass" = ["wasmer-singlepass-backend"]
|
||||||
|
wasi = ["wasmer-wasi"]
|
||||||
|
vfs = ["wasmer-runtime-abi"]
|
||||||
|
25
Dockerfile
Normal file
25
Dockerfile
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
FROM circleci/rust:1.33.0-stretch as wasmer-build-env
|
||||||
|
RUN sudo apt-get update && \
|
||||||
|
sudo apt-get install -y --no-install-recommends \
|
||||||
|
cmake \
|
||||||
|
&& sudo rm -rf /var/lib/apt/lists/*
|
||||||
|
RUN curl -SL https://releases.llvm.org/7.0.0/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz \
|
||||||
|
| tar -xJC /home/circleci
|
||||||
|
ENV LLVM_SYS_70_PREFIX /home/circleci/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/
|
||||||
|
|
||||||
|
FROM wasmer-build-env AS wasmer-debug-env
|
||||||
|
RUN sudo apt-get update && \
|
||||||
|
sudo apt-get install -y --no-install-recommends \
|
||||||
|
valgrind \
|
||||||
|
&& sudo rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
FROM wasmer-build-env AS wasmer-build
|
||||||
|
WORKDIR /home/circleci/wasmer
|
||||||
|
COPY . /home/circleci/wasmer
|
||||||
|
RUN sudo chmod -R 777 .
|
||||||
|
RUN cargo build --release
|
||||||
|
|
||||||
|
FROM debian:stretch AS wasmer
|
||||||
|
WORKDIR /root/
|
||||||
|
COPY --from=wasmer-build /home/circleci/wasmer/target/release/wasmer .
|
||||||
|
ENTRYPOINT ["./wasmer"]
|
4
LICENSE
4
LICENSE
@ -1,4 +1,6 @@
|
|||||||
Copyright (c) 2019 Syrus Akbary
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2019 Wasmer, Inc. and its affiliates.
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
44
Makefile
44
Makefile
@ -12,14 +12,11 @@ spectests:
|
|||||||
emtests:
|
emtests:
|
||||||
WASM_EMSCRIPTEN_GENERATE_EMTESTS=1 cargo build -p wasmer-emscripten
|
WASM_EMSCRIPTEN_GENERATE_EMTESTS=1 cargo build -p wasmer-emscripten
|
||||||
|
|
||||||
capi:
|
|
||||||
WASM_EMSCRIPTEN_GENERATE_C_API_HEADERS=1 cargo build --manifest-path lib/runtime-c-api/Cargo.toml --features generate-c-api-headers
|
|
||||||
|
|
||||||
# clean:
|
# clean:
|
||||||
# rm -rf artifacts
|
# rm -rf artifacts
|
||||||
|
|
||||||
build:
|
build:
|
||||||
cargo build
|
cargo build --features debug
|
||||||
|
|
||||||
install:
|
install:
|
||||||
cargo install --path .
|
cargo install --path .
|
||||||
@ -31,22 +28,57 @@ integration-tests: release
|
|||||||
|
|
||||||
lint:
|
lint:
|
||||||
cargo fmt --all -- --check
|
cargo fmt --all -- --check
|
||||||
cargo clippy --all
|
cargo +nightly-2019-02-27 clippy --all
|
||||||
|
|
||||||
precommit: lint test
|
precommit: lint test
|
||||||
|
|
||||||
|
build-install:
|
||||||
|
mkdir -p ./install/bin
|
||||||
|
cp ./target/release/wasmer ./install/bin/
|
||||||
|
tar -C ./install -zcvf wasmer.tar.gz bin/wasmer
|
||||||
|
|
||||||
|
# For installing the contents locally
|
||||||
|
do-install:
|
||||||
|
tar -C ~/.wasmer -zxvf wasmer.tar.gz
|
||||||
|
|
||||||
test:
|
test:
|
||||||
# We use one thread so the emscripten stdouts doesn't collide
|
# We use one thread so the emscripten stdouts doesn't collide
|
||||||
cargo test --all --exclude wasmer-runtime-c-api -- --test-threads=1 $(runargs)
|
cargo test --all --exclude wasmer-runtime-c-api --exclude wasmer-emscripten --exclude wasmer-spectests --exclude wasmer-singlepass-backend -- $(runargs)
|
||||||
# cargo test --all --exclude wasmer-emscripten -- --test-threads=1 $(runargs)
|
# cargo test --all --exclude wasmer-emscripten -- --test-threads=1 $(runargs)
|
||||||
|
cargo test --manifest-path lib/spectests/Cargo.toml --features clif
|
||||||
|
cargo test --manifest-path lib/spectests/Cargo.toml --features llvm
|
||||||
cargo build -p wasmer-runtime-c-api
|
cargo build -p wasmer-runtime-c-api
|
||||||
cargo test -p wasmer-runtime-c-api -- --nocapture
|
cargo test -p wasmer-runtime-c-api -- --nocapture
|
||||||
|
|
||||||
|
test-singlepass:
|
||||||
|
cargo test --manifest-path lib/spectests/Cargo.toml --features singlepass
|
||||||
|
|
||||||
|
test-emscripten-llvm:
|
||||||
|
cargo test --manifest-path lib/emscripten/Cargo.toml --features llvm -- --test-threads=1 $(runargs)
|
||||||
|
|
||||||
|
test-emscripten-clif:
|
||||||
|
cargo test --manifest-path lib/emscripten/Cargo.toml --features clif -- --test-threads=1 $(runargs)
|
||||||
|
|
||||||
|
test-emscripten-singlepass:
|
||||||
|
cargo test --manifest-path lib/emscripten/Cargo.toml --features singlepass -- --test-threads=1 $(runargs)
|
||||||
|
|
||||||
|
singlepass-debug-release:
|
||||||
|
cargo +nightly build --features "backend:singlepass debug" --release
|
||||||
|
|
||||||
|
singlepass-release:
|
||||||
|
cargo +nightly build --features "backend:singlepass" --release
|
||||||
|
|
||||||
|
singlepass-build:
|
||||||
|
cargo +nightly build --features "backend:singlepass debug"
|
||||||
|
|
||||||
release:
|
release:
|
||||||
# If you are in OS-X, you will need mingw-w64 for cross compiling to windows
|
# If you are in OS-X, you will need mingw-w64 for cross compiling to windows
|
||||||
# brew install mingw-w64
|
# brew install mingw-w64
|
||||||
cargo build --release
|
cargo build --release
|
||||||
|
|
||||||
|
production-release:
|
||||||
|
cargo build --release --features backend:singlepass,backend:llvm
|
||||||
|
|
||||||
debug-release:
|
debug-release:
|
||||||
cargo build --release --features "debug"
|
cargo build --release --features "debug"
|
||||||
|
|
||||||
|
36
README.md
36
README.md
@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
## Introduction
|
## Introduction
|
||||||
|
|
||||||
[Wasmer](https://wasmer.io/) is a standalone JIT WebAssembly runtime, aiming to be fully compatible with Emscripten, Rust and Go.
|
[Wasmer](https://wasmer.io/) is a standalone JIT WebAssembly runtime, aiming to be fully compatible with [WASI](https://hacks.mozilla.org/2019/03/standardizing-wasi-a-webassembly-system-interface/) and [Emscripten](https://emscripten.org/).
|
||||||
|
|
||||||
Install Wasmer with:
|
Install Wasmer with:
|
||||||
|
|
||||||
@ -26,19 +26,29 @@ Install Wasmer with:
|
|||||||
curl https://get.wasmer.io -sSfL | sh
|
curl https://get.wasmer.io -sSfL | sh
|
||||||
```
|
```
|
||||||
|
|
||||||
_**NEW ✨**: You can now embed Wasmer in your Rust application, check our [example repo](https://github.com/wasmerio/wasmer-rust-example) to see how!_
|
Wasmer runtime can also be embedded in different languages, so you can use WebAssembly anywhere ✨:
|
||||||
|
* [**Rust**](https://github.com/wasmerio/wasmer-rust-example)
|
||||||
|
* [**C/C++**](https://github.com/wasmerio/wasmer-c-api)
|
||||||
|
* [**PHP**](https://github.com/wasmerio/php-ext-wasm)
|
||||||
|
* [**Python**](https://github.com/wasmerio/python-ext-wasm)
|
||||||
|
|
||||||
### Usage
|
### Usage
|
||||||
|
|
||||||
Wasmer can execute both the standard binary format (`.wasm`) and the text
|
Wasmer can execute both the standard binary format (`.wasm`) and the text
|
||||||
format defined by the WebAssembly reference interpreter (`.wat`).
|
format defined by the WebAssembly reference interpreter (`.wat`).
|
||||||
|
|
||||||
Once installed, you will be able to run any WebAssembly files (_including nginx and Lua!_):
|
Once installed, you will be able to run any WebAssembly files (_including Lua, PHP, SQLite and nginx!_):
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
# Run Lua
|
# Run Lua
|
||||||
wasmer run examples/lua.wasm
|
wasmer run examples/lua.wasm
|
||||||
|
|
||||||
|
# Run PHP
|
||||||
|
wasmer run examples/php.wasm
|
||||||
|
|
||||||
|
# Run SQLite
|
||||||
|
wasmer run examples/sqlite.wasm
|
||||||
|
|
||||||
# Run nginx
|
# Run nginx
|
||||||
wasmer run examples/nginx/nginx.wasm -- -p examples/nginx -c nginx.conf
|
wasmer run examples/nginx/nginx.wasm -- -p examples/nginx -c nginx.conf
|
||||||
```
|
```
|
||||||
@ -70,6 +80,7 @@ Please select your operating system:
|
|||||||
|
|
||||||
- [macOS](#macos)
|
- [macOS](#macos)
|
||||||
- [Debian-based Linuxes](#debian-based-linuxes)
|
- [Debian-based Linuxes](#debian-based-linuxes)
|
||||||
|
- [FreeBSD](#freebsd)
|
||||||
- [Microsoft Windows](#windows-msvc)
|
- [Microsoft Windows](#windows-msvc)
|
||||||
|
|
||||||
#### macOS
|
#### macOS
|
||||||
@ -92,18 +103,30 @@ sudo port install cmake
|
|||||||
sudo apt install cmake
|
sudo apt install cmake
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### FreeBSD
|
||||||
|
|
||||||
|
```sh
|
||||||
|
pkg install cmake
|
||||||
|
```
|
||||||
|
|
||||||
#### Windows (MSVC)
|
#### Windows (MSVC)
|
||||||
|
|
||||||
Windows support is _highly experimental_. Only simple Wasm programs may be run, and no syscalls are allowed. This means
|
Windows support is _highly experimental_. Only simple Wasm programs may be run, and no syscalls are allowed. This means
|
||||||
nginx and Lua do not work on Windows. See [this issue](https://github.com/wasmerio/wasmer/issues/176) regarding Emscripten syscall polyfills for Windows.
|
nginx and Lua do not work on Windows. See [this issue](https://github.com/wasmerio/wasmer/issues/176) regarding Emscripten syscall polyfills for Windows.
|
||||||
|
|
||||||
1. Install [Python for Windows](https://www.python.org/downloads/release/python-2714/). The Windows x86-64 MSI installer is fine.
|
1. Install [Visual Studio](https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/?sku=Community&rel=15)
|
||||||
|
|
||||||
|
2. Install [Rust for Windows](https://win.rustup.rs)
|
||||||
|
|
||||||
|
3. Install [Python for Windows](https://www.python.org/downloads/release/python-2714/). The Windows x86-64 MSI installer is fine.
|
||||||
Make sure to enable "Add python.exe to Path" during installation.
|
Make sure to enable "Add python.exe to Path" during installation.
|
||||||
|
|
||||||
2. Install [Git for Windows](https://git-scm.com/download/win). Allow it to add `git.exe` to your PATH (default
|
4. Install [Git for Windows](https://git-scm.com/download/win). Allow it to add `git.exe` to your PATH (default
|
||||||
settings for the installer are fine).
|
settings for the installer are fine).
|
||||||
|
|
||||||
3. Install [CMake](https://cmake.org/download/). Ensure CMake is in your PATH.
|
5. Install [CMake](https://cmake.org/download/). Ensure CMake is in your PATH.
|
||||||
|
|
||||||
|
6. Install [LLVM 7.0](https://prereleases.llvm.org/win-snapshots/LLVM-7.0.0-r336178-win64.exe)
|
||||||
|
|
||||||
## Building
|
## Building
|
||||||
|
|
||||||
@ -158,6 +181,7 @@ 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)_
|
||||||
|
- [ ] Support WASI _(in the works)_
|
||||||
- [ ] Support Emscripten calls _(in the works)_
|
- [ ] Support Emscripten calls _(in the works)_
|
||||||
- [ ] Support Rust ABI calls
|
- [ ] Support Rust ABI calls
|
||||||
- [ ] Support Go ABI calls
|
- [ ] Support Go ABI calls
|
||||||
|
@ -23,8 +23,8 @@ initOS() {
|
|||||||
darwin) OS='darwin';;
|
darwin) OS='darwin';;
|
||||||
linux) OS='linux';;
|
linux) OS='linux';;
|
||||||
freebsd) OS='freebsd';;
|
freebsd) OS='freebsd';;
|
||||||
mingw*) OS='windows';;
|
# mingw*) OS='windows';;
|
||||||
msys*) OS='windows';;
|
# msys*) OS='windows';;
|
||||||
*) echo "OS ${OS} is not supported by this installation script"; exit 1;;
|
*) echo "OS ${OS} is not supported by this installation script"; exit 1;;
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
@ -34,11 +34,11 @@ initArch
|
|||||||
initOS
|
initOS
|
||||||
|
|
||||||
# determine install directory if required
|
# determine install directory if required
|
||||||
BINARY="wasmer-${OS}-${ARCH}"
|
BINARY="wasmer-${OS}-${ARCH}.tar.gz"
|
||||||
|
|
||||||
# add .exe if on windows
|
# add .exe if on windows
|
||||||
if [ "$OS" = "windows" ]; then
|
# if [ "$OS" = "windows" ]; then
|
||||||
BINARY="$BINARY.exe"
|
# BINARY="$BINARY.exe"
|
||||||
fi
|
# fi
|
||||||
|
|
||||||
echo "${BINARY}"
|
echo "${BINARY}"
|
||||||
|
10
bors.toml
Normal file
10
bors.toml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
status = [
|
||||||
|
"ci/circleci: lint",
|
||||||
|
"ci/circleci: test",
|
||||||
|
"ci/circleci: test-macos",
|
||||||
|
"ci/circleci: test-rust-nightly",
|
||||||
|
"continuous-integration/appveyor/branch"
|
||||||
|
]
|
||||||
|
required_approvals = 1
|
||||||
|
timeout_sec = 900
|
||||||
|
delete_merged_branches = true
|
39
docs/docker.md
Normal file
39
docs/docker.md
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
# Dockerfile Documentation
|
||||||
|
The `Dockerfile` included in the project root directory could be used for development purposes or to build a small image containing the `wasmer` executable.
|
||||||
|
|
||||||
|
The `wasmer-build-env` stage in the Dockerfile contains the dependencies needed to compile Wasmer including LLVM.
|
||||||
|
|
||||||
|
The `wasmer-debug-env` stage adds the `valgrind` profiling tool to the `wasmer-build-env` stage.
|
||||||
|
|
||||||
|
The `wasmer-build` stage in the Dockerfile will copy the current directory, assuming the build context is the `wasmer` project, and build the project using `cargo build --release`.
|
||||||
|
|
||||||
|
The `wasmer` stage will copy the resulting `wasmer` executable from the `wasmer-build` stage into a new base image to create a smaller image containing `wasmer`.
|
||||||
|
|
||||||
|
## Example Usages
|
||||||
|
|
||||||
|
### Wasmer image
|
||||||
|
1. From the `wasmer` project directory, build the image:
|
||||||
|
`docker build -t wasmer --target=wasmer .`
|
||||||
|
|
||||||
|
2. List options:
|
||||||
|
`docker run wasmer --help`
|
||||||
|
|
||||||
|
3. Mount a directory, and run an example wasm file:
|
||||||
|
`docker run -v /Users/admin/Documents/wasmer-workspace:/root/wasmer-workspace wasmer run /root/wasmer-workspace/examples/hello.wasm`
|
||||||
|
|
||||||
|
### Profiling
|
||||||
|
1. Build `wasmer-debug-env`:
|
||||||
|
`docker build --tag=wasmer-debug-env --target wasmer-debug-env .`
|
||||||
|
|
||||||
|
2. Mount a directory from the host and run interactively:
|
||||||
|
`docker run -it -v /Users/admin/Documents/wasmer-workspace:/home/circleci/wasmer-workspace wasmer-debug-env /bin/bash`
|
||||||
|
|
||||||
|
3. Inside the container, build `wasmer` and run profiling tool:
|
||||||
|
```
|
||||||
|
cd /home/circleci/wasmer-workspace/wasmer`
|
||||||
|
cargo build
|
||||||
|
valgrind --tool=callgrind --dump-instr=yes --collect-jumps=yes --simulate-cache=yes target/debug/wasmer run test.wasm
|
||||||
|
```
|
||||||
|
|
||||||
|
The `callgrind.out` can be viewed with the `qcachegrind` tool on Mac OS (`brew install qcachegrind`).
|
||||||
|
|
Binary file not shown.
26
examples/nginx/LICENSE
Normal file
26
examples/nginx/LICENSE
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2002-2019 Igor Sysoev
|
||||||
|
* Copyright (C) 2011-2019 Nginx, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
BIN
examples/php.wasm
Normal file
BIN
examples/php.wasm
Normal file
Binary file not shown.
37
examples/single_pass_tests/br_table.wat
Normal file
37
examples/single_pass_tests/br_table.wat
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
(module
|
||||||
|
(func $main (export "main")
|
||||||
|
(i32.eq (call $test (i32.const 0)) (i32.const 2))
|
||||||
|
(i32.eq (call $test (i32.const 1)) (i32.const 0))
|
||||||
|
(i32.eq (call $test (i32.const 2)) (i32.const 1))
|
||||||
|
(i32.eq (call $test (i32.const 3)) (i32.const 3))
|
||||||
|
(i32.eq (call $test (i32.const 4)) (i32.const 3))
|
||||||
|
(i32.and)
|
||||||
|
(i32.and)
|
||||||
|
(i32.and)
|
||||||
|
(i32.and)
|
||||||
|
(i32.const 1)
|
||||||
|
(i32.eq)
|
||||||
|
(br_if 0)
|
||||||
|
(unreachable)
|
||||||
|
)
|
||||||
|
|
||||||
|
(func $test (param $p i32) (result i32)
|
||||||
|
(block
|
||||||
|
(block
|
||||||
|
(block
|
||||||
|
(block
|
||||||
|
(block
|
||||||
|
(get_local $p)
|
||||||
|
(br_table 2 0 1 3)
|
||||||
|
)
|
||||||
|
(return (i32.const 0))
|
||||||
|
)
|
||||||
|
(return (i32.const 1))
|
||||||
|
)
|
||||||
|
(return (i32.const 2))
|
||||||
|
)
|
||||||
|
(return (i32.const 3))
|
||||||
|
)
|
||||||
|
(unreachable)
|
||||||
|
)
|
||||||
|
)
|
23
examples/single_pass_tests/call.wat
Normal file
23
examples/single_pass_tests/call.wat
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
(module
|
||||||
|
(func $main (export "main")
|
||||||
|
(local $a i32)
|
||||||
|
(block
|
||||||
|
(set_local $a (i32.const 33))
|
||||||
|
(i32.const 11)
|
||||||
|
(call $foo (get_local $a))
|
||||||
|
(i32.add)
|
||||||
|
(i32.const 86)
|
||||||
|
(i32.eq)
|
||||||
|
(br_if 0)
|
||||||
|
(unreachable)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
(func $foo (param $input i32) (result i32)
|
||||||
|
(local $a i32)
|
||||||
|
(set_local $a (i32.const 42))
|
||||||
|
(get_local $a)
|
||||||
|
(get_local $input)
|
||||||
|
(i32.add)
|
||||||
|
)
|
||||||
|
)
|
25
examples/single_pass_tests/call_indirect.wat
Normal file
25
examples/single_pass_tests/call_indirect.wat
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
(module
|
||||||
|
(type $binop (func (param i32 i32) (result i32)))
|
||||||
|
(table 1 100 anyfunc)
|
||||||
|
(elem (i32.const 5) $sub)
|
||||||
|
(elem (i32.const 10) $add)
|
||||||
|
|
||||||
|
(func $main (export "main")
|
||||||
|
(if (i32.eq (call_indirect (type $binop) (i32.const 42) (i32.const 1) (i32.const 10)) (i32.const 43))
|
||||||
|
(then)
|
||||||
|
(else unreachable)
|
||||||
|
)
|
||||||
|
(if (i32.eq (call_indirect (type $binop) (i32.const 42) (i32.const 1) (i32.const 5)) (i32.const 41))
|
||||||
|
(then)
|
||||||
|
(else unreachable)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
(func $add (param i32) (param i32) (result i32)
|
||||||
|
(i32.add (get_local 0) (get_local 1))
|
||||||
|
)
|
||||||
|
|
||||||
|
(func $sub (param i32) (param i32) (result i32)
|
||||||
|
(i32.sub (get_local 0) (get_local 1))
|
||||||
|
)
|
||||||
|
)
|
36
examples/single_pass_tests/div.wat
Normal file
36
examples/single_pass_tests/div.wat
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
(module
|
||||||
|
(func $main (export "main")
|
||||||
|
(i32.const 1)
|
||||||
|
(if (i32.ne (i32.div_s (i32.const 2) (i32.const -1)) (i32.const -2))
|
||||||
|
(then unreachable)
|
||||||
|
)
|
||||||
|
(i32.const 2)
|
||||||
|
(if (i32.ne (i32.div_u (i32.const 2) (i32.const -1)) (i32.const 0))
|
||||||
|
(then unreachable)
|
||||||
|
)
|
||||||
|
(i32.const 3)
|
||||||
|
(if (i32.ne (i32.div_u (i32.const 10) (i32.const 5)) (i32.const 2))
|
||||||
|
(then unreachable)
|
||||||
|
)
|
||||||
|
(i32.const 4)
|
||||||
|
(if (i64.ne (i64.div_s (i64.const 300000000000) (i64.const -1)) (i64.const -300000000000))
|
||||||
|
(then unreachable)
|
||||||
|
)
|
||||||
|
(i32.const 5)
|
||||||
|
(if (i64.ne (i64.div_u (i64.const 300000000000) (i64.const -1)) (i64.const 0))
|
||||||
|
(then unreachable)
|
||||||
|
)
|
||||||
|
(i32.const 6)
|
||||||
|
(if (i64.ne (i64.div_u (i64.const 300000000000) (i64.const 2)) (i64.const 150000000000))
|
||||||
|
(then unreachable)
|
||||||
|
)
|
||||||
|
(i32.add)
|
||||||
|
(i32.add)
|
||||||
|
(i32.add)
|
||||||
|
(i32.add)
|
||||||
|
(i32.add)
|
||||||
|
(if (i32.ne (i32.const 21))
|
||||||
|
(then unreachable)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
26
examples/single_pass_tests/global.wat
Normal file
26
examples/single_pass_tests/global.wat
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
(module
|
||||||
|
(global $g1 (mut i32) (i32.const 0))
|
||||||
|
(global $g2 (mut i32) (i32.const 99))
|
||||||
|
(func $main (export "main")
|
||||||
|
(if (i32.eq (get_global $g1) (i32.const 0))
|
||||||
|
(then)
|
||||||
|
(else unreachable)
|
||||||
|
)
|
||||||
|
(if (i32.eq (get_global $g2) (i32.const 99))
|
||||||
|
(then)
|
||||||
|
(else unreachable)
|
||||||
|
)
|
||||||
|
|
||||||
|
(set_global $g1 (i32.add (get_global $g1) (i32.const 1)))
|
||||||
|
(set_global $g2 (i32.sub (get_global $g2) (i32.const 1)))
|
||||||
|
|
||||||
|
(if (i32.eq (get_global $g1) (i32.const 1))
|
||||||
|
(then)
|
||||||
|
(else unreachable)
|
||||||
|
)
|
||||||
|
(if (i32.eq (get_global $g2) (i32.const 98))
|
||||||
|
(then)
|
||||||
|
(else unreachable)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
44
examples/single_pass_tests/i32.wat
Normal file
44
examples/single_pass_tests/i32.wat
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
(module
|
||||||
|
(func $main (export "main") (result i32)
|
||||||
|
(local $v1 i32)
|
||||||
|
(block
|
||||||
|
(i32.const 10)
|
||||||
|
(set_local $v1)
|
||||||
|
|
||||||
|
(i32.const 42)
|
||||||
|
(get_local $v1)
|
||||||
|
(i32.add)
|
||||||
|
(i32.const 53)
|
||||||
|
(i32.eq)
|
||||||
|
(br_if 0)
|
||||||
|
|
||||||
|
(i32.const 1)
|
||||||
|
(i32.const -100)
|
||||||
|
(i32.const 41)
|
||||||
|
(i32.lt_s)
|
||||||
|
(i32.sub)
|
||||||
|
(br_if 0)
|
||||||
|
|
||||||
|
(i32.const -100)
|
||||||
|
(i32.const 41)
|
||||||
|
(i32.lt_u)
|
||||||
|
(br_if 0)
|
||||||
|
|
||||||
|
(i32.const 1)
|
||||||
|
(i32.const 100)
|
||||||
|
(i32.const -41)
|
||||||
|
(i32.gt_s)
|
||||||
|
(i32.sub)
|
||||||
|
(br_if 0)
|
||||||
|
|
||||||
|
(i32.const 100)
|
||||||
|
(i32.const -41)
|
||||||
|
(i32.gt_u)
|
||||||
|
(br_if 0)
|
||||||
|
|
||||||
|
(i32.const 0)
|
||||||
|
(return)
|
||||||
|
)
|
||||||
|
(unreachable)
|
||||||
|
)
|
||||||
|
)
|
48
examples/single_pass_tests/i64.wat
Normal file
48
examples/single_pass_tests/i64.wat
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
(module
|
||||||
|
(func $main (export "main") (result i64)
|
||||||
|
(local $v1 i64)
|
||||||
|
(block
|
||||||
|
(i64.const 10)
|
||||||
|
(set_local $v1)
|
||||||
|
|
||||||
|
(i64.const 42)
|
||||||
|
(get_local $v1)
|
||||||
|
(i64.add)
|
||||||
|
(i64.const 53)
|
||||||
|
(i64.eq)
|
||||||
|
(br_if 0)
|
||||||
|
|
||||||
|
(i64.const 1)
|
||||||
|
(i64.const -100)
|
||||||
|
(i64.const 41)
|
||||||
|
(i64.lt_s)
|
||||||
|
(i64.extend_u/i32)
|
||||||
|
(i64.sub)
|
||||||
|
(i32.wrap/i64)
|
||||||
|
(br_if 0)
|
||||||
|
|
||||||
|
(i64.const -100)
|
||||||
|
(i64.const 41)
|
||||||
|
(i64.lt_u)
|
||||||
|
(br_if 0)
|
||||||
|
|
||||||
|
(i64.const 1)
|
||||||
|
(i64.const 100)
|
||||||
|
(i64.const -41)
|
||||||
|
(i64.gt_s)
|
||||||
|
(i64.extend_u/i32)
|
||||||
|
(i64.sub)
|
||||||
|
(i32.wrap/i64)
|
||||||
|
(br_if 0)
|
||||||
|
|
||||||
|
(i64.const 100)
|
||||||
|
(i64.const -41)
|
||||||
|
(i64.gt_u)
|
||||||
|
(br_if 0)
|
||||||
|
|
||||||
|
(i64.const 0)
|
||||||
|
(return)
|
||||||
|
)
|
||||||
|
(unreachable)
|
||||||
|
)
|
||||||
|
)
|
33
examples/single_pass_tests/if_else.wat
Normal file
33
examples/single_pass_tests/if_else.wat
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
(module
|
||||||
|
(func $main (export "main")
|
||||||
|
(local $a i32)
|
||||||
|
(set_local $a (i32.const 33))
|
||||||
|
|
||||||
|
(block
|
||||||
|
(call $foo (if (result i32) (i32.eq (get_local $a) (i32.const 33))
|
||||||
|
(then (i32.const 1))
|
||||||
|
(else (i32.const 2))
|
||||||
|
))
|
||||||
|
(i32.eq (i32.const 43))
|
||||||
|
(br_if 0)
|
||||||
|
(unreachable)
|
||||||
|
)
|
||||||
|
(block
|
||||||
|
(call $foo (if (result i32) (i32.eq (get_local $a) (i32.const 30))
|
||||||
|
(then (i32.const 1))
|
||||||
|
(else (i32.const 2))
|
||||||
|
))
|
||||||
|
(i32.eq (i32.const 44))
|
||||||
|
(br_if 0)
|
||||||
|
(unreachable)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
(func $foo (param $input i32) (result i32)
|
||||||
|
(local $a i32)
|
||||||
|
(set_local $a (i32.const 42))
|
||||||
|
(get_local $a)
|
||||||
|
(get_local $input)
|
||||||
|
(i32.add)
|
||||||
|
)
|
||||||
|
)
|
17
examples/single_pass_tests/loop.wat
Normal file
17
examples/single_pass_tests/loop.wat
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
(module
|
||||||
|
(func $main (export "main")
|
||||||
|
(local $count i32)
|
||||||
|
(local $sum i32)
|
||||||
|
(loop (result i32)
|
||||||
|
(set_local $count (i32.add (get_local $count) (i32.const 1)))
|
||||||
|
(set_local $sum (i32.add (get_local $sum) (get_local $count)))
|
||||||
|
(i32.sub (i32.const 1) (i32.eq
|
||||||
|
(get_local $count)
|
||||||
|
(i32.const 50000)
|
||||||
|
))
|
||||||
|
(br_if 0)
|
||||||
|
(get_local $sum)
|
||||||
|
)
|
||||||
|
(if (i32.ne (i32.const 1250025000)) (unreachable))
|
||||||
|
)
|
||||||
|
)
|
90
examples/single_pass_tests/memory.wat
Normal file
90
examples/single_pass_tests/memory.wat
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
(module
|
||||||
|
(memory 1)
|
||||||
|
(func $main (export "main")
|
||||||
|
(call $test_stack_layout)
|
||||||
|
)
|
||||||
|
|
||||||
|
(func $test_stack_layout
|
||||||
|
(local $addr i32)
|
||||||
|
(set_local $addr (i32.const 16))
|
||||||
|
|
||||||
|
(i32.store (get_local $addr) (i32.const 10))
|
||||||
|
(if (i32.eq (i32.load (i32.const 14)) (i32.const 655360))
|
||||||
|
(then)
|
||||||
|
(else (unreachable))
|
||||||
|
)
|
||||||
|
|
||||||
|
(i32.const 1)
|
||||||
|
(i32.store (get_local $addr) (i32.const 11))
|
||||||
|
(if (i32.eq (i32.load (i32.const 14)) (i32.const 720896))
|
||||||
|
(then)
|
||||||
|
(else (unreachable))
|
||||||
|
)
|
||||||
|
|
||||||
|
(i32.const 1)
|
||||||
|
(i32.store (get_local $addr) (i32.const 12))
|
||||||
|
(if (i32.eq (i32.load (i32.const 14)) (i32.const 786432))
|
||||||
|
(then)
|
||||||
|
(else (unreachable))
|
||||||
|
)
|
||||||
|
|
||||||
|
(i32.const 1)
|
||||||
|
(i32.store (get_local $addr) (i32.const 13))
|
||||||
|
(if (i32.eq (i32.load (i32.const 14)) (i32.const 851968))
|
||||||
|
(then)
|
||||||
|
(else (unreachable))
|
||||||
|
)
|
||||||
|
|
||||||
|
(i32.const 1)
|
||||||
|
(i32.store (get_local $addr) (i32.const 14))
|
||||||
|
(if (i32.eq (i32.load (i32.const 14)) (i32.const 917504))
|
||||||
|
(then)
|
||||||
|
(else (unreachable))
|
||||||
|
)
|
||||||
|
|
||||||
|
(i32.const 1)
|
||||||
|
(i32.store (get_local $addr) (i32.const 15))
|
||||||
|
(if (i32.eq (i32.load (i32.const 14)) (i32.const 983040))
|
||||||
|
(then)
|
||||||
|
(else (unreachable))
|
||||||
|
)
|
||||||
|
|
||||||
|
(i32.const 1)
|
||||||
|
(i32.store (get_local $addr) (i32.const 16))
|
||||||
|
(if (i32.eq (i32.load (i32.const 14)) (i32.const 1048576))
|
||||||
|
(then)
|
||||||
|
(else (unreachable))
|
||||||
|
)
|
||||||
|
|
||||||
|
(i32.const 1)
|
||||||
|
(i32.store (get_local $addr) (i32.const 17))
|
||||||
|
(if (i32.eq (i32.load (i32.const 14)) (i32.const 1114112))
|
||||||
|
(then)
|
||||||
|
(else (unreachable))
|
||||||
|
)
|
||||||
|
|
||||||
|
(i32.const 1)
|
||||||
|
(i32.store (get_local $addr) (i32.const 18))
|
||||||
|
(if (i32.eq (i32.load (i32.const 14)) (i32.const 1179648))
|
||||||
|
(then)
|
||||||
|
(else (unreachable))
|
||||||
|
)
|
||||||
|
|
||||||
|
(i32.const 1)
|
||||||
|
(i32.store (get_local $addr) (i32.const 19))
|
||||||
|
(if (i32.eq (i32.load (i32.const 14)) (i32.const 1245184))
|
||||||
|
(then)
|
||||||
|
(else (unreachable))
|
||||||
|
)
|
||||||
|
|
||||||
|
(drop)
|
||||||
|
(drop)
|
||||||
|
(drop)
|
||||||
|
(drop)
|
||||||
|
(drop)
|
||||||
|
(drop)
|
||||||
|
(drop)
|
||||||
|
(drop)
|
||||||
|
(drop)
|
||||||
|
)
|
||||||
|
)
|
20
examples/single_pass_tests/select.wat
Normal file
20
examples/single_pass_tests/select.wat
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
(module
|
||||||
|
(func $main (export "main")
|
||||||
|
(if (i32.eq (select
|
||||||
|
(i32.const 10)
|
||||||
|
(i32.const 20)
|
||||||
|
(i32.const 1)
|
||||||
|
) (i32.const 10))
|
||||||
|
(then)
|
||||||
|
(else (unreachable))
|
||||||
|
)
|
||||||
|
(if (i32.eq (select
|
||||||
|
(i32.const 10)
|
||||||
|
(i32.const 20)
|
||||||
|
(i32.const 0)
|
||||||
|
) (i32.const 20))
|
||||||
|
(then)
|
||||||
|
(else (unreachable))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
11
examples/single_pass_tests/tee_local.wat
Normal file
11
examples/single_pass_tests/tee_local.wat
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
(module
|
||||||
|
(func $main (export "main")
|
||||||
|
(local $x i32)
|
||||||
|
(tee_local $x (i32.const 3))
|
||||||
|
(i32.add (i32.const 4))
|
||||||
|
(if (i32.eq (i32.const 7))
|
||||||
|
(then)
|
||||||
|
(else unreachable)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
38
examples/single_pass_tests/unwinding.wat
Normal file
38
examples/single_pass_tests/unwinding.wat
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
(module
|
||||||
|
(func $main (export "main")
|
||||||
|
(i32.const 5)
|
||||||
|
(block (result i32)
|
||||||
|
(i32.const 10)
|
||||||
|
(block
|
||||||
|
(i32.const 20)
|
||||||
|
(block
|
||||||
|
(i32.const 50)
|
||||||
|
(br 1)
|
||||||
|
)
|
||||||
|
(unreachable)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(i32.add)
|
||||||
|
(if (i32.eq (i32.const 15))
|
||||||
|
(then)
|
||||||
|
(else unreachable)
|
||||||
|
)
|
||||||
|
|
||||||
|
(block (result i32)
|
||||||
|
(i32.const 10)
|
||||||
|
(block (result i32)
|
||||||
|
(i32.const 20)
|
||||||
|
(block
|
||||||
|
(i32.const 50)
|
||||||
|
(br 1)
|
||||||
|
)
|
||||||
|
(unreachable)
|
||||||
|
)
|
||||||
|
(i32.add)
|
||||||
|
)
|
||||||
|
(if (i32.eq (i32.const 60))
|
||||||
|
(then)
|
||||||
|
(else unreachable)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
BIN
examples/sqlite.wasm
Normal file
BIN
examples/sqlite.wasm
Normal file
Binary file not shown.
19
install.sh
19
install.sh
@ -32,6 +32,7 @@ white="\033[37m"
|
|||||||
bold="\e[1m"
|
bold="\e[1m"
|
||||||
dim="\e[2m"
|
dim="\e[2m"
|
||||||
|
|
||||||
|
# Warning: Remove this on the public repo
|
||||||
RELEASES_URL="https://github.com/wasmerio/wasmer/releases"
|
RELEASES_URL="https://github.com/wasmerio/wasmer/releases"
|
||||||
|
|
||||||
wasmer_download_json() {
|
wasmer_download_json() {
|
||||||
@ -133,7 +134,7 @@ wasmer_link() {
|
|||||||
SOURCE_STR="# Wasmer config\nexport WASMER_DIR=\"\$HOME/.wasmer\"\nexport WASMER_CACHE_DIR=\"\$WASMER_DIR/cache\"\nexport PATH=\"\$HOME/.wasmer/bin:\$PATH\"\n"
|
SOURCE_STR="# Wasmer config\nexport WASMER_DIR=\"\$HOME/.wasmer\"\nexport WASMER_CACHE_DIR=\"\$WASMER_DIR/cache\"\nexport PATH=\"\$HOME/.wasmer/bin:\$PATH\"\n"
|
||||||
|
|
||||||
# We create the wasmer.sh file
|
# We create the wasmer.sh file
|
||||||
echo "$SOURCE_STR" > "$HOME/.wasmer/wasmer.sh"
|
printf "$SOURCE_STR" > "$HOME/.wasmer/wasmer.sh"
|
||||||
|
|
||||||
if [ -z "${WASMER_PROFILE-}" ] ; then
|
if [ -z "${WASMER_PROFILE-}" ] ; then
|
||||||
printf "${red}Profile not found. Tried:\n* ${WASMER_PROFILE} (as defined in \$PROFILE)\n* ~/.bashrc\n* ~/.bash_profile\n* ~/.zshrc\n* ~/.profile.\n"
|
printf "${red}Profile not found. Tried:\n* ${WASMER_PROFILE} (as defined in \$PROFILE)\n* ~/.bashrc\n* ~/.bash_profile\n* ~/.zshrc\n* ~/.profile.\n"
|
||||||
@ -369,12 +370,12 @@ wasmer_download() {
|
|||||||
WASMER=INSTALL_DIRECTORY
|
WASMER=INSTALL_DIRECTORY
|
||||||
|
|
||||||
# assemble expected release artifact name
|
# assemble expected release artifact name
|
||||||
BINARY="wasmer-${OS}-${ARCH}"
|
BINARY="wasmer-${OS}-${ARCH}.tar.gz"
|
||||||
|
|
||||||
# add .exe if on windows
|
# add .exe if on windows
|
||||||
if [ "$OS" = "windows" ]; then
|
# if [ "$OS" = "windows" ]; then
|
||||||
BINARY="$BINARY.exe"
|
# BINARY="$BINARY.exe"
|
||||||
fi
|
# fi
|
||||||
|
|
||||||
# if WASMER_RELEASE_TAG was not provided, assume latest
|
# if WASMER_RELEASE_TAG was not provided, assume latest
|
||||||
if [ -z "$WASMER_RELEASE_TAG" ]; then
|
if [ -z "$WASMER_RELEASE_TAG" ]; then
|
||||||
@ -417,9 +418,6 @@ wasmer_download() {
|
|||||||
printf "\033[K\n\033[1A"
|
printf "\033[K\n\033[1A"
|
||||||
# printf "\033[1A$cyan> Downloaded$reset\033[K\n"
|
# printf "\033[1A$cyan> Downloaded$reset\033[K\n"
|
||||||
# echo "Setting executable permissions."
|
# echo "Setting executable permissions."
|
||||||
chmod +x "$DOWNLOAD_FILE"
|
|
||||||
|
|
||||||
INSTALL_NAME="wasmer"
|
|
||||||
|
|
||||||
# windows not supported yet
|
# windows not supported yet
|
||||||
# if [ "$OS" = "windows" ]; then
|
# if [ "$OS" = "windows" ]; then
|
||||||
@ -428,8 +426,9 @@ wasmer_download() {
|
|||||||
|
|
||||||
# echo "Moving executable to $INSTALL_DIRECTORY/$INSTALL_NAME"
|
# echo "Moving executable to $INSTALL_DIRECTORY/$INSTALL_NAME"
|
||||||
|
|
||||||
mkdir -p $INSTALL_DIRECTORY/bin
|
mkdir -p $INSTALL_DIRECTORY
|
||||||
mv "$DOWNLOAD_FILE" "$INSTALL_DIRECTORY/bin/$INSTALL_NAME"
|
# Untar the wasmer contents in the install directory
|
||||||
|
tar -C $INSTALL_DIRECTORY -zxvf $DOWNLOAD_FILE
|
||||||
}
|
}
|
||||||
|
|
||||||
wasmer_verify_or_quit() {
|
wasmer_verify_or_quit() {
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
#! /bin/bash
|
#! /bin/bash
|
||||||
|
|
||||||
nohup ./target/release/wasmer run examples/lua.wasm &
|
nohup ./target/release/wasmer run examples/lua.wasm --disable-cache -- -v
|
||||||
sleep 3s
|
|
||||||
|
|
||||||
if grep "Lua 5.4.0 Copyright (C) 1994-2018 Lua.org, PUC-Rio" ./nohup.out
|
if grep "Lua 5.4.0 Copyright (C) 1994-2018 Lua.org, PUC-Rio" ./nohup.out
|
||||||
then
|
then
|
||||||
|
@ -1,22 +1,14 @@
|
|||||||
#! /bin/bash
|
#! /bin/bash
|
||||||
|
|
||||||
nohup ./target/release/wasmer run examples/nginx/nginx.wasm -- -p integration_tests/nginx/ -c nginx.conf &
|
nohup ./target/release/wasmer run examples/nginx/nginx.wasm --disable-cache -- -v
|
||||||
sleep 3s
|
|
||||||
|
|
||||||
curl localhost:8080 > ./nginx.out
|
if grep "nginx version: nginx/1.15.3" ./nohup.out
|
||||||
|
|
||||||
|
|
||||||
if grep "wasmer" ./nginx.out
|
|
||||||
then
|
then
|
||||||
echo "nginx integration test succeeded"
|
echo "nginx integration test succeeded"
|
||||||
rm ./nohup.out
|
rm ./nohup.out
|
||||||
rm ./nginx.out
|
|
||||||
rm -rf ./integration_tests/nginx/*_temp
|
|
||||||
exit 0
|
exit 0
|
||||||
else
|
else
|
||||||
echo "nginx integration test failed"
|
echo "nginx integration test failed"
|
||||||
rm ./nohup.out
|
rm ./nohup.out
|
||||||
rm ./nginx.out
|
|
||||||
rm -rf ./integration_tests/nginx/*_temp
|
|
||||||
exit -1
|
exit -1
|
||||||
fi
|
fi
|
||||||
|
@ -22,7 +22,8 @@ The integration builds on the Wasmer runtime and allow us to run WebAssembly fil
|
|||||||
|
|
||||||
Wasmer intends to support different integrations:
|
Wasmer intends to support different integrations:
|
||||||
|
|
||||||
- [emscripten](./emscripten): run Emscripten-generated WebAssembly files, such as [Lua](../examples/lua.wasm) or [nginx](../examples/nginx/nginx.wasm).
|
- [WASI](./wasi): run WebAssembly files with the [WASI ABI](https://hacks.mozilla.org/2019/03/standardizing-wasi-a-webassembly-system-interface/).
|
||||||
|
- [Emscripten](./emscripten): run Emscripten-generated WebAssembly files, such as [Lua](../examples/lua.wasm) or [nginx](../examples/nginx/nginx.wasm).
|
||||||
- Go ABI: _we will work on this soon! Want to give us a hand? ✋_
|
- Go ABI: _we will work on this soon! Want to give us a hand? ✋_
|
||||||
- Blazor: _research period, see [tracking issue](https://github.com/wasmerio/wasmer/issues/97)_
|
- Blazor: _research period, see [tracking issue](https://github.com/wasmerio/wasmer/issues/97)_
|
||||||
|
|
||||||
@ -31,6 +32,8 @@ Wasmer intends to support different integrations:
|
|||||||
The Wasmer [runtime](./runtime) is designed to support multiple compiler backends, allowing the user
|
The Wasmer [runtime](./runtime) is designed to support multiple compiler backends, allowing the user
|
||||||
to tune the codegen properties (compile speed, performance, etc) to best fit their use case.
|
to tune the codegen properties (compile speed, performance, etc) to best fit their use case.
|
||||||
|
|
||||||
Currently, we support a Cranelift compiler backend:
|
Currently, we support multiple backends for compiling WebAssembly to machine code:
|
||||||
|
|
||||||
- [clif-backend](./clif-backend/): The integration of Wasmer with Cranelift
|
- [singlepass-backend](./singlepass-backend/): Single pass backend - super fast compilation, slower runtime speed
|
||||||
|
- [clif-backend](./clif-backend/): Cranelift backend - slower compilation, normal runtime speed
|
||||||
|
- [llvm-backend](./llvm-backend/): LLVM backend - slow compilation, native runtime speed
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "wasmer-clif-backend"
|
name = "wasmer-clif-backend"
|
||||||
version = "0.1.2"
|
version = "0.3.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>"]
|
||||||
@ -8,17 +8,18 @@ repository = "https://github.com/wasmerio/wasmer"
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
wasmer-runtime-core = { path = "../runtime-core", version = "0.1.2" }
|
wasmer-runtime-core = { path = "../runtime-core", version = "0.3.0" }
|
||||||
cranelift-native = "0.26.0"
|
cranelift-native = "0.30.0"
|
||||||
cranelift-codegen = "0.26.0"
|
cranelift-codegen = "0.30.0"
|
||||||
cranelift-entity = "0.26.0"
|
cranelift-entity = "0.30.0"
|
||||||
cranelift-wasm = "0.26.0"
|
cranelift-wasm = "0.30.0"
|
||||||
hashbrown = "0.1"
|
hashbrown = "0.1"
|
||||||
target-lexicon = "0.2.0"
|
target-lexicon = "0.3.0"
|
||||||
wasmparser = "0.23.0"
|
wasmparser = "0.23.0"
|
||||||
byteorder = "1"
|
byteorder = "1"
|
||||||
nix = "0.13.0"
|
nix = "0.13.0"
|
||||||
libc = "0.2.48"
|
libc = "0.2.49"
|
||||||
|
rayon = "1.0"
|
||||||
|
|
||||||
# Dependencies for caching.
|
# Dependencies for caching.
|
||||||
[dependencies.serde]
|
[dependencies.serde]
|
||||||
@ -32,7 +33,7 @@ version = "0.0.7"
|
|||||||
|
|
||||||
[target.'cfg(windows)'.dependencies]
|
[target.'cfg(windows)'.dependencies]
|
||||||
winapi = { version = "0.3", features = ["errhandlingapi", "minwindef", "minwinbase", "winnt"] }
|
winapi = { version = "0.3", features = ["errhandlingapi", "minwindef", "minwinbase", "winnt"] }
|
||||||
wasmer-win-exception-handler = { path = "../win-exception-handler", version = "0.0.1" }
|
wasmer-win-exception-handler = { path = "../win-exception-handler", version = "0.3.0" }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
debug = ["wasmer-runtime-core/debug"]
|
debug = ["wasmer-runtime-core/debug"]
|
||||||
|
31
lib/clif-backend/README.md
Normal file
31
lib/clif-backend/README.md
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<p align="center">
|
||||||
|
<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">
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<a href="https://circleci.com/gh/wasmerio/wasmer/">
|
||||||
|
<img src="https://img.shields.io/circleci/project/github/wasmerio/wasmer/master.svg" alt="Build Status">
|
||||||
|
</a>
|
||||||
|
<a href="https://github.com/wasmerio/wasmer/blob/master/LICENSE">
|
||||||
|
<img src="https://img.shields.io/github/license/wasmerio/wasmer.svg" alt="License">
|
||||||
|
</a>
|
||||||
|
<a href="https://spectrum.chat/wasmer">
|
||||||
|
<img src="https://withspectrum.github.io/badge/badge.svg" alt="Join the Wasmer Community">
|
||||||
|
</a>
|
||||||
|
<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">
|
||||||
|
</a>
|
||||||
|
<a href="https://docs.rs/wasmer-clif-backend">
|
||||||
|
<img src="https://docs.rs/wasmer-clif-backend/badge.svg" alt="Read our API documentation">
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
# Wasmer Cranelift backend
|
||||||
|
|
||||||
|
Wasmer is a standalone JIT WebAssembly runtime, aiming to be fully
|
||||||
|
compatible with Emscripten, Rust and Go. [Learn
|
||||||
|
more](https://github.com/wasmerio/wasmer).
|
||||||
|
|
||||||
|
This crate represents the Cranelift backend.
|
@ -27,18 +27,12 @@ impl CacheGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl CacheGen for CacheGenerator {
|
impl CacheGen for CacheGenerator {
|
||||||
fn generate_cache(
|
fn generate_cache(&self) -> Result<(Box<[u8]>, Memory), Error> {
|
||||||
&self,
|
|
||||||
module: &ModuleInner,
|
|
||||||
) -> Result<(Box<ModuleInfo>, Box<[u8]>, Memory), Error> {
|
|
||||||
let info = Box::new(module.info.clone());
|
|
||||||
|
|
||||||
// Clone the memory to a new location. This could take a long time,
|
// Clone the memory to a new location. This could take a long time,
|
||||||
// depending on the throughput of your memcpy implementation.
|
// depending on the throughput of your memcpy implementation.
|
||||||
let compiled_code = (*self.memory).clone();
|
let compiled_code = (*self.memory).clone();
|
||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
info,
|
|
||||||
self.backend_cache.into_backend_data()?.into_boxed_slice(),
|
self.backend_cache.into_backend_data()?.into_boxed_slice(),
|
||||||
compiled_code,
|
compiled_code,
|
||||||
))
|
))
|
||||||
|
@ -445,6 +445,12 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
|||||||
|
|
||||||
pos.ins().symbol_value(ir::types::I64, sig_index_global)
|
pos.ins().symbol_value(ir::types::I64, sig_index_global)
|
||||||
|
|
||||||
|
// let dynamic_sigindices_array_ptr = pos.ins().load(
|
||||||
|
// ptr_type,
|
||||||
|
// mflags,
|
||||||
|
|
||||||
|
// )
|
||||||
|
|
||||||
// let expected_sig = pos.ins().iconst(ir::types::I32, sig_index.index() as i64);
|
// let expected_sig = pos.ins().iconst(ir::types::I32, sig_index.index() as i64);
|
||||||
|
|
||||||
// self.env.deduplicated[clif_sig_index]
|
// self.env.deduplicated[clif_sig_index]
|
||||||
@ -477,9 +483,10 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
|||||||
call_args: &[ir::Value],
|
call_args: &[ir::Value],
|
||||||
) -> cranelift_wasm::WasmResult<ir::Inst> {
|
) -> cranelift_wasm::WasmResult<ir::Inst> {
|
||||||
let callee_index: FuncIndex = Converter(clif_callee_index).into();
|
let callee_index: FuncIndex = Converter(clif_callee_index).into();
|
||||||
|
let ptr_type = self.pointer_type();
|
||||||
|
|
||||||
match callee_index.local_or_import(&self.env.module.info) {
|
match callee_index.local_or_import(&self.env.module.info) {
|
||||||
LocalOrImport::Local(_) => {
|
LocalOrImport::Local(local_function_index) => {
|
||||||
// this is an internal function
|
// this is an internal function
|
||||||
let vmctx = pos
|
let vmctx = pos
|
||||||
.func
|
.func
|
||||||
@ -490,10 +497,28 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
|||||||
args.push(vmctx);
|
args.push(vmctx);
|
||||||
args.extend(call_args.iter().cloned());
|
args.extend(call_args.iter().cloned());
|
||||||
|
|
||||||
Ok(pos.ins().call(callee, &args))
|
let sig_ref = pos.func.dfg.ext_funcs[callee].signature;
|
||||||
|
let function_ptr = {
|
||||||
|
let mflags = ir::MemFlags::trusted();
|
||||||
|
|
||||||
|
let function_array_ptr = pos.ins().load(
|
||||||
|
ptr_type,
|
||||||
|
mflags,
|
||||||
|
vmctx,
|
||||||
|
vm::Ctx::offset_local_functions() as i32,
|
||||||
|
);
|
||||||
|
|
||||||
|
pos.ins().load(
|
||||||
|
ptr_type,
|
||||||
|
mflags,
|
||||||
|
function_array_ptr,
|
||||||
|
(local_function_index.index() as i32) * 8,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(pos.ins().call_indirect(sig_ref, function_ptr, &args))
|
||||||
}
|
}
|
||||||
LocalOrImport::Import(imported_func_index) => {
|
LocalOrImport::Import(imported_func_index) => {
|
||||||
let ptr_type = self.pointer_type();
|
|
||||||
// this is an imported function
|
// this is an imported function
|
||||||
let vmctx = pos.func.create_global_value(ir::GlobalValueData::VMContext);
|
let vmctx = pos.func.create_global_value(ir::GlobalValueData::VMContext);
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ use target_lexicon::Triple;
|
|||||||
|
|
||||||
use wasmer_runtime_core::cache::{Artifact, Error as CacheError};
|
use wasmer_runtime_core::cache::{Artifact, Error as CacheError};
|
||||||
use wasmer_runtime_core::{
|
use wasmer_runtime_core::{
|
||||||
backend::{Compiler, Token},
|
backend::{Compiler, CompilerConfig, Token},
|
||||||
error::{CompileError, CompileResult},
|
error::{CompileError, CompileResult},
|
||||||
module::ModuleInner,
|
module::ModuleInner,
|
||||||
};
|
};
|
||||||
@ -24,6 +24,7 @@ use wasmer_runtime_core::{
|
|||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate serde_derive;
|
extern crate serde_derive;
|
||||||
|
|
||||||
|
extern crate rayon;
|
||||||
extern crate serde;
|
extern crate serde;
|
||||||
|
|
||||||
use wasmparser::{self, WasmDecoder};
|
use wasmparser::{self, WasmDecoder};
|
||||||
@ -38,12 +39,17 @@ impl CraneliftCompiler {
|
|||||||
|
|
||||||
impl Compiler for CraneliftCompiler {
|
impl Compiler for CraneliftCompiler {
|
||||||
/// Compiles wasm binary to a wasmer module.
|
/// Compiles wasm binary to a wasmer module.
|
||||||
fn compile(&self, wasm: &[u8], _: Token) -> CompileResult<ModuleInner> {
|
fn compile(
|
||||||
|
&self,
|
||||||
|
wasm: &[u8],
|
||||||
|
compiler_config: CompilerConfig,
|
||||||
|
_: Token,
|
||||||
|
) -> CompileResult<ModuleInner> {
|
||||||
validate(wasm)?;
|
validate(wasm)?;
|
||||||
|
|
||||||
let isa = get_isa();
|
let isa = get_isa();
|
||||||
|
|
||||||
let mut module = module::Module::new(wasm);
|
let mut module = module::Module::new(&compiler_config);
|
||||||
let module_env = module_env::ModuleEnv::new(&mut module, &*isa);
|
let module_env = module_env::ModuleEnv::new(&mut module, &*isa);
|
||||||
|
|
||||||
let func_bodies = module_env.translate(wasm)?;
|
let func_bodies = module_env.translate(wasm)?;
|
||||||
|
@ -10,7 +10,7 @@ use std::sync::Arc;
|
|||||||
use wasmer_runtime_core::cache::{Artifact, Error as CacheError};
|
use wasmer_runtime_core::cache::{Artifact, Error as CacheError};
|
||||||
|
|
||||||
use wasmer_runtime_core::{
|
use wasmer_runtime_core::{
|
||||||
backend::Backend,
|
backend::{Backend, CompilerConfig},
|
||||||
error::CompileResult,
|
error::CompileResult,
|
||||||
module::{ModuleInfo, ModuleInner, StringTable},
|
module::{ModuleInfo, ModuleInner, StringTable},
|
||||||
structures::{Map, TypedIndex},
|
structures::{Map, TypedIndex},
|
||||||
@ -25,7 +25,7 @@ pub struct Module {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Module {
|
impl Module {
|
||||||
pub fn new(wasm: &[u8]) -> Self {
|
pub fn new(compiler_config: &CompilerConfig) -> Self {
|
||||||
Self {
|
Self {
|
||||||
info: ModuleInfo {
|
info: ModuleInfo {
|
||||||
memories: Map::new(),
|
memories: Map::new(),
|
||||||
@ -50,6 +50,9 @@ impl Module {
|
|||||||
|
|
||||||
namespace_table: StringTable::new(),
|
namespace_table: StringTable::new(),
|
||||||
name_table: StringTable::new(),
|
name_table: StringTable::new(),
|
||||||
|
em_symbol_map: compiler_config.symbol_map.clone(),
|
||||||
|
|
||||||
|
custom_sections: HashMap::new(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -70,16 +73,15 @@ impl Module {
|
|||||||
handler_data.clone(),
|
handler_data.clone(),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let protected_caller = Caller::new(&self.info, handler_data, trampolines);
|
|
||||||
|
|
||||||
let cache_gen = Box::new(CacheGenerator::new(
|
let cache_gen = Box::new(CacheGenerator::new(
|
||||||
backend_cache,
|
backend_cache,
|
||||||
Arc::clone(&func_resolver.memory),
|
Arc::clone(&func_resolver.memory),
|
||||||
));
|
));
|
||||||
|
|
||||||
|
let runnable_module = Caller::new(handler_data, trampolines, func_resolver);
|
||||||
|
|
||||||
Ok(ModuleInner {
|
Ok(ModuleInner {
|
||||||
func_resolver: Box::new(func_resolver),
|
runnable_module: Box::new(runnable_module),
|
||||||
protected_caller: Box::new(protected_caller),
|
|
||||||
cache_gen,
|
cache_gen,
|
||||||
|
|
||||||
info: self.info,
|
info: self.info,
|
||||||
@ -100,16 +102,15 @@ impl Module {
|
|||||||
)
|
)
|
||||||
.map_err(|e| CacheError::Unknown(format!("{:?}", e)))?;
|
.map_err(|e| CacheError::Unknown(format!("{:?}", e)))?;
|
||||||
|
|
||||||
let protected_caller = Caller::new(&info, handler_data, trampolines);
|
|
||||||
|
|
||||||
let cache_gen = Box::new(CacheGenerator::new(
|
let cache_gen = Box::new(CacheGenerator::new(
|
||||||
backend_cache,
|
backend_cache,
|
||||||
Arc::clone(&func_resolver.memory),
|
Arc::clone(&func_resolver.memory),
|
||||||
));
|
));
|
||||||
|
|
||||||
|
let runnable_module = Caller::new(handler_data, trampolines, func_resolver);
|
||||||
|
|
||||||
Ok(ModuleInner {
|
Ok(ModuleInner {
|
||||||
func_resolver: Box::new(func_resolver),
|
runnable_module: Box::new(runnable_module),
|
||||||
protected_caller: Box::new(protected_caller),
|
|
||||||
cache_gen,
|
cache_gen,
|
||||||
|
|
||||||
info,
|
info,
|
||||||
@ -148,8 +149,8 @@ convert_clif_to_runtime_index![
|
|||||||
(SignatureIndex: SigIndex),
|
(SignatureIndex: SigIndex),
|
||||||
];
|
];
|
||||||
|
|
||||||
impl<'a> From<Converter<&'a ir::Signature>> for FuncSig {
|
impl From<Converter<ir::Signature>> for FuncSig {
|
||||||
fn from(signature: Converter<&'a ir::Signature>) -> Self {
|
fn from(signature: Converter<ir::Signature>) -> Self {
|
||||||
FuncSig::new(
|
FuncSig::new(
|
||||||
signature
|
signature
|
||||||
.0
|
.0
|
||||||
|
@ -4,7 +4,6 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use cranelift_codegen::{ir, isa};
|
use cranelift_codegen::{ir, isa};
|
||||||
use cranelift_wasm::{self, translate_module, FuncTranslator, ModuleEnvironment};
|
use cranelift_wasm::{self, translate_module, FuncTranslator, ModuleEnvironment};
|
||||||
use std::sync::Arc;
|
|
||||||
use wasmer_runtime_core::{
|
use wasmer_runtime_core::{
|
||||||
error::{CompileError, CompileResult},
|
error::{CompileError, CompileResult},
|
||||||
module::{
|
module::{
|
||||||
@ -51,6 +50,20 @@ impl<'module, 'isa> ModuleEnv<'module, 'isa> {
|
|||||||
|
|
||||||
Ok(self.func_bodies)
|
Ok(self.func_bodies)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return the global for the given global index.
|
||||||
|
pub fn get_global(&self, global_index: cranelift_wasm::GlobalIndex) -> &cranelift_wasm::Global {
|
||||||
|
&self.globals[Converter(global_index).into()]
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the signature index for the given function index.
|
||||||
|
pub fn get_func_type(
|
||||||
|
&self,
|
||||||
|
func_index: cranelift_wasm::FuncIndex,
|
||||||
|
) -> cranelift_wasm::SignatureIndex {
|
||||||
|
let sig_index: SigIndex = self.module.info.func_assoc[Converter(func_index).into()];
|
||||||
|
Converter(sig_index).into()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'module, 'isa, 'data> ModuleEnvironment<'data> for ModuleEnv<'module, 'isa> {
|
impl<'module, 'isa, 'data> ModuleEnvironment<'data> for ModuleEnv<'module, 'isa> {
|
||||||
@ -60,17 +73,9 @@ impl<'module, 'isa, 'data> ModuleEnvironment<'data> for ModuleEnv<'module, 'isa>
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Declares a function signature to the environment.
|
/// Declares a function signature to the environment.
|
||||||
fn declare_signature(&mut self, sig: &ir::Signature) {
|
fn declare_signature(&mut self, sig: ir::Signature) {
|
||||||
self.signatures.push(sig.clone());
|
self.signatures.push(sig.clone());
|
||||||
self.module
|
self.module.info.signatures.push(Converter(sig).into());
|
||||||
.info
|
|
||||||
.signatures
|
|
||||||
.push(Arc::new(Converter(sig).into()));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the signature with the given index.
|
|
||||||
fn get_signature(&self, clif_sig_index: cranelift_wasm::SignatureIndex) -> &ir::Signature {
|
|
||||||
&self.signatures[Converter(clif_sig_index).into()]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Declares a function import to the environment.
|
/// Declares a function import to the environment.
|
||||||
@ -96,11 +101,6 @@ impl<'module, 'isa, 'data> ModuleEnvironment<'data> for ModuleEnv<'module, 'isa>
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the number of imported funcs.
|
|
||||||
fn get_num_func_imports(&self) -> usize {
|
|
||||||
self.module.info.imported_functions.len()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Declares the type (signature) of a local function in the module.
|
/// Declares the type (signature) of a local function in the module.
|
||||||
fn declare_func_type(&mut self, clif_sig_index: cranelift_wasm::SignatureIndex) {
|
fn declare_func_type(&mut self, clif_sig_index: cranelift_wasm::SignatureIndex) {
|
||||||
// We convert the cranelift signature index to
|
// We convert the cranelift signature index to
|
||||||
@ -110,15 +110,6 @@ impl<'module, 'isa, 'data> ModuleEnvironment<'data> for ModuleEnv<'module, 'isa>
|
|||||||
self.module.info.func_assoc.push(sig_index);
|
self.module.info.func_assoc.push(sig_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the signature index for the given function index.
|
|
||||||
fn get_func_type(
|
|
||||||
&self,
|
|
||||||
func_index: cranelift_wasm::FuncIndex,
|
|
||||||
) -> cranelift_wasm::SignatureIndex {
|
|
||||||
let sig_index: SigIndex = self.module.info.func_assoc[Converter(func_index).into()];
|
|
||||||
Converter(sig_index).into()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Declares a global to the environment.
|
/// Declares a global to the environment.
|
||||||
fn declare_global(&mut self, global: cranelift_wasm::Global) {
|
fn declare_global(&mut self, global: cranelift_wasm::Global) {
|
||||||
let desc = GlobalDescriptor {
|
let desc = GlobalDescriptor {
|
||||||
@ -184,11 +175,6 @@ impl<'module, 'isa, 'data> ModuleEnvironment<'data> for ModuleEnv<'module, 'isa>
|
|||||||
self.globals.push(global);
|
self.globals.push(global);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the global for the given global index.
|
|
||||||
fn get_global(&self, global_index: cranelift_wasm::GlobalIndex) -> &cranelift_wasm::Global {
|
|
||||||
&self.globals[Converter(global_index).into()]
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Declares a table to the environment.
|
/// Declares a table to the environment.
|
||||||
fn declare_table(&mut self, table: cranelift_wasm::Table) {
|
fn declare_table(&mut self, table: cranelift_wasm::Table) {
|
||||||
use cranelift_wasm::TableElementType;
|
use cranelift_wasm::TableElementType;
|
||||||
@ -242,7 +228,7 @@ impl<'module, 'isa, 'data> ModuleEnvironment<'data> for ModuleEnv<'module, 'isa>
|
|||||||
table_index: cranelift_wasm::TableIndex,
|
table_index: cranelift_wasm::TableIndex,
|
||||||
base: Option<cranelift_wasm::GlobalIndex>,
|
base: Option<cranelift_wasm::GlobalIndex>,
|
||||||
offset: usize,
|
offset: usize,
|
||||||
elements: Vec<cranelift_wasm::FuncIndex>,
|
elements: Box<[cranelift_wasm::FuncIndex]>,
|
||||||
) {
|
) {
|
||||||
// Convert Cranelift GlobalIndex to wamser GlobalIndex
|
// Convert Cranelift GlobalIndex to wamser GlobalIndex
|
||||||
// let base = base.map(|index| WasmerGlobalIndex::new(index.index()));
|
// let base = base.map(|index| WasmerGlobalIndex::new(index.index()));
|
||||||
@ -380,7 +366,11 @@ impl<'module, 'isa, 'data> ModuleEnvironment<'data> for ModuleEnv<'module, 'isa>
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Provides the contents of a function body.
|
/// Provides the contents of a function body.
|
||||||
fn define_function_body(&mut self, body_bytes: &'data [u8]) -> cranelift_wasm::WasmResult<()> {
|
fn define_function_body(
|
||||||
|
&mut self,
|
||||||
|
body_bytes: &'data [u8],
|
||||||
|
body_offset: usize,
|
||||||
|
) -> cranelift_wasm::WasmResult<()> {
|
||||||
let mut func_translator = FuncTranslator::new();
|
let mut func_translator = FuncTranslator::new();
|
||||||
|
|
||||||
let func_body = {
|
let func_body = {
|
||||||
@ -394,7 +384,7 @@ impl<'module, 'isa, 'data> ModuleEnvironment<'data> for ModuleEnv<'module, 'isa>
|
|||||||
|
|
||||||
let mut func = ir::Function::with_name_signature(name, sig);
|
let mut func = ir::Function::with_name_signature(name, sig);
|
||||||
|
|
||||||
func_translator.translate(body_bytes, &mut func, &mut func_env)?;
|
func_translator.translate(body_bytes, body_offset, &mut func, &mut func_env)?;
|
||||||
|
|
||||||
#[cfg(feature = "debug")]
|
#[cfg(feature = "debug")]
|
||||||
{
|
{
|
||||||
@ -534,7 +524,10 @@ impl<'module, 'isa, 'data> ModuleEnvironment<'data> for ModuleEnv<'module, 'isa>
|
|||||||
.special_param(ir::ArgumentPurpose::VMContext)
|
.special_param(ir::ArgumentPurpose::VMContext)
|
||||||
.expect("missing vmctx parameter");
|
.expect("missing vmctx parameter");
|
||||||
|
|
||||||
let func_index = pos.ins().iconst(ir::types::I32, func_index.index() as i64);
|
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]);
|
pos.ins().call(start_debug, &[vmctx, func_index]);
|
||||||
|
|
||||||
|
@ -224,6 +224,7 @@ pub enum TrapCode {
|
|||||||
IntegerDivisionByZero,
|
IntegerDivisionByZero,
|
||||||
BadConversionToInteger,
|
BadConversionToInteger,
|
||||||
Interrupt,
|
Interrupt,
|
||||||
|
UnreachableCodeReached,
|
||||||
User(u16),
|
User(u16),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -297,6 +298,7 @@ impl binemit::TrapSink for LocalTrapSink {
|
|||||||
ir::TrapCode::IntegerDivisionByZero => TrapCode::IntegerDivisionByZero,
|
ir::TrapCode::IntegerDivisionByZero => TrapCode::IntegerDivisionByZero,
|
||||||
ir::TrapCode::BadConversionToInteger => TrapCode::BadConversionToInteger,
|
ir::TrapCode::BadConversionToInteger => TrapCode::BadConversionToInteger,
|
||||||
ir::TrapCode::Interrupt => TrapCode::Interrupt,
|
ir::TrapCode::Interrupt => TrapCode::Interrupt,
|
||||||
|
ir::TrapCode::UnreachableCodeReached => TrapCode::UnreachableCodeReached,
|
||||||
ir::TrapCode::User(x) => TrapCode::User(x),
|
ir::TrapCode::User(x) => TrapCode::User(x),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ use crate::{
|
|||||||
},
|
},
|
||||||
signal::HandlerData,
|
signal::HandlerData,
|
||||||
};
|
};
|
||||||
|
use rayon::prelude::*;
|
||||||
|
|
||||||
use byteorder::{ByteOrder, LittleEndian};
|
use byteorder::{ByteOrder, LittleEndian};
|
||||||
use cranelift_codegen::{ir, isa, Context};
|
use cranelift_codegen::{ir, isa, Context};
|
||||||
@ -20,7 +21,6 @@ use wasmer_runtime_core::cache::Error as CacheError;
|
|||||||
use wasmer_runtime_core::{
|
use wasmer_runtime_core::{
|
||||||
self,
|
self,
|
||||||
backend::{
|
backend::{
|
||||||
self,
|
|
||||||
sys::{Memory, Protect},
|
sys::{Memory, Protect},
|
||||||
SigRegistry,
|
SigRegistry,
|
||||||
},
|
},
|
||||||
@ -92,25 +92,44 @@ impl FuncResolverBuilder {
|
|||||||
function_bodies: Map<LocalFuncIndex, ir::Function>,
|
function_bodies: Map<LocalFuncIndex, ir::Function>,
|
||||||
info: &ModuleInfo,
|
info: &ModuleInfo,
|
||||||
) -> CompileResult<(Self, HandlerData)> {
|
) -> CompileResult<(Self, HandlerData)> {
|
||||||
let mut compiled_functions: Vec<Vec<u8>> = Vec::with_capacity(function_bodies.len());
|
let num_func_bodies = function_bodies.len();
|
||||||
let mut local_relocs = Map::with_capacity(function_bodies.len());
|
let mut local_relocs = Map::with_capacity(num_func_bodies);
|
||||||
let mut external_relocs = Map::new();
|
let mut external_relocs = Map::with_capacity(num_func_bodies);
|
||||||
|
|
||||||
let mut trap_sink = TrapSink::new();
|
let mut trap_sink = TrapSink::new();
|
||||||
|
|
||||||
|
let compiled_functions: Result<Vec<(Vec<u8>, (RelocSink, LocalTrapSink))>, CompileError> =
|
||||||
|
function_bodies
|
||||||
|
.into_vec()
|
||||||
|
.par_iter()
|
||||||
|
.map_init(
|
||||||
|
|| Context::new(),
|
||||||
|
|ctx, func| {
|
||||||
|
let mut code_buf = Vec::new();
|
||||||
|
ctx.func = func.to_owned();
|
||||||
|
let mut reloc_sink = RelocSink::new();
|
||||||
let mut local_trap_sink = LocalTrapSink::new();
|
let mut local_trap_sink = LocalTrapSink::new();
|
||||||
|
|
||||||
let mut ctx = Context::new();
|
ctx.compile_and_emit(
|
||||||
let mut total_size = 0;
|
isa,
|
||||||
|
&mut code_buf,
|
||||||
for (_, func) in function_bodies {
|
&mut reloc_sink,
|
||||||
ctx.func = func;
|
&mut local_trap_sink,
|
||||||
let mut code_buf = Vec::new();
|
)
|
||||||
let mut reloc_sink = RelocSink::new();
|
|
||||||
|
|
||||||
ctx.compile_and_emit(isa, &mut code_buf, &mut reloc_sink, &mut local_trap_sink)
|
|
||||||
.map_err(|e| CompileError::InternalError { msg: e.to_string() })?;
|
.map_err(|e| CompileError::InternalError { msg: e.to_string() })?;
|
||||||
ctx.clear();
|
ctx.clear();
|
||||||
|
Ok((code_buf, (reloc_sink, local_trap_sink)))
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let compiled_functions = compiled_functions?;
|
||||||
|
let mut total_size = 0;
|
||||||
|
// We separate into two iterators, one iterable and one into iterable
|
||||||
|
let (code_bufs, sinks): (Vec<Vec<u8>>, Vec<(RelocSink, LocalTrapSink)>) =
|
||||||
|
compiled_functions.into_iter().unzip();
|
||||||
|
for (code_buf, (reloc_sink, mut local_trap_sink)) in code_bufs.iter().zip(sinks.into_iter())
|
||||||
|
{
|
||||||
// Clear the local trap sink and consolidate all trap info
|
// Clear the local trap sink and consolidate all trap info
|
||||||
// into a single location.
|
// into a single location.
|
||||||
trap_sink.drain_local(total_size, &mut local_trap_sink);
|
trap_sink.drain_local(total_size, &mut local_trap_sink);
|
||||||
@ -118,7 +137,6 @@ impl FuncResolverBuilder {
|
|||||||
// Round up each function's size to pointer alignment.
|
// Round up each function's size to pointer alignment.
|
||||||
total_size += round_up(code_buf.len(), mem::size_of::<usize>());
|
total_size += round_up(code_buf.len(), mem::size_of::<usize>());
|
||||||
|
|
||||||
compiled_functions.push(code_buf);
|
|
||||||
local_relocs.push(reloc_sink.local_relocs.into_boxed_slice());
|
local_relocs.push(reloc_sink.local_relocs.into_boxed_slice());
|
||||||
external_relocs.push(reloc_sink.external_relocs.into_boxed_slice());
|
external_relocs.push(reloc_sink.external_relocs.into_boxed_slice());
|
||||||
}
|
}
|
||||||
@ -145,10 +163,10 @@ impl FuncResolverBuilder {
|
|||||||
*i = 0xCC;
|
*i = 0xCC;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut map = Map::with_capacity(compiled_functions.len());
|
let mut map = Map::with_capacity(num_func_bodies);
|
||||||
|
|
||||||
let mut previous_end = 0;
|
let mut previous_end = 0;
|
||||||
for compiled in compiled_functions.iter() {
|
for compiled in code_bufs.iter() {
|
||||||
let new_end = previous_end + round_up(compiled.len(), mem::size_of::<usize>());
|
let new_end = previous_end + round_up(compiled.len(), mem::size_of::<usize>());
|
||||||
unsafe {
|
unsafe {
|
||||||
memory.as_slice_mut()[previous_end..previous_end + compiled.len()]
|
memory.as_slice_mut()[previous_end..previous_end + compiled.len()]
|
||||||
@ -202,7 +220,7 @@ impl FuncResolverBuilder {
|
|||||||
|
|
||||||
pub fn finalize(
|
pub fn finalize(
|
||||||
mut self,
|
mut self,
|
||||||
signatures: &SliceMap<SigIndex, Arc<FuncSig>>,
|
signatures: &SliceMap<SigIndex, FuncSig>,
|
||||||
trampolines: Arc<Trampolines>,
|
trampolines: Arc<Trampolines>,
|
||||||
handler_data: HandlerData,
|
handler_data: HandlerData,
|
||||||
) -> CompileResult<(FuncResolver, BackendCache)> {
|
) -> CompileResult<(FuncResolver, BackendCache)> {
|
||||||
@ -269,8 +287,8 @@ impl FuncResolverBuilder {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
RelocationType::Signature(sig_index) => {
|
RelocationType::Signature(sig_index) => {
|
||||||
let sig_index =
|
let signature = SigRegistry.lookup_signature_ref(&signatures[sig_index]);
|
||||||
SigRegistry.lookup_sig_index(Arc::clone(&signatures[sig_index]));
|
let sig_index = SigRegistry.lookup_sig_index(signature);
|
||||||
sig_index.index() as _
|
sig_index.index() as _
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -338,13 +356,8 @@ pub struct FuncResolver {
|
|||||||
pub(crate) memory: Arc<Memory>,
|
pub(crate) memory: Arc<Memory>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements FuncResolver trait.
|
impl FuncResolver {
|
||||||
impl backend::FuncResolver for FuncResolver {
|
pub fn lookup(&self, index: LocalFuncIndex) -> Option<NonNull<vm::Func>> {
|
||||||
fn get(
|
|
||||||
&self,
|
|
||||||
_module: &wasmer_runtime_core::module::ModuleInner,
|
|
||||||
index: LocalFuncIndex,
|
|
||||||
) -> Option<NonNull<vm::Func>> {
|
|
||||||
lookup_func(&self.map, &self.memory, index)
|
lookup_func(&self.map, &self.memory, index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -355,20 +368,26 @@ fn round_up(n: usize, multiple: usize) -> usize {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" fn i32_print(_ctx: &mut vm::Ctx, n: i32) {
|
extern "C" fn i32_print(_ctx: &mut vm::Ctx, n: i32) {
|
||||||
print!(" i32: {},", n);
|
eprint!(" i32: {},", n);
|
||||||
}
|
}
|
||||||
extern "C" fn i64_print(_ctx: &mut vm::Ctx, n: i64) {
|
extern "C" fn i64_print(_ctx: &mut vm::Ctx, n: i64) {
|
||||||
print!(" i64: {},", n);
|
eprint!(" i64: {},", n);
|
||||||
}
|
}
|
||||||
extern "C" fn f32_print(_ctx: &mut vm::Ctx, n: f32) {
|
extern "C" fn f32_print(_ctx: &mut vm::Ctx, n: f32) {
|
||||||
print!(" f32: {},", n);
|
eprint!(" f32: {},", n);
|
||||||
}
|
}
|
||||||
extern "C" fn f64_print(_ctx: &mut vm::Ctx, n: f64) {
|
extern "C" fn f64_print(_ctx: &mut vm::Ctx, n: f64) {
|
||||||
print!(" f64: {},", n);
|
eprint!(" f64: {},", n);
|
||||||
}
|
}
|
||||||
extern "C" fn start_debug(_ctx: &mut vm::Ctx, func_index: u32) {
|
extern "C" fn start_debug(ctx: &mut vm::Ctx, func_index: u32) {
|
||||||
print!("func ({}), args: [", func_index);
|
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) {
|
extern "C" fn end_debug(_ctx: &mut vm::Ctx) {
|
||||||
println!(" ]");
|
eprintln!(" ]");
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,14 @@
|
|||||||
use crate::relocation::{TrapData, TrapSink};
|
use crate::relocation::{TrapData, TrapSink};
|
||||||
|
use crate::resolver::FuncResolver;
|
||||||
use crate::trampoline::Trampolines;
|
use crate::trampoline::Trampolines;
|
||||||
use hashbrown::HashSet;
|
|
||||||
use libc::c_void;
|
use libc::c_void;
|
||||||
use std::{cell::Cell, sync::Arc};
|
use std::{any::Any, cell::Cell, ptr::NonNull, sync::Arc};
|
||||||
use wasmer_runtime_core::{
|
use wasmer_runtime_core::{
|
||||||
backend::{ProtectedCaller, Token, UserTrapper},
|
backend::RunnableModule,
|
||||||
error::RuntimeResult,
|
module::ModuleInfo,
|
||||||
export::Context,
|
typed_func::{Wasm, WasmTrapInfo},
|
||||||
module::{ExportIndex, ModuleInfo, ModuleInner},
|
types::{LocalFuncIndex, SigIndex},
|
||||||
types::{FuncIndex, FuncSig, LocalOrImport, SigIndex, Type, Value},
|
vm,
|
||||||
vm::{self, ImportBacking},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
@ -25,167 +24,78 @@ pub use self::unix::*;
|
|||||||
pub use self::windows::*;
|
pub use self::windows::*;
|
||||||
|
|
||||||
thread_local! {
|
thread_local! {
|
||||||
pub static TRAP_EARLY_DATA: Cell<Option<String>> = Cell::new(None);
|
pub static TRAP_EARLY_DATA: Cell<Option<Box<dyn Any>>> = Cell::new(None);
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Trapper;
|
|
||||||
|
|
||||||
impl UserTrapper for Trapper {
|
|
||||||
unsafe fn do_early_trap(&self, msg: String) -> ! {
|
|
||||||
TRAP_EARLY_DATA.with(|cell| cell.set(Some(msg)));
|
|
||||||
trigger_trap()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Caller {
|
pub struct Caller {
|
||||||
func_export_set: HashSet<FuncIndex>,
|
|
||||||
handler_data: HandlerData,
|
handler_data: HandlerData,
|
||||||
trampolines: Arc<Trampolines>,
|
trampolines: Arc<Trampolines>,
|
||||||
|
resolver: FuncResolver,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Caller {
|
impl Caller {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
module: &ModuleInfo,
|
|
||||||
handler_data: HandlerData,
|
handler_data: HandlerData,
|
||||||
trampolines: Arc<Trampolines>,
|
trampolines: Arc<Trampolines>,
|
||||||
|
resolver: FuncResolver,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let mut func_export_set = HashSet::new();
|
|
||||||
for export_index in module.exports.values() {
|
|
||||||
if let ExportIndex::Func(func_index) = export_index {
|
|
||||||
func_export_set.insert(*func_index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if let Some(start_func_index) = module.start_func {
|
|
||||||
func_export_set.insert(start_func_index);
|
|
||||||
}
|
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
func_export_set,
|
|
||||||
handler_data,
|
handler_data,
|
||||||
trampolines,
|
trampolines,
|
||||||
|
resolver,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ProtectedCaller for Caller {
|
impl RunnableModule for Caller {
|
||||||
fn call(
|
fn get_func(&self, _: &ModuleInfo, func_index: LocalFuncIndex) -> Option<NonNull<vm::Func>> {
|
||||||
&self,
|
self.resolver.lookup(func_index)
|
||||||
module: &ModuleInner,
|
}
|
||||||
func_index: FuncIndex,
|
|
||||||
params: &[Value],
|
|
||||||
import_backing: &ImportBacking,
|
|
||||||
vmctx: *mut vm::Ctx,
|
|
||||||
_: Token,
|
|
||||||
) -> RuntimeResult<Vec<Value>> {
|
|
||||||
let (func_ptr, ctx, signature, sig_index) =
|
|
||||||
get_func_from_index(&module, import_backing, func_index);
|
|
||||||
|
|
||||||
let vmctx_ptr = match ctx {
|
fn get_trampoline(&self, _: &ModuleInfo, sig_index: SigIndex) -> Option<Wasm> {
|
||||||
Context::External(external_vmctx) => external_vmctx,
|
unsafe extern "C" fn invoke(
|
||||||
Context::Internal => vmctx,
|
trampoline: unsafe extern "C" fn(*mut vm::Ctx, NonNull<vm::Func>, *const u64, *mut u64),
|
||||||
};
|
ctx: *mut vm::Ctx,
|
||||||
|
func: NonNull<vm::Func>,
|
||||||
|
args: *const u64,
|
||||||
|
rets: *mut u64,
|
||||||
|
_trap_info: *mut WasmTrapInfo,
|
||||||
|
invoke_env: Option<NonNull<c_void>>,
|
||||||
|
) -> bool {
|
||||||
|
let handler_data = &*invoke_env.unwrap().cast().as_ptr();
|
||||||
|
|
||||||
assert!(self.func_export_set.contains(&func_index));
|
#[cfg(not(target_os = "windows"))]
|
||||||
|
let res = call_protected(handler_data, || {
|
||||||
assert!(
|
// Leap of faith.
|
||||||
signature.returns().len() <= 1,
|
trampoline(ctx, func, args, rets);
|
||||||
"multi-value returns not yet supported"
|
|
||||||
);
|
|
||||||
|
|
||||||
assert!(
|
|
||||||
signature.check_param_value_types(params),
|
|
||||||
"incorrect signature"
|
|
||||||
);
|
|
||||||
|
|
||||||
let param_vec: Vec<u64> = params
|
|
||||||
.iter()
|
|
||||||
.map(|val| match val {
|
|
||||||
Value::I32(x) => *x as u64,
|
|
||||||
Value::I64(x) => *x as u64,
|
|
||||||
Value::F32(x) => x.to_bits() as u64,
|
|
||||||
Value::F64(x) => x.to_bits(),
|
|
||||||
})
|
})
|
||||||
.collect();
|
.is_ok();
|
||||||
|
|
||||||
let mut return_vec = vec![0; signature.returns().len()];
|
// the trampoline is called from C on windows
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
let res = call_protected(handler_data, trampoline, ctx, func, args, rets).is_ok();
|
||||||
|
|
||||||
|
res
|
||||||
|
}
|
||||||
|
|
||||||
let trampoline = self
|
let trampoline = self
|
||||||
.trampolines
|
.trampolines
|
||||||
.lookup(sig_index)
|
.lookup(sig_index)
|
||||||
.expect("that trampoline doesn't exist");
|
.expect("that trampoline doesn't exist");
|
||||||
|
|
||||||
#[cfg(not(target_os = "windows"))]
|
Some(unsafe {
|
||||||
call_protected(&self.handler_data, || unsafe {
|
Wasm::from_raw_parts(
|
||||||
// Leap of faith.
|
|
||||||
trampoline(
|
|
||||||
vmctx_ptr,
|
|
||||||
func_ptr,
|
|
||||||
param_vec.as_ptr(),
|
|
||||||
return_vec.as_mut_ptr(),
|
|
||||||
);
|
|
||||||
})?;
|
|
||||||
|
|
||||||
// the trampoline is called from C on windows
|
|
||||||
#[cfg(target_os = "windows")]
|
|
||||||
call_protected(
|
|
||||||
&self.handler_data,
|
|
||||||
trampoline,
|
trampoline,
|
||||||
vmctx_ptr,
|
invoke,
|
||||||
func_ptr,
|
Some(NonNull::from(&self.handler_data).cast()),
|
||||||
param_vec.as_ptr(),
|
|
||||||
return_vec.as_mut_ptr(),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
Ok(return_vec
|
|
||||||
.iter()
|
|
||||||
.zip(signature.returns().iter())
|
|
||||||
.map(|(&x, ty)| match ty {
|
|
||||||
Type::I32 => Value::I32(x as i32),
|
|
||||||
Type::I64 => Value::I64(x as i64),
|
|
||||||
Type::F32 => Value::F32(f32::from_bits(x as u32)),
|
|
||||||
Type::F64 => Value::F64(f64::from_bits(x as u64)),
|
|
||||||
})
|
|
||||||
.collect())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_early_trapper(&self) -> Box<dyn UserTrapper> {
|
|
||||||
Box::new(Trapper)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_func_from_index(
|
|
||||||
module: &ModuleInner,
|
|
||||||
import_backing: &ImportBacking,
|
|
||||||
func_index: FuncIndex,
|
|
||||||
) -> (*const vm::Func, Context, Arc<FuncSig>, SigIndex) {
|
|
||||||
let sig_index = *module
|
|
||||||
.info
|
|
||||||
.func_assoc
|
|
||||||
.get(func_index)
|
|
||||||
.expect("broken invariant, incorrect func index");
|
|
||||||
|
|
||||||
let (func_ptr, ctx) = match func_index.local_or_import(&module.info) {
|
|
||||||
LocalOrImport::Local(local_func_index) => (
|
|
||||||
module
|
|
||||||
.func_resolver
|
|
||||||
.get(&module, local_func_index)
|
|
||||||
.expect("broken invariant, func resolver not synced with module.exports")
|
|
||||||
.cast()
|
|
||||||
.as_ptr() as *const _,
|
|
||||||
Context::Internal,
|
|
||||||
),
|
|
||||||
LocalOrImport::Import(imported_func_index) => {
|
|
||||||
let imported_func = import_backing.imported_func(imported_func_index);
|
|
||||||
(
|
|
||||||
imported_func.func as *const _,
|
|
||||||
Context::External(imported_func.vmctx),
|
|
||||||
)
|
)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
let signature = Arc::clone(&module.info.signatures[sig_index]);
|
unsafe fn do_early_trap(&self, data: Box<dyn Any>) -> ! {
|
||||||
|
TRAP_EARLY_DATA.with(|cell| cell.set(Some(data)));
|
||||||
(func_ptr, ctx, signature, sig_index)
|
trigger_trap()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl Send for HandlerData {}
|
unsafe impl Send for HandlerData {}
|
||||||
|
@ -18,11 +18,7 @@ use nix::sys::signal::{
|
|||||||
use std::cell::{Cell, UnsafeCell};
|
use std::cell::{Cell, UnsafeCell};
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::sync::Once;
|
use std::sync::Once;
|
||||||
use wasmer_runtime_core::{
|
use wasmer_runtime_core::error::{RuntimeError, RuntimeResult};
|
||||||
error::{RuntimeError, RuntimeResult},
|
|
||||||
structures::TypedIndex,
|
|
||||||
types::{MemoryIndex, TableIndex},
|
|
||||||
};
|
|
||||||
|
|
||||||
extern "C" fn signal_trap_handler(
|
extern "C" fn signal_trap_handler(
|
||||||
signum: ::nix::libc::c_int,
|
signum: ::nix::libc::c_int,
|
||||||
@ -79,8 +75,8 @@ pub fn call_protected<T>(handler_data: &HandlerData, f: impl FnOnce() -> T) -> R
|
|||||||
if signum != 0 {
|
if signum != 0 {
|
||||||
*jmp_buf = prev_jmp_buf;
|
*jmp_buf = prev_jmp_buf;
|
||||||
|
|
||||||
if let Some(msg) = super::TRAP_EARLY_DATA.with(|cell| cell.replace(None)) {
|
if let Some(data) = super::TRAP_EARLY_DATA.with(|cell| cell.replace(None)) {
|
||||||
Err(RuntimeError::User { msg })
|
Err(RuntimeError::Panic { data })
|
||||||
} else {
|
} else {
|
||||||
let (faulting_addr, inst_ptr) = CAUGHT_ADDRESSES.with(|cell| cell.get());
|
let (faulting_addr, inst_ptr) = CAUGHT_ADDRESSES.with(|cell| cell.get());
|
||||||
|
|
||||||
@ -91,28 +87,28 @@ pub fn call_protected<T>(handler_data: &HandlerData, f: impl FnOnce() -> T) -> R
|
|||||||
{
|
{
|
||||||
Err(match Signal::from_c_int(signum) {
|
Err(match Signal::from_c_int(signum) {
|
||||||
Ok(SIGILL) => match trapcode {
|
Ok(SIGILL) => match trapcode {
|
||||||
TrapCode::BadSignature => RuntimeError::IndirectCallSignature {
|
TrapCode::BadSignature => RuntimeError::Trap {
|
||||||
table: TableIndex::new(0),
|
msg: "incorrect call_indirect signature".into(),
|
||||||
},
|
},
|
||||||
TrapCode::IndirectCallToNull => RuntimeError::IndirectCallToNull {
|
TrapCode::IndirectCallToNull => RuntimeError::Trap {
|
||||||
table: TableIndex::new(0),
|
msg: "indirect call to null".into(),
|
||||||
},
|
},
|
||||||
TrapCode::HeapOutOfBounds => RuntimeError::OutOfBoundsAccess {
|
TrapCode::HeapOutOfBounds => RuntimeError::Trap {
|
||||||
memory: MemoryIndex::new(0),
|
msg: "memory out-of-bounds access".into(),
|
||||||
addr: None,
|
|
||||||
},
|
},
|
||||||
TrapCode::TableOutOfBounds => RuntimeError::TableOutOfBounds {
|
TrapCode::TableOutOfBounds => RuntimeError::Trap {
|
||||||
table: TableIndex::new(0),
|
msg: "table out-of-bounds access".into(),
|
||||||
},
|
},
|
||||||
_ => RuntimeError::Unknown {
|
_ => RuntimeError::Trap {
|
||||||
msg: "unknown trap".to_string(),
|
msg: "unknown trap".into(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Ok(SIGSEGV) | Ok(SIGBUS) => RuntimeError::OutOfBoundsAccess {
|
Ok(SIGSEGV) | Ok(SIGBUS) => RuntimeError::Trap {
|
||||||
memory: MemoryIndex::new(0),
|
msg: "memory out-of-bounds access".into(),
|
||||||
addr: None,
|
},
|
||||||
|
Ok(SIGFPE) => RuntimeError::Trap {
|
||||||
|
msg: "illegal arithmetic operation".into(),
|
||||||
},
|
},
|
||||||
Ok(SIGFPE) => RuntimeError::IllegalArithmeticOperation,
|
|
||||||
_ => unimplemented!(),
|
_ => unimplemented!(),
|
||||||
}
|
}
|
||||||
.into())
|
.into())
|
||||||
@ -126,8 +122,8 @@ pub fn call_protected<T>(handler_data: &HandlerData, f: impl FnOnce() -> T) -> R
|
|||||||
_ => "unkown trapped signal",
|
_ => "unkown trapped signal",
|
||||||
};
|
};
|
||||||
// When the trap-handler is fully implemented, this will return more information.
|
// When the trap-handler is fully implemented, this will return more information.
|
||||||
Err(RuntimeError::Unknown {
|
Err(RuntimeError::Trap {
|
||||||
msg: format!("trap at {:p} - {}", faulting_addr, signal),
|
msg: format!("unknown trap at {:p} - {}", faulting_addr, signal).into(),
|
||||||
}
|
}
|
||||||
.into())
|
.into())
|
||||||
}
|
}
|
||||||
|
@ -3,14 +3,10 @@ use crate::signal::HandlerData;
|
|||||||
use crate::trampoline::Trampoline;
|
use crate::trampoline::Trampoline;
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::ffi::c_void;
|
use std::ffi::c_void;
|
||||||
use std::ptr;
|
use std::ptr::{self, NonNull};
|
||||||
|
use wasmer_runtime_core::error::{RuntimeError, RuntimeResult};
|
||||||
use wasmer_runtime_core::vm::Ctx;
|
use wasmer_runtime_core::vm::Ctx;
|
||||||
use wasmer_runtime_core::vm::Func;
|
use wasmer_runtime_core::vm::Func;
|
||||||
use wasmer_runtime_core::{
|
|
||||||
error::{RuntimeError, RuntimeResult},
|
|
||||||
structures::TypedIndex,
|
|
||||||
types::{MemoryIndex, TableIndex},
|
|
||||||
};
|
|
||||||
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::shared::minwindef::DWORD;
|
||||||
@ -29,7 +25,7 @@ pub fn call_protected(
|
|||||||
handler_data: &HandlerData,
|
handler_data: &HandlerData,
|
||||||
trampoline: Trampoline,
|
trampoline: Trampoline,
|
||||||
ctx: *mut Ctx,
|
ctx: *mut Ctx,
|
||||||
func: *const Func,
|
func: NonNull<Func>,
|
||||||
param_vec: *const u64,
|
param_vec: *const u64,
|
||||||
return_vec: *mut u64,
|
return_vec: *mut u64,
|
||||||
) -> RuntimeResult<()> {
|
) -> RuntimeResult<()> {
|
||||||
@ -47,8 +43,8 @@ pub fn call_protected(
|
|||||||
|
|
||||||
let CallProtectedData {
|
let CallProtectedData {
|
||||||
code: signum,
|
code: signum,
|
||||||
exceptionAddress: exception_address,
|
exception_address,
|
||||||
instructionPointer: instruction_pointer,
|
instruction_pointer,
|
||||||
} = result.unwrap_err();
|
} = result.unwrap_err();
|
||||||
|
|
||||||
if let Some(TrapData {
|
if let Some(TrapData {
|
||||||
@ -57,35 +53,34 @@ pub fn call_protected(
|
|||||||
}) = handler_data.lookup(instruction_pointer as _)
|
}) = handler_data.lookup(instruction_pointer as _)
|
||||||
{
|
{
|
||||||
Err(match signum as DWORD {
|
Err(match signum as DWORD {
|
||||||
EXCEPTION_ACCESS_VIOLATION => RuntimeError::OutOfBoundsAccess {
|
EXCEPTION_ACCESS_VIOLATION => RuntimeError::Trap {
|
||||||
memory: MemoryIndex::new(0),
|
msg: "memory out-of-bounds access".into(),
|
||||||
addr: None,
|
|
||||||
},
|
},
|
||||||
EXCEPTION_ILLEGAL_INSTRUCTION => match trapcode {
|
EXCEPTION_ILLEGAL_INSTRUCTION => match trapcode {
|
||||||
TrapCode::BadSignature => RuntimeError::IndirectCallSignature {
|
TrapCode::BadSignature => RuntimeError::Trap {
|
||||||
table: TableIndex::new(0),
|
msg: "incorrect call_indirect signature".into(),
|
||||||
},
|
},
|
||||||
TrapCode::IndirectCallToNull => RuntimeError::IndirectCallToNull {
|
TrapCode::IndirectCallToNull => RuntimeError::Trap {
|
||||||
table: TableIndex::new(0),
|
msg: "indirect call to null".into(),
|
||||||
},
|
},
|
||||||
TrapCode::HeapOutOfBounds => RuntimeError::OutOfBoundsAccess {
|
TrapCode::HeapOutOfBounds => RuntimeError::Trap {
|
||||||
memory: MemoryIndex::new(0),
|
msg: "memory out-of-bounds access".into(),
|
||||||
addr: None,
|
|
||||||
},
|
},
|
||||||
TrapCode::TableOutOfBounds => RuntimeError::TableOutOfBounds {
|
TrapCode::TableOutOfBounds => RuntimeError::Trap {
|
||||||
table: TableIndex::new(0),
|
msg: "table out-of-bounds access".into(),
|
||||||
},
|
},
|
||||||
_ => RuntimeError::Unknown {
|
_ => RuntimeError::Trap {
|
||||||
msg: "unknown trap".to_string(),
|
msg: "unknown trap".into(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
EXCEPTION_STACK_OVERFLOW => RuntimeError::Unknown {
|
EXCEPTION_STACK_OVERFLOW => RuntimeError::Trap {
|
||||||
msg: "unknown trap".to_string(),
|
msg: "stack overflow trap".into(),
|
||||||
},
|
},
|
||||||
EXCEPTION_INT_DIVIDE_BY_ZERO => RuntimeError::IllegalArithmeticOperation,
|
EXCEPTION_INT_DIVIDE_BY_ZERO | EXCEPTION_INT_OVERFLOW => RuntimeError::Trap {
|
||||||
EXCEPTION_INT_OVERFLOW => RuntimeError::IllegalArithmeticOperation,
|
msg: "illegal arithmetic operation".into(),
|
||||||
_ => RuntimeError::Unknown {
|
},
|
||||||
msg: "unknown trap".to_string(),
|
_ => RuntimeError::Trap {
|
||||||
|
msg: "unknown trap".into(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
.into())
|
.into())
|
||||||
@ -103,8 +98,8 @@ pub fn call_protected(
|
|||||||
_ => "unkown trapped signal",
|
_ => "unkown trapped signal",
|
||||||
};
|
};
|
||||||
|
|
||||||
Err(RuntimeError::Unknown {
|
Err(RuntimeError::Trap {
|
||||||
msg: format!("trap at {} - {}", exception_address, signal),
|
msg: format!("unknown trap at {} - {}", exception_address, signal).into(),
|
||||||
}
|
}
|
||||||
.into())
|
.into())
|
||||||
}
|
}
|
||||||
|
@ -6,8 +6,7 @@ use cranelift_codegen::{
|
|||||||
isa, Context,
|
isa, Context,
|
||||||
};
|
};
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
use std::ffi::c_void;
|
use std::{iter, mem, ptr::NonNull};
|
||||||
use std::{iter, mem};
|
|
||||||
use wasmer_runtime_core::{
|
use wasmer_runtime_core::{
|
||||||
backend::sys::{Memory, Protect},
|
backend::sys::{Memory, Protect},
|
||||||
module::{ExportIndex, ModuleInfo},
|
module::{ExportIndex, ModuleInfo},
|
||||||
@ -23,8 +22,7 @@ impl RelocSink for NullRelocSink {
|
|||||||
fn reloc_jt(&mut self, _: u32, _: Reloc, _: ir::JumpTable) {}
|
fn reloc_jt(&mut self, _: u32, _: Reloc, _: ir::JumpTable) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type Trampoline =
|
pub type Trampoline = unsafe extern "C" fn(*mut vm::Ctx, NonNull<vm::Func>, *const u64, *mut u64);
|
||||||
unsafe extern "C" fn(*mut vm::Ctx, *const vm::Func, *const u64, *mut u64) -> c_void;
|
|
||||||
|
|
||||||
pub struct Trampolines {
|
pub struct Trampolines {
|
||||||
memory: Memory,
|
memory: Memory,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "wasmer-emscripten"
|
name = "wasmer-emscripten"
|
||||||
version = "0.1.0"
|
version = "0.3.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>"]
|
||||||
@ -9,18 +9,26 @@ edition = "2018"
|
|||||||
build = "build/mod.rs"
|
build = "build/mod.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
wasmer-runtime-core = { path = "../runtime-core", version = "0.1.0" }
|
wasmer-runtime-core = { path = "../runtime-core", version = "0.3.0" }
|
||||||
lazy_static = "1.2.0"
|
lazy_static = "1.2.0"
|
||||||
libc = { git = "https://github.com/rust-lang/libc" }
|
libc = "0.2.49"
|
||||||
byteorder = "1"
|
byteorder = "1"
|
||||||
time = "0.1.41"
|
time = "0.1.41"
|
||||||
|
wasmer-clif-backend = { path = "../clif-backend", version = "0.3.0" }
|
||||||
|
wasmer-singlepass-backend = { path = "../singlepass-backend", version = "0.3.0", optional = true }
|
||||||
|
wasmer-llvm-backend = { path = "../llvm-backend", version = "0.3.0", optional = true }
|
||||||
|
|
||||||
[target.'cfg(windows)'.dependencies]
|
[target.'cfg(windows)'.dependencies]
|
||||||
rand = "0.6"
|
rand = "0.6"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
wasmer-clif-backend = { path = "../clif-backend", version = "0.1.0" }
|
|
||||||
wabt = "0.7.2"
|
wabt = "0.7.2"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
glob = "0.2.11"
|
glob = "0.2.11"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
clif = []
|
||||||
|
llvm = ["wasmer-llvm-backend"]
|
||||||
|
singlepass = ["wasmer-singlepass-backend"]
|
||||||
|
debug = ["wasmer-clif-backend/debug", "wasmer-runtime-core/debug"]
|
||||||
|
@ -46,6 +46,21 @@ pub fn compile(file: &str, ignores: &Vec<String>) -> Option<String> {
|
|||||||
output_path.set_extension("js");
|
output_path.set_extension("js");
|
||||||
let output_str = output_path.to_str().unwrap();
|
let output_str = output_path.to_str().unwrap();
|
||||||
|
|
||||||
|
let wasm_file_metadata = {
|
||||||
|
let mut wasm_file_path = PathBuf::from(file);
|
||||||
|
wasm_file_path.set_extension("wasm");
|
||||||
|
if let Ok(wasm_file) = File::open(wasm_file_path) {
|
||||||
|
Some(wasm_file.metadata().unwrap())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let real_file = File::open(file).unwrap();
|
||||||
|
let file_metadata = real_file.metadata().unwrap();
|
||||||
|
if wasm_file_metadata.is_none()
|
||||||
|
|| file_metadata.modified().unwrap() >= wasm_file_metadata.unwrap().modified().unwrap()
|
||||||
|
{
|
||||||
// Compile to wasm
|
// Compile to wasm
|
||||||
let _wasm_compilation = Command::new("emcc")
|
let _wasm_compilation = Command::new("emcc")
|
||||||
.arg(file)
|
.arg(file)
|
||||||
@ -67,6 +82,7 @@ pub fn compile(file: &str, ignores: &Vec<String>) -> Option<String> {
|
|||||||
} else {
|
} else {
|
||||||
println!("Output JS not found: {}", output_str);
|
println!("Output JS not found: {}", output_str);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let mut output_path = PathBuf::from(file);
|
let mut output_path = PathBuf::from(file);
|
||||||
output_path.set_extension("output");
|
output_path.set_extension("output");
|
||||||
|
4
lib/emscripten/emtests/hello.cpp
vendored
Normal file
4
lib/emscripten/emtests/hello.cpp
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
#include <iostream>
|
||||||
|
int main() {
|
||||||
|
std::cout << "hello world\n";
|
||||||
|
}
|
2
lib/emscripten/emtests/hello.out
vendored
Normal file
2
lib/emscripten/emtests/hello.out
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
hello world
|
||||||
|
|
BIN
lib/emscripten/emtests/hello.wasm
vendored
Normal file
BIN
lib/emscripten/emtests/hello.wasm
vendored
Normal file
Binary file not shown.
52
lib/emscripten/emtests/ignores.txt
vendored
52
lib/emscripten/emtests/ignores.txt
vendored
@ -30,16 +30,7 @@ test_i64
|
|||||||
test_i64_7z
|
test_i64_7z
|
||||||
test_i64_varargs
|
test_i64_varargs
|
||||||
test_llvm_intrinsics
|
test_llvm_intrinsics
|
||||||
test_longjmp2
|
|
||||||
test_longjmp3
|
|
||||||
test_longjmp4
|
|
||||||
test_longjmp
|
|
||||||
test_longjmp_exc
|
test_longjmp_exc
|
||||||
test_longjmp_funcptr
|
|
||||||
test_longjmp_repeat
|
|
||||||
test_longjmp_stacked
|
|
||||||
test_longjmp_throw
|
|
||||||
test_longjmp_unwind
|
|
||||||
test_lower_intrinsics
|
test_lower_intrinsics
|
||||||
test_main_thread_async_em_asm
|
test_main_thread_async_em_asm
|
||||||
test_mainenv
|
test_mainenv
|
||||||
@ -72,3 +63,46 @@ test_std_cout_new
|
|||||||
test_strptime_reentrant
|
test_strptime_reentrant
|
||||||
test_gmtime
|
test_gmtime
|
||||||
test_time_c
|
test_time_c
|
||||||
|
test_execvp
|
||||||
|
test_nl_types
|
||||||
|
test_phiundef
|
||||||
|
test_pipe
|
||||||
|
test_printf_2
|
||||||
|
test_printf_more
|
||||||
|
test_regex
|
||||||
|
test_relocatable_void_function
|
||||||
|
test_rounding
|
||||||
|
test_set_align
|
||||||
|
test_sintvars
|
||||||
|
test_sizeof
|
||||||
|
test_sscanf
|
||||||
|
test_sscanf_3
|
||||||
|
test_sscanf_4
|
||||||
|
test_sscanf_5
|
||||||
|
test_sscanf_6
|
||||||
|
test_sscanf_caps
|
||||||
|
test_sscanf_float
|
||||||
|
test_sscanf_n
|
||||||
|
test_strcasecmp
|
||||||
|
test_strcmp_uni
|
||||||
|
test_strndup
|
||||||
|
test_strstr
|
||||||
|
test_strtod
|
||||||
|
test_strtok
|
||||||
|
test_strtol_bin
|
||||||
|
test_strtol_dec
|
||||||
|
test_strtol_hex
|
||||||
|
test_strtol_oct
|
||||||
|
test_strtoll_bin
|
||||||
|
test_strtoll_dec
|
||||||
|
test_strtoll_hex
|
||||||
|
test_strtoll_oct
|
||||||
|
test_struct_varargs
|
||||||
|
test_transtrcase
|
||||||
|
test_trickystring
|
||||||
|
test_unary_literal
|
||||||
|
test_vfs
|
||||||
|
test_vprintf
|
||||||
|
test_vsnprintf
|
||||||
|
test_write_stdout_fileno
|
||||||
|
test_zerodiv
|
||||||
|
17
lib/emscripten/emtests/test_execvp.c
vendored
Normal file
17
lib/emscripten/emtests/test_execvp.c
vendored
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
char command[] = "touch";
|
||||||
|
char arg1[] = "foo.txt";
|
||||||
|
char* argv[3];
|
||||||
|
argv[0] = command;
|
||||||
|
argv[1] = arg1;
|
||||||
|
argv[2] = 0;
|
||||||
|
|
||||||
|
printf("_execvp\n");
|
||||||
|
int result = execvp(command, argv);
|
||||||
|
// should not return, and not print this message
|
||||||
|
printf("error");
|
||||||
|
return 0;
|
||||||
|
}
|
1
lib/emscripten/emtests/test_execvp.out
vendored
Normal file
1
lib/emscripten/emtests/test_execvp.out
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
_execvp
|
BIN
lib/emscripten/emtests/test_execvp.wasm
vendored
Normal file
BIN
lib/emscripten/emtests/test_execvp.wasm
vendored
Normal file
Binary file not shown.
18
lib/emscripten/emtests/test_execvp_windows.c
vendored
Normal file
18
lib/emscripten/emtests/test_execvp_windows.c
vendored
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
char command[] = "C:\\Windows\\System32\\cmd.exe";
|
||||||
|
char arg1[] = "echo";
|
||||||
|
char arg2[] = "foo";
|
||||||
|
char* argv[4];
|
||||||
|
argv[0] = command;
|
||||||
|
argv[1] = arg1;
|
||||||
|
argv[2] = arg2;
|
||||||
|
argv[3] = 0;
|
||||||
|
printf("_execvp\n");
|
||||||
|
int result = execvp(command, argv);
|
||||||
|
// should not return, and not print this message
|
||||||
|
printf("error");
|
||||||
|
return 0;
|
||||||
|
}
|
BIN
lib/emscripten/emtests/test_execvp_windows.wasm
vendored
Normal file
BIN
lib/emscripten/emtests/test_execvp_windows.wasm
vendored
Normal file
Binary file not shown.
10
lib/emscripten/emtests/test_getcwd.c
vendored
Normal file
10
lib/emscripten/emtests/test_getcwd.c
vendored
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
const unsigned int size = 256;
|
||||||
|
char cwd[size] = {};
|
||||||
|
char* buf = getcwd(cwd, size);
|
||||||
|
printf("getcwd\n");
|
||||||
|
return 0;
|
||||||
|
}
|
1
lib/emscripten/emtests/test_getcwd.out
vendored
Normal file
1
lib/emscripten/emtests/test_getcwd.out
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
getcwd
|
BIN
lib/emscripten/emtests/test_getcwd.wasm
vendored
Normal file
BIN
lib/emscripten/emtests/test_getcwd.wasm
vendored
Normal file
Binary file not shown.
13
lib/emscripten/emtests/test_pipe.c
vendored
Normal file
13
lib/emscripten/emtests/test_pipe.c
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
int mypipe[2];
|
||||||
|
printf("pipe\n");
|
||||||
|
if (pipe(mypipe)) {
|
||||||
|
printf("error\n");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
1
lib/emscripten/emtests/test_pipe.out
vendored
Normal file
1
lib/emscripten/emtests/test_pipe.out
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
pipe
|
BIN
lib/emscripten/emtests/test_pipe.wasm
vendored
Normal file
BIN
lib/emscripten/emtests/test_pipe.wasm
vendored
Normal file
Binary file not shown.
12
lib/emscripten/emtests/test_vfs.c
vendored
Normal file
12
lib/emscripten/emtests/test_vfs.c
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
char data[256] = {0};
|
||||||
|
ssize_t fd = open("data.txt", 0);
|
||||||
|
ssize_t result = read((int)fd, &data, 255);
|
||||||
|
printf("content: %s", data);
|
||||||
|
printf("fd: %zd\n", fd);
|
||||||
|
return 0;
|
||||||
|
}
|
6
lib/emscripten/emtests/test_vfs.md
vendored
Normal file
6
lib/emscripten/emtests/test_vfs.md
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
The wasm file `test_vfs.wasm` is generated by compiling the `test_vfs.c` and writing a tar.zst blob with a single file
|
||||||
|
named `data.txt`.
|
||||||
|
|
||||||
|
The program expects to find a file named `data.txt` and reads the contents and the file descriptor.
|
||||||
|
|
||||||
|
The runtime should mount the virtual filesystem and expose the file.
|
1
lib/emscripten/emtests/test_vfs.out
vendored
Normal file
1
lib/emscripten/emtests/test_vfs.out
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
content: wasmer is awesomer
|
BIN
lib/emscripten/emtests/test_vfs.wasm
vendored
Normal file
BIN
lib/emscripten/emtests/test_vfs.wasm
vendored
Normal file
Binary file not shown.
BIN
lib/emscripten/emtests/test_vfs_bundle.wasm
vendored
Normal file
BIN
lib/emscripten/emtests/test_vfs_bundle.wasm
vendored
Normal file
Binary file not shown.
1
lib/emscripten/emtests/test_vfs_data.txt
vendored
Normal file
1
lib/emscripten/emtests/test_vfs_data.txt
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
wasmer is awesomer
|
9
lib/emscripten/src/bitwise.rs
Normal file
9
lib/emscripten/src/bitwise.rs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
use crate::emscripten_target;
|
||||||
|
use wasmer_runtime_core::vm::Ctx;
|
||||||
|
|
||||||
|
///emscripten: _llvm_bswap_i64
|
||||||
|
pub fn _llvm_bswap_i64(_ctx: &mut Ctx, _low: i32, high: i32) -> i32 {
|
||||||
|
debug!("emscripten::_llvm_bswap_i64");
|
||||||
|
emscripten_target::setTempRet0(_ctx, _low.swap_bytes());
|
||||||
|
high.swap_bytes()
|
||||||
|
}
|
@ -1,265 +1,267 @@
|
|||||||
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
use crate::env::get_emscripten_data;
|
use crate::env::get_emscripten_data;
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
use libc::getdtablesize;
|
||||||
use wasmer_runtime_core::vm::Ctx;
|
use wasmer_runtime_core::vm::Ctx;
|
||||||
|
|
||||||
pub fn setTempRet0(ctx: &mut Ctx, a: i32) {
|
pub fn setTempRet0(ctx: &mut Ctx, val: i32) {
|
||||||
debug!("emscripten::setTempRet0");
|
debug!("emscripten::setTempRet0: {}", val);
|
||||||
|
get_emscripten_data(ctx).temp_ret_0 = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getTempRet0(ctx: &mut Ctx) -> i32 {
|
pub fn getTempRet0(ctx: &mut Ctx) -> i32 {
|
||||||
debug!("emscripten::getTempRet0");
|
debug!("emscripten::getTempRet0");
|
||||||
0
|
get_emscripten_data(ctx).temp_ret_0
|
||||||
}
|
}
|
||||||
pub fn nullFunc_ji(ctx: &mut Ctx, a: i32) {
|
|
||||||
debug!("emscripten::nullFunc_ji");
|
pub fn __Unwind_Backtrace(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
|
||||||
}
|
|
||||||
pub fn invoke_i(ctx: &mut Ctx, index: i32) -> i32 {
|
|
||||||
debug!("emscripten::invoke_i");
|
|
||||||
if let Some(dyn_call_i) = &get_emscripten_data(ctx).dyn_call_i {
|
|
||||||
dyn_call_i.call(index).unwrap()
|
|
||||||
} else {
|
|
||||||
panic!("dyn_call_i is set to None");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn invoke_ii(ctx: &mut Ctx, index: i32, a1: i32) -> i32 {
|
|
||||||
debug!("emscripten::invoke_ii");
|
|
||||||
if let Some(dyn_call_ii) = &get_emscripten_data(ctx).dyn_call_ii {
|
|
||||||
dyn_call_ii.call(index, a1).unwrap()
|
|
||||||
} else {
|
|
||||||
panic!("dyn_call_ii is set to None");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn invoke_iii(ctx: &mut Ctx, index: i32, a1: i32, a2: i32) -> i32 {
|
|
||||||
debug!("emscripten::invoke_iii");
|
|
||||||
if let Some(dyn_call_iii) = &get_emscripten_data(ctx).dyn_call_iii {
|
|
||||||
dyn_call_iii.call(index, a1, a2).unwrap()
|
|
||||||
} else {
|
|
||||||
panic!("dyn_call_iii is set to None");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn invoke_iiii(ctx: &mut Ctx, index: i32, a1: i32, a2: i32, a3: i32) -> i32 {
|
|
||||||
debug!("emscripten::invoke_iiii");
|
|
||||||
if let Some(dyn_call_iiii) = &get_emscripten_data(ctx).dyn_call_iiii {
|
|
||||||
dyn_call_iiii.call(index, a1, a2, a3).unwrap()
|
|
||||||
} else {
|
|
||||||
panic!("dyn_call_iiii is set to None");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn invoke_v(ctx: &mut Ctx, index: i32) {
|
|
||||||
debug!("emscripten::invoke_v");
|
|
||||||
if let Some(dyn_call_v) = &get_emscripten_data(ctx).dyn_call_v {
|
|
||||||
dyn_call_v.call(index).unwrap();
|
|
||||||
} else {
|
|
||||||
panic!("dyn_call_v is set to None");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn invoke_vi(ctx: &mut Ctx, index: i32, a1: i32) {
|
|
||||||
debug!("emscripten::invoke_vi");
|
|
||||||
if let Some(dyn_call_vi) = &get_emscripten_data(ctx).dyn_call_vi {
|
|
||||||
dyn_call_vi.call(index, a1).unwrap();
|
|
||||||
} else {
|
|
||||||
panic!("dyn_call_vi is set to None");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn invoke_vii(ctx: &mut Ctx, index: i32, a1: i32, a2: i32) {
|
|
||||||
debug!("emscripten::invoke_vii");
|
|
||||||
if let Some(dyn_call_vii) = &get_emscripten_data(ctx).dyn_call_vii {
|
|
||||||
dyn_call_vii.call(index, a1, a2).unwrap();
|
|
||||||
} else {
|
|
||||||
panic!("dyn_call_vii is set to None");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn invoke_viii(ctx: &mut Ctx, index: i32, a1: i32, a2: i32, a3: i32) {
|
|
||||||
debug!("emscripten::invoke_viii");
|
|
||||||
if let Some(dyn_call_viii) = &get_emscripten_data(ctx).dyn_call_viii {
|
|
||||||
dyn_call_viii.call(index, a1, a2, a3).unwrap();
|
|
||||||
} else {
|
|
||||||
panic!("dyn_call_viii is set to None");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn invoke_viiii(ctx: &mut Ctx, index: i32, a1: i32, a2: i32, a3: i32, a4: i32) {
|
|
||||||
debug!("emscripten::invoke_viiii");
|
|
||||||
if let Some(dyn_call_viiii) = &get_emscripten_data(ctx).dyn_call_viiii {
|
|
||||||
dyn_call_viiii.call(index, a1, a2, a3, a4).unwrap();
|
|
||||||
} else {
|
|
||||||
panic!("dyn_call_viiii is set to None");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn __Unwind_Backtrace(ctx: &mut Ctx, a: i32, b: i32) -> i32 {
|
|
||||||
debug!("emscripten::__Unwind_Backtrace");
|
debug!("emscripten::__Unwind_Backtrace");
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
pub fn __Unwind_FindEnclosingFunction(ctx: &mut Ctx, a: i32) -> i32 {
|
pub fn __Unwind_FindEnclosingFunction(_ctx: &mut Ctx, _a: i32) -> i32 {
|
||||||
debug!("emscripten::__Unwind_FindEnclosingFunction");
|
debug!("emscripten::__Unwind_FindEnclosingFunction");
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
pub fn __Unwind_GetIPInfo(ctx: &mut Ctx, a: i32, b: i32) -> i32 {
|
pub fn __Unwind_GetIPInfo(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
|
||||||
debug!("emscripten::__Unwind_GetIPInfo");
|
debug!("emscripten::__Unwind_GetIPInfo");
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
pub fn ___cxa_find_matching_catch_2(ctx: &mut Ctx) -> i32 {
|
pub fn ___cxa_find_matching_catch_2(_ctx: &mut Ctx) -> i32 {
|
||||||
debug!("emscripten::___cxa_find_matching_catch_2");
|
debug!("emscripten::___cxa_find_matching_catch_2");
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
pub fn ___cxa_find_matching_catch_3(ctx: &mut Ctx, a: i32) -> i32 {
|
pub fn ___cxa_find_matching_catch_3(_ctx: &mut Ctx, _a: i32) -> i32 {
|
||||||
debug!("emscripten::___cxa_find_matching_catch_3");
|
debug!("emscripten::___cxa_find_matching_catch_3");
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
pub fn ___cxa_free_exception(ctx: &mut Ctx, a: i32) {
|
pub fn ___cxa_free_exception(_ctx: &mut Ctx, _a: i32) {
|
||||||
debug!("emscripten::___cxa_free_exception");
|
debug!("emscripten::___cxa_free_exception");
|
||||||
}
|
}
|
||||||
pub fn ___resumeException(ctx: &mut Ctx, a: i32) {
|
pub fn ___resumeException(_ctx: &mut Ctx, _a: i32) {
|
||||||
debug!("emscripten::___resumeException");
|
debug!("emscripten::___resumeException");
|
||||||
}
|
}
|
||||||
pub fn _dladdr(ctx: &mut Ctx, a: i32, b: i32) -> i32 {
|
pub fn _dladdr(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
|
||||||
debug!("emscripten::_dladdr");
|
debug!("emscripten::_dladdr");
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
pub fn _pthread_cond_destroy(ctx: &mut Ctx, a: i32) -> i32 {
|
pub fn _pthread_cond_destroy(_ctx: &mut Ctx, _a: i32) -> i32 {
|
||||||
debug!("emscripten::_pthread_cond_destroy");
|
debug!("emscripten::_pthread_cond_destroy");
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
pub fn _pthread_cond_init(ctx: &mut Ctx, a: i32, b: i32) -> i32 {
|
pub fn _pthread_getspecific(_ctx: &mut Ctx, _a: i32) -> i32 {
|
||||||
|
debug!("emscripten::_pthread_getspecific");
|
||||||
|
0
|
||||||
|
}
|
||||||
|
pub fn _pthread_setspecific(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
|
||||||
|
debug!("emscripten::_pthread_setspecific");
|
||||||
|
0
|
||||||
|
}
|
||||||
|
pub fn _pthread_once(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
|
||||||
|
debug!("emscripten::_pthread_once");
|
||||||
|
0
|
||||||
|
}
|
||||||
|
pub fn _pthread_key_create(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
|
||||||
|
debug!("emscripten::_pthread_key_create");
|
||||||
|
0
|
||||||
|
}
|
||||||
|
pub fn _pthread_create(_ctx: &mut Ctx, _a: i32, _b: i32, _c: i32, _d: i32) -> i32 {
|
||||||
|
debug!("emscripten::_pthread_create");
|
||||||
|
0
|
||||||
|
}
|
||||||
|
pub fn _pthread_join(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
|
||||||
|
debug!("emscripten::_pthread_join");
|
||||||
|
0
|
||||||
|
}
|
||||||
|
pub fn _pthread_cond_init(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
|
||||||
debug!("emscripten::_pthread_cond_init");
|
debug!("emscripten::_pthread_cond_init");
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
pub fn _pthread_cond_signal(ctx: &mut Ctx, a: i32) -> i32 {
|
pub fn _pthread_cond_signal(_ctx: &mut Ctx, _a: i32) -> i32 {
|
||||||
debug!("emscripten::_pthread_cond_signal");
|
debug!("emscripten::_pthread_cond_signal");
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
pub fn _pthread_cond_wait(ctx: &mut Ctx, a: i32, b: i32) -> i32 {
|
pub fn _pthread_cond_wait(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
|
||||||
debug!("emscripten::_pthread_cond_wait");
|
debug!("emscripten::_pthread_cond_wait");
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
pub fn _pthread_condattr_destroy(ctx: &mut Ctx, a: i32) -> i32 {
|
pub fn _pthread_condattr_destroy(_ctx: &mut Ctx, _a: i32) -> i32 {
|
||||||
debug!("emscripten::_pthread_condattr_destroy");
|
debug!("emscripten::_pthread_condattr_destroy");
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
pub fn _pthread_condattr_init(ctx: &mut Ctx, a: i32) -> i32 {
|
pub fn _pthread_condattr_init(_ctx: &mut Ctx, _a: i32) -> i32 {
|
||||||
debug!("emscripten::_pthread_condattr_init");
|
debug!("emscripten::_pthread_condattr_init");
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
pub fn _pthread_condattr_setclock(ctx: &mut Ctx, a: i32, b: i32) -> i32 {
|
pub fn _pthread_condattr_setclock(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
|
||||||
debug!("emscripten::_pthread_condattr_setclock");
|
debug!("emscripten::_pthread_condattr_setclock");
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
pub fn _pthread_mutex_destroy(ctx: &mut Ctx, a: i32) -> i32 {
|
pub fn _pthread_mutex_destroy(_ctx: &mut Ctx, _a: i32) -> i32 {
|
||||||
debug!("emscripten::_pthread_mutex_destroy");
|
debug!("emscripten::_pthread_mutex_destroy");
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
pub fn _pthread_mutex_init(ctx: &mut Ctx, a: i32, b: i32) -> i32 {
|
pub fn _pthread_mutex_init(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
|
||||||
debug!("emscripten::_pthread_mutex_init");
|
debug!("emscripten::_pthread_mutex_init");
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
pub fn _pthread_mutexattr_destroy(ctx: &mut Ctx, a: i32) -> i32 {
|
pub fn _pthread_mutexattr_destroy(_ctx: &mut Ctx, _a: i32) -> i32 {
|
||||||
debug!("emscripten::_pthread_mutexattr_destroy");
|
debug!("emscripten::_pthread_mutexattr_destroy");
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
pub fn _pthread_mutexattr_init(ctx: &mut Ctx, a: i32) -> i32 {
|
pub fn _pthread_mutexattr_init(_ctx: &mut Ctx, _a: i32) -> i32 {
|
||||||
debug!("emscripten::_pthread_mutexattr_init");
|
debug!("emscripten::_pthread_mutexattr_init");
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
pub fn _pthread_mutexattr_settype(ctx: &mut Ctx, a: i32, b: i32) -> i32 {
|
pub fn _pthread_mutexattr_settype(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
|
||||||
debug!("emscripten::_pthread_mutexattr_settype");
|
debug!("emscripten::_pthread_mutexattr_settype");
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
pub fn _pthread_rwlock_rdlock(ctx: &mut Ctx, a: i32) -> i32 {
|
pub fn _pthread_rwlock_rdlock(_ctx: &mut Ctx, _a: i32) -> i32 {
|
||||||
debug!("emscripten::_pthread_rwlock_rdlock");
|
debug!("emscripten::_pthread_rwlock_rdlock");
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
pub fn _pthread_rwlock_unlock(ctx: &mut Ctx, a: i32) -> i32 {
|
pub fn _pthread_rwlock_unlock(_ctx: &mut Ctx, _a: i32) -> i32 {
|
||||||
debug!("emscripten::_pthread_rwlock_unlock");
|
debug!("emscripten::_pthread_rwlock_unlock");
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
pub fn ___gxx_personality_v0(ctx: &mut Ctx, a: i32, b: i32, c: i32, d: i32, e: i32, f: i32) -> i32 {
|
pub fn _pthread_setcancelstate(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
|
||||||
|
debug!("emscripten::_pthread_setcancelstate");
|
||||||
|
0
|
||||||
|
}
|
||||||
|
pub fn ___gxx_personality_v0(
|
||||||
|
_ctx: &mut Ctx,
|
||||||
|
_a: i32,
|
||||||
|
_b: i32,
|
||||||
|
_c: i32,
|
||||||
|
_d: i32,
|
||||||
|
_e: i32,
|
||||||
|
_f: i32,
|
||||||
|
) -> i32 {
|
||||||
debug!("emscripten::___gxx_personality_v0");
|
debug!("emscripten::___gxx_personality_v0");
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
// round 2
|
#[cfg(target_os = "linux")]
|
||||||
pub fn nullFunc_dii(ctx: &mut Ctx, index: i32) {
|
pub fn _getdtablesize(_ctx: &mut Ctx) -> i32 {
|
||||||
debug!("emscripten::nullFunc_dii");
|
debug!("emscripten::getdtablesize");
|
||||||
|
unsafe { getdtablesize() }
|
||||||
}
|
}
|
||||||
pub fn nullFunc_diiii(ctx: &mut Ctx, index: i32) {
|
#[cfg(not(target_os = "linux"))]
|
||||||
debug!("emscripten::nullFunc_diiii");
|
pub fn _getdtablesize(_ctx: &mut Ctx) -> i32 {
|
||||||
|
debug!("emscripten::getdtablesize");
|
||||||
|
-1
|
||||||
}
|
}
|
||||||
pub fn nullFunc_iiji(ctx: &mut Ctx, index: i32) {
|
pub fn _gethostbyaddr(_ctx: &mut Ctx, _addr: i32, _addrlen: i32, _atype: i32) -> i32 {
|
||||||
debug!("emscripten::nullFunc_iiji");
|
debug!("emscripten::gethostbyaddr");
|
||||||
|
0
|
||||||
}
|
}
|
||||||
pub fn nullFunc_j(ctx: &mut Ctx, index: i32) {
|
pub fn _gethostbyname_r(
|
||||||
debug!("emscripten::nullFunc_j");
|
_ctx: &mut Ctx,
|
||||||
|
_name: i32,
|
||||||
|
_ret: i32,
|
||||||
|
_buf: i32,
|
||||||
|
_buflen: i32,
|
||||||
|
_out: i32,
|
||||||
|
_err: i32,
|
||||||
|
) -> i32 {
|
||||||
|
debug!("emscripten::gethostbyname_r");
|
||||||
|
0
|
||||||
}
|
}
|
||||||
pub fn nullFunc_jij(ctx: &mut Ctx, index: i32) {
|
// NOTE: php.js has proper impl; libc has proper impl for linux
|
||||||
debug!("emscripten::nullFunc_jij");
|
pub fn _getloadavg(_ctx: &mut Ctx, _loadavg: i32, _nelem: i32) -> i32 {
|
||||||
|
debug!("emscripten::getloadavg");
|
||||||
|
0
|
||||||
}
|
}
|
||||||
pub fn nullFunc_jjj(ctx: &mut Ctx, index: i32) {
|
|
||||||
debug!("emscripten::nullFunc_jjj");
|
// Invoke functions
|
||||||
|
// They save the stack to allow unwinding
|
||||||
|
|
||||||
|
// Macro definitions
|
||||||
|
macro_rules! invoke {
|
||||||
|
($ctx: ident, $name:ident, $( $arg:ident ),*) => {{
|
||||||
|
let sp = get_emscripten_data($ctx).stack_save.as_ref().expect("stack_save is None").call().expect("stack_save call failed");
|
||||||
|
let result = get_emscripten_data($ctx).$name.as_ref().expect(concat!("Dynamic call is None: ", stringify!($name))).call($($arg),*);
|
||||||
|
match result {
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(_e) => {
|
||||||
|
get_emscripten_data($ctx).stack_restore.as_ref().expect("stack_restore is None").call(sp).expect("stack_restore call failed");
|
||||||
|
// TODO: We should check if _e != "longjmp" and if that's the case, re-throw the error
|
||||||
|
// JS version is: if (e !== e+0 && e !== 'longjmp') throw e;
|
||||||
|
get_emscripten_data($ctx).set_threw.as_ref().expect("set_threw is None").call(1, 0).expect("set_threw call failed");
|
||||||
|
0 as _
|
||||||
}
|
}
|
||||||
pub fn nullFunc_vd(ctx: &mut Ctx, index: i32) {
|
|
||||||
debug!("emscripten::nullFunc_vd");
|
|
||||||
}
|
}
|
||||||
pub fn nullFunc_viiiiiii(ctx: &mut Ctx, index: i32) {
|
}};
|
||||||
debug!("emscripten::nullFunc_viiiiiii");
|
|
||||||
}
|
}
|
||||||
pub fn nullFunc_viiiiiiii(ctx: &mut Ctx, index: i32) {
|
macro_rules! invoke_no_return {
|
||||||
debug!("emscripten::nullFunc_viiiiiiii");
|
($ctx: ident, $name:ident, $( $arg:ident ),*) => {{
|
||||||
|
let sp = get_emscripten_data($ctx).stack_save.as_ref().expect("stack_save is None").call().expect("stack_save call failed");
|
||||||
|
let result = get_emscripten_data($ctx).$name.as_ref().expect(concat!("Dynamic call is None: ", stringify!($name))).call($($arg),*);
|
||||||
|
match result {
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(_e) => {
|
||||||
|
get_emscripten_data($ctx).stack_restore.as_ref().expect("stack_restore is None").call(sp).expect("stack_restore call failed");
|
||||||
|
// TODO: We should check if _e != "longjmp" and if that's the case, re-throw the error
|
||||||
|
// JS version is: if (e !== e+0 && e !== 'longjmp') throw e;
|
||||||
|
get_emscripten_data($ctx).set_threw.as_ref().expect("set_threw is None").call(1, 0).expect("set_threw call failed");
|
||||||
}
|
}
|
||||||
pub fn nullFunc_viiiiiiiii(ctx: &mut Ctx, index: i32) {
|
|
||||||
debug!("emscripten::nullFunc_viiiiiiiii");
|
|
||||||
}
|
}
|
||||||
pub fn nullFunc_viiij(ctx: &mut Ctx, index: i32) {
|
}};
|
||||||
debug!("emscripten::nullFunc_viiij");
|
|
||||||
}
|
}
|
||||||
pub fn nullFunc_viiijiiii(ctx: &mut Ctx, index: i32) {
|
|
||||||
debug!("emscripten::nullFunc_viiijiiii");
|
// Invoke functions
|
||||||
|
pub fn invoke_i(ctx: &mut Ctx, index: i32) -> i32 {
|
||||||
|
debug!("emscripten::invoke_i");
|
||||||
|
invoke!(ctx, dyn_call_i, index)
|
||||||
}
|
}
|
||||||
pub fn nullFunc_viiijiiiiii(ctx: &mut Ctx, index: i32) {
|
pub fn invoke_ii(ctx: &mut Ctx, index: i32, a1: i32) -> i32 {
|
||||||
debug!("emscripten::nullFunc_viiijiiiiii");
|
debug!("emscripten::invoke_ii");
|
||||||
|
invoke!(ctx, dyn_call_ii, index, a1)
|
||||||
}
|
}
|
||||||
pub fn nullFunc_viij(ctx: &mut Ctx, index: i32) {
|
pub fn invoke_iii(ctx: &mut Ctx, index: i32, a1: i32, a2: i32) -> i32 {
|
||||||
debug!("emscripten::nullFunc_viij");
|
debug!("emscripten::invoke_iii");
|
||||||
|
invoke!(ctx, dyn_call_iii, index, a1, a2)
|
||||||
}
|
}
|
||||||
pub fn nullFunc_viiji(ctx: &mut Ctx, index: i32) {
|
pub fn invoke_iiii(ctx: &mut Ctx, index: i32, a1: i32, a2: i32, a3: i32) -> i32 {
|
||||||
debug!("emscripten::nullFunc_viiji");
|
debug!("emscripten::invoke_iiii");
|
||||||
|
invoke!(ctx, dyn_call_iiii, index, a1, a2, a3)
|
||||||
}
|
}
|
||||||
pub fn nullFunc_viijiii(ctx: &mut Ctx, index: i32) {
|
pub fn invoke_iifi(ctx: &mut Ctx, index: i32, a1: i32, a2: f64, a3: i32) -> i32 {
|
||||||
debug!("emscripten::nullFunc_viijiii");
|
debug!("emscripten::invoke_iifi");
|
||||||
|
invoke!(ctx, dyn_call_iifi, index, a1, a2, a3)
|
||||||
}
|
}
|
||||||
pub fn nullFunc_viijj(ctx: &mut Ctx, index: i32) {
|
pub fn invoke_v(ctx: &mut Ctx, index: i32) {
|
||||||
debug!("emscripten::nullFunc_viijj");
|
debug!("emscripten::invoke_v");
|
||||||
|
invoke_no_return!(ctx, dyn_call_v, index);
|
||||||
}
|
}
|
||||||
pub fn nullFunc_vij(ctx: &mut Ctx, index: i32) {
|
pub fn invoke_vi(ctx: &mut Ctx, index: i32, a1: i32) {
|
||||||
debug!("emscripten::nullFunc_vij");
|
debug!("emscripten::invoke_vi");
|
||||||
|
invoke_no_return!(ctx, dyn_call_vi, index, a1);
|
||||||
}
|
}
|
||||||
pub fn nullFunc_viji(ctx: &mut Ctx, index: i32) {
|
pub fn invoke_vii(ctx: &mut Ctx, index: i32, a1: i32, a2: i32) {
|
||||||
debug!("emscripten::nullFunc_viji");
|
debug!("emscripten::invoke_vii");
|
||||||
|
invoke_no_return!(ctx, dyn_call_vii, index, a1, a2);
|
||||||
}
|
}
|
||||||
pub fn nullFunc_vijiii(ctx: &mut Ctx, index: i32) {
|
|
||||||
debug!("emscripten::nullFunc_vijiii");
|
pub fn invoke_viii(ctx: &mut Ctx, index: i32, a1: i32, a2: i32, a3: i32) {
|
||||||
|
debug!("emscripten::invoke_viii");
|
||||||
|
invoke_no_return!(ctx, dyn_call_viii, index, a1, a2, a3);
|
||||||
}
|
}
|
||||||
pub fn nullFunc_vijj(ctx: &mut Ctx, index: i32) {
|
pub fn invoke_viiii(ctx: &mut Ctx, index: i32, a1: i32, a2: i32, a3: i32, a4: i32) {
|
||||||
debug!("emscripten::nullFunc_vijj");
|
debug!("emscripten::invoke_viiii");
|
||||||
|
invoke_no_return!(ctx, dyn_call_viiii, index, a1, a2, a3, a4);
|
||||||
}
|
}
|
||||||
pub fn invoke_dii(ctx: &mut Ctx, index: i32, a1: i32, a2: i32) -> f64 {
|
pub fn invoke_dii(ctx: &mut Ctx, index: i32, a1: i32, a2: i32) -> f64 {
|
||||||
debug!("emscripten::invoke_dii");
|
debug!("emscripten::invoke_dii");
|
||||||
if let Some(dyn_call_dii) = &get_emscripten_data(ctx).dyn_call_dii {
|
invoke!(ctx, dyn_call_dii, index, a1, a2)
|
||||||
dyn_call_dii.call(index, a1, a2).unwrap()
|
|
||||||
} else {
|
|
||||||
panic!("dyn_call_dii is set to None");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
pub fn invoke_diiii(ctx: &mut Ctx, index: i32, a1: i32, a2: i32, a3: i32, a4: i32) -> f64 {
|
pub fn invoke_diiii(ctx: &mut Ctx, index: i32, a1: i32, a2: i32, a3: i32, a4: i32) -> f64 {
|
||||||
debug!("emscripten::invoke_diiii");
|
debug!("emscripten::invoke_diiii");
|
||||||
if let Some(dyn_call_diiii) = &get_emscripten_data(ctx).dyn_call_diiii {
|
invoke!(ctx, dyn_call_diiii, index, a1, a2, a3, a4)
|
||||||
dyn_call_diiii.call(index, a1, a2, a3, a4).unwrap()
|
|
||||||
} else {
|
|
||||||
panic!("dyn_call_diiii is set to None");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
pub fn invoke_iiiii(ctx: &mut Ctx, index: i32, a1: i32, a2: i32, a3: i32, a4: i32) -> i32 {
|
pub fn invoke_iiiii(ctx: &mut Ctx, index: i32, a1: i32, a2: i32, a3: i32, a4: i32) -> i32 {
|
||||||
debug!("emscripten::invoke_iiiii");
|
debug!("emscripten::invoke_iiiii");
|
||||||
if let Some(dyn_call_iiiii) = &get_emscripten_data(ctx).dyn_call_iiiii {
|
invoke!(ctx, dyn_call_iiiii, index, a1, a2, a3, a4)
|
||||||
dyn_call_iiiii.call(index, a1, a2, a3, a4).unwrap()
|
|
||||||
} else {
|
|
||||||
panic!("dyn_call_iiiii is set to None");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
pub fn invoke_iiiiii(
|
pub fn invoke_iiiiii(
|
||||||
ctx: &mut Ctx,
|
ctx: &mut Ctx,
|
||||||
@ -271,27 +273,129 @@ pub fn invoke_iiiiii(
|
|||||||
a5: i32,
|
a5: i32,
|
||||||
) -> i32 {
|
) -> i32 {
|
||||||
debug!("emscripten::invoke_iiiiii");
|
debug!("emscripten::invoke_iiiiii");
|
||||||
if let Some(dyn_call_iiiiii) = &get_emscripten_data(ctx).dyn_call_iiiiii {
|
invoke!(ctx, dyn_call_iiiiii, index, a1, a2, a3, a4, a5)
|
||||||
dyn_call_iiiiii.call(index, a1, a2, a3, a4, a5).unwrap()
|
|
||||||
} else {
|
|
||||||
panic!("dyn_call_iiiiii is set to None");
|
|
||||||
}
|
}
|
||||||
|
pub fn invoke_iiiiiii(
|
||||||
|
ctx: &mut Ctx,
|
||||||
|
index: i32,
|
||||||
|
a1: i32,
|
||||||
|
a2: i32,
|
||||||
|
a3: i32,
|
||||||
|
a4: i32,
|
||||||
|
a5: i32,
|
||||||
|
a6: i32,
|
||||||
|
) -> i32 {
|
||||||
|
debug!("emscripten::invoke_iiiiiii");
|
||||||
|
invoke!(ctx, dyn_call_iiiiiii, index, a1, a2, a3, a4, a5, a6)
|
||||||
|
}
|
||||||
|
pub fn invoke_iiiiiiii(
|
||||||
|
ctx: &mut Ctx,
|
||||||
|
index: i32,
|
||||||
|
a1: i32,
|
||||||
|
a2: i32,
|
||||||
|
a3: i32,
|
||||||
|
a4: i32,
|
||||||
|
a5: i32,
|
||||||
|
a6: i32,
|
||||||
|
a7: i32,
|
||||||
|
) -> i32 {
|
||||||
|
debug!("emscripten::invoke_iiiiiiii");
|
||||||
|
invoke!(ctx, dyn_call_iiiiiiii, index, a1, a2, a3, a4, a5, a6, a7)
|
||||||
|
}
|
||||||
|
pub fn invoke_iiiiiiiii(
|
||||||
|
ctx: &mut Ctx,
|
||||||
|
index: i32,
|
||||||
|
a1: i32,
|
||||||
|
a2: i32,
|
||||||
|
a3: i32,
|
||||||
|
a4: i32,
|
||||||
|
a5: i32,
|
||||||
|
a6: i32,
|
||||||
|
a7: i32,
|
||||||
|
a8: i32,
|
||||||
|
) -> i32 {
|
||||||
|
debug!("emscripten::invoke_iiiiiiiii");
|
||||||
|
invoke!(
|
||||||
|
ctx,
|
||||||
|
dyn_call_iiiiiiiii,
|
||||||
|
index,
|
||||||
|
a1,
|
||||||
|
a2,
|
||||||
|
a3,
|
||||||
|
a4,
|
||||||
|
a5,
|
||||||
|
a6,
|
||||||
|
a7,
|
||||||
|
a8
|
||||||
|
)
|
||||||
|
}
|
||||||
|
pub fn invoke_iiiiiiiiii(
|
||||||
|
ctx: &mut Ctx,
|
||||||
|
index: i32,
|
||||||
|
a1: i32,
|
||||||
|
a2: i32,
|
||||||
|
a3: i32,
|
||||||
|
a4: i32,
|
||||||
|
a5: i32,
|
||||||
|
a6: i32,
|
||||||
|
a7: i32,
|
||||||
|
a8: i32,
|
||||||
|
a9: i32,
|
||||||
|
) -> i32 {
|
||||||
|
debug!("emscripten::invoke_iiiiiiiiii");
|
||||||
|
invoke!(
|
||||||
|
ctx,
|
||||||
|
dyn_call_iiiiiiiiii,
|
||||||
|
index,
|
||||||
|
a1,
|
||||||
|
a2,
|
||||||
|
a3,
|
||||||
|
a4,
|
||||||
|
a5,
|
||||||
|
a6,
|
||||||
|
a7,
|
||||||
|
a8,
|
||||||
|
a9
|
||||||
|
)
|
||||||
|
}
|
||||||
|
pub fn invoke_iiiiiiiiiii(
|
||||||
|
ctx: &mut Ctx,
|
||||||
|
index: i32,
|
||||||
|
a1: i32,
|
||||||
|
a2: i32,
|
||||||
|
a3: i32,
|
||||||
|
a4: i32,
|
||||||
|
a5: i32,
|
||||||
|
a6: i32,
|
||||||
|
a7: i32,
|
||||||
|
a8: i32,
|
||||||
|
a9: i32,
|
||||||
|
a10: i32,
|
||||||
|
) -> i32 {
|
||||||
|
debug!("emscripten::invoke_iiiiiiiiiii");
|
||||||
|
invoke!(
|
||||||
|
ctx,
|
||||||
|
dyn_call_iiiiiiiiiii,
|
||||||
|
index,
|
||||||
|
a1,
|
||||||
|
a2,
|
||||||
|
a3,
|
||||||
|
a4,
|
||||||
|
a5,
|
||||||
|
a6,
|
||||||
|
a7,
|
||||||
|
a8,
|
||||||
|
a9,
|
||||||
|
a10
|
||||||
|
)
|
||||||
}
|
}
|
||||||
pub fn invoke_vd(ctx: &mut Ctx, index: i32, a1: f64) {
|
pub fn invoke_vd(ctx: &mut Ctx, index: i32, a1: f64) {
|
||||||
debug!("emscripten::invoke_vd");
|
debug!("emscripten::invoke_vd");
|
||||||
if let Some(dyn_call_vd) = &get_emscripten_data(ctx).dyn_call_vd {
|
invoke_no_return!(ctx, dyn_call_vd, index, a1)
|
||||||
dyn_call_vd.call(index, a1).unwrap();
|
|
||||||
} else {
|
|
||||||
panic!("dyn_call_vd is set to None");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
pub fn invoke_viiiii(ctx: &mut Ctx, index: i32, a1: i32, a2: i32, a3: i32, a4: i32, a5: i32) {
|
pub fn invoke_viiiii(ctx: &mut Ctx, index: i32, a1: i32, a2: i32, a3: i32, a4: i32, a5: i32) {
|
||||||
debug!("emscripten::invoke_viiiii");
|
debug!("emscripten::invoke_viiiii");
|
||||||
if let Some(dyn_call_viiiii) = &get_emscripten_data(ctx).dyn_call_viiiii {
|
invoke_no_return!(ctx, dyn_call_viiiii, index, a1, a2, a3, a4, a5)
|
||||||
dyn_call_viiiii.call(index, a1, a2, a3, a4, a5).unwrap();
|
|
||||||
} else {
|
|
||||||
panic!("dyn_call_viiiii is set to None");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
pub fn invoke_viiiiii(
|
pub fn invoke_viiiiii(
|
||||||
ctx: &mut Ctx,
|
ctx: &mut Ctx,
|
||||||
@ -304,13 +408,7 @@ pub fn invoke_viiiiii(
|
|||||||
a6: i32,
|
a6: i32,
|
||||||
) {
|
) {
|
||||||
debug!("emscripten::invoke_viiiiii");
|
debug!("emscripten::invoke_viiiiii");
|
||||||
if let Some(dyn_call_viiiiii) = &get_emscripten_data(ctx).dyn_call_viiiiii {
|
invoke_no_return!(ctx, dyn_call_viiiiii, index, a1, a2, a3, a4, a5, a6)
|
||||||
dyn_call_viiiiii
|
|
||||||
.call(index, a1, a2, a3, a4, a5, a6)
|
|
||||||
.unwrap();
|
|
||||||
} else {
|
|
||||||
panic!("dyn_call_viiiiii is set to None");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
pub fn invoke_viiiiiii(
|
pub fn invoke_viiiiiii(
|
||||||
ctx: &mut Ctx,
|
ctx: &mut Ctx,
|
||||||
@ -324,13 +422,7 @@ pub fn invoke_viiiiiii(
|
|||||||
a7: i32,
|
a7: i32,
|
||||||
) {
|
) {
|
||||||
debug!("emscripten::invoke_viiiiiii");
|
debug!("emscripten::invoke_viiiiiii");
|
||||||
if let Some(dyn_call_viiiiiii) = &get_emscripten_data(ctx).dyn_call_viiiiiii {
|
invoke_no_return!(ctx, dyn_call_viiiiiii, index, a1, a2, a3, a4, a5, a6, a7)
|
||||||
dyn_call_viiiiiii
|
|
||||||
.call(index, a1, a2, a3, a4, a5, a6, a7)
|
|
||||||
.unwrap();
|
|
||||||
} else {
|
|
||||||
panic!("dyn_call_viiiiiii is set to None");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
pub fn invoke_viiiiiiii(
|
pub fn invoke_viiiiiiii(
|
||||||
ctx: &mut Ctx,
|
ctx: &mut Ctx,
|
||||||
@ -345,13 +437,19 @@ pub fn invoke_viiiiiiii(
|
|||||||
a8: i32,
|
a8: i32,
|
||||||
) {
|
) {
|
||||||
debug!("emscripten::invoke_viiiiiiii");
|
debug!("emscripten::invoke_viiiiiiii");
|
||||||
if let Some(dyn_call_viiiiiiii) = &get_emscripten_data(ctx).dyn_call_viiiiiiii {
|
invoke_no_return!(
|
||||||
dyn_call_viiiiiiii
|
ctx,
|
||||||
.call(index, a1, a2, a3, a4, a5, a6, a7, a8)
|
dyn_call_viiiiiiii,
|
||||||
.unwrap();
|
index,
|
||||||
} else {
|
a1,
|
||||||
panic!("dyn_call_viiiiiiii is set to None");
|
a2,
|
||||||
}
|
a3,
|
||||||
|
a4,
|
||||||
|
a5,
|
||||||
|
a6,
|
||||||
|
a7,
|
||||||
|
a8
|
||||||
|
)
|
||||||
}
|
}
|
||||||
pub fn invoke_viiiiiiiii(
|
pub fn invoke_viiiiiiiii(
|
||||||
ctx: &mut Ctx,
|
ctx: &mut Ctx,
|
||||||
@ -367,21 +465,75 @@ pub fn invoke_viiiiiiiii(
|
|||||||
a9: i32,
|
a9: i32,
|
||||||
) {
|
) {
|
||||||
debug!("emscripten::invoke_viiiiiiiii");
|
debug!("emscripten::invoke_viiiiiiiii");
|
||||||
if let Some(dyn_call_viiiiiiiii) = &get_emscripten_data(ctx).dyn_call_viiiiiiiii {
|
invoke_no_return!(
|
||||||
dyn_call_viiiiiiiii
|
ctx,
|
||||||
.call(index, a1, a2, a3, a4, a5, a6, a7, a8, a9)
|
dyn_call_viiiiiiiii,
|
||||||
.unwrap();
|
index,
|
||||||
} else {
|
a1,
|
||||||
panic!("dyn_call_viiiiiiiii is set to None");
|
a2,
|
||||||
|
a3,
|
||||||
|
a4,
|
||||||
|
a5,
|
||||||
|
a6,
|
||||||
|
a7,
|
||||||
|
a8,
|
||||||
|
a9
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
pub fn invoke_viiiiiiiiii(
|
||||||
|
ctx: &mut Ctx,
|
||||||
|
index: i32,
|
||||||
|
a1: i32,
|
||||||
|
a2: i32,
|
||||||
|
a3: i32,
|
||||||
|
a4: i32,
|
||||||
|
a5: i32,
|
||||||
|
a6: i32,
|
||||||
|
a7: i32,
|
||||||
|
a8: i32,
|
||||||
|
a9: i32,
|
||||||
|
a10: i32,
|
||||||
|
) {
|
||||||
|
debug!("emscripten::invoke_viiiiiiiiii");
|
||||||
|
invoke_no_return!(
|
||||||
|
ctx,
|
||||||
|
dyn_call_viiiiiiiiii,
|
||||||
|
index,
|
||||||
|
a1,
|
||||||
|
a2,
|
||||||
|
a3,
|
||||||
|
a4,
|
||||||
|
a5,
|
||||||
|
a6,
|
||||||
|
a7,
|
||||||
|
a8,
|
||||||
|
a9,
|
||||||
|
a10
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn invoke_iij(ctx: &mut Ctx, index: i32, a1: i32, a2: i32, a3: i32) -> i32 {
|
||||||
|
debug!("emscripten::invoke_iij");
|
||||||
|
invoke!(ctx, dyn_call_iij, index, a1, a2, a3)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn invoke_iiji(ctx: &mut Ctx, index: i32, a1: i32, a2: i32, a3: i32, a4: i32) -> i32 {
|
pub fn invoke_iiji(ctx: &mut Ctx, index: i32, a1: i32, a2: i32, a3: i32, a4: i32) -> i32 {
|
||||||
debug!("emscripten::invoke_iiji");
|
debug!("emscripten::invoke_iiji");
|
||||||
if let Some(dyn_call_iiji) = &get_emscripten_data(ctx).dyn_call_iiji {
|
invoke!(ctx, dyn_call_iiji, index, a1, a2, a3, a4)
|
||||||
dyn_call_iiji.call(index, a1, a2, a3, a4).unwrap()
|
|
||||||
} else {
|
|
||||||
panic!("dyn_call_iiji is set to None");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn invoke_iiijj(
|
||||||
|
ctx: &mut Ctx,
|
||||||
|
index: i32,
|
||||||
|
a1: i32,
|
||||||
|
a2: i32,
|
||||||
|
a3: i32,
|
||||||
|
a4: i32,
|
||||||
|
a5: i32,
|
||||||
|
a6: i32,
|
||||||
|
) -> i32 {
|
||||||
|
debug!("emscripten::invoke_iiijj");
|
||||||
|
invoke!(ctx, dyn_call_iiijj, index, a1, a2, a3, a4, a5, a6)
|
||||||
}
|
}
|
||||||
pub fn invoke_j(ctx: &mut Ctx, index: i32) -> i32 {
|
pub fn invoke_j(ctx: &mut Ctx, index: i32) -> i32 {
|
||||||
debug!("emscripten::invoke_j");
|
debug!("emscripten::invoke_j");
|
||||||
@ -399,6 +551,15 @@ pub fn invoke_ji(ctx: &mut Ctx, index: i32, a1: i32) -> i32 {
|
|||||||
panic!("dyn_call_ji is set to None");
|
panic!("dyn_call_ji is set to None");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn invoke_jii(ctx: &mut Ctx, index: i32, a1: i32, a2: i32) -> i32 {
|
||||||
|
debug!("emscripten::invoke_jii");
|
||||||
|
if let Some(dyn_call_jii) = &get_emscripten_data(ctx).dyn_call_jii {
|
||||||
|
dyn_call_jii.call(index, a1, a2).unwrap()
|
||||||
|
} else {
|
||||||
|
panic!("dyn_call_jii is set to None");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn invoke_jij(ctx: &mut Ctx, index: i32, a1: i32, a2: i32, a3: i32) -> i32 {
|
pub fn invoke_jij(ctx: &mut Ctx, index: i32, a1: i32, a2: i32, a3: i32) -> i32 {
|
||||||
debug!("emscripten::invoke_jij");
|
debug!("emscripten::invoke_jij");
|
||||||
if let Some(dyn_call_jij) = &get_emscripten_data(ctx).dyn_call_jij {
|
if let Some(dyn_call_jij) = &get_emscripten_data(ctx).dyn_call_jij {
|
||||||
@ -522,6 +683,14 @@ pub fn invoke_viijj(
|
|||||||
panic!("dyn_call_viijj is set to None");
|
panic!("dyn_call_viijj is set to None");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn invoke_vj(ctx: &mut Ctx, index: i32, a1: i32, a2: i32) {
|
||||||
|
debug!("emscripten::invoke_vj");
|
||||||
|
if let Some(dyn_call_vj) = &get_emscripten_data(ctx).dyn_call_vj {
|
||||||
|
dyn_call_vj.call(index, a1, a2).unwrap();
|
||||||
|
} else {
|
||||||
|
panic!("dyn_call_vj is set to None");
|
||||||
|
}
|
||||||
|
}
|
||||||
pub fn invoke_vij(ctx: &mut Ctx, index: i32, a1: i32, a2: i32, a3: i32) {
|
pub fn invoke_vij(ctx: &mut Ctx, index: i32, a1: i32, a2: i32, a3: i32) {
|
||||||
debug!("emscripten::invoke_vij");
|
debug!("emscripten::invoke_vij");
|
||||||
if let Some(dyn_call_vij) = &get_emscripten_data(ctx).dyn_call_vij {
|
if let Some(dyn_call_vij) = &get_emscripten_data(ctx).dyn_call_vij {
|
||||||
@ -563,3 +732,42 @@ pub fn invoke_vijj(ctx: &mut Ctx, index: i32, a1: i32, a2: i32, a3: i32, a4: i32
|
|||||||
panic!("dyn_call_vijj is set to None");
|
panic!("dyn_call_vijj is set to None");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn invoke_viid(ctx: &mut Ctx, index: i32, a1: i32, a2: i32, a3: f64) {
|
||||||
|
debug!("emscripten::invoke_viid");
|
||||||
|
invoke_no_return!(ctx, dyn_call_viid, index, a1, a2, a3);
|
||||||
|
}
|
||||||
|
pub fn invoke_viidii(ctx: &mut Ctx, index: i32, a1: i32, a2: i32, a3: f64, a4: i32, a5: i32) {
|
||||||
|
debug!("emscripten::invoke_viidii");
|
||||||
|
invoke_no_return!(ctx, dyn_call_viidii, index, a1, a2, a3, a4, a5);
|
||||||
|
}
|
||||||
|
pub fn invoke_viidddddddd(
|
||||||
|
ctx: &mut Ctx,
|
||||||
|
index: i32,
|
||||||
|
a1: i32,
|
||||||
|
a2: i32,
|
||||||
|
a3: f64,
|
||||||
|
a4: f64,
|
||||||
|
a5: f64,
|
||||||
|
a6: f64,
|
||||||
|
a7: f64,
|
||||||
|
a8: f64,
|
||||||
|
a9: f64,
|
||||||
|
a10: f64,
|
||||||
|
) {
|
||||||
|
debug!("emscripten::invoke_viidddddddd");
|
||||||
|
invoke_no_return!(
|
||||||
|
ctx,
|
||||||
|
dyn_call_viidddddddd,
|
||||||
|
index,
|
||||||
|
a1,
|
||||||
|
a2,
|
||||||
|
a3,
|
||||||
|
a4,
|
||||||
|
a5,
|
||||||
|
a6,
|
||||||
|
a7,
|
||||||
|
a8,
|
||||||
|
a9,
|
||||||
|
a10
|
||||||
|
);
|
||||||
|
}
|
||||||
|
11
lib/emscripten/src/env/mod.rs
vendored
11
lib/emscripten/src/env/mod.rs
vendored
@ -47,6 +47,13 @@ pub fn _getpagesize(_ctx: &mut Ctx) -> u32 {
|
|||||||
16384
|
16384
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn _times(ctx: &mut Ctx, buffer: u32) -> u32 {
|
||||||
|
if buffer != 0 {
|
||||||
|
call_memset(ctx, buffer, 0, 16);
|
||||||
|
}
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(clippy::cast_ptr_alignment)]
|
#[allow(clippy::cast_ptr_alignment)]
|
||||||
pub fn ___build_environment(ctx: &mut Ctx, environ: c_int) {
|
pub fn ___build_environment(ctx: &mut Ctx, environ: c_int) {
|
||||||
debug!("emscripten::___build_environment {}", environ);
|
debug!("emscripten::___build_environment {}", environ);
|
||||||
@ -70,8 +77,8 @@ pub fn ___build_environment(ctx: &mut Ctx, environ: c_int) {
|
|||||||
// };
|
// };
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ___assert_fail(_ctx: &mut Ctx, a: c_int, b: c_int, c: c_int, d: c_int) {
|
pub fn ___assert_fail(_ctx: &mut Ctx, _a: c_int, _b: c_int, _c: c_int, _d: c_int) {
|
||||||
debug!("emscripten::___assert_fail {} {} {} {}", a, b, c, d);
|
debug!("emscripten::___assert_fail {} {} {} {}", _a, _b, _c, _d);
|
||||||
// TODO: Implement like emscripten expects regarding memory/page size
|
// TODO: Implement like emscripten expects regarding memory/page size
|
||||||
// TODO raise an error
|
// TODO raise an error
|
||||||
}
|
}
|
||||||
|
2
lib/emscripten/src/env/unix/mod.rs
vendored
2
lib/emscripten/src/env/unix/mod.rs
vendored
@ -66,6 +66,8 @@ pub fn _unsetenv(ctx: &mut Ctx, name: c_int) -> c_int {
|
|||||||
#[allow(clippy::cast_ptr_alignment)]
|
#[allow(clippy::cast_ptr_alignment)]
|
||||||
pub fn _getpwnam(ctx: &mut Ctx, name_ptr: c_int) -> c_int {
|
pub fn _getpwnam(ctx: &mut Ctx, name_ptr: c_int) -> c_int {
|
||||||
debug!("emscripten::_getpwnam {}", name_ptr);
|
debug!("emscripten::_getpwnam {}", name_ptr);
|
||||||
|
#[cfg(feature = "debug")]
|
||||||
|
let _ = name_ptr;
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
struct GuestPasswd {
|
struct GuestPasswd {
|
||||||
|
18
lib/emscripten/src/env/windows/mod.rs
vendored
18
lib/emscripten/src/env/windows/mod.rs
vendored
@ -7,7 +7,6 @@ use std::os::raw::c_char;
|
|||||||
|
|
||||||
use crate::env::call_malloc;
|
use crate::env::call_malloc;
|
||||||
use crate::utils::{copy_cstr_into_wasm, read_string_from_wasm};
|
use crate::utils::{copy_cstr_into_wasm, read_string_from_wasm};
|
||||||
use std::ffi::CStr;
|
|
||||||
use wasmer_runtime_core::vm::Ctx;
|
use wasmer_runtime_core::vm::Ctx;
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@ -29,10 +28,8 @@ pub fn _getenv(ctx: &mut Ctx, name: u32) -> u32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// emscripten: _setenv // (name: *const char, name: *const value, overwrite: int);
|
/// emscripten: _setenv // (name: *const char, name: *const value, overwrite: int);
|
||||||
pub fn _setenv(ctx: &mut Ctx, name: u32, value: u32, overwrite: u32) -> c_int {
|
pub fn _setenv(ctx: &mut Ctx, name: u32, value: u32, _overwrite: u32) -> c_int {
|
||||||
debug!("emscripten::_setenv");
|
debug!("emscripten::_setenv");
|
||||||
let name_addr = emscripten_memory_pointer!(ctx.memory(0), name);
|
|
||||||
let value_addr = emscripten_memory_pointer!(ctx.memory(0), value);
|
|
||||||
// setenv does not exist on windows, so we hack it with _putenv
|
// setenv does not exist on windows, so we hack it with _putenv
|
||||||
let name = read_string_from_wasm(ctx.memory(0), name);
|
let name = read_string_from_wasm(ctx.memory(0), name);
|
||||||
let value = read_string_from_wasm(ctx.memory(0), value);
|
let value = read_string_from_wasm(ctx.memory(0), value);
|
||||||
@ -47,17 +44,16 @@ pub fn _setenv(ctx: &mut Ctx, name: u32, value: u32, overwrite: u32) -> c_int {
|
|||||||
/// emscripten: _putenv // (name: *const char);
|
/// emscripten: _putenv // (name: *const char);
|
||||||
pub fn _putenv(ctx: &mut Ctx, name: c_int) -> c_int {
|
pub fn _putenv(ctx: &mut Ctx, name: c_int) -> c_int {
|
||||||
debug!("emscripten::_putenv");
|
debug!("emscripten::_putenv");
|
||||||
|
|
||||||
let name_addr = emscripten_memory_pointer!(ctx.memory(0), name) as *const c_char;
|
let name_addr = emscripten_memory_pointer!(ctx.memory(0), name) as *const c_char;
|
||||||
|
debug!("=> name({:?})", unsafe {
|
||||||
debug!("=> name({:?})", unsafe { CStr::from_ptr(name_addr) });
|
std::ffi::CStr::from_ptr(name_addr)
|
||||||
|
});
|
||||||
unsafe { putenv(name_addr) }
|
unsafe { putenv(name_addr) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// emscripten: _unsetenv // (name: *const char);
|
/// emscripten: _unsetenv // (name: *const char);
|
||||||
pub fn _unsetenv(ctx: &mut Ctx, name: u32) -> c_int {
|
pub fn _unsetenv(ctx: &mut Ctx, name: u32) -> c_int {
|
||||||
debug!("emscripten::_unsetenv");
|
debug!("emscripten::_unsetenv");
|
||||||
let name_addr = emscripten_memory_pointer!(ctx.memory(0), name);
|
|
||||||
let name = read_string_from_wasm(ctx.memory(0), name);
|
let name = read_string_from_wasm(ctx.memory(0), name);
|
||||||
// no unsetenv on windows, so use putenv with an empty value
|
// no unsetenv on windows, so use putenv with an empty value
|
||||||
let unsetenv_string = format!("{}=", name);
|
let unsetenv_string = format!("{}=", name);
|
||||||
@ -70,6 +66,8 @@ pub fn _unsetenv(ctx: &mut Ctx, name: u32) -> c_int {
|
|||||||
#[allow(clippy::cast_ptr_alignment)]
|
#[allow(clippy::cast_ptr_alignment)]
|
||||||
pub fn _getpwnam(ctx: &mut Ctx, name_ptr: c_int) -> c_int {
|
pub fn _getpwnam(ctx: &mut Ctx, name_ptr: c_int) -> c_int {
|
||||||
debug!("emscripten::_getpwnam {}", name_ptr);
|
debug!("emscripten::_getpwnam {}", name_ptr);
|
||||||
|
#[cfg(not(feature = "debug"))]
|
||||||
|
let _ = name_ptr;
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
struct GuestPasswd {
|
struct GuestPasswd {
|
||||||
@ -102,6 +100,8 @@ pub fn _getpwnam(ctx: &mut Ctx, name_ptr: c_int) -> c_int {
|
|||||||
#[allow(clippy::cast_ptr_alignment)]
|
#[allow(clippy::cast_ptr_alignment)]
|
||||||
pub fn _getgrnam(ctx: &mut Ctx, name_ptr: c_int) -> c_int {
|
pub fn _getgrnam(ctx: &mut Ctx, name_ptr: c_int) -> c_int {
|
||||||
debug!("emscripten::_getgrnam {}", name_ptr);
|
debug!("emscripten::_getgrnam {}", name_ptr);
|
||||||
|
#[cfg(not(feature = "debug"))]
|
||||||
|
let _ = name_ptr;
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
struct GuestGroup {
|
struct GuestGroup {
|
||||||
@ -126,6 +126,8 @@ pub fn _getgrnam(ctx: &mut Ctx, name_ptr: c_int) -> c_int {
|
|||||||
|
|
||||||
pub fn _sysconf(_ctx: &mut Ctx, name: c_int) -> c_long {
|
pub fn _sysconf(_ctx: &mut Ctx, name: c_int) -> c_long {
|
||||||
debug!("emscripten::_sysconf {}", name);
|
debug!("emscripten::_sysconf {}", name);
|
||||||
|
#[cfg(not(feature = "debug"))]
|
||||||
|
let _ = name;
|
||||||
// stub because sysconf is not valid on windows
|
// stub because sysconf is not valid on windows
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
// use std::collections::HashMap;
|
// use std::collections::HashMap;
|
||||||
use wasmer_runtime_core::vm::Ctx;
|
use wasmer_runtime_core::vm::Ctx;
|
||||||
|
|
||||||
pub fn ___seterrno(_ctx: &mut Ctx, value: i32) {
|
pub fn ___seterrno(_ctx: &mut Ctx, _value: i32) {
|
||||||
debug!("emscripten::___seterrno {}", value);
|
debug!("emscripten::___seterrno {}", _value);
|
||||||
// TODO: Incomplete impl
|
// TODO: Incomplete impl
|
||||||
eprintln!("failed to set errno!");
|
eprintln!("failed to set errno!");
|
||||||
// value
|
// value
|
||||||
|
@ -14,3 +14,17 @@ pub fn ___cxa_throw(ctx: &mut Ctx, _ptr: u32, _ty: u32, _destructor: u32) {
|
|||||||
debug!("emscripten::___cxa_throw");
|
debug!("emscripten::___cxa_throw");
|
||||||
_abort(ctx);
|
_abort(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn ___cxa_begin_catch(_ctx: &mut Ctx, _exception_object_ptr: u32) -> i32 {
|
||||||
|
debug!("emscripten::___cxa_begin_catch");
|
||||||
|
-1
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn ___cxa_end_catch(_ctx: &mut Ctx) {
|
||||||
|
debug!("emscripten::___cxa_end_catch");
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn ___cxa_uncaught_exception(_ctx: &mut Ctx) -> i32 {
|
||||||
|
debug!("emscripten::___cxa_uncaught_exception");
|
||||||
|
-1
|
||||||
|
}
|
||||||
|
53
lib/emscripten/src/exec.rs
Normal file
53
lib/emscripten/src/exec.rs
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
use crate::varargs::VarArgs;
|
||||||
|
use libc::execvp as libc_execvp;
|
||||||
|
use std::cell::Cell;
|
||||||
|
use std::ffi::CString;
|
||||||
|
use wasmer_runtime_core::vm::Ctx;
|
||||||
|
|
||||||
|
pub fn execvp(ctx: &mut Ctx, command_name_offset: u32, argv_offset: u32) -> i32 {
|
||||||
|
// a single reference to re-use
|
||||||
|
let emscripten_memory = ctx.memory(0);
|
||||||
|
|
||||||
|
// read command name as string
|
||||||
|
let command_name_string_vec: Vec<u8> = emscripten_memory.view()
|
||||||
|
[(command_name_offset as usize)..]
|
||||||
|
.iter()
|
||||||
|
.map(|cell| cell.get())
|
||||||
|
.take_while(|&byte| byte != 0)
|
||||||
|
.collect();
|
||||||
|
let command_name_string = CString::new(command_name_string_vec).unwrap();
|
||||||
|
|
||||||
|
// get the array of args
|
||||||
|
let mut argv: Vec<*const i8> = emscripten_memory.view()[((argv_offset / 4) as usize)..]
|
||||||
|
.iter()
|
||||||
|
.map(|cell: &Cell<u32>| cell.get())
|
||||||
|
.take_while(|&byte| byte != 0)
|
||||||
|
.map(|offset| {
|
||||||
|
let p: *const i8 = (emscripten_memory.view::<u8>()[(offset as usize)..])
|
||||||
|
.iter()
|
||||||
|
.map(|cell| cell.as_ptr() as *const i8)
|
||||||
|
.collect::<Vec<*const i8>>()[0];
|
||||||
|
p
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
// push a nullptr on to the end of the args array
|
||||||
|
argv.push(std::ptr::null());
|
||||||
|
|
||||||
|
// construct raw pointers and hand them to `execvp`
|
||||||
|
let command_pointer = command_name_string.as_ptr() as *const i8;
|
||||||
|
let args_pointer = argv.as_ptr();
|
||||||
|
unsafe { libc_execvp(command_pointer, args_pointer) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// execl
|
||||||
|
pub fn execl(_ctx: &mut Ctx, _path_ptr: i32, _arg0_ptr: i32, _varargs: VarArgs) -> i32 {
|
||||||
|
debug!("emscripten::execl");
|
||||||
|
-1
|
||||||
|
}
|
||||||
|
|
||||||
|
/// execle
|
||||||
|
pub fn execle(_ctx: &mut Ctx, _path_ptr: i32, _arg0_ptr: i32, _varargs: VarArgs) -> i32 {
|
||||||
|
debug!("emscripten::execle");
|
||||||
|
-1
|
||||||
|
}
|
7
lib/emscripten/src/exit.rs
Normal file
7
lib/emscripten/src/exit.rs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
use wasmer_runtime_core::vm::Ctx;
|
||||||
|
|
||||||
|
// __exit
|
||||||
|
pub fn exit(_ctx: &mut Ctx, value: i32) {
|
||||||
|
debug!("emscripten::exit {}", value);
|
||||||
|
::std::process::exit(value);
|
||||||
|
}
|
@ -9,3 +9,55 @@ pub use self::unix::*;
|
|||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
pub use self::windows::*;
|
pub use self::windows::*;
|
||||||
|
|
||||||
|
use wasmer_runtime_core::vm::Ctx;
|
||||||
|
|
||||||
|
/// getprotobyname
|
||||||
|
pub fn getprotobyname(_ctx: &mut Ctx, _name_ptr: i32) -> i32 {
|
||||||
|
debug!("emscripten::getprotobyname");
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// getprotobynumber
|
||||||
|
pub fn getprotobynumber(_ctx: &mut Ctx, _one: i32) -> i32 {
|
||||||
|
debug!("emscripten::getprotobynumber");
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// sigdelset
|
||||||
|
pub fn sigdelset(ctx: &mut Ctx, set: i32, signum: i32) -> i32 {
|
||||||
|
debug!("emscripten::sigdelset");
|
||||||
|
let memory = ctx.memory(0);
|
||||||
|
#[allow(clippy::cast_ptr_alignment)]
|
||||||
|
let ptr = emscripten_memory_pointer!(memory, set) as *mut i32;
|
||||||
|
|
||||||
|
unsafe { *ptr = *ptr & !(1 << (signum - 1)) }
|
||||||
|
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
|
/// sigfillset
|
||||||
|
pub fn sigfillset(ctx: &mut Ctx, set: i32) -> i32 {
|
||||||
|
debug!("emscripten::sigfillset");
|
||||||
|
let memory = ctx.memory(0);
|
||||||
|
#[allow(clippy::cast_ptr_alignment)]
|
||||||
|
let ptr = emscripten_memory_pointer!(memory, set) as *mut i32;
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
*ptr = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
|
/// tzset
|
||||||
|
pub fn tzset(_ctx: &mut Ctx) {
|
||||||
|
debug!("emscripten::tzset - stub");
|
||||||
|
//unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// strptime
|
||||||
|
pub fn strptime(_ctx: &mut Ctx, _one: i32, _two: i32, _three: i32) -> i32 {
|
||||||
|
debug!("emscripten::strptime");
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
use libc::printf as _printf;
|
use libc::{chroot as _chroot, printf as _printf};
|
||||||
|
|
||||||
use wasmer_runtime_core::vm::Ctx;
|
use wasmer_runtime_core::vm::Ctx;
|
||||||
|
|
||||||
/// putchar
|
/// putchar
|
||||||
pub fn putchar(ctx: &mut Ctx, chr: i32) {
|
pub fn putchar(_ctx: &mut Ctx, chr: i32) {
|
||||||
unsafe { libc::putchar(chr) };
|
unsafe { libc::putchar(chr) };
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -15,3 +15,16 @@ pub fn printf(ctx: &mut Ctx, memory_offset: i32, extra: i32) -> i32 {
|
|||||||
_printf(addr, extra)
|
_printf(addr, extra)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// chroot
|
||||||
|
pub fn chroot(ctx: &mut Ctx, name_ptr: i32) -> i32 {
|
||||||
|
debug!("emscripten::chroot");
|
||||||
|
let name = emscripten_memory_pointer!(ctx.memory(0), name_ptr) as *const i8;
|
||||||
|
unsafe { _chroot(name) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// getpwuid
|
||||||
|
pub fn getpwuid(_ctx: &mut Ctx, _uid: i32) -> i32 {
|
||||||
|
debug!("emscripten::getpwuid");
|
||||||
|
0
|
||||||
|
}
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
use libc::{c_char, c_int};
|
|
||||||
use wasmer_runtime_core::vm::Ctx;
|
use wasmer_runtime_core::vm::Ctx;
|
||||||
|
|
||||||
// This may be problematic for msvc which uses inline functions for the printf family
|
// This may be problematic for msvc which uses inline functions for the printf family
|
||||||
@ -15,16 +14,33 @@ use wasmer_runtime_core::vm::Ctx;
|
|||||||
//}
|
//}
|
||||||
|
|
||||||
/// putchar
|
/// putchar
|
||||||
pub fn putchar(ctx: &mut Ctx, chr: i32) {
|
pub fn putchar(_ctx: &mut Ctx, chr: i32) {
|
||||||
unsafe { libc::putchar(chr) };
|
unsafe { libc::putchar(chr) };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// printf
|
/// printf
|
||||||
pub fn printf(ctx: &mut Ctx, memory_offset: i32, extra: i32) -> i32 {
|
pub fn printf(_ctx: &mut Ctx, memory_offset: i32, extra: i32) -> i32 {
|
||||||
debug!("emscripten::printf {}, {}", memory_offset, extra);
|
debug!("emscripten::printf {}, {}", memory_offset, extra);
|
||||||
|
#[cfg(not(feature = "debug"))]
|
||||||
|
{
|
||||||
|
let _ = memory_offset;
|
||||||
|
let _ = extra;
|
||||||
|
}
|
||||||
// unsafe {
|
// unsafe {
|
||||||
// let addr = emscripten_memory_pointer!(ctx.memory(0), memory_offset) as _;
|
// let addr = emscripten_memory_pointer!(ctx.memory(0), memory_offset) as _;
|
||||||
// _printf(addr, extra)
|
// _printf(addr, extra)
|
||||||
// }
|
// }
|
||||||
-1
|
-1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// chroot
|
||||||
|
pub fn chroot(_ctx: &mut Ctx, _name_ptr: i32) -> i32 {
|
||||||
|
debug!("emscripten::chroot");
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// getpwuid
|
||||||
|
pub fn getpwuid(_ctx: &mut Ctx, _uid: i32) -> i32 {
|
||||||
|
debug!("emscripten::getpwuid");
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
@ -1,43 +1,61 @@
|
|||||||
use super::env::get_emscripten_data;
|
use super::env::get_emscripten_data;
|
||||||
use libc::{c_int, c_void};
|
use super::process::abort_with_message;
|
||||||
use std::cell::UnsafeCell;
|
use libc::c_int;
|
||||||
|
// use std::cell::UnsafeCell;
|
||||||
use wasmer_runtime_core::vm::Ctx;
|
use wasmer_runtime_core::vm::Ctx;
|
||||||
|
|
||||||
/// setjmp
|
/// setjmp
|
||||||
pub fn __setjmp(ctx: &mut Ctx, env_addr: u32) -> c_int {
|
pub fn __setjmp(ctx: &mut Ctx, _env_addr: u32) -> c_int {
|
||||||
debug!("emscripten::__setjmp (setjmp)");
|
debug!("emscripten::__setjmp (setjmp)");
|
||||||
unsafe {
|
abort_with_message(ctx, "missing function: _longjmp");
|
||||||
// Rather than using the env as the holder of the jump buffer pointer,
|
unreachable!()
|
||||||
// we use the environment address to store the index relative to jumps
|
// unsafe {
|
||||||
// so the address of the jump it's outside the wasm memory itself.
|
// // Rather than using the env as the holder of the jump buffer pointer,
|
||||||
let jump_index = emscripten_memory_pointer!(ctx.memory(0), env_addr) as *mut i8;
|
// // we use the environment address to store the index relative to jumps
|
||||||
// We create the jump buffer outside of the wasm memory
|
// // so the address of the jump it's outside the wasm memory itself.
|
||||||
let jump_buf: UnsafeCell<[u32; 27]> = UnsafeCell::new([0; 27]);
|
// let jump_index = emscripten_memory_pointer!(ctx.memory(0), env_addr) as *mut i8;
|
||||||
let jumps = &mut get_emscripten_data(ctx).jumps;
|
// // We create the jump buffer outside of the wasm memory
|
||||||
let result = setjmp(jump_buf.get() as _);
|
// let jump_buf: UnsafeCell<[u32; 27]> = UnsafeCell::new([0; 27]);
|
||||||
// We set the jump index to be the last 3value of jumps
|
// let jumps = &mut get_emscripten_data(ctx).jumps;
|
||||||
*jump_index = jumps.len() as _;
|
// let result = setjmp(jump_buf.get() as _);
|
||||||
// We hold the reference of the jump buffer
|
// // We set the jump index to be the last 3value of jumps
|
||||||
jumps.push(jump_buf);
|
// *jump_index = jumps.len() as _;
|
||||||
result
|
// // We hold the reference of the jump buffer
|
||||||
}
|
// jumps.push(jump_buf);
|
||||||
|
// result
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// longjmp
|
/// longjmp
|
||||||
#[allow(unreachable_code)]
|
#[allow(unreachable_code)]
|
||||||
pub fn __longjmp(ctx: &mut Ctx, env_addr: u32, val: c_int) {
|
pub fn __longjmp(ctx: &mut Ctx, _env_addr: u32, _val: c_int) {
|
||||||
debug!("emscripten::__longjmp (longmp)");
|
debug!("emscripten::__longjmp (longmp)");
|
||||||
unsafe {
|
abort_with_message(ctx, "missing function: _longjmp");
|
||||||
// We retrieve the jump index from the env address
|
// unsafe {
|
||||||
let jump_index = emscripten_memory_pointer!(ctx.memory(0), env_addr) as *mut i8;
|
// // We retrieve the jump index from the env address
|
||||||
let jumps = &mut get_emscripten_data(ctx).jumps;
|
// let jump_index = emscripten_memory_pointer!(ctx.memory(0), env_addr) as *mut i8;
|
||||||
// We get the real jump buffer from the jumps vector, using the retrieved index
|
// let jumps = &mut get_emscripten_data(ctx).jumps;
|
||||||
let jump_buf = &jumps[*jump_index as usize];
|
// // We get the real jump buffer from the jumps vector, using the retrieved index
|
||||||
longjmp(jump_buf.get() as _, val)
|
// let jump_buf = &jumps[*jump_index as usize];
|
||||||
};
|
// longjmp(jump_buf.get() as _, val)
|
||||||
|
// };
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" {
|
/// _longjmp
|
||||||
fn setjmp(env: *mut c_void) -> c_int;
|
// This function differs from the js implementation, it should return Result<(), &'static str>
|
||||||
fn longjmp(env: *mut c_void, val: c_int) -> !;
|
pub fn _longjmp(ctx: &mut Ctx, env_addr: i32, val: c_int) -> Result<(), ()> {
|
||||||
|
let val = if val == 0 { 1 } else { val };
|
||||||
|
get_emscripten_data(ctx)
|
||||||
|
.set_threw
|
||||||
|
.as_ref()
|
||||||
|
.expect("set_threw is None")
|
||||||
|
.call(env_addr, val)
|
||||||
|
.expect("set_threw failed to call");
|
||||||
|
// TODO: return Err("longjmp")
|
||||||
|
Err(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// extern "C" {
|
||||||
|
// fn setjmp(env: *mut c_void) -> c_int;
|
||||||
|
// fn longjmp(env: *mut c_void, val: c_int) -> !;
|
||||||
|
// }
|
||||||
|
@ -27,17 +27,19 @@ mod file_descriptor;
|
|||||||
pub mod stdio;
|
pub mod stdio;
|
||||||
|
|
||||||
// EMSCRIPTEN APIS
|
// EMSCRIPTEN APIS
|
||||||
|
mod bitwise;
|
||||||
mod emscripten_target;
|
mod emscripten_target;
|
||||||
mod env;
|
mod env;
|
||||||
mod errno;
|
mod errno;
|
||||||
mod exception;
|
mod exception;
|
||||||
|
mod exec;
|
||||||
|
mod exit;
|
||||||
mod io;
|
mod io;
|
||||||
mod jmp;
|
mod jmp;
|
||||||
mod linking;
|
mod linking;
|
||||||
mod lock;
|
mod lock;
|
||||||
mod math;
|
mod math;
|
||||||
mod memory;
|
mod memory;
|
||||||
mod nullfunc;
|
|
||||||
mod process;
|
mod process;
|
||||||
mod signal;
|
mod signal;
|
||||||
mod storage;
|
mod storage;
|
||||||
@ -54,8 +56,6 @@ pub use self::utils::{
|
|||||||
|
|
||||||
// TODO: Magic number - how is this calculated?
|
// TODO: Magic number - how is this calculated?
|
||||||
const TOTAL_STACK: u32 = 5_242_880;
|
const TOTAL_STACK: u32 = 5_242_880;
|
||||||
// TODO: Magic number - how is this calculated?
|
|
||||||
const DYNAMICTOP_PTR_DIFF: u32 = 1088;
|
|
||||||
// TODO: make this variable
|
// TODO: make this variable
|
||||||
const STATIC_BUMP: u32 = 215_536;
|
const STATIC_BUMP: u32 = 215_536;
|
||||||
|
|
||||||
@ -71,22 +71,6 @@ lazy_static! {
|
|||||||
const GLOBAL_BASE: u32 = 1024;
|
const GLOBAL_BASE: u32 = 1024;
|
||||||
const STATIC_BASE: u32 = GLOBAL_BASE;
|
const STATIC_BASE: u32 = GLOBAL_BASE;
|
||||||
|
|
||||||
fn stacktop(static_bump: u32) -> u32 {
|
|
||||||
align_memory(dynamictop_ptr(static_bump) + 4)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn stack_max(static_bump: u32) -> u32 {
|
|
||||||
stacktop(static_bump) + TOTAL_STACK
|
|
||||||
}
|
|
||||||
|
|
||||||
fn dynamic_base(static_bump: u32) -> u32 {
|
|
||||||
align_memory(stack_max(static_bump))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn dynamictop_ptr(static_bump: u32) -> u32 {
|
|
||||||
static_bump + DYNAMICTOP_PTR_DIFF
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct EmscriptenData<'a> {
|
pub struct EmscriptenData<'a> {
|
||||||
pub malloc: Func<'a, u32, u32>,
|
pub malloc: Func<'a, u32, u32>,
|
||||||
pub free: Func<'a, u32>,
|
pub free: Func<'a, u32>,
|
||||||
@ -99,6 +83,7 @@ pub struct EmscriptenData<'a> {
|
|||||||
pub dyn_call_ii: Option<Func<'a, (i32, i32), i32>>,
|
pub dyn_call_ii: Option<Func<'a, (i32, i32), i32>>,
|
||||||
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_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)>>,
|
||||||
@ -110,15 +95,27 @@ pub struct EmscriptenData<'a> {
|
|||||||
pub dyn_call_diiii: Option<Func<'a, (i32, i32, i32, i32, i32), f64>>,
|
pub dyn_call_diiii: Option<Func<'a, (i32, i32, i32, i32, i32), f64>>,
|
||||||
pub dyn_call_iiiii: Option<Func<'a, (i32, i32, i32, i32, i32), i32>>,
|
pub dyn_call_iiiii: Option<Func<'a, (i32, i32, i32, i32, i32), i32>>,
|
||||||
pub dyn_call_iiiiii: Option<Func<'a, (i32, i32, i32, i32, i32, i32), i32>>,
|
pub dyn_call_iiiiii: Option<Func<'a, (i32, i32, i32, i32, i32, i32), i32>>,
|
||||||
|
pub dyn_call_iiiiiii: Option<Func<'a, (i32, i32, i32, i32, i32, i32, i32), i32>>,
|
||||||
|
pub dyn_call_iiiiiiii: Option<Func<'a, (i32, i32, i32, i32, i32, i32, i32, i32), i32>>,
|
||||||
|
pub dyn_call_iiiiiiiii: Option<Func<'a, (i32, i32, i32, i32, i32, i32, i32, i32, i32), i32>>,
|
||||||
|
pub dyn_call_iiiiiiiiii:
|
||||||
|
Option<Func<'a, (i32, i32, i32, i32, i32, i32, i32, i32, i32, i32), i32>>,
|
||||||
|
pub dyn_call_iiiiiiiiiii:
|
||||||
|
Option<Func<'a, (i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32), i32>>,
|
||||||
pub dyn_call_vd: Option<Func<'a, (i32, f64)>>,
|
pub dyn_call_vd: Option<Func<'a, (i32, f64)>>,
|
||||||
pub dyn_call_viiiii: Option<Func<'a, (i32, i32, i32, i32, i32, i32)>>,
|
pub dyn_call_viiiii: Option<Func<'a, (i32, i32, i32, i32, i32, i32)>>,
|
||||||
pub dyn_call_viiiiii: Option<Func<'a, (i32, i32, i32, i32, i32, i32, i32)>>,
|
pub dyn_call_viiiiii: Option<Func<'a, (i32, i32, i32, i32, i32, i32, i32)>>,
|
||||||
pub dyn_call_viiiiiii: Option<Func<'a, (i32, i32, i32, i32, i32, i32, i32, i32)>>,
|
pub dyn_call_viiiiiii: Option<Func<'a, (i32, i32, i32, i32, i32, i32, i32, i32)>>,
|
||||||
pub dyn_call_viiiiiiii: Option<Func<'a, (i32, i32, i32, i32, i32, i32, i32, i32, i32)>>,
|
pub dyn_call_viiiiiiii: Option<Func<'a, (i32, i32, i32, i32, i32, i32, i32, i32, i32)>>,
|
||||||
pub dyn_call_viiiiiiiii: Option<Func<'a, (i32, i32, i32, i32, i32, i32, i32, i32, i32, i32)>>,
|
pub dyn_call_viiiiiiiii: Option<Func<'a, (i32, i32, i32, i32, i32, i32, i32, i32, i32, i32)>>,
|
||||||
|
pub dyn_call_viiiiiiiiii:
|
||||||
|
Option<Func<'a, (i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32)>>,
|
||||||
|
pub dyn_call_iij: Option<Func<'a, (i32, i32, i32, i32), i32>>,
|
||||||
pub dyn_call_iiji: Option<Func<'a, (i32, i32, i32, i32, i32), i32>>,
|
pub dyn_call_iiji: Option<Func<'a, (i32, i32, i32, i32, i32), i32>>,
|
||||||
|
pub dyn_call_iiijj: Option<Func<'a, (i32, i32, i32, i32, i32, i32, i32), i32>>,
|
||||||
pub dyn_call_j: Option<Func<'a, i32, i32>>,
|
pub dyn_call_j: Option<Func<'a, i32, i32>>,
|
||||||
pub dyn_call_ji: Option<Func<'a, (i32, i32), i32>>,
|
pub dyn_call_ji: Option<Func<'a, (i32, i32), i32>>,
|
||||||
|
pub dyn_call_jii: Option<Func<'a, (i32, i32, i32), i32>>,
|
||||||
pub dyn_call_jij: Option<Func<'a, (i32, i32, i32, i32), i32>>,
|
pub dyn_call_jij: Option<Func<'a, (i32, i32, i32, i32), i32>>,
|
||||||
pub dyn_call_jjj: Option<Func<'a, (i32, i32, i32, i32, i32), i32>>,
|
pub dyn_call_jjj: Option<Func<'a, (i32, i32, i32, i32, i32), i32>>,
|
||||||
pub dyn_call_viiij: Option<Func<'a, (i32, i32, i32, i32, i32, i32)>>,
|
pub dyn_call_viiij: Option<Func<'a, (i32, i32, i32, i32, i32, i32)>>,
|
||||||
@ -129,10 +126,20 @@ pub struct EmscriptenData<'a> {
|
|||||||
pub dyn_call_viiji: Option<Func<'a, (i32, i32, i32, i32, i32, i32)>>,
|
pub dyn_call_viiji: Option<Func<'a, (i32, i32, i32, i32, i32, i32)>>,
|
||||||
pub dyn_call_viijiii: Option<Func<'a, (i32, i32, i32, i32, i32, i32, i32, i32)>>,
|
pub dyn_call_viijiii: Option<Func<'a, (i32, i32, i32, i32, i32, i32, i32, i32)>>,
|
||||||
pub dyn_call_viijj: Option<Func<'a, (i32, i32, i32, i32, i32, i32, i32)>>,
|
pub dyn_call_viijj: Option<Func<'a, (i32, i32, i32, i32, i32, i32, i32)>>,
|
||||||
|
pub dyn_call_vj: Option<Func<'a, (i32, i32, i32)>>,
|
||||||
pub dyn_call_vij: Option<Func<'a, (i32, i32, i32, i32)>>,
|
pub dyn_call_vij: Option<Func<'a, (i32, i32, i32, i32)>>,
|
||||||
pub dyn_call_viji: Option<Func<'a, (i32, i32, i32, i32, i32)>>,
|
pub dyn_call_viji: Option<Func<'a, (i32, i32, i32, i32, i32)>>,
|
||||||
pub dyn_call_vijiii: Option<Func<'a, (i32, i32, i32, i32, i32, i32, i32)>>,
|
pub dyn_call_vijiii: Option<Func<'a, (i32, i32, i32, i32, i32, i32, i32)>>,
|
||||||
pub dyn_call_vijj: Option<Func<'a, (i32, i32, i32, i32, i32, i32)>>,
|
pub dyn_call_vijj: Option<Func<'a, (i32, i32, i32, i32, i32, i32)>>,
|
||||||
|
pub dyn_call_viid: Option<Func<'a, (i32, i32, i32, f64)>>,
|
||||||
|
pub dyn_call_viidii: Option<Func<'a, (i32, i32, i32, f64, i32, i32)>>,
|
||||||
|
pub dyn_call_viidddddddd:
|
||||||
|
Option<Func<'a, (i32, i32, i32, f64, f64, f64, f64, f64, f64, f64, f64)>>,
|
||||||
|
pub temp_ret_0: i32,
|
||||||
|
|
||||||
|
pub stack_save: Option<Func<'a, (), i32>>,
|
||||||
|
pub stack_restore: Option<Func<'a, (i32)>>,
|
||||||
|
pub set_threw: Option<Func<'a, (i32, i32)>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> EmscriptenData<'a> {
|
impl<'a> EmscriptenData<'a> {
|
||||||
@ -151,6 +158,7 @@ impl<'a> EmscriptenData<'a> {
|
|||||||
let dyn_call_ii = instance.func("dynCall_ii").ok();
|
let dyn_call_ii = instance.func("dynCall_ii").ok();
|
||||||
let dyn_call_iii = instance.func("dynCall_iii").ok();
|
let dyn_call_iii = instance.func("dynCall_iii").ok();
|
||||||
let dyn_call_iiii = instance.func("dynCall_iiii").ok();
|
let dyn_call_iiii = instance.func("dynCall_iiii").ok();
|
||||||
|
let dyn_call_iifi = instance.func("dynCall_iifi").ok();
|
||||||
let dyn_call_v = instance.func("dynCall_v").ok();
|
let dyn_call_v = instance.func("dynCall_v").ok();
|
||||||
let dyn_call_vi = instance.func("dynCall_vi").ok();
|
let dyn_call_vi = instance.func("dynCall_vi").ok();
|
||||||
let dyn_call_vii = instance.func("dynCall_vii").ok();
|
let dyn_call_vii = instance.func("dynCall_vii").ok();
|
||||||
@ -162,15 +170,24 @@ impl<'a> EmscriptenData<'a> {
|
|||||||
let dyn_call_diiii = instance.func("dynCall_diiii").ok();
|
let dyn_call_diiii = instance.func("dynCall_diiii").ok();
|
||||||
let dyn_call_iiiii = instance.func("dynCall_iiiii").ok();
|
let dyn_call_iiiii = instance.func("dynCall_iiiii").ok();
|
||||||
let dyn_call_iiiiii = instance.func("dynCall_iiiiii").ok();
|
let dyn_call_iiiiii = instance.func("dynCall_iiiiii").ok();
|
||||||
|
let dyn_call_iiiiiii = instance.func("dynCall_iiiiiii").ok();
|
||||||
|
let dyn_call_iiiiiiii = instance.func("dynCall_iiiiiiii").ok();
|
||||||
|
let dyn_call_iiiiiiiii = instance.func("dynCall_iiiiiiiii").ok();
|
||||||
|
let dyn_call_iiiiiiiiii = instance.func("dynCall_iiiiiiiiii").ok();
|
||||||
|
let dyn_call_iiiiiiiiiii = instance.func("dynCall_iiiiiiiiiii").ok();
|
||||||
let dyn_call_vd = instance.func("dynCall_vd").ok();
|
let dyn_call_vd = instance.func("dynCall_vd").ok();
|
||||||
let dyn_call_viiiii = instance.func("dynCall_viiiii").ok();
|
let dyn_call_viiiii = instance.func("dynCall_viiiii").ok();
|
||||||
let dyn_call_viiiiii = instance.func("dynCall_viiiiii").ok();
|
let dyn_call_viiiiii = instance.func("dynCall_viiiiii").ok();
|
||||||
let dyn_call_viiiiiii = instance.func("dynCall_viiiiiii").ok();
|
let dyn_call_viiiiiii = instance.func("dynCall_viiiiiii").ok();
|
||||||
let dyn_call_viiiiiiii = instance.func("dynCall_viiiiiiii").ok();
|
let dyn_call_viiiiiiii = instance.func("dynCall_viiiiiiii").ok();
|
||||||
let dyn_call_viiiiiiiii = instance.func("dynCall_viiiiiiiii").ok();
|
let dyn_call_viiiiiiiii = instance.func("dynCall_viiiiiiiii").ok();
|
||||||
|
let dyn_call_viiiiiiiiii = instance.func("dynCall_viiiiiiiiii").ok();
|
||||||
|
let dyn_call_iij = instance.func("dynCall_iij").ok();
|
||||||
let dyn_call_iiji = instance.func("dynCall_iiji").ok();
|
let dyn_call_iiji = instance.func("dynCall_iiji").ok();
|
||||||
|
let dyn_call_iiijj = instance.func("dynCall_iiijj").ok();
|
||||||
let dyn_call_j = instance.func("dynCall_j").ok();
|
let dyn_call_j = instance.func("dynCall_j").ok();
|
||||||
let dyn_call_ji = instance.func("dynCall_ji").ok();
|
let dyn_call_ji = instance.func("dynCall_ji").ok();
|
||||||
|
let dyn_call_jii = instance.func("dynCall_jii").ok();
|
||||||
let dyn_call_jij = instance.func("dynCall_jij").ok();
|
let dyn_call_jij = instance.func("dynCall_jij").ok();
|
||||||
let dyn_call_jjj = instance.func("dynCall_jjj").ok();
|
let dyn_call_jjj = instance.func("dynCall_jjj").ok();
|
||||||
let dyn_call_viiij = instance.func("dynCall_viiij").ok();
|
let dyn_call_viiij = instance.func("dynCall_viiij").ok();
|
||||||
@ -180,10 +197,18 @@ impl<'a> EmscriptenData<'a> {
|
|||||||
let dyn_call_viiji = instance.func("dynCall_viiji").ok();
|
let dyn_call_viiji = instance.func("dynCall_viiji").ok();
|
||||||
let dyn_call_viijiii = instance.func("dynCall_viijiii").ok();
|
let dyn_call_viijiii = instance.func("dynCall_viijiii").ok();
|
||||||
let dyn_call_viijj = instance.func("dynCall_viijj").ok();
|
let dyn_call_viijj = instance.func("dynCall_viijj").ok();
|
||||||
|
let dyn_call_vj = instance.func("dynCall_vj").ok();
|
||||||
let dyn_call_vij = instance.func("dynCall_vij").ok();
|
let dyn_call_vij = instance.func("dynCall_vij").ok();
|
||||||
let dyn_call_viji = instance.func("dynCall_viji").ok();
|
let dyn_call_viji = instance.func("dynCall_viji").ok();
|
||||||
let dyn_call_vijiii = instance.func("dynCall_vijiii").ok();
|
let dyn_call_vijiii = instance.func("dynCall_vijiii").ok();
|
||||||
let dyn_call_vijj = instance.func("dynCall_vijj").ok();
|
let dyn_call_vijj = instance.func("dynCall_vijj").ok();
|
||||||
|
let dyn_call_viid = instance.func("dynCall_viid").ok();
|
||||||
|
let dyn_call_viidii = instance.func("dynCall_viidii").ok();
|
||||||
|
let dyn_call_viidddddddd = instance.func("dynCall_viidddddddd").ok();
|
||||||
|
|
||||||
|
let stack_save = instance.func("stackSave").ok();
|
||||||
|
let stack_restore = instance.func("stackRestore").ok();
|
||||||
|
let set_threw = instance.func("_setThrew").ok();
|
||||||
|
|
||||||
EmscriptenData {
|
EmscriptenData {
|
||||||
malloc,
|
malloc,
|
||||||
@ -196,6 +221,7 @@ impl<'a> EmscriptenData<'a> {
|
|||||||
dyn_call_ii,
|
dyn_call_ii,
|
||||||
dyn_call_iii,
|
dyn_call_iii,
|
||||||
dyn_call_iiii,
|
dyn_call_iiii,
|
||||||
|
dyn_call_iifi,
|
||||||
dyn_call_v,
|
dyn_call_v,
|
||||||
dyn_call_vi,
|
dyn_call_vi,
|
||||||
dyn_call_vii,
|
dyn_call_vii,
|
||||||
@ -207,15 +233,24 @@ impl<'a> EmscriptenData<'a> {
|
|||||||
dyn_call_diiii,
|
dyn_call_diiii,
|
||||||
dyn_call_iiiii,
|
dyn_call_iiiii,
|
||||||
dyn_call_iiiiii,
|
dyn_call_iiiiii,
|
||||||
|
dyn_call_iiiiiii,
|
||||||
|
dyn_call_iiiiiiii,
|
||||||
|
dyn_call_iiiiiiiii,
|
||||||
|
dyn_call_iiiiiiiiii,
|
||||||
|
dyn_call_iiiiiiiiiii,
|
||||||
dyn_call_vd,
|
dyn_call_vd,
|
||||||
dyn_call_viiiii,
|
dyn_call_viiiii,
|
||||||
dyn_call_viiiiii,
|
dyn_call_viiiiii,
|
||||||
dyn_call_viiiiiii,
|
dyn_call_viiiiiii,
|
||||||
dyn_call_viiiiiiii,
|
dyn_call_viiiiiiii,
|
||||||
dyn_call_viiiiiiiii,
|
dyn_call_viiiiiiiii,
|
||||||
|
dyn_call_viiiiiiiiii,
|
||||||
|
dyn_call_iij,
|
||||||
dyn_call_iiji,
|
dyn_call_iiji,
|
||||||
|
dyn_call_iiijj,
|
||||||
dyn_call_j,
|
dyn_call_j,
|
||||||
dyn_call_ji,
|
dyn_call_ji,
|
||||||
|
dyn_call_jii,
|
||||||
dyn_call_jij,
|
dyn_call_jij,
|
||||||
dyn_call_jjj,
|
dyn_call_jjj,
|
||||||
dyn_call_viiij,
|
dyn_call_viiij,
|
||||||
@ -225,10 +260,19 @@ impl<'a> EmscriptenData<'a> {
|
|||||||
dyn_call_viiji,
|
dyn_call_viiji,
|
||||||
dyn_call_viijiii,
|
dyn_call_viijiii,
|
||||||
dyn_call_viijj,
|
dyn_call_viijj,
|
||||||
|
dyn_call_vj,
|
||||||
dyn_call_vij,
|
dyn_call_vij,
|
||||||
dyn_call_viji,
|
dyn_call_viji,
|
||||||
dyn_call_vijiii,
|
dyn_call_vijiii,
|
||||||
dyn_call_vijj,
|
dyn_call_vijj,
|
||||||
|
dyn_call_viid,
|
||||||
|
dyn_call_viidii,
|
||||||
|
dyn_call_viidddddddd,
|
||||||
|
temp_ret_0: 0,
|
||||||
|
|
||||||
|
stack_save,
|
||||||
|
stack_restore,
|
||||||
|
set_threw,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -243,6 +287,12 @@ pub fn run_emscripten_instance(
|
|||||||
let data_ptr = &mut data as *mut _ as *mut c_void;
|
let data_ptr = &mut data as *mut _ as *mut c_void;
|
||||||
instance.context_mut().data = data_ptr;
|
instance.context_mut().data = data_ptr;
|
||||||
|
|
||||||
|
// ATINIT
|
||||||
|
// (used by C++)
|
||||||
|
if let Ok(_func) = instance.dyn_func("globalCtors") {
|
||||||
|
instance.call("globalCtors", &[])?;
|
||||||
|
}
|
||||||
|
|
||||||
if let Ok(_func) = instance.dyn_func("___emscripten_environ_constructor") {
|
if let Ok(_func) = instance.dyn_func("___emscripten_environ_constructor") {
|
||||||
instance.call("___emscripten_environ_constructor", &[])?;
|
instance.call("___emscripten_environ_constructor", &[])?;
|
||||||
}
|
}
|
||||||
@ -265,7 +315,7 @@ pub fn run_emscripten_instance(
|
|||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO atinit and atexit for emscripten
|
// TODO atexit for emscripten
|
||||||
// println!("{:?}", data);
|
// println!("{:?}", data);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -309,10 +359,6 @@ pub struct EmscriptenGlobalsData {
|
|||||||
table_base: u32,
|
table_base: u32,
|
||||||
temp_double_ptr: u32,
|
temp_double_ptr: u32,
|
||||||
use_old_abort_on_cannot_grow_memory: bool,
|
use_old_abort_on_cannot_grow_memory: bool,
|
||||||
|
|
||||||
// Global namespace
|
|
||||||
infinity: f64,
|
|
||||||
nan: f64,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct EmscriptenGlobals {
|
pub struct EmscriptenGlobals {
|
||||||
@ -323,6 +369,7 @@ pub struct EmscriptenGlobals {
|
|||||||
pub table: Table,
|
pub table: Table,
|
||||||
pub memory_min: Pages,
|
pub memory_min: Pages,
|
||||||
pub memory_max: Option<Pages>,
|
pub memory_max: Option<Pages>,
|
||||||
|
pub null_func_names: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EmscriptenGlobals {
|
impl EmscriptenGlobals {
|
||||||
@ -341,7 +388,7 @@ impl EmscriptenGlobals {
|
|||||||
if name == "abortOnCannotGrowMemory" && namespace == "env" {
|
if name == "abortOnCannotGrowMemory" && namespace == "env" {
|
||||||
let sig_index = module.info().func_assoc[index.convert_up(module.info())];
|
let sig_index = module.info().func_assoc[index.convert_up(module.info())];
|
||||||
let expected_sig = &module.info().signatures[sig_index];
|
let expected_sig = &module.info().signatures[sig_index];
|
||||||
if **expected_sig == *OLD_ABORT_ON_CANNOT_GROW_MEMORY_SIG {
|
if *expected_sig == *OLD_ABORT_ON_CANNOT_GROW_MEMORY_SIG {
|
||||||
use_old_abort_on_cannot_grow_memory = true;
|
use_old_abort_on_cannot_grow_memory = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -364,22 +411,22 @@ impl EmscriptenGlobals {
|
|||||||
minimum: table_min,
|
minimum: table_min,
|
||||||
maximum: table_max,
|
maximum: table_max,
|
||||||
};
|
};
|
||||||
let mut table = Table::new(table_type).unwrap();
|
let table = Table::new(table_type).unwrap();
|
||||||
|
|
||||||
let data = {
|
let data = {
|
||||||
let static_bump = STATIC_BUMP;
|
let static_bump = STATIC_BUMP;
|
||||||
|
|
||||||
let mut STATIC_TOP = STATIC_BASE + static_bump;
|
let mut static_top = STATIC_BASE + static_bump;
|
||||||
|
|
||||||
let memory_base = STATIC_BASE;
|
let memory_base = STATIC_BASE;
|
||||||
let table_base = 0;
|
let table_base = 0;
|
||||||
|
|
||||||
let temp_double_ptr = STATIC_TOP;
|
let temp_double_ptr = static_top;
|
||||||
STATIC_TOP += 16;
|
static_top += 16;
|
||||||
|
|
||||||
let dynamictop_ptr = static_alloc(&mut STATIC_TOP, 4);
|
let dynamictop_ptr = static_alloc(&mut static_top, 4);
|
||||||
|
|
||||||
let stacktop = align_memory(STATIC_TOP);
|
let stacktop = align_memory(static_top);
|
||||||
let stack_max = stacktop + TOTAL_STACK;
|
let stack_max = stacktop + TOTAL_STACK;
|
||||||
|
|
||||||
EmscriptenGlobalsData {
|
EmscriptenGlobalsData {
|
||||||
@ -391,20 +438,34 @@ impl EmscriptenGlobals {
|
|||||||
table_base,
|
table_base,
|
||||||
temp_double_ptr,
|
temp_double_ptr,
|
||||||
use_old_abort_on_cannot_grow_memory,
|
use_old_abort_on_cannot_grow_memory,
|
||||||
|
|
||||||
infinity: std::f64::INFINITY,
|
|
||||||
nan: std::f64::NAN,
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
emscripten_set_up_memory(&memory, &data);
|
emscripten_set_up_memory(&memory, &data);
|
||||||
|
|
||||||
|
let mut null_func_names = vec![];
|
||||||
|
for (
|
||||||
|
_,
|
||||||
|
ImportName {
|
||||||
|
namespace_index,
|
||||||
|
name_index,
|
||||||
|
},
|
||||||
|
) in &module.info().imported_functions
|
||||||
|
{
|
||||||
|
let namespace = module.info().namespace_table.get(*namespace_index);
|
||||||
|
let name = module.info().name_table.get(*name_index);
|
||||||
|
if namespace == "env" && name.starts_with("nullFunc_") {
|
||||||
|
null_func_names.push(name.to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
data,
|
data,
|
||||||
memory,
|
memory,
|
||||||
table,
|
table,
|
||||||
memory_min,
|
memory_min,
|
||||||
memory_max,
|
memory_max,
|
||||||
|
null_func_names,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -416,8 +477,7 @@ pub fn generate_emscripten_env(globals: &mut EmscriptenGlobals) -> ImportObject
|
|||||||
func!(crate::memory::abort_on_cannot_grow_memory).to_export()
|
func!(crate::memory::abort_on_cannot_grow_memory).to_export()
|
||||||
};
|
};
|
||||||
|
|
||||||
imports! {
|
let mut env_ns = namespace! {
|
||||||
"env" => {
|
|
||||||
"memory" => Export::Memory(globals.memory.clone()),
|
"memory" => Export::Memory(globals.memory.clone()),
|
||||||
"table" => Export::Table(globals.table.clone()),
|
"table" => Export::Table(globals.table.clone()),
|
||||||
|
|
||||||
@ -438,6 +498,23 @@ pub fn generate_emscripten_env(globals: &mut EmscriptenGlobals) -> ImportObject
|
|||||||
"___lock" => func!(crate::lock::___lock),
|
"___lock" => func!(crate::lock::___lock),
|
||||||
"___unlock" => func!(crate::lock::___unlock),
|
"___unlock" => func!(crate::lock::___unlock),
|
||||||
"___wait" => func!(crate::lock::___wait),
|
"___wait" => func!(crate::lock::___wait),
|
||||||
|
"_flock" => func!(crate::lock::_flock),
|
||||||
|
"_chroot" => func!(crate::io::chroot),
|
||||||
|
"_getprotobyname" => func!(crate::io::getprotobyname),
|
||||||
|
"_getprotobynumber" => func!(crate::io::getprotobynumber),
|
||||||
|
"_getpwuid" => func!(crate::io::getpwuid),
|
||||||
|
"_sigdelset" => func!(crate::io::sigdelset),
|
||||||
|
"_sigfillset" => func!(crate::io::sigfillset),
|
||||||
|
"_tzset" => func!(crate::io::tzset),
|
||||||
|
"_strptime" => func!(crate::io::strptime),
|
||||||
|
|
||||||
|
// exec
|
||||||
|
"_execvp" => func!(crate::exec::execvp),
|
||||||
|
"_execl" => func!(crate::exec::execl),
|
||||||
|
"_execle" => func!(crate::exec::execle),
|
||||||
|
|
||||||
|
// exit
|
||||||
|
"__exit" => func!(crate::exit::exit),
|
||||||
|
|
||||||
// Env
|
// Env
|
||||||
"___assert_fail" => func!(crate::env::___assert_fail),
|
"___assert_fail" => func!(crate::env::___assert_fail),
|
||||||
@ -452,21 +529,7 @@ pub fn generate_emscripten_env(globals: &mut EmscriptenGlobals) -> ImportObject
|
|||||||
"_getpagesize" => func!(crate::env::_getpagesize),
|
"_getpagesize" => func!(crate::env::_getpagesize),
|
||||||
"_sysconf" => func!(crate::env::_sysconf),
|
"_sysconf" => func!(crate::env::_sysconf),
|
||||||
"_getaddrinfo" => func!(crate::env::_getaddrinfo),
|
"_getaddrinfo" => func!(crate::env::_getaddrinfo),
|
||||||
|
"_times" => func!(crate::env::_times),
|
||||||
// Null func
|
|
||||||
"nullFunc_i" => func!(crate::nullfunc::nullfunc_i),
|
|
||||||
"nullFunc_ii" => func!(crate::nullfunc::nullfunc_ii),
|
|
||||||
"nullFunc_iii" => func!(crate::nullfunc::nullfunc_iii),
|
|
||||||
"nullFunc_iiii" => func!(crate::nullfunc::nullfunc_iiii),
|
|
||||||
"nullFunc_iiiii" => func!(crate::nullfunc::nullfunc_iiiii),
|
|
||||||
"nullFunc_iiiiii" => func!(crate::nullfunc::nullfunc_iiiiii),
|
|
||||||
"nullFunc_v" => func!(crate::nullfunc::nullfunc_v),
|
|
||||||
"nullFunc_vi" => func!(crate::nullfunc::nullfunc_vi),
|
|
||||||
"nullFunc_vii" => func!(crate::nullfunc::nullfunc_vii),
|
|
||||||
"nullFunc_viii" => func!(crate::nullfunc::nullfunc_viii),
|
|
||||||
"nullFunc_viiii" => func!(crate::nullfunc::nullfunc_viiii),
|
|
||||||
"nullFunc_viiiii" => func!(crate::nullfunc::nullfunc_viiiii),
|
|
||||||
"nullFunc_viiiiii" => func!(crate::nullfunc::nullfunc_viiiiii),
|
|
||||||
|
|
||||||
// Syscalls
|
// Syscalls
|
||||||
"___syscall1" => func!(crate::syscalls::___syscall1),
|
"___syscall1" => func!(crate::syscalls::___syscall1),
|
||||||
@ -474,13 +537,18 @@ pub fn generate_emscripten_env(globals: &mut EmscriptenGlobals) -> ImportObject
|
|||||||
"___syscall4" => func!(crate::syscalls::___syscall4),
|
"___syscall4" => func!(crate::syscalls::___syscall4),
|
||||||
"___syscall5" => func!(crate::syscalls::___syscall5),
|
"___syscall5" => func!(crate::syscalls::___syscall5),
|
||||||
"___syscall6" => func!(crate::syscalls::___syscall6),
|
"___syscall6" => func!(crate::syscalls::___syscall6),
|
||||||
|
"___syscall9" => func!(crate::syscalls::___syscall9),
|
||||||
"___syscall10" => func!(crate::syscalls::___syscall10),
|
"___syscall10" => func!(crate::syscalls::___syscall10),
|
||||||
"___syscall12" => func!(crate::syscalls::___syscall12),
|
"___syscall12" => func!(crate::syscalls::___syscall12),
|
||||||
"___syscall15" => func!(crate::syscalls::___syscall15),
|
"___syscall15" => func!(crate::syscalls::___syscall15),
|
||||||
"___syscall20" => func!(crate::syscalls::___syscall20),
|
"___syscall20" => func!(crate::syscalls::___syscall20),
|
||||||
|
"___syscall33" => func!(crate::syscalls::___syscall33),
|
||||||
|
"___syscall34" => func!(crate::syscalls::___syscall34),
|
||||||
"___syscall39" => func!(crate::syscalls::___syscall39),
|
"___syscall39" => func!(crate::syscalls::___syscall39),
|
||||||
"___syscall38" => func!(crate::syscalls::___syscall38),
|
"___syscall38" => func!(crate::syscalls::___syscall38),
|
||||||
"___syscall40" => func!(crate::syscalls::___syscall40),
|
"___syscall40" => func!(crate::syscalls::___syscall40),
|
||||||
|
"___syscall41" => func!(crate::syscalls::___syscall41),
|
||||||
|
"___syscall42" => func!(crate::syscalls::___syscall42),
|
||||||
"___syscall54" => func!(crate::syscalls::___syscall54),
|
"___syscall54" => func!(crate::syscalls::___syscall54),
|
||||||
"___syscall57" => func!(crate::syscalls::___syscall57),
|
"___syscall57" => func!(crate::syscalls::___syscall57),
|
||||||
"___syscall60" => func!(crate::syscalls::___syscall60),
|
"___syscall60" => func!(crate::syscalls::___syscall60),
|
||||||
@ -488,36 +556,48 @@ pub fn generate_emscripten_env(globals: &mut EmscriptenGlobals) -> ImportObject
|
|||||||
"___syscall64" => func!(crate::syscalls::___syscall64),
|
"___syscall64" => func!(crate::syscalls::___syscall64),
|
||||||
"___syscall66" => func!(crate::syscalls::___syscall66),
|
"___syscall66" => func!(crate::syscalls::___syscall66),
|
||||||
"___syscall75" => func!(crate::syscalls::___syscall75),
|
"___syscall75" => func!(crate::syscalls::___syscall75),
|
||||||
|
"___syscall77" => func!(crate::syscalls::___syscall77),
|
||||||
|
"___syscall83" => func!(crate::syscalls::___syscall83),
|
||||||
"___syscall85" => func!(crate::syscalls::___syscall85),
|
"___syscall85" => func!(crate::syscalls::___syscall85),
|
||||||
"___syscall91" => func!(crate::syscalls::___syscall191),
|
"___syscall91" => func!(crate::syscalls::___syscall91),
|
||||||
|
"___syscall94" => func!(crate::syscalls::___syscall94),
|
||||||
"___syscall97" => func!(crate::syscalls::___syscall97),
|
"___syscall97" => func!(crate::syscalls::___syscall97),
|
||||||
"___syscall102" => func!(crate::syscalls::___syscall102),
|
"___syscall102" => func!(crate::syscalls::___syscall102),
|
||||||
"___syscall110" => func!(crate::syscalls::___syscall110),
|
"___syscall110" => func!(crate::syscalls::___syscall110),
|
||||||
"___syscall114" => func!(crate::syscalls::___syscall114),
|
"___syscall114" => func!(crate::syscalls::___syscall114),
|
||||||
|
"___syscall118" => func!(crate::syscalls::___syscall118),
|
||||||
"___syscall122" => func!(crate::syscalls::___syscall122),
|
"___syscall122" => func!(crate::syscalls::___syscall122),
|
||||||
"___syscall140" => func!(crate::syscalls::___syscall140),
|
"___syscall140" => func!(crate::syscalls::___syscall140),
|
||||||
"___syscall142" => func!(crate::syscalls::___syscall142),
|
"___syscall142" => func!(crate::syscalls::___syscall142),
|
||||||
"___syscall145" => func!(crate::syscalls::___syscall145),
|
"___syscall145" => func!(crate::syscalls::___syscall145),
|
||||||
"___syscall146" => func!(crate::syscalls::___syscall146),
|
"___syscall146" => func!(crate::syscalls::___syscall146),
|
||||||
|
"___syscall148" => func!(crate::syscalls::___syscall148),
|
||||||
"___syscall168" => func!(crate::syscalls::___syscall168),
|
"___syscall168" => func!(crate::syscalls::___syscall168),
|
||||||
"___syscall180" => func!(crate::syscalls::___syscall180),
|
"___syscall180" => func!(crate::syscalls::___syscall180),
|
||||||
"___syscall181" => func!(crate::syscalls::___syscall181),
|
"___syscall181" => func!(crate::syscalls::___syscall181),
|
||||||
|
"___syscall183" => func!(crate::syscalls::___syscall183),
|
||||||
"___syscall191" => func!(crate::syscalls::___syscall191),
|
"___syscall191" => func!(crate::syscalls::___syscall191),
|
||||||
"___syscall192" => func!(crate::syscalls::___syscall192),
|
"___syscall192" => func!(crate::syscalls::___syscall192),
|
||||||
"___syscall194" => func!(crate::syscalls::___syscall194),
|
"___syscall194" => func!(crate::syscalls::___syscall194),
|
||||||
"___syscall195" => func!(crate::syscalls::___syscall195),
|
"___syscall195" => func!(crate::syscalls::___syscall195),
|
||||||
"___syscall196" => func!(crate::syscalls::___syscall196),
|
"___syscall196" => func!(crate::syscalls::___syscall196),
|
||||||
"___syscall197" => func!(crate::syscalls::___syscall197),
|
"___syscall197" => func!(crate::syscalls::___syscall197),
|
||||||
|
"___syscall198" => func!(crate::syscalls::___syscall198),
|
||||||
"___syscall199" => func!(crate::syscalls::___syscall199),
|
"___syscall199" => func!(crate::syscalls::___syscall199),
|
||||||
|
"___syscall200" => func!(crate::syscalls::___syscall200),
|
||||||
"___syscall201" => func!(crate::syscalls::___syscall201),
|
"___syscall201" => func!(crate::syscalls::___syscall201),
|
||||||
"___syscall202" => func!(crate::syscalls::___syscall202),
|
"___syscall202" => func!(crate::syscalls::___syscall202),
|
||||||
|
"___syscall205" => func!(crate::syscalls::___syscall205),
|
||||||
|
"___syscall207" => func!(crate::syscalls::___syscall207),
|
||||||
"___syscall212" => func!(crate::syscalls::___syscall212),
|
"___syscall212" => func!(crate::syscalls::___syscall212),
|
||||||
|
"___syscall219" => func!(crate::syscalls::___syscall219),
|
||||||
"___syscall220" => func!(crate::syscalls::___syscall220),
|
"___syscall220" => func!(crate::syscalls::___syscall220),
|
||||||
"___syscall221" => func!(crate::syscalls::___syscall221),
|
"___syscall221" => func!(crate::syscalls::___syscall221),
|
||||||
"___syscall268" => func!(crate::syscalls::___syscall268),
|
"___syscall268" => func!(crate::syscalls::___syscall268),
|
||||||
"___syscall272" => func!(crate::syscalls::___syscall272),
|
"___syscall272" => func!(crate::syscalls::___syscall272),
|
||||||
"___syscall295" => func!(crate::syscalls::___syscall295),
|
"___syscall295" => func!(crate::syscalls::___syscall295),
|
||||||
"___syscall300" => func!(crate::syscalls::___syscall300),
|
"___syscall300" => func!(crate::syscalls::___syscall300),
|
||||||
|
"___syscall324" => func!(crate::syscalls::___syscall324),
|
||||||
"___syscall330" => func!(crate::syscalls::___syscall330),
|
"___syscall330" => func!(crate::syscalls::___syscall330),
|
||||||
"___syscall334" => func!(crate::syscalls::___syscall334),
|
"___syscall334" => func!(crate::syscalls::___syscall334),
|
||||||
"___syscall340" => func!(crate::syscalls::___syscall340),
|
"___syscall340" => func!(crate::syscalls::___syscall340),
|
||||||
@ -536,6 +616,7 @@ pub fn generate_emscripten_env(globals: &mut EmscriptenGlobals) -> ImportObject
|
|||||||
"_kill" => func!(crate::process::_kill),
|
"_kill" => func!(crate::process::_kill),
|
||||||
"_llvm_stackrestore" => func!(crate::process::_llvm_stackrestore),
|
"_llvm_stackrestore" => func!(crate::process::_llvm_stackrestore),
|
||||||
"_llvm_stacksave" => func!(crate::process::_llvm_stacksave),
|
"_llvm_stacksave" => func!(crate::process::_llvm_stacksave),
|
||||||
|
"_llvm_eh_typeid_for" => func!(crate::process::_llvm_eh_typeid_for),
|
||||||
"_raise" => func!(crate::process::_raise),
|
"_raise" => func!(crate::process::_raise),
|
||||||
"_sem_init" => func!(crate::process::_sem_init),
|
"_sem_init" => func!(crate::process::_sem_init),
|
||||||
"_sem_post" => func!(crate::process::_sem_post),
|
"_sem_post" => func!(crate::process::_sem_post),
|
||||||
@ -546,6 +627,7 @@ pub fn generate_emscripten_env(globals: &mut EmscriptenGlobals) -> ImportObject
|
|||||||
"_setgroups" => func!(crate::process::_setgroups),
|
"_setgroups" => func!(crate::process::_setgroups),
|
||||||
"_setitimer" => func!(crate::process::_setitimer),
|
"_setitimer" => func!(crate::process::_setitimer),
|
||||||
"_usleep" => func!(crate::process::_usleep),
|
"_usleep" => func!(crate::process::_usleep),
|
||||||
|
"_nanosleep" => func!(crate::process::_nanosleep),
|
||||||
"_utimes" => func!(crate::process::_utimes),
|
"_utimes" => func!(crate::process::_utimes),
|
||||||
"_waitpid" => func!(crate::process::_waitpid),
|
"_waitpid" => func!(crate::process::_waitpid),
|
||||||
|
|
||||||
@ -570,6 +652,9 @@ pub fn generate_emscripten_env(globals: &mut EmscriptenGlobals) -> ImportObject
|
|||||||
// Exception
|
// Exception
|
||||||
"___cxa_allocate_exception" => func!(crate::exception::___cxa_allocate_exception),
|
"___cxa_allocate_exception" => func!(crate::exception::___cxa_allocate_exception),
|
||||||
"___cxa_throw" => func!(crate::exception::___cxa_throw),
|
"___cxa_throw" => func!(crate::exception::___cxa_throw),
|
||||||
|
"___cxa_begin_catch" => func!(crate::exception::___cxa_begin_catch),
|
||||||
|
"___cxa_end_catch" => func!(crate::exception::___cxa_end_catch),
|
||||||
|
"___cxa_uncaught_exception" => func!(crate::exception::___cxa_uncaught_exception),
|
||||||
|
|
||||||
// Time
|
// Time
|
||||||
"_gettimeofday" => func!(crate::time::_gettimeofday),
|
"_gettimeofday" => func!(crate::time::_gettimeofday),
|
||||||
@ -582,6 +667,7 @@ pub fn generate_emscripten_env(globals: &mut EmscriptenGlobals) -> ImportObject
|
|||||||
"_localtime" => func!(crate::time::_localtime),
|
"_localtime" => func!(crate::time::_localtime),
|
||||||
"_time" => func!(crate::time::_time),
|
"_time" => func!(crate::time::_time),
|
||||||
"_strftime" => func!(crate::time::_strftime),
|
"_strftime" => func!(crate::time::_strftime),
|
||||||
|
"_strftime_l" => func!(crate::time::_strftime_l),
|
||||||
"_localtime_r" => func!(crate::time::_localtime_r),
|
"_localtime_r" => func!(crate::time::_localtime_r),
|
||||||
"_gmtime_r" => func!(crate::time::_gmtime_r),
|
"_gmtime_r" => func!(crate::time::_gmtime_r),
|
||||||
"_mktime" => func!(crate::time::_mktime),
|
"_mktime" => func!(crate::time::_mktime),
|
||||||
@ -593,11 +679,20 @@ pub fn generate_emscripten_env(globals: &mut EmscriptenGlobals) -> ImportObject
|
|||||||
"_llvm_log2_f64" => func!(crate::math::_llvm_log2_f64),
|
"_llvm_log2_f64" => func!(crate::math::_llvm_log2_f64),
|
||||||
"_llvm_log10_f32" => func!(crate::math::_llvm_log10_f32),
|
"_llvm_log10_f32" => func!(crate::math::_llvm_log10_f32),
|
||||||
"_llvm_log2_f32" => func!(crate::math::_llvm_log2_f64),
|
"_llvm_log2_f32" => func!(crate::math::_llvm_log2_f64),
|
||||||
|
"_llvm_sin_f64" => func!(crate::math::_llvm_sin_f64),
|
||||||
|
"_llvm_cos_f64" => func!(crate::math::_llvm_cos_f64),
|
||||||
|
"_llvm_exp2_f32" => func!(crate::math::_llvm_exp2_f32),
|
||||||
|
"_llvm_exp2_f64" => func!(crate::math::_llvm_exp2_f64),
|
||||||
"_emscripten_random" => func!(crate::math::_emscripten_random),
|
"_emscripten_random" => func!(crate::math::_emscripten_random),
|
||||||
|
|
||||||
// Jump
|
// Jump
|
||||||
"__setjmp" => func!(crate::jmp::__setjmp),
|
"__setjmp" => func!(crate::jmp::__setjmp),
|
||||||
"__longjmp" => func!(crate::jmp::__longjmp),
|
"__longjmp" => func!(crate::jmp::__longjmp),
|
||||||
|
"_longjmp" => func!(crate::jmp::_longjmp),
|
||||||
|
"_emscripten_longjmp" => func!(crate::jmp::_longjmp),
|
||||||
|
|
||||||
|
// Bitwise
|
||||||
|
"_llvm_bswap_i64" => func!(crate::bitwise::_llvm_bswap_i64),
|
||||||
|
|
||||||
// Linking
|
// Linking
|
||||||
"_dlclose" => func!(crate::linking::_dlclose),
|
"_dlclose" => func!(crate::linking::_dlclose),
|
||||||
@ -608,13 +703,14 @@ pub fn generate_emscripten_env(globals: &mut EmscriptenGlobals) -> ImportObject
|
|||||||
// wasm32-unknown-emscripten
|
// wasm32-unknown-emscripten
|
||||||
"setTempRet0" => func!(crate::emscripten_target::setTempRet0),
|
"setTempRet0" => func!(crate::emscripten_target::setTempRet0),
|
||||||
"getTempRet0" => func!(crate::emscripten_target::getTempRet0),
|
"getTempRet0" => func!(crate::emscripten_target::getTempRet0),
|
||||||
"nullFunc_ji" => func!(crate::emscripten_target::nullFunc_ji),
|
|
||||||
"invoke_i" => func!(crate::emscripten_target::invoke_i),
|
"invoke_i" => func!(crate::emscripten_target::invoke_i),
|
||||||
"invoke_ii" => func!(crate::emscripten_target::invoke_ii),
|
"invoke_ii" => func!(crate::emscripten_target::invoke_ii),
|
||||||
"invoke_iii" => func!(crate::emscripten_target::invoke_iii),
|
"invoke_iii" => func!(crate::emscripten_target::invoke_iii),
|
||||||
"invoke_iiii" => func!(crate::emscripten_target::invoke_iiii),
|
"invoke_iiii" => func!(crate::emscripten_target::invoke_iiii),
|
||||||
|
"invoke_iifi" => func!(crate::emscripten_target::invoke_iifi),
|
||||||
"invoke_v" => func!(crate::emscripten_target::invoke_v),
|
"invoke_v" => func!(crate::emscripten_target::invoke_v),
|
||||||
"invoke_vi" => func!(crate::emscripten_target::invoke_vi),
|
"invoke_vi" => func!(crate::emscripten_target::invoke_vi),
|
||||||
|
"invoke_vj" => func!(crate::emscripten_target::invoke_vj),
|
||||||
"invoke_vii" => func!(crate::emscripten_target::invoke_vii),
|
"invoke_vii" => func!(crate::emscripten_target::invoke_vii),
|
||||||
"invoke_viii" => func!(crate::emscripten_target::invoke_viii),
|
"invoke_viii" => func!(crate::emscripten_target::invoke_viii),
|
||||||
"invoke_viiii" => func!(crate::emscripten_target::invoke_viiii),
|
"invoke_viiii" => func!(crate::emscripten_target::invoke_viiii),
|
||||||
@ -626,6 +722,8 @@ pub fn generate_emscripten_env(globals: &mut EmscriptenGlobals) -> ImportObject
|
|||||||
"___cxa_free_exception" => func!(crate::emscripten_target::___cxa_free_exception),
|
"___cxa_free_exception" => func!(crate::emscripten_target::___cxa_free_exception),
|
||||||
"___resumeException" => func!(crate::emscripten_target::___resumeException),
|
"___resumeException" => func!(crate::emscripten_target::___resumeException),
|
||||||
"_dladdr" => func!(crate::emscripten_target::_dladdr),
|
"_dladdr" => func!(crate::emscripten_target::_dladdr),
|
||||||
|
"_pthread_create" => func!(crate::emscripten_target::_pthread_create),
|
||||||
|
"_pthread_join" => func!(crate::emscripten_target::_pthread_join),
|
||||||
"_pthread_cond_destroy" => func!(crate::emscripten_target::_pthread_cond_destroy),
|
"_pthread_cond_destroy" => func!(crate::emscripten_target::_pthread_cond_destroy),
|
||||||
"_pthread_cond_init" => func!(crate::emscripten_target::_pthread_cond_init),
|
"_pthread_cond_init" => func!(crate::emscripten_target::_pthread_cond_init),
|
||||||
"_pthread_cond_signal" => func!(crate::emscripten_target::_pthread_cond_signal),
|
"_pthread_cond_signal" => func!(crate::emscripten_target::_pthread_cond_signal),
|
||||||
@ -640,42 +738,39 @@ pub fn generate_emscripten_env(globals: &mut EmscriptenGlobals) -> ImportObject
|
|||||||
"_pthread_mutexattr_settype" => func!(crate::emscripten_target::_pthread_mutexattr_settype),
|
"_pthread_mutexattr_settype" => func!(crate::emscripten_target::_pthread_mutexattr_settype),
|
||||||
"_pthread_rwlock_rdlock" => func!(crate::emscripten_target::_pthread_rwlock_rdlock),
|
"_pthread_rwlock_rdlock" => func!(crate::emscripten_target::_pthread_rwlock_rdlock),
|
||||||
"_pthread_rwlock_unlock" => func!(crate::emscripten_target::_pthread_rwlock_unlock),
|
"_pthread_rwlock_unlock" => func!(crate::emscripten_target::_pthread_rwlock_unlock),
|
||||||
|
"_pthread_setcancelstate" => func!(crate::emscripten_target::_pthread_setcancelstate),
|
||||||
|
"_pthread_getspecific" => func!(crate::emscripten_target::_pthread_getspecific),
|
||||||
|
"_pthread_setspecific" => func!(crate::emscripten_target::_pthread_setspecific),
|
||||||
|
"_pthread_once" => func!(crate::emscripten_target::_pthread_once),
|
||||||
|
"_pthread_key_create" => func!(crate::emscripten_target::_pthread_key_create),
|
||||||
"___gxx_personality_v0" => func!(crate::emscripten_target::___gxx_personality_v0),
|
"___gxx_personality_v0" => func!(crate::emscripten_target::___gxx_personality_v0),
|
||||||
// round 2
|
"_getdtablesize" => func!(crate::emscripten_target::_getdtablesize),
|
||||||
"nullFunc_dii" => func!(crate::emscripten_target::nullFunc_dii),
|
"_gethostbyaddr" => func!(crate::emscripten_target::_gethostbyaddr),
|
||||||
"nullFunc_diiii" => func!(crate::emscripten_target::nullFunc_diiii),
|
"_gethostbyname_r" => func!(crate::emscripten_target::_gethostbyname_r),
|
||||||
"nullFunc_iiji" => func!(crate::emscripten_target::nullFunc_iiji),
|
"_getloadavg" => func!(crate::emscripten_target::_getloadavg),
|
||||||
"nullFunc_j" => func!(crate::emscripten_target::nullFunc_j),
|
|
||||||
"nullFunc_jij" => func!(crate::emscripten_target::nullFunc_jij),
|
|
||||||
"nullFunc_jjj" => func!(crate::emscripten_target::nullFunc_jjj),
|
|
||||||
"nullFunc_vd" => func!(crate::emscripten_target::nullFunc_vd),
|
|
||||||
"nullFunc_viiiiiii" => func!(crate::emscripten_target::nullFunc_viiiiiii),
|
|
||||||
"nullFunc_viiiiiiii" => func!(crate::emscripten_target::nullFunc_viiiiiiii),
|
|
||||||
"nullFunc_viiiiiiiii" => func!(crate::emscripten_target::nullFunc_viiiiiiiii),
|
|
||||||
"nullFunc_viiij" => func!(crate::emscripten_target::nullFunc_viiij),
|
|
||||||
"nullFunc_viiijiiii" => func!(crate::emscripten_target::nullFunc_viiijiiii),
|
|
||||||
"nullFunc_viiijiiiiii" => func!(crate::emscripten_target::nullFunc_viiijiiiiii),
|
|
||||||
"nullFunc_viij" => func!(crate::emscripten_target::nullFunc_viij),
|
|
||||||
"nullFunc_viiji" => func!(crate::emscripten_target::nullFunc_viiji),
|
|
||||||
"nullFunc_viijiii" => func!(crate::emscripten_target::nullFunc_viijiii),
|
|
||||||
"nullFunc_viijj" => func!(crate::emscripten_target::nullFunc_viijj),
|
|
||||||
"nullFunc_vij" => func!(crate::emscripten_target::nullFunc_vij),
|
|
||||||
"nullFunc_viji" => func!(crate::emscripten_target::nullFunc_viji),
|
|
||||||
"nullFunc_vijiii" => func!(crate::emscripten_target::nullFunc_vijiii),
|
|
||||||
"nullFunc_vijj" => func!(crate::emscripten_target::nullFunc_vijj),
|
|
||||||
"invoke_dii" => func!(crate::emscripten_target::invoke_dii),
|
"invoke_dii" => func!(crate::emscripten_target::invoke_dii),
|
||||||
"invoke_diiii" => func!(crate::emscripten_target::invoke_diiii),
|
"invoke_diiii" => func!(crate::emscripten_target::invoke_diiii),
|
||||||
"invoke_iiiii" => func!(crate::emscripten_target::invoke_iiiii),
|
"invoke_iiiii" => func!(crate::emscripten_target::invoke_iiiii),
|
||||||
"invoke_iiiiii" => func!(crate::emscripten_target::invoke_iiiiii),
|
"invoke_iiiiii" => func!(crate::emscripten_target::invoke_iiiiii),
|
||||||
|
"invoke_iiiiiii" => func!(crate::emscripten_target::invoke_iiiiiii),
|
||||||
|
"invoke_iiiiiiii" => func!(crate::emscripten_target::invoke_iiiiiiii),
|
||||||
|
"invoke_iiiiiiiii" => func!(crate::emscripten_target::invoke_iiiiiiiii),
|
||||||
|
"invoke_iiiiiiiiii" => func!(crate::emscripten_target::invoke_iiiiiiiiii),
|
||||||
|
"invoke_iiiiiiiiiii" => func!(crate::emscripten_target::invoke_iiiiiiiiiii),
|
||||||
"invoke_vd" => func!(crate::emscripten_target::invoke_vd),
|
"invoke_vd" => func!(crate::emscripten_target::invoke_vd),
|
||||||
"invoke_viiiii" => func!(crate::emscripten_target::invoke_viiiii),
|
"invoke_viiiii" => func!(crate::emscripten_target::invoke_viiiii),
|
||||||
"invoke_viiiiii" => func!(crate::emscripten_target::invoke_viiiiii),
|
"invoke_viiiiii" => func!(crate::emscripten_target::invoke_viiiiii),
|
||||||
"invoke_viiiiiii" => func!(crate::emscripten_target::invoke_viiiiiii),
|
"invoke_viiiiiii" => func!(crate::emscripten_target::invoke_viiiiiii),
|
||||||
"invoke_viiiiiiii" => func!(crate::emscripten_target::invoke_viiiiiiii),
|
"invoke_viiiiiiii" => func!(crate::emscripten_target::invoke_viiiiiiii),
|
||||||
"invoke_viiiiiiiii" => func!(crate::emscripten_target::invoke_viiiiiiiii),
|
"invoke_viiiiiiiii" => func!(crate::emscripten_target::invoke_viiiiiiiii),
|
||||||
|
"invoke_viiiiiiiii" => func!(crate::emscripten_target::invoke_viiiiiiiii),
|
||||||
|
"invoke_viiiiiiiiii" => func!(crate::emscripten_target::invoke_viiiiiiiiii),
|
||||||
|
"invoke_iij" => func!(crate::emscripten_target::invoke_iij),
|
||||||
"invoke_iiji" => func!(crate::emscripten_target::invoke_iiji),
|
"invoke_iiji" => func!(crate::emscripten_target::invoke_iiji),
|
||||||
|
"invoke_iiijj" => func!(crate::emscripten_target::invoke_iiijj),
|
||||||
"invoke_j" => func!(crate::emscripten_target::invoke_j),
|
"invoke_j" => func!(crate::emscripten_target::invoke_j),
|
||||||
"invoke_ji" => func!(crate::emscripten_target::invoke_ji),
|
"invoke_ji" => func!(crate::emscripten_target::invoke_ji),
|
||||||
|
"invoke_jii" => func!(crate::emscripten_target::invoke_jii),
|
||||||
"invoke_jij" => func!(crate::emscripten_target::invoke_jij),
|
"invoke_jij" => func!(crate::emscripten_target::invoke_jij),
|
||||||
"invoke_jjj" => func!(crate::emscripten_target::invoke_jjj),
|
"invoke_jjj" => func!(crate::emscripten_target::invoke_jjj),
|
||||||
"invoke_viiij" => func!(crate::emscripten_target::invoke_viiij),
|
"invoke_viiij" => func!(crate::emscripten_target::invoke_viiij),
|
||||||
@ -689,18 +784,42 @@ pub fn generate_emscripten_env(globals: &mut EmscriptenGlobals) -> ImportObject
|
|||||||
"invoke_viji" => func!(crate::emscripten_target::invoke_viji),
|
"invoke_viji" => func!(crate::emscripten_target::invoke_viji),
|
||||||
"invoke_vijiii" => func!(crate::emscripten_target::invoke_vijiii),
|
"invoke_vijiii" => func!(crate::emscripten_target::invoke_vijiii),
|
||||||
"invoke_vijj" => func!(crate::emscripten_target::invoke_vijj),
|
"invoke_vijj" => func!(crate::emscripten_target::invoke_vijj),
|
||||||
},
|
"invoke_viid" => func!(crate::emscripten_target::invoke_viid),
|
||||||
|
"invoke_viidii" => func!(crate::emscripten_target::invoke_viidii),
|
||||||
|
"invoke_viidddddddd" => func!(crate::emscripten_target::invoke_viidddddddd),
|
||||||
|
};
|
||||||
|
|
||||||
|
for null_func_name in globals.null_func_names.iter() {
|
||||||
|
env_ns.insert(null_func_name.as_str(), Func::new(nullfunc).to_export());
|
||||||
|
}
|
||||||
|
|
||||||
|
let import_object: ImportObject = imports! {
|
||||||
|
"env" => env_ns,
|
||||||
"global" => {
|
"global" => {
|
||||||
"NaN" => Global::new(Value::F64(f64::NAN)),
|
"NaN" => Global::new(Value::F64(f64::NAN)),
|
||||||
"Infinity" => Global::new(Value::F64(f64::INFINITY)),
|
"Infinity" => Global::new(Value::F64(f64::INFINITY)),
|
||||||
},
|
},
|
||||||
"global.Math" => {
|
"global.Math" => {
|
||||||
"pow" => func!(crate::math::pow),
|
"pow" => func!(crate::math::pow),
|
||||||
|
"exp" => func!(crate::math::exp),
|
||||||
|
"log" => func!(crate::math::log),
|
||||||
},
|
},
|
||||||
"asm2wasm" => {
|
"asm2wasm" => {
|
||||||
"f64-rem" => func!(crate::math::f64_rem),
|
"f64-rem" => func!(crate::math::f64_rem),
|
||||||
|
"f64-to-int" => func!(crate::math::f64_to_int),
|
||||||
},
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
import_object
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn nullfunc(ctx: &mut Ctx, _x: u32) {
|
||||||
|
use crate::process::abort_with_message;
|
||||||
|
debug!("emscripten::nullfunc_i {}", _x);
|
||||||
|
abort_with_message(ctx, "Invalid function pointer. Perhaps this is an invalid value \
|
||||||
|
(e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an \
|
||||||
|
incorrect type, which will fail? (it is worth building your source files with -Werror (\
|
||||||
|
warnings are errors), as warnings can indicate undefined behavior which can cause this)");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The current version of this crate
|
/// The current version of this crate
|
||||||
|
@ -2,16 +2,21 @@ use libc::c_int;
|
|||||||
use wasmer_runtime_core::vm::Ctx;
|
use wasmer_runtime_core::vm::Ctx;
|
||||||
|
|
||||||
// NOTE: Not implemented by Emscripten
|
// NOTE: Not implemented by Emscripten
|
||||||
pub fn ___lock(_ctx: &mut Ctx, what: c_int) {
|
pub fn ___lock(_ctx: &mut Ctx, _what: c_int) {
|
||||||
debug!("emscripten::___lock {}", what);
|
debug!("emscripten::___lock {}", _what);
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: Not implemented by Emscripten
|
// NOTE: Not implemented by Emscripten
|
||||||
pub fn ___unlock(_ctx: &mut Ctx, what: c_int) {
|
pub fn ___unlock(_ctx: &mut Ctx, _what: c_int) {
|
||||||
debug!("emscripten::___unlock {}", what);
|
debug!("emscripten::___unlock {}", _what);
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: Not implemented by Emscripten
|
// NOTE: Not implemented by Emscripten
|
||||||
pub fn ___wait(_ctx: &mut Ctx, _which: u32, _varargs: u32, _three: u32, _four: u32) {
|
pub fn ___wait(_ctx: &mut Ctx, _which: u32, _varargs: u32, _three: u32, _four: u32) {
|
||||||
debug!("emscripten::___wait");
|
debug!("emscripten::___wait");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn _flock(_ctx: &mut Ctx, _fd: u32, _op: u32) -> u32 {
|
||||||
|
debug!("emscripten::_flock");
|
||||||
|
0
|
||||||
|
}
|
||||||
|
@ -12,6 +12,18 @@ pub fn _llvm_log2_f64(_ctx: &mut Ctx, value: f64) -> f64 {
|
|||||||
value.log2()
|
value.log2()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// emscripten: _llvm_sin_f64
|
||||||
|
pub fn _llvm_sin_f64(_ctx: &mut Ctx, value: f64) -> f64 {
|
||||||
|
debug!("emscripten::_llvm_sin_f64");
|
||||||
|
value.sin()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// emscripten: _llvm_cos_f64
|
||||||
|
pub fn _llvm_cos_f64(_ctx: &mut Ctx, value: f64) -> f64 {
|
||||||
|
debug!("emscripten::_llvm_cos_f64");
|
||||||
|
value.cos()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn _llvm_log10_f32(_ctx: &mut Ctx, _value: f64) -> f64 {
|
pub fn _llvm_log10_f32(_ctx: &mut Ctx, _value: f64) -> f64 {
|
||||||
debug!("emscripten::_llvm_log10_f32");
|
debug!("emscripten::_llvm_log10_f32");
|
||||||
-1.0
|
-1.0
|
||||||
@ -22,12 +34,22 @@ pub fn _llvm_log2_f32(_ctx: &mut Ctx, _value: f64) -> f64 {
|
|||||||
-1.0
|
-1.0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn _llvm_exp2_f32(_ctx: &mut Ctx, value: f32) -> f32 {
|
||||||
|
debug!("emscripten::_llvm_exp2_f32");
|
||||||
|
2f32.powf(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn _llvm_exp2_f64(_ctx: &mut Ctx, value: f64) -> f64 {
|
||||||
|
debug!("emscripten::_llvm_exp2_f64");
|
||||||
|
2f64.powf(value)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn _emscripten_random(_ctx: &mut Ctx) -> f64 {
|
pub fn _emscripten_random(_ctx: &mut Ctx) -> f64 {
|
||||||
debug!("emscripten::_emscripten_random");
|
debug!("emscripten::_emscripten_random");
|
||||||
-1.0
|
-1.0
|
||||||
}
|
}
|
||||||
|
|
||||||
// emscripten: f64-rem
|
// emscripten: asm2wasm.f64-rem
|
||||||
pub fn f64_rem(_ctx: &mut Ctx, x: f64, y: f64) -> f64 {
|
pub fn f64_rem(_ctx: &mut Ctx, x: f64, y: f64) -> f64 {
|
||||||
debug!("emscripten::f64-rem");
|
debug!("emscripten::f64-rem");
|
||||||
x % y
|
x % y
|
||||||
@ -37,3 +59,19 @@ pub fn f64_rem(_ctx: &mut Ctx, x: f64, y: f64) -> f64 {
|
|||||||
pub fn pow(_ctx: &mut Ctx, x: f64, y: f64) -> f64 {
|
pub fn pow(_ctx: &mut Ctx, x: f64, y: f64) -> f64 {
|
||||||
x.powf(y)
|
x.powf(y)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// emscripten: global.Math exp
|
||||||
|
pub fn exp(_ctx: &mut Ctx, value: f64) -> f64 {
|
||||||
|
value.exp()
|
||||||
|
}
|
||||||
|
|
||||||
|
// emscripten: global.Math log
|
||||||
|
pub fn log(_ctx: &mut Ctx, value: f64) -> f64 {
|
||||||
|
value.ln()
|
||||||
|
}
|
||||||
|
|
||||||
|
// emscripten: asm2wasm.f64-to-int
|
||||||
|
pub fn f64_to_int(_ctx: &mut Ctx, value: f64) -> i32 {
|
||||||
|
debug!("emscripten::f64_to_int {}", value);
|
||||||
|
value as i32
|
||||||
|
}
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
use super::process::abort_with_message;
|
use super::process::abort_with_message;
|
||||||
use libc::{c_int, c_void, memcpy, size_t};
|
use libc::{c_int, c_void, memcpy, size_t};
|
||||||
use wasmer_runtime_core::vm::Ctx;
|
use wasmer_runtime_core::{
|
||||||
|
units::{Pages, WASM_MAX_PAGES, WASM_MIN_PAGES, WASM_PAGE_SIZE},
|
||||||
|
vm::Ctx,
|
||||||
|
};
|
||||||
|
|
||||||
/// emscripten: _emscripten_memcpy_big
|
/// emscripten: _emscripten_memcpy_big
|
||||||
pub fn _emscripten_memcpy_big(ctx: &mut Ctx, dest: u32, src: u32, len: u32) -> u32 {
|
pub fn _emscripten_memcpy_big(ctx: &mut Ctx, dest: u32, src: u32, len: u32) -> u32 {
|
||||||
@ -19,23 +22,52 @@ pub fn _emscripten_memcpy_big(ctx: &mut Ctx, dest: u32, src: u32, len: u32) -> u
|
|||||||
/// emscripten: _emscripten_get_heap_size
|
/// emscripten: _emscripten_get_heap_size
|
||||||
pub fn _emscripten_get_heap_size(ctx: &mut Ctx) -> u32 {
|
pub fn _emscripten_get_heap_size(ctx: &mut Ctx) -> u32 {
|
||||||
debug!("emscripten::_emscripten_get_heap_size",);
|
debug!("emscripten::_emscripten_get_heap_size",);
|
||||||
// TODO: Fix implementation
|
ctx.memory(0).size().bytes().0 as u32
|
||||||
16_777_216
|
}
|
||||||
|
|
||||||
|
// From emscripten implementation
|
||||||
|
fn align_up(mut val: usize, multiple: usize) -> usize {
|
||||||
|
if val % multiple > 0 {
|
||||||
|
val += multiple - val % multiple;
|
||||||
|
}
|
||||||
|
val
|
||||||
}
|
}
|
||||||
|
|
||||||
/// emscripten: _emscripten_resize_heap
|
/// emscripten: _emscripten_resize_heap
|
||||||
|
/// Note: this function only allows growing the size of heap
|
||||||
pub fn _emscripten_resize_heap(ctx: &mut Ctx, requested_size: u32) -> u32 {
|
pub fn _emscripten_resize_heap(ctx: &mut Ctx, requested_size: u32) -> u32 {
|
||||||
debug!("emscripten::_emscripten_resize_heap {}", requested_size);
|
debug!("emscripten::_emscripten_resize_heap {}", requested_size);
|
||||||
// TODO: Fix implementation
|
let current_memory_pages = ctx.memory(0).size();
|
||||||
|
let current_memory = current_memory_pages.bytes().0 as u32;
|
||||||
|
|
||||||
|
// implementation from emscripten
|
||||||
|
let mut new_size = usize::max(current_memory as usize, WASM_MIN_PAGES * WASM_PAGE_SIZE);
|
||||||
|
while new_size < requested_size as usize {
|
||||||
|
if new_size <= 0x2000_0000 {
|
||||||
|
new_size = align_up(new_size * 2, WASM_PAGE_SIZE);
|
||||||
|
} else {
|
||||||
|
new_size = usize::min(
|
||||||
|
align_up((3 * new_size + 0x8000_0000) / 4, WASM_PAGE_SIZE),
|
||||||
|
WASM_PAGE_SIZE * WASM_MAX_PAGES,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let amount_to_grow = (new_size - current_memory as usize) / WASM_PAGE_SIZE;
|
||||||
|
if let Ok(_pages_allocated) = ctx.memory(0).grow(Pages(amount_to_grow as u32)) {
|
||||||
|
debug!("{} pages allocated", _pages_allocated.0);
|
||||||
|
1
|
||||||
|
} else {
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// emscripten: getTotalMemory
|
/// emscripten: getTotalMemory
|
||||||
pub fn get_total_memory(_ctx: &mut Ctx) -> u32 {
|
pub fn get_total_memory(_ctx: &mut Ctx) -> u32 {
|
||||||
debug!("emscripten::get_total_memory");
|
debug!("emscripten::get_total_memory");
|
||||||
// instance.memories[0].current_pages()
|
// instance.memories[0].current_pages()
|
||||||
// TODO: Fix implementation
|
// TODO: Fix implementation
|
||||||
16_777_216
|
_ctx.memory(0).size().bytes().0 as u32
|
||||||
}
|
}
|
||||||
|
|
||||||
/// emscripten: enlargeMemory
|
/// emscripten: enlargeMemory
|
||||||
@ -47,8 +79,11 @@ pub fn enlarge_memory(_ctx: &mut Ctx) -> u32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// emscripten: abortOnCannotGrowMemory
|
/// emscripten: abortOnCannotGrowMemory
|
||||||
pub fn abort_on_cannot_grow_memory(ctx: &mut Ctx, requested_size: u32) -> u32 {
|
pub fn abort_on_cannot_grow_memory(ctx: &mut Ctx, _requested_size: u32) -> u32 {
|
||||||
debug!("emscripten::abort_on_cannot_grow_memory {}", requested_size);
|
debug!(
|
||||||
|
"emscripten::abort_on_cannot_grow_memory {}",
|
||||||
|
_requested_size
|
||||||
|
);
|
||||||
abort_with_message(ctx, "Cannot enlarge memory arrays!");
|
abort_with_message(ctx, "Cannot enlarge memory arrays!");
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
@ -1,67 +0,0 @@
|
|||||||
use super::process::abort_with_message;
|
|
||||||
use wasmer_runtime_core::vm::Ctx;
|
|
||||||
|
|
||||||
pub fn nullfunc_i(ctx: &mut Ctx, x: u32) {
|
|
||||||
debug!("emscripten::nullfunc_i {}", x);
|
|
||||||
abort_with_message(ctx, "Invalid function pointer called with signature 'i'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)");
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn nullfunc_ii(ctx: &mut Ctx, x: u32) {
|
|
||||||
debug!("emscripten::nullfunc_ii {}", x);
|
|
||||||
abort_with_message(ctx, "Invalid function pointer called with signature 'ii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)");
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn nullfunc_iii(ctx: &mut Ctx, x: u32) {
|
|
||||||
debug!("emscripten::nullfunc_iii {}", x);
|
|
||||||
abort_with_message(ctx, "Invalid function pointer called with signature 'iii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)");
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn nullfunc_iiii(ctx: &mut Ctx, x: u32) {
|
|
||||||
debug!("emscripten::nullfunc_iiii {}", x);
|
|
||||||
abort_with_message(ctx, "Invalid function pointer called with signature 'iiii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)");
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn nullfunc_iiiii(ctx: &mut Ctx, x: u32) {
|
|
||||||
debug!("emscripten::nullfunc_iiiii {}", x);
|
|
||||||
abort_with_message(ctx, "Invalid function pointer called with signature 'iiiii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)");
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn nullfunc_iiiiii(ctx: &mut Ctx, x: u32) {
|
|
||||||
debug!("emscripten::nullfunc_iiiiii {}", x);
|
|
||||||
abort_with_message(ctx, "Invalid function pointer called with signature 'iiiiii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)");
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn nullfunc_v(ctx: &mut Ctx, x: u32) {
|
|
||||||
debug!("emscripten::nullfunc_v {}", x);
|
|
||||||
abort_with_message(ctx, "Invalid function pointer called with signature 'v'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)");
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn nullfunc_vi(ctx: &mut Ctx, x: u32) {
|
|
||||||
debug!("emscripten::nullfunc_vi {}", x);
|
|
||||||
abort_with_message(ctx, "Invalid function pointer called with signature 'vi'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)");
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn nullfunc_vii(ctx: &mut Ctx, x: u32) {
|
|
||||||
debug!("emscripten::nullfunc_vii {}", x);
|
|
||||||
abort_with_message(ctx, "Invalid function pointer called with signature 'vii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)");
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn nullfunc_viii(ctx: &mut Ctx, x: u32) {
|
|
||||||
debug!("emscripten::nullfunc_viii {}", x);
|
|
||||||
abort_with_message(ctx, "Invalid function pointer called with signature 'viii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)");
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn nullfunc_viiii(ctx: &mut Ctx, x: u32) {
|
|
||||||
debug!("emscripten::nullfunc_viiii {}", x);
|
|
||||||
abort_with_message(ctx, "Invalid function pointer called with signature 'viiii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)");
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn nullfunc_viiiii(ctx: &mut Ctx, _x: u32) {
|
|
||||||
debug!("emscripten::nullfunc_viiiii");
|
|
||||||
abort_with_message(ctx, "Invalid function pointer called with signature 'viiiii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)");
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn nullfunc_viiiiii(ctx: &mut Ctx, _x: u32) {
|
|
||||||
debug!("emscripten::nullfunc_viiiiii");
|
|
||||||
abort_with_message(ctx, "Invalid function pointer called with signature 'viiiiii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)");
|
|
||||||
}
|
|
@ -1,10 +1,9 @@
|
|||||||
use libc::{abort, c_char, c_int, exit, EAGAIN};
|
use libc::{abort, c_char, c_int, exit, EAGAIN};
|
||||||
|
|
||||||
#[cfg(not(target_os = "windows"))]
|
#[cfg(not(target_os = "windows"))]
|
||||||
use libc::pid_t;
|
type PidT = libc::pid_t;
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
type pid_t = c_int;
|
type PidT = c_int;
|
||||||
|
|
||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
use wasmer_runtime_core::vm::Ctx;
|
use wasmer_runtime_core::vm::Ctx;
|
||||||
@ -22,7 +21,7 @@ pub fn _abort(_ctx: &mut Ctx) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn _fork(_ctx: &mut Ctx) -> pid_t {
|
pub fn _fork(_ctx: &mut Ctx) -> PidT {
|
||||||
debug!("emscripten::_fork");
|
debug!("emscripten::_fork");
|
||||||
// unsafe {
|
// unsafe {
|
||||||
// fork()
|
// fork()
|
||||||
@ -98,7 +97,7 @@ pub fn _sem_wait(_ctx: &mut Ctx, _one: i32) -> i32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::cast_ptr_alignment)]
|
#[allow(clippy::cast_ptr_alignment)]
|
||||||
pub fn _getgrent(ctx: &mut Ctx) -> c_int {
|
pub fn _getgrent(_ctx: &mut Ctx) -> c_int {
|
||||||
debug!("emscripten::_getgrent");
|
debug!("emscripten::_getgrent");
|
||||||
-1
|
-1
|
||||||
}
|
}
|
||||||
@ -122,6 +121,11 @@ pub fn _usleep(_ctx: &mut Ctx, _one: i32) -> i32 {
|
|||||||
-1
|
-1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn _nanosleep(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
||||||
|
debug!("emscripten::_nanosleep");
|
||||||
|
-1
|
||||||
|
}
|
||||||
|
|
||||||
pub fn _utimes(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
pub fn _utimes(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
||||||
debug!("emscripten::_utimes");
|
debug!("emscripten::_utimes");
|
||||||
-1
|
-1
|
||||||
@ -146,6 +150,11 @@ pub fn _llvm_trap(ctx: &mut Ctx) {
|
|||||||
abort_with_message(ctx, "abort!");
|
abort_with_message(ctx, "abort!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn _llvm_eh_typeid_for(_ctx: &mut Ctx, _type_info_addr: u32) -> i32 {
|
||||||
|
debug!("emscripten::_llvm_eh_typeid_for");
|
||||||
|
-1
|
||||||
|
}
|
||||||
|
|
||||||
pub fn _system(_ctx: &mut Ctx, _one: i32) -> c_int {
|
pub fn _system(_ctx: &mut Ctx, _one: i32) -> c_int {
|
||||||
debug!("emscripten::_system");
|
debug!("emscripten::_system");
|
||||||
// TODO: May need to change this Em impl to a working version
|
// TODO: May need to change this Em impl to a working version
|
||||||
|
@ -11,8 +11,8 @@ pub fn _sigemptyset(ctx: &mut Ctx, set: u32) -> i32 {
|
|||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn _sigaction(_ctx: &mut Ctx, signum: u32, act: u32, oldact: u32) -> i32 {
|
pub fn _sigaction(_ctx: &mut Ctx, _signum: u32, _act: u32, _oldact: u32) -> i32 {
|
||||||
debug!("emscripten::_sigaction {}, {}, {}", signum, act, oldact);
|
debug!("emscripten::_sigaction {}, {}, {}", _signum, _act, _oldact);
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,7 +36,7 @@ pub fn _sigprocmask(_ctx: &mut Ctx, _one: i32, _two: i32, _three: i32) -> i32 {
|
|||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn _signal(_ctx: &mut Ctx, sig: u32, _two: i32) -> i32 {
|
pub fn _signal(_ctx: &mut Ctx, _sig: u32, _two: i32) -> i32 {
|
||||||
debug!("emscripten::_signal ({})", sig);
|
debug!("emscripten::_signal ({})", _sig);
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ pub struct StdioCapturer {
|
|||||||
use libc::{STDERR_FILENO, STDOUT_FILENO};
|
use libc::{STDERR_FILENO, STDOUT_FILENO};
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
const STDIN_FILENO: libc::c_int = 0;
|
const _STDIN_FILENO: libc::c_int = 0;
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
const STDOUT_FILENO: libc::c_int = 1;
|
const STDOUT_FILENO: libc::c_int = 1;
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
|
@ -28,6 +28,7 @@ use libc::{
|
|||||||
getpid,
|
getpid,
|
||||||
// iovec,
|
// iovec,
|
||||||
lseek,
|
lseek,
|
||||||
|
off_t,
|
||||||
// open,
|
// open,
|
||||||
read,
|
read,
|
||||||
// readv,
|
// readv,
|
||||||
@ -40,20 +41,15 @@ use libc::{
|
|||||||
use wasmer_runtime_core::vm::Ctx;
|
use wasmer_runtime_core::vm::Ctx;
|
||||||
|
|
||||||
use super::env;
|
use super::env;
|
||||||
|
use std::cell::Cell;
|
||||||
|
#[allow(unused_imports)]
|
||||||
|
use std::io::Error;
|
||||||
|
use std::mem;
|
||||||
use std::slice;
|
use std::slice;
|
||||||
// use std::sys::fd::FileDesc;
|
|
||||||
|
|
||||||
// Another conditional constant for name resolution: Macos et iOS use
|
|
||||||
// SO_NOSIGPIPE as a setsockopt flag to disable SIGPIPE emission on socket.
|
|
||||||
// Other platforms do otherwise.
|
|
||||||
#[cfg(target_os = "darwin")]
|
|
||||||
use libc::SO_NOSIGPIPE;
|
|
||||||
#[cfg(not(target_os = "darwin"))]
|
|
||||||
const SO_NOSIGPIPE: c_int = 0;
|
|
||||||
|
|
||||||
/// exit
|
/// exit
|
||||||
pub fn ___syscall1(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) {
|
pub fn ___syscall1(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) {
|
||||||
debug!("emscripten::___syscall1 (exit) {}", which);
|
debug!("emscripten::___syscall1 (exit) {}", _which);
|
||||||
let status: i32 = varargs.get(ctx);
|
let status: i32 = varargs.get(ctx);
|
||||||
unsafe {
|
unsafe {
|
||||||
exit(status);
|
exit(status);
|
||||||
@ -61,47 +57,47 @@ pub fn ___syscall1(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// read
|
/// read
|
||||||
pub fn ___syscall3(ctx: &mut Ctx, which: i32, mut varargs: VarArgs) -> i32 {
|
pub fn ___syscall3(ctx: &mut Ctx, _which: i32, mut varargs: VarArgs) -> i32 {
|
||||||
// -> ssize_t
|
// -> ssize_t
|
||||||
debug!("emscripten::___syscall3 (read) {}", which);
|
debug!("emscripten::___syscall3 (read) {}", _which);
|
||||||
let fd: i32 = varargs.get(ctx);
|
let fd: i32 = varargs.get(ctx);
|
||||||
let buf: u32 = varargs.get(ctx);
|
let buf: u32 = varargs.get(ctx);
|
||||||
let count = varargs.get(ctx);
|
let count: i32 = varargs.get(ctx);
|
||||||
debug!("=> fd: {}, buf_offset: {}, count: {}", fd, buf, count);
|
debug!("=> fd: {}, buf_offset: {}, count: {}", fd, buf, count);
|
||||||
let buf_addr = emscripten_memory_pointer!(ctx.memory(0), buf) as *mut c_void;
|
let buf_addr = emscripten_memory_pointer!(ctx.memory(0), buf) as *mut c_void;
|
||||||
let ret = unsafe { read(fd, buf_addr, count) };
|
let ret = unsafe { read(fd, buf_addr, count as _) };
|
||||||
debug!("=> ret: {}", ret);
|
debug!("=> ret: {}", ret);
|
||||||
ret as _
|
ret as _
|
||||||
}
|
}
|
||||||
|
|
||||||
/// write
|
/// write
|
||||||
pub fn ___syscall4(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
pub fn ___syscall4(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||||
debug!("emscripten::___syscall4 (write) {}", which);
|
debug!("emscripten::___syscall4 (write) {}", _which);
|
||||||
let fd: i32 = varargs.get(ctx);
|
let fd: i32 = varargs.get(ctx);
|
||||||
let buf: u32 = varargs.get(ctx);
|
let buf: u32 = varargs.get(ctx);
|
||||||
let count = varargs.get(ctx);
|
let count: i32 = varargs.get(ctx);
|
||||||
debug!("=> fd: {}, buf: {}, count: {}", fd, buf, count);
|
debug!("=> fd: {}, buf: {}, count: {}", fd, buf, count);
|
||||||
let buf_addr = emscripten_memory_pointer!(ctx.memory(0), buf) as *const c_void;
|
let buf_addr = emscripten_memory_pointer!(ctx.memory(0), buf) as *const c_void;
|
||||||
unsafe { write(fd, buf_addr, count) as i32 }
|
unsafe { write(fd, buf_addr, count as _) as i32 }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// close
|
/// close
|
||||||
pub fn ___syscall6(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
pub fn ___syscall6(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||||
debug!("emscripten::___syscall6 (close) {}", which);
|
debug!("emscripten::___syscall6 (close) {}", _which);
|
||||||
let fd: i32 = varargs.get(ctx);
|
let fd: i32 = varargs.get(ctx);
|
||||||
debug!("fd: {}", fd);
|
debug!("fd: {}", fd);
|
||||||
unsafe { close(fd) }
|
unsafe { close(fd) }
|
||||||
}
|
}
|
||||||
|
|
||||||
// chdir
|
// chdir
|
||||||
pub fn ___syscall12(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
pub fn ___syscall12(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||||
debug!("emscripten::___syscall12 (chdir) {}", which);
|
debug!("emscripten::___syscall12 (chdir) {}", _which);
|
||||||
let path_addr: i32 = varargs.get(ctx);
|
let path_addr: i32 = varargs.get(ctx);
|
||||||
unsafe {
|
unsafe {
|
||||||
let path_ptr = emscripten_memory_pointer!(ctx.memory(0), path_addr) as *const i8;
|
let path_ptr = emscripten_memory_pointer!(ctx.memory(0), path_addr) as *const i8;
|
||||||
let path = std::ffi::CStr::from_ptr(path_ptr);
|
let _path = std::ffi::CStr::from_ptr(path_ptr);
|
||||||
let ret = chdir(path_ptr);
|
let ret = chdir(path_ptr);
|
||||||
debug!("=> path: {:?}, ret: {}", path, ret);
|
debug!("=> path: {:?}, ret: {}", _path, ret);
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -135,14 +131,40 @@ pub fn ___syscall40(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int
|
|||||||
unsafe { rmdir(pathname_addr) }
|
unsafe { rmdir(pathname_addr) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// pipe
|
||||||
|
pub fn ___syscall42(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||||
|
debug!("emscripten::___syscall42 (pipe)");
|
||||||
|
// offset to a file descriptor, which contains a read end and write end, 2 integers
|
||||||
|
let fd_offset: u32 = varargs.get(ctx);
|
||||||
|
|
||||||
|
let emscripten_memory = ctx.memory(0);
|
||||||
|
|
||||||
|
// convert the file descriptor into a vec with two slots
|
||||||
|
let mut fd_vec: Vec<c_int> = emscripten_memory.view()[((fd_offset / 4) as usize)..]
|
||||||
|
.iter()
|
||||||
|
.map(|pipe_end: &Cell<c_int>| pipe_end.get())
|
||||||
|
.take(2)
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
// get it as a mutable pointer
|
||||||
|
let fd_ptr = fd_vec.as_mut_ptr();
|
||||||
|
|
||||||
|
// call pipe and store the pointers in this array
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
let result: c_int = unsafe { libc::pipe(fd_ptr, 2048, 0) };
|
||||||
|
#[cfg(not(target_os = "windows"))]
|
||||||
|
let result: c_int = unsafe { libc::pipe(fd_ptr) };
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
pub fn ___syscall60(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
pub fn ___syscall60(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
||||||
debug!("emscripten::___syscall60");
|
debug!("emscripten::___syscall60");
|
||||||
-1
|
-1
|
||||||
}
|
}
|
||||||
|
|
||||||
// dup2
|
// dup2
|
||||||
pub fn ___syscall63(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
pub fn ___syscall63(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||||
debug!("emscripten::___syscall63 (dup2) {}", which);
|
debug!("emscripten::___syscall63 (dup2) {}", _which);
|
||||||
|
|
||||||
let src: i32 = varargs.get(ctx);
|
let src: i32 = varargs.get(ctx);
|
||||||
let dst: i32 = varargs.get(ctx);
|
let dst: i32 = varargs.get(ctx);
|
||||||
@ -172,8 +194,8 @@ pub fn ___syscall85(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn ___syscall91(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
pub fn ___syscall91(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
||||||
debug!("emscripten::___syscall91");
|
debug!("emscripten::___syscall91 - stub");
|
||||||
-1
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ___syscall97(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
pub fn ___syscall97(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
||||||
@ -186,18 +208,39 @@ pub fn ___syscall110(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
|||||||
-1
|
-1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getcwd
|
||||||
|
pub fn ___syscall183(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> i32 {
|
||||||
|
debug!("emscripten::___syscall183");
|
||||||
|
use std::env;
|
||||||
|
let buf_offset: c_int = varargs.get(ctx);
|
||||||
|
let _size: c_int = varargs.get(ctx);
|
||||||
|
let path = env::current_dir();
|
||||||
|
let path_string = path.unwrap().display().to_string();
|
||||||
|
let len = path_string.len();
|
||||||
|
unsafe {
|
||||||
|
let pointer_to_buffer =
|
||||||
|
emscripten_memory_pointer!(ctx.memory(0), buf_offset) as *mut libc::c_char;
|
||||||
|
let slice = slice::from_raw_parts_mut(pointer_to_buffer, len.clone());
|
||||||
|
for (byte, loc) in path_string.bytes().zip(slice.iter_mut()) {
|
||||||
|
*loc = byte as _;
|
||||||
|
}
|
||||||
|
*pointer_to_buffer.add(len.clone()) = 0;
|
||||||
|
}
|
||||||
|
buf_offset
|
||||||
|
}
|
||||||
|
|
||||||
// mmap2
|
// mmap2
|
||||||
pub fn ___syscall192(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
pub fn ___syscall192(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||||
debug!("emscripten::___syscall192 (mmap2) {}", which);
|
debug!("emscripten::___syscall192 (mmap2) {}", _which);
|
||||||
let addr: i32 = varargs.get(ctx);
|
let _addr: i32 = varargs.get(ctx);
|
||||||
let len: u32 = varargs.get(ctx);
|
let len: u32 = varargs.get(ctx);
|
||||||
let prot: i32 = varargs.get(ctx);
|
let _prot: i32 = varargs.get(ctx);
|
||||||
let flags: i32 = varargs.get(ctx);
|
let _flags: i32 = varargs.get(ctx);
|
||||||
let fd: i32 = varargs.get(ctx);
|
let fd: i32 = varargs.get(ctx);
|
||||||
let off: i32 = varargs.get(ctx);
|
let _off: i32 = varargs.get(ctx);
|
||||||
debug!(
|
debug!(
|
||||||
"=> addr: {}, len: {}, prot: {}, flags: {}, fd: {}, off: {}",
|
"=> addr: {}, len: {}, prot: {}, flags: {}, fd: {}, off: {}",
|
||||||
addr, len, prot, flags, fd, off
|
_addr, len, _prot, _flags, fd, _off
|
||||||
);
|
);
|
||||||
|
|
||||||
if fd == -1 {
|
if fd == -1 {
|
||||||
@ -213,27 +256,39 @@ pub fn ___syscall192(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// lseek
|
/// lseek
|
||||||
pub fn ___syscall140(ctx: &mut Ctx, which: i32, mut varargs: VarArgs) -> i32 {
|
pub fn ___syscall140(ctx: &mut Ctx, _which: i32, mut varargs: VarArgs) -> i32 {
|
||||||
// -> c_int
|
// -> c_int
|
||||||
debug!("emscripten::___syscall140 (lseek) {}", which);
|
debug!("emscripten::___syscall140 (lseek) {}", _which);
|
||||||
let fd: i32 = varargs.get(ctx);
|
let fd: i32 = varargs.get(ctx);
|
||||||
let offset = varargs.get(ctx);
|
let _ = varargs.get::<i32>(ctx); // ignore high offset
|
||||||
|
let offset_low: i32 = varargs.get(ctx);
|
||||||
|
let result_ptr_value = varargs.get::<i32>(ctx);
|
||||||
let whence: i32 = varargs.get(ctx);
|
let whence: i32 = varargs.get(ctx);
|
||||||
debug!("=> fd: {}, offset: {}, whence = {}", fd, offset, whence);
|
let offset = offset_low as off_t;
|
||||||
unsafe { lseek(fd, offset, whence) as _ }
|
let ret = unsafe { lseek(fd, offset, whence) as i32 };
|
||||||
|
#[allow(clippy::cast_ptr_alignment)]
|
||||||
|
let result_ptr = emscripten_memory_pointer!(ctx.memory(0), result_ptr_value) as *mut i32;
|
||||||
|
assert_eq!(8, mem::align_of_val(&result_ptr));
|
||||||
|
unsafe {
|
||||||
|
*result_ptr = ret;
|
||||||
|
}
|
||||||
|
debug!(
|
||||||
|
"=> fd: {}, offset: {}, result_ptr: {}, whence: {} = {}\nlast os error: {}",
|
||||||
|
fd,
|
||||||
|
offset,
|
||||||
|
result_ptr_value,
|
||||||
|
whence,
|
||||||
|
0,
|
||||||
|
Error::last_os_error(),
|
||||||
|
);
|
||||||
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
/// readv
|
/// readv
|
||||||
#[allow(clippy::cast_ptr_alignment)]
|
#[allow(clippy::cast_ptr_alignment)]
|
||||||
pub fn ___syscall145(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> i32 {
|
pub fn ___syscall145(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> i32 {
|
||||||
// -> ssize_t
|
// -> ssize_t
|
||||||
debug!("emscripten::___syscall145 (readv) {}", which);
|
debug!("emscripten::___syscall145 (readv) {}", _which);
|
||||||
// let fd: i32 = varargs.get(ctx);
|
|
||||||
// let iov: u32 = varargs.get(ctx);
|
|
||||||
// let iovcnt: i32 = varargs.get(ctx);
|
|
||||||
// debug!("=> fd: {}, iov: {}, iovcnt = {}", fd, iov, iovcnt);
|
|
||||||
// let iov_addr = emscripten_memory_pointer!(ctx.memory(0), iov) as *mut iovec;
|
|
||||||
// unsafe { readv(fd, iov_addr, iovcnt) }
|
|
||||||
|
|
||||||
let fd: i32 = varargs.get(ctx);
|
let fd: i32 = varargs.get(ctx);
|
||||||
let iov: i32 = varargs.get(ctx);
|
let iov: i32 = varargs.get(ctx);
|
||||||
@ -268,9 +323,9 @@ pub fn ___syscall145(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> i32 {
|
|||||||
|
|
||||||
// writev
|
// writev
|
||||||
#[allow(clippy::cast_ptr_alignment)]
|
#[allow(clippy::cast_ptr_alignment)]
|
||||||
pub fn ___syscall146(ctx: &mut Ctx, which: i32, mut varargs: VarArgs) -> i32 {
|
pub fn ___syscall146(ctx: &mut Ctx, _which: i32, mut varargs: VarArgs) -> i32 {
|
||||||
// -> ssize_t
|
// -> ssize_t
|
||||||
debug!("emscripten::___syscall146 (writev) {}", which);
|
debug!("emscripten::___syscall146 (writev) {}", _which);
|
||||||
let fd: i32 = varargs.get(ctx);
|
let fd: i32 = varargs.get(ctx);
|
||||||
let iov: i32 = varargs.get(ctx);
|
let iov: i32 = varargs.get(ctx);
|
||||||
let iovcnt: i32 = varargs.get(ctx);
|
let iovcnt: i32 = varargs.get(ctx);
|
||||||
@ -312,24 +367,14 @@ pub fn ___syscall191(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
|||||||
-1
|
-1
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ___syscall194(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
|
||||||
debug!("emscripten::___syscall194 - stub");
|
|
||||||
-1
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn ___syscall196(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
|
||||||
debug!("emscripten::___syscall194 - stub");
|
|
||||||
-1
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn ___syscall199(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
pub fn ___syscall199(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
||||||
debug!("emscripten::___syscall199 - stub");
|
debug!("emscripten::___syscall199 - stub");
|
||||||
-1
|
-1
|
||||||
}
|
}
|
||||||
|
|
||||||
// stat64
|
// stat64
|
||||||
pub fn ___syscall195(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
pub fn ___syscall195(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||||
debug!("emscripten::___syscall195 (stat64) {}", which);
|
debug!("emscripten::___syscall195 (stat64) {}", _which);
|
||||||
let pathname: u32 = varargs.get(ctx);
|
let pathname: u32 = varargs.get(ctx);
|
||||||
let buf: u32 = varargs.get(ctx);
|
let buf: u32 = varargs.get(ctx);
|
||||||
|
|
||||||
@ -338,7 +383,14 @@ pub fn ___syscall195(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int
|
|||||||
unsafe {
|
unsafe {
|
||||||
let mut _stat: stat = std::mem::zeroed();
|
let mut _stat: stat = std::mem::zeroed();
|
||||||
let ret = stat(pathname_addr, &mut _stat);
|
let ret = stat(pathname_addr, &mut _stat);
|
||||||
debug!("ret: {}", ret);
|
debug!(
|
||||||
|
"=> pathname: {}, buf: {}, path: {} = {}\nlast os error: {}",
|
||||||
|
pathname,
|
||||||
|
buf,
|
||||||
|
std::ffi::CStr::from_ptr(pathname_addr).to_str().unwrap(),
|
||||||
|
ret,
|
||||||
|
Error::last_os_error()
|
||||||
|
);
|
||||||
if ret != 0 {
|
if ret != 0 {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -348,8 +400,8 @@ pub fn ___syscall195(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int
|
|||||||
}
|
}
|
||||||
|
|
||||||
// fstat64
|
// fstat64
|
||||||
pub fn ___syscall197(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
pub fn ___syscall197(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||||
debug!("emscripten::___syscall197 (fstat64) {}", which);
|
debug!("emscripten::___syscall197 (fstat64) {}", _which);
|
||||||
let fd: c_int = varargs.get(ctx);
|
let fd: c_int = varargs.get(ctx);
|
||||||
let buf: u32 = varargs.get(ctx);
|
let buf: u32 = varargs.get(ctx);
|
||||||
|
|
||||||
@ -372,13 +424,19 @@ pub fn ___syscall220(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// fcntl64
|
// fcntl64
|
||||||
pub fn ___syscall221(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
pub fn ___syscall221(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||||
debug!("emscripten::___syscall221 (fcntl64) {}", which);
|
debug!("emscripten::___syscall221 (fcntl64) {}", _which);
|
||||||
// fcntl64
|
// fcntl64
|
||||||
let _fd: i32 = varargs.get(ctx);
|
let _fd: i32 = varargs.get(ctx);
|
||||||
let cmd: u32 = varargs.get(ctx);
|
let cmd: u32 = varargs.get(ctx);
|
||||||
|
// (FAPPEND - 0x08
|
||||||
|
// |FASYNC - 0x40
|
||||||
|
// |FFSYNC - 0x80
|
||||||
|
// |FNONBLOCK - 0x04
|
||||||
|
debug!("=> fd: {}, cmd: {}", _fd, cmd);
|
||||||
match cmd {
|
match cmd {
|
||||||
2 => 0,
|
2 => 0,
|
||||||
|
13 | 14 => 0, // pretend file locking worked
|
||||||
_ => -1,
|
_ => -1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -409,8 +467,8 @@ pub fn ___syscall334(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// prlimit64
|
// prlimit64
|
||||||
pub fn ___syscall340(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
pub fn ___syscall340(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||||
debug!("emscripten::___syscall340 (prlimit64), {}", which);
|
debug!("emscripten::___syscall340 (prlimit64), {}", _which);
|
||||||
// NOTE: Doesn't really matter. Wasm modules cannot exceed WASM_PAGE_SIZE anyway.
|
// NOTE: Doesn't really matter. Wasm modules cannot exceed WASM_PAGE_SIZE anyway.
|
||||||
let _pid: i32 = varargs.get(ctx);
|
let _pid: i32 = varargs.get(ctx);
|
||||||
let _resource: i32 = varargs.get(ctx);
|
let _resource: i32 = varargs.get(ctx);
|
||||||
|
@ -3,27 +3,40 @@ use crate::varargs::VarArgs;
|
|||||||
/// Syscall list: https://www.cs.utexas.edu/~bismith/test/syscalls/syscalls32.html
|
/// Syscall list: https://www.cs.utexas.edu/~bismith/test/syscalls/syscalls32.html
|
||||||
use libc::{
|
use libc::{
|
||||||
accept,
|
accept,
|
||||||
|
access,
|
||||||
bind,
|
bind,
|
||||||
// ENOTTY,
|
|
||||||
c_char,
|
c_char,
|
||||||
c_int,
|
c_int,
|
||||||
c_void,
|
c_void,
|
||||||
chown,
|
chown,
|
||||||
// fcntl, setsockopt, getppid
|
// fcntl, setsockopt, getppid
|
||||||
connect,
|
connect,
|
||||||
|
dup,
|
||||||
dup2,
|
dup2,
|
||||||
|
fchmod,
|
||||||
|
fchown,
|
||||||
fcntl,
|
fcntl,
|
||||||
|
// ENOTTY,
|
||||||
|
fsync,
|
||||||
getgid,
|
getgid,
|
||||||
|
getgroups,
|
||||||
getpeername,
|
getpeername,
|
||||||
|
getrusage,
|
||||||
getsockname,
|
getsockname,
|
||||||
getsockopt,
|
getsockopt,
|
||||||
|
gid_t,
|
||||||
in_addr_t,
|
in_addr_t,
|
||||||
in_port_t,
|
in_port_t,
|
||||||
ioctl,
|
ioctl,
|
||||||
|
lchown,
|
||||||
|
link,
|
||||||
// iovec,
|
// iovec,
|
||||||
listen,
|
listen,
|
||||||
mkdir,
|
mkdir,
|
||||||
|
mode_t,
|
||||||
msghdr,
|
msghdr,
|
||||||
|
nice,
|
||||||
|
off_t,
|
||||||
open,
|
open,
|
||||||
pid_t,
|
pid_t,
|
||||||
pread,
|
pread,
|
||||||
@ -40,9 +53,13 @@ use libc::{
|
|||||||
sendto,
|
sendto,
|
||||||
setpgid,
|
setpgid,
|
||||||
setsockopt,
|
setsockopt,
|
||||||
|
size_t,
|
||||||
sockaddr,
|
sockaddr,
|
||||||
socket,
|
socket,
|
||||||
socklen_t,
|
socklen_t,
|
||||||
|
stat,
|
||||||
|
symlink,
|
||||||
|
uid_t,
|
||||||
uname,
|
uname,
|
||||||
utsname,
|
utsname,
|
||||||
EINVAL,
|
EINVAL,
|
||||||
@ -57,6 +74,9 @@ use libc::{
|
|||||||
};
|
};
|
||||||
use wasmer_runtime_core::vm::Ctx;
|
use wasmer_runtime_core::vm::Ctx;
|
||||||
|
|
||||||
|
use crate::utils;
|
||||||
|
#[allow(unused_imports)]
|
||||||
|
use std::io::Error;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
// Linking to functions that are not provided by rust libc
|
// Linking to functions that are not provided by rust libc
|
||||||
@ -64,10 +84,13 @@ use std::mem;
|
|||||||
#[link(name = "c")]
|
#[link(name = "c")]
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn wait4(pid: pid_t, status: *mut c_int, options: c_int, rusage: *mut rusage) -> pid_t;
|
pub fn wait4(pid: pid_t, status: *mut c_int, options: c_int, rusage: *mut rusage) -> pid_t;
|
||||||
|
pub fn madvise(addr: *mut c_void, len: size_t, advice: c_int) -> c_int;
|
||||||
|
pub fn fdatasync(fd: c_int) -> c_int;
|
||||||
|
pub fn lstat64(path: *const c_char, buf: *mut c_void) -> c_int;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(target_os = "macos"))]
|
#[cfg(not(target_os = "macos"))]
|
||||||
use libc::wait4;
|
use libc::{fallocate, fdatasync, ftruncate64, lstat, madvise, wait4};
|
||||||
|
|
||||||
// Another conditional constant for name resolution: Macos et iOS use
|
// Another conditional constant for name resolution: Macos et iOS use
|
||||||
// SO_NOSIGPIPE as a setsockopt flag to disable SIGPIPE emission on socket.
|
// SO_NOSIGPIPE as a setsockopt flag to disable SIGPIPE emission on socket.
|
||||||
@ -78,24 +101,125 @@ use libc::SO_NOSIGPIPE;
|
|||||||
const SO_NOSIGPIPE: c_int = 0;
|
const SO_NOSIGPIPE: c_int = 0;
|
||||||
|
|
||||||
/// open
|
/// open
|
||||||
pub fn ___syscall5(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
pub fn ___syscall5(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||||
debug!("emscripten::___syscall5 (open) {}", which);
|
debug!("emscripten::___syscall5 (open) {}", _which);
|
||||||
let pathname: u32 = varargs.get(ctx);
|
let pathname: u32 = varargs.get(ctx);
|
||||||
let flags: i32 = varargs.get(ctx);
|
let flags: i32 = varargs.get(ctx);
|
||||||
let mode: u32 = varargs.get(ctx);
|
let mode: u32 = varargs.get(ctx);
|
||||||
let pathname_addr = emscripten_memory_pointer!(ctx.memory(0), pathname) as *const i8;
|
let pathname_addr = emscripten_memory_pointer!(ctx.memory(0), pathname) as *const i8;
|
||||||
let path_str = unsafe { std::ffi::CStr::from_ptr(pathname_addr).to_str().unwrap() };
|
let _path_str = unsafe { std::ffi::CStr::from_ptr(pathname_addr).to_str().unwrap() };
|
||||||
let fd = unsafe { open(pathname_addr, flags, mode) };
|
let fd = unsafe { open(pathname_addr, flags, mode) };
|
||||||
debug!(
|
debug!(
|
||||||
"=> pathname: {}, flags: {}, mode: {} = fd: {}\npath: {}",
|
"=> pathname: {}, flags: {}, mode: {} = fd: {}\npath: {}\nlast os error: {}",
|
||||||
pathname, flags, mode, fd, path_str
|
pathname,
|
||||||
|
flags,
|
||||||
|
mode,
|
||||||
|
fd,
|
||||||
|
_path_str,
|
||||||
|
Error::last_os_error(),
|
||||||
);
|
);
|
||||||
fd
|
fd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// link
|
||||||
|
pub fn ___syscall9(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||||
|
debug!("emscripten::___syscall9 (link) {}", _which);
|
||||||
|
|
||||||
|
let oldname: c_int = varargs.get(ctx);
|
||||||
|
let newname: c_int = varargs.get(ctx);
|
||||||
|
let oldname_ptr = emscripten_memory_pointer!(ctx.memory(0), oldname) as *const i8;
|
||||||
|
let newname_ptr = emscripten_memory_pointer!(ctx.memory(0), newname) as *const i8;
|
||||||
|
let result = unsafe { link(oldname_ptr, newname_ptr) };
|
||||||
|
debug!(
|
||||||
|
"=> oldname: {}, newname: {}, result: {}",
|
||||||
|
unsafe { std::ffi::CStr::from_ptr(oldname_ptr).to_str().unwrap() },
|
||||||
|
unsafe { std::ffi::CStr::from_ptr(newname_ptr).to_str().unwrap() },
|
||||||
|
result,
|
||||||
|
);
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
/// getrusage
|
||||||
|
pub fn ___syscall77(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||||
|
debug!("emscripten::___syscall77 (getrusage) {}", _which);
|
||||||
|
|
||||||
|
let resource: c_int = varargs.get(ctx);
|
||||||
|
let rusage_ptr: c_int = varargs.get(ctx);
|
||||||
|
#[allow(clippy::cast_ptr_alignment)]
|
||||||
|
let rusage = emscripten_memory_pointer!(ctx.memory(0), rusage_ptr) as *mut rusage;
|
||||||
|
assert_eq!(8, mem::align_of_val(&rusage));
|
||||||
|
unsafe { getrusage(resource, rusage) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// symlink
|
||||||
|
pub fn ___syscall83(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||||
|
debug!("emscripten::___syscall83 (symlink) {}", _which);
|
||||||
|
|
||||||
|
let path1_ptr: c_int = varargs.get(ctx);
|
||||||
|
let path2_ptr: c_int = varargs.get(ctx);
|
||||||
|
let path1 = emscripten_memory_pointer!(ctx.memory(0), path1_ptr) as *mut i8;
|
||||||
|
let path2 = emscripten_memory_pointer!(ctx.memory(0), path2_ptr) as *mut i8;
|
||||||
|
let result = unsafe { symlink(path1, path2) };
|
||||||
|
debug!(
|
||||||
|
"=> path1: {}, path2: {}, result: {}",
|
||||||
|
unsafe { std::ffi::CStr::from_ptr(path1).to_str().unwrap() },
|
||||||
|
unsafe { std::ffi::CStr::from_ptr(path2).to_str().unwrap() },
|
||||||
|
result,
|
||||||
|
);
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ftruncate64
|
||||||
|
pub fn ___syscall194(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||||
|
debug!("emscripten::___syscall194 (ftruncate64) {}", _which);
|
||||||
|
let _fd: c_int = varargs.get(ctx);
|
||||||
|
let _length: i64 = varargs.get(ctx);
|
||||||
|
#[cfg(not(target_os = "macos"))]
|
||||||
|
unsafe {
|
||||||
|
ftruncate64(_fd, _length)
|
||||||
|
}
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// lchown
|
||||||
|
pub fn ___syscall198(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||||
|
debug!("emscripten::___syscall198 (lchown) {}", _which);
|
||||||
|
let path: c_int = varargs.get(ctx);
|
||||||
|
let uid: uid_t = varargs.get(ctx);
|
||||||
|
let gid: gid_t = varargs.get(ctx);
|
||||||
|
let path_ptr = emscripten_memory_pointer!(ctx.memory(0), path) as *const i8;
|
||||||
|
let result = unsafe { lchown(path_ptr, uid, gid) };
|
||||||
|
debug!(
|
||||||
|
"=> path: {}, uid: {}, gid: {}, result: {}",
|
||||||
|
unsafe { std::ffi::CStr::from_ptr(path_ptr).to_str().unwrap() },
|
||||||
|
uid,
|
||||||
|
gid,
|
||||||
|
result,
|
||||||
|
);
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
/// getgroups
|
||||||
|
pub fn ___syscall205(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||||
|
debug!("emscripten::___syscall205 (getgroups) {}", _which);
|
||||||
|
let ngroups_max: c_int = varargs.get(ctx);
|
||||||
|
let groups: c_int = varargs.get(ctx);
|
||||||
|
|
||||||
|
#[allow(clippy::cast_ptr_alignment)]
|
||||||
|
let gid_ptr = emscripten_memory_pointer!(ctx.memory(0), groups) as *mut gid_t;
|
||||||
|
assert_eq!(4, mem::align_of_val(&gid_ptr));
|
||||||
|
let result = unsafe { getgroups(ngroups_max, gid_ptr) };
|
||||||
|
debug!(
|
||||||
|
"=> ngroups_max: {}, gid_ptr: {:?}, result: {}",
|
||||||
|
ngroups_max, gid_ptr, result,
|
||||||
|
);
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
// chown
|
// chown
|
||||||
pub fn ___syscall212(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
pub fn ___syscall212(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||||
debug!("emscripten::___syscall212 (chown) {}", which);
|
debug!("emscripten::___syscall212 (chown) {}", _which);
|
||||||
|
|
||||||
let pathname: u32 = varargs.get(ctx);
|
let pathname: u32 = varargs.get(ctx);
|
||||||
let owner: u32 = varargs.get(ctx);
|
let owner: u32 = varargs.get(ctx);
|
||||||
@ -106,15 +230,63 @@ pub fn ___syscall212(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int
|
|||||||
unsafe { chown(pathname_addr, owner, group) }
|
unsafe { chown(pathname_addr, owner, group) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// madvise
|
||||||
|
pub fn ___syscall219(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||||
|
debug!("emscripten::___syscall212 (chown) {}", _which);
|
||||||
|
|
||||||
|
let addr_ptr: c_int = varargs.get(ctx);
|
||||||
|
let len: usize = varargs.get(ctx);
|
||||||
|
let advice: c_int = varargs.get(ctx);
|
||||||
|
|
||||||
|
let addr = emscripten_memory_pointer!(ctx.memory(0), addr_ptr) as *mut c_void;
|
||||||
|
|
||||||
|
unsafe { madvise(addr, len, advice) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// access
|
||||||
|
pub fn ___syscall33(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||||
|
debug!("emscripten::___syscall33 (access) {}", _which);
|
||||||
|
let path_ptr: c_int = varargs.get(ctx);
|
||||||
|
let amode: c_int = varargs.get(ctx);
|
||||||
|
let path = emscripten_memory_pointer!(ctx.memory(0), path_ptr) as *const i8;
|
||||||
|
let result = unsafe { access(path, amode) };
|
||||||
|
debug!(
|
||||||
|
"=> path: {}, result: {}",
|
||||||
|
unsafe { std::ffi::CStr::from_ptr(path).to_str().unwrap() },
|
||||||
|
result
|
||||||
|
);
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
/// nice
|
||||||
|
pub fn ___syscall34(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||||
|
debug!("emscripten::___syscall34 (nice) {}", _which);
|
||||||
|
let inc_r: c_int = varargs.get(ctx);
|
||||||
|
unsafe { nice(inc_r) }
|
||||||
|
}
|
||||||
|
|
||||||
// mkdir
|
// mkdir
|
||||||
pub fn ___syscall39(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
pub fn ___syscall39(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||||
debug!("emscripten::___syscall39 (mkdir) {}", which);
|
debug!("emscripten::___syscall39 (mkdir) {}", _which);
|
||||||
let pathname: u32 = varargs.get(ctx);
|
let pathname: u32 = varargs.get(ctx);
|
||||||
let mode: u32 = varargs.get(ctx);
|
let mode: u32 = varargs.get(ctx);
|
||||||
let pathname_addr = emscripten_memory_pointer!(ctx.memory(0), pathname) as *const i8;
|
let pathname_addr = emscripten_memory_pointer!(ctx.memory(0), pathname) as *const i8;
|
||||||
unsafe { mkdir(pathname_addr, mode as _) }
|
unsafe { mkdir(pathname_addr, mode as _) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// dup
|
||||||
|
pub fn ___syscall41(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||||
|
debug!("emscripten::___syscall41 (dup) {}", _which);
|
||||||
|
let fd: c_int = varargs.get(ctx);
|
||||||
|
unsafe { dup(fd) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// getgid
|
||||||
|
pub fn ___syscall200(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
||||||
|
debug!("emscripten::___syscall200 (getgid)");
|
||||||
|
unsafe { getgid() as i32 }
|
||||||
|
}
|
||||||
|
|
||||||
// getgid
|
// getgid
|
||||||
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 (getgid)");
|
debug!("emscripten::___syscall201 (getgid)");
|
||||||
@ -134,6 +306,15 @@ pub fn ___syscall202(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// fchown
|
||||||
|
pub fn ___syscall207(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||||
|
debug!("emscripten::___syscall207 (fchown) {}", _which);
|
||||||
|
let fd: c_int = varargs.get(ctx);
|
||||||
|
let owner: uid_t = varargs.get(ctx);
|
||||||
|
let group: gid_t = varargs.get(ctx);
|
||||||
|
unsafe { fchown(fd, owner, group) }
|
||||||
|
}
|
||||||
|
|
||||||
/// dup3
|
/// dup3
|
||||||
pub fn ___syscall330(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> pid_t {
|
pub fn ___syscall330(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> pid_t {
|
||||||
// Implementation based on description at https://linux.die.net/man/2/dup3
|
// Implementation based on description at https://linux.die.net/man/2/dup3
|
||||||
@ -169,8 +350,8 @@ pub fn ___syscall330(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> pid_
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// ioctl
|
/// ioctl
|
||||||
pub fn ___syscall54(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
pub fn ___syscall54(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||||
debug!("emscripten::___syscall54 (ioctl) {}", which);
|
debug!("emscripten::___syscall54 (ioctl) {}", _which);
|
||||||
let fd: i32 = varargs.get(ctx);
|
let fd: i32 = varargs.get(ctx);
|
||||||
let request: u32 = varargs.get(ctx);
|
let request: u32 = varargs.get(ctx);
|
||||||
debug!("fd: {}, op: {}", fd, request);
|
debug!("fd: {}, op: {}", fd, request);
|
||||||
@ -212,8 +393,8 @@ pub fn ___syscall54(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int
|
|||||||
|
|
||||||
// socketcall
|
// socketcall
|
||||||
#[allow(clippy::cast_ptr_alignment)]
|
#[allow(clippy::cast_ptr_alignment)]
|
||||||
pub fn ___syscall102(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
pub fn ___syscall102(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||||
debug!("emscripten::___syscall102 (socketcall) {}", which);
|
debug!("emscripten::___syscall102 (socketcall) {}", _which);
|
||||||
let call: u32 = varargs.get(ctx);
|
let call: u32 = varargs.get(ctx);
|
||||||
let mut socket_varargs: VarArgs = varargs.get(ctx);
|
let mut socket_varargs: VarArgs = varargs.get(ctx);
|
||||||
|
|
||||||
@ -279,13 +460,11 @@ pub fn ___syscall102(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int
|
|||||||
let address = emscripten_memory_pointer!(ctx.memory(0), address) as *mut sockaddr;
|
let address = emscripten_memory_pointer!(ctx.memory(0), address) as *mut sockaddr;
|
||||||
|
|
||||||
// Debug received address
|
// Debug received address
|
||||||
unsafe {
|
let _proper_address = address as *const GuestSockaddrIn;
|
||||||
let proper_address = address as *const GuestSockaddrIn;
|
|
||||||
debug!(
|
debug!(
|
||||||
"=> address.sin_family: {:?}, address.sin_port: {:?}, address.sin_addr.s_addr: {:?}",
|
"=> address.sin_family: {:?}, address.sin_port: {:?}, address.sin_addr.s_addr: {:?}",
|
||||||
(*proper_address).sin_family, (*proper_address).sin_port, (*proper_address).sin_addr.s_addr
|
unsafe { (*_proper_address).sin_family }, unsafe { (*_proper_address).sin_port }, unsafe { (*_proper_address).sin_addr.s_addr }
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
let status = unsafe { bind(socket, address, address_len) };
|
let status = unsafe { bind(socket, address, address_len) };
|
||||||
// debug!("=> status: {}", status);
|
// debug!("=> status: {}", status);
|
||||||
@ -464,8 +643,8 @@ pub fn ___syscall102(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int
|
|||||||
}
|
}
|
||||||
|
|
||||||
// pread
|
// pread
|
||||||
pub fn ___syscall180(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
pub fn ___syscall180(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||||
debug!("emscripten::___syscall180 (pread) {}", which);
|
debug!("emscripten::___syscall180 (pread) {}", _which);
|
||||||
let fd: i32 = varargs.get(ctx);
|
let fd: i32 = varargs.get(ctx);
|
||||||
let buf: u32 = varargs.get(ctx);
|
let buf: u32 = varargs.get(ctx);
|
||||||
let count: u32 = varargs.get(ctx);
|
let count: u32 = varargs.get(ctx);
|
||||||
@ -481,8 +660,8 @@ pub fn ___syscall180(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int
|
|||||||
}
|
}
|
||||||
|
|
||||||
// pwrite
|
// pwrite
|
||||||
pub fn ___syscall181(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
pub fn ___syscall181(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||||
debug!("emscripten::___syscall181 (pwrite) {}", which);
|
debug!("emscripten::___syscall181 (pwrite) {}", _which);
|
||||||
let fd: i32 = varargs.get(ctx);
|
let fd: i32 = varargs.get(ctx);
|
||||||
let buf: u32 = varargs.get(ctx);
|
let buf: u32 = varargs.get(ctx);
|
||||||
let count: u32 = varargs.get(ctx);
|
let count: u32 = varargs.get(ctx);
|
||||||
@ -501,6 +680,14 @@ pub fn ___syscall181(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int
|
|||||||
status
|
status
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// fchmod
|
||||||
|
pub fn ___syscall94(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||||
|
debug!("emscripten::___syscall118 (fchmod) {}", _which);
|
||||||
|
let fd: c_int = varargs.get(ctx);
|
||||||
|
let mode: mode_t = varargs.get(ctx);
|
||||||
|
unsafe { fchmod(fd, mode) }
|
||||||
|
}
|
||||||
|
|
||||||
/// wait4
|
/// wait4
|
||||||
#[allow(clippy::cast_ptr_alignment)]
|
#[allow(clippy::cast_ptr_alignment)]
|
||||||
pub fn ___syscall114(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> pid_t {
|
pub fn ___syscall114(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> pid_t {
|
||||||
@ -510,6 +697,7 @@ pub fn ___syscall114(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> pid_
|
|||||||
let options: c_int = varargs.get(ctx);
|
let options: c_int = varargs.get(ctx);
|
||||||
let rusage: u32 = varargs.get(ctx);
|
let rusage: u32 = varargs.get(ctx);
|
||||||
let status_addr = emscripten_memory_pointer!(ctx.memory(0), status) as *mut c_int;
|
let status_addr = emscripten_memory_pointer!(ctx.memory(0), status) as *mut c_int;
|
||||||
|
|
||||||
let rusage_addr = emscripten_memory_pointer!(ctx.memory(0), rusage) as *mut rusage;
|
let rusage_addr = emscripten_memory_pointer!(ctx.memory(0), rusage) as *mut rusage;
|
||||||
let res = unsafe { wait4(pid, status_addr, options, rusage_addr) };
|
let res = unsafe { wait4(pid, status_addr, options, rusage_addr) };
|
||||||
debug!(
|
debug!(
|
||||||
@ -519,10 +707,17 @@ pub fn ___syscall114(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> pid_
|
|||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// fsync
|
||||||
|
pub fn ___syscall118(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||||
|
debug!("emscripten::___syscall118 (fsync) {}", _which);
|
||||||
|
let fd: c_int = varargs.get(ctx);
|
||||||
|
unsafe { fsync(fd) }
|
||||||
|
}
|
||||||
|
|
||||||
// select
|
// select
|
||||||
#[allow(clippy::cast_ptr_alignment)]
|
#[allow(clippy::cast_ptr_alignment)]
|
||||||
pub fn ___syscall142(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
pub fn ___syscall142(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||||
debug!("emscripten::___syscall142 (newselect) {}", which);
|
debug!("emscripten::___syscall142 (newselect) {}", _which);
|
||||||
|
|
||||||
let nfds: i32 = varargs.get(ctx);
|
let nfds: i32 = varargs.get(ctx);
|
||||||
let readfds: u32 = varargs.get(ctx);
|
let readfds: u32 = varargs.get(ctx);
|
||||||
@ -539,9 +734,18 @@ pub fn ___syscall142(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int
|
|||||||
unsafe { select(nfds, readfds_ptr, writefds_ptr, 0 as _, 0 as _) }
|
unsafe { select(nfds, readfds_ptr, writefds_ptr, 0 as _, 0 as _) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// fdatasync
|
||||||
|
pub fn ___syscall148(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||||
|
debug!("emscripten::___syscall148 (fdatasync) {}", _which);
|
||||||
|
|
||||||
|
let fd: i32 = varargs.get(ctx);
|
||||||
|
|
||||||
|
unsafe { fdatasync(fd) }
|
||||||
|
}
|
||||||
|
|
||||||
// setpgid
|
// setpgid
|
||||||
pub fn ___syscall57(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
pub fn ___syscall57(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||||
debug!("emscripten::___syscall57 (setpgid) {}", which);
|
debug!("emscripten::___syscall57 (setpgid) {}", _which);
|
||||||
let pid: i32 = varargs.get(ctx);
|
let pid: i32 = varargs.get(ctx);
|
||||||
let pgid: i32 = varargs.get(ctx);
|
let pgid: i32 = varargs.get(ctx);
|
||||||
unsafe { setpgid(pid, pgid) }
|
unsafe { setpgid(pid, pgid) }
|
||||||
@ -549,10 +753,55 @@ pub fn ___syscall57(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int
|
|||||||
|
|
||||||
/// uname
|
/// uname
|
||||||
// NOTE: Wondering if we should return custom utsname, like Emscripten.
|
// NOTE: Wondering if we should return custom utsname, like Emscripten.
|
||||||
pub fn ___syscall122(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
pub fn ___syscall122(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||||
debug!("emscripten::___syscall122 (uname) {}", which);
|
debug!("emscripten::___syscall122 (uname) {}", _which);
|
||||||
let buf: u32 = varargs.get(ctx);
|
let buf: u32 = varargs.get(ctx);
|
||||||
debug!("=> buf: {}", buf);
|
debug!("=> buf: {}", buf);
|
||||||
let buf_addr = emscripten_memory_pointer!(ctx.memory(0), buf) as *mut utsname;
|
let buf_addr = emscripten_memory_pointer!(ctx.memory(0), buf) as *mut utsname;
|
||||||
unsafe { uname(buf_addr) }
|
unsafe { uname(buf_addr) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// lstat64
|
||||||
|
pub fn ___syscall196(ctx: &mut Ctx, _which: i32, mut varargs: VarArgs) -> i32 {
|
||||||
|
debug!("emscripten::___syscall196 (lstat64) {}", _which);
|
||||||
|
let path_ptr: c_int = varargs.get(ctx);
|
||||||
|
let buf_ptr: u32 = varargs.get(ctx);
|
||||||
|
let path = emscripten_memory_pointer!(ctx.memory(0), path_ptr) as *const i8;
|
||||||
|
unsafe {
|
||||||
|
let mut stat: stat = std::mem::zeroed();
|
||||||
|
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
|
let stat_ptr = &mut stat as *mut stat as *mut c_void;
|
||||||
|
#[cfg(not(target_os = "macos"))]
|
||||||
|
let stat_ptr = &mut stat as *mut stat;
|
||||||
|
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
|
let ret = lstat64(path, stat_ptr);
|
||||||
|
#[cfg(not(target_os = "macos"))]
|
||||||
|
let ret = lstat(path, stat_ptr);
|
||||||
|
|
||||||
|
debug!("ret: {}", ret);
|
||||||
|
if ret != 0 {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
utils::copy_stat_into_wasm(ctx, buf_ptr, &stat);
|
||||||
|
}
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
|
/// fallocate
|
||||||
|
pub fn ___syscall324(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||||
|
debug!("emscripten::___syscall324 (fallocate) {}", _which);
|
||||||
|
let _fd: c_int = varargs.get(ctx);
|
||||||
|
let _mode: c_int = varargs.get(ctx);
|
||||||
|
let _offset: off_t = varargs.get(ctx);
|
||||||
|
let _len: off_t = varargs.get(ctx);
|
||||||
|
#[cfg(not(target_os = "macos"))]
|
||||||
|
unsafe {
|
||||||
|
fallocate(_fd, _mode, _offset, _len)
|
||||||
|
}
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
|
{
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,22 +1,23 @@
|
|||||||
use crate::utils::copy_cstr_into_wasm;
|
use crate::utils::copy_cstr_into_wasm;
|
||||||
use crate::utils::read_string_from_wasm;
|
|
||||||
use crate::varargs::VarArgs;
|
use crate::varargs::VarArgs;
|
||||||
use libc::mkdir;
|
use libc::mkdir;
|
||||||
use libc::open;
|
use libc::open;
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::ffi::CStr;
|
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::os::raw::c_int;
|
use std::os::raw::c_int;
|
||||||
use wasmer_runtime_core::vm::Ctx;
|
use wasmer_runtime_core::vm::Ctx;
|
||||||
|
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
type pid_t = c_int;
|
type pid_t = c_int;
|
||||||
|
|
||||||
/// open
|
/// open
|
||||||
pub fn ___syscall5(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
pub fn ___syscall5(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
||||||
debug!("emscripten::___syscall5 (open) {}", which);
|
debug!("emscripten::___syscall5 (open) {}", which);
|
||||||
|
#[cfg(not(feature = "debug"))]
|
||||||
|
let _ = which;
|
||||||
let pathname: u32 = varargs.get(ctx);
|
let pathname: u32 = varargs.get(ctx);
|
||||||
let flags: i32 = varargs.get(ctx);
|
let flags: i32 = varargs.get(ctx);
|
||||||
let mode: u32 = varargs.get(ctx);
|
let mode: u32 = varargs.get(ctx);
|
||||||
@ -34,15 +35,15 @@ pub fn ___syscall5(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
|||||||
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 random_bytes = rand::thread_rng().gen::<[u8; 32]>();
|
||||||
urandom_file.write_all(&random_bytes);
|
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) };
|
||||||
let raw_pointer_to_urandom_file =
|
let raw_pointer_to_urandom_file =
|
||||||
emscripten_memory_pointer!(ctx.memory(0), urandom_file_offset) as *const i8;
|
emscripten_memory_pointer!(ctx.memory(0), urandom_file_offset) as *const i8;
|
||||||
let fd = unsafe { open(raw_pointer_to_urandom_file, flags, mode) };
|
let fd = unsafe { open(raw_pointer_to_urandom_file, flags, mode) };
|
||||||
debug!(
|
debug!(
|
||||||
"=> pathname: {}, flags: {}, mode: {} = fd: {}\npath: {}",
|
"=> pathname: {}, flags: {}, mode: {} = fd: {}",
|
||||||
pathname, flags, mode, fd, s
|
pathname, flags, mode, fd
|
||||||
);
|
);
|
||||||
fd
|
fd
|
||||||
}
|
}
|
||||||
@ -57,21 +58,78 @@ pub fn ___syscall5(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// link
|
||||||
|
pub fn ___syscall9(_ctx: &mut Ctx, _which: c_int, mut _varargs: VarArgs) -> c_int {
|
||||||
|
debug!("emscripten::___syscall9 (link) {}", _which);
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ftruncate64
|
||||||
|
pub fn ___syscall194(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
||||||
|
debug!("emscripten::___syscall194 - stub");
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
// chown
|
// chown
|
||||||
pub fn ___syscall212(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
pub fn ___syscall212(_ctx: &mut Ctx, which: c_int, mut _varargs: VarArgs) -> c_int {
|
||||||
debug!("emscripten::___syscall212 (chown) {}", which);
|
debug!("emscripten::___syscall212 (chown) {}", which);
|
||||||
|
#[cfg(not(feature = "debug"))]
|
||||||
|
let _ = which;
|
||||||
-1
|
-1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// access
|
||||||
|
pub fn ___syscall33(_ctx: &mut Ctx, _which: c_int, mut _varargs: VarArgs) -> c_int {
|
||||||
|
debug!("emscripten::___syscall33 (access) {}", _which);
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// nice
|
||||||
|
pub fn ___syscall34(_ctx: &mut Ctx, _which: c_int, mut _varargs: VarArgs) -> c_int {
|
||||||
|
debug!("emscripten::___syscall34 (nice) {}", _which);
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
// mkdir
|
// mkdir
|
||||||
pub fn ___syscall39(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
pub fn ___syscall39(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
||||||
debug!("emscripten::___syscall39 (mkdir) {}", which);
|
debug!("emscripten::___syscall39 (mkdir) {}", which);
|
||||||
|
#[cfg(not(feature = "debug"))]
|
||||||
|
let _ = which;
|
||||||
let pathname: u32 = varargs.get(ctx);
|
let pathname: u32 = varargs.get(ctx);
|
||||||
let mode: u32 = varargs.get(ctx);
|
|
||||||
let pathname_addr = emscripten_memory_pointer!(ctx.memory(0), pathname) as *const i8;
|
let pathname_addr = emscripten_memory_pointer!(ctx.memory(0), pathname) as *const i8;
|
||||||
unsafe { mkdir(pathname_addr) }
|
unsafe { mkdir(pathname_addr) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// dup
|
||||||
|
pub fn ___syscall41(_ctx: &mut Ctx, _which: c_int, _varargs: VarArgs) -> c_int {
|
||||||
|
debug!("emscripten::___syscall41 (dup) {}", _which);
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// getrusage
|
||||||
|
pub fn ___syscall77(_ctx: &mut Ctx, _which: c_int, _varargs: VarArgs) -> c_int {
|
||||||
|
debug!("emscripten::___syscall77 (getrusage) {}", _which);
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// symlink
|
||||||
|
pub fn ___syscall83(_ctx: &mut Ctx, _which: c_int, _varargs: VarArgs) -> c_int {
|
||||||
|
debug!("emscripten::___syscall83 (symlink) {}", _which);
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// lchown
|
||||||
|
pub fn ___syscall198(_ctx: &mut Ctx, _which: c_int, _varargs: VarArgs) -> c_int {
|
||||||
|
debug!("emscripten::___syscall198 (lchown) {}", _which);
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// getgid
|
||||||
|
pub fn ___syscall200(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
||||||
|
debug!("emscripten::___syscall200 (getgid)");
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
// getgid
|
// getgid
|
||||||
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 (getgid)");
|
debug!("emscripten::___syscall201 (getgid)");
|
||||||
@ -85,60 +143,122 @@ pub fn ___syscall202(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
|||||||
-1
|
-1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// getgroups
|
||||||
|
pub fn ___syscall205(_ctx: &mut Ctx, _which: c_int, _varargs: VarArgs) -> c_int {
|
||||||
|
debug!("emscripten::___syscall205 (getgroups) {}", _which);
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// madvise
|
||||||
|
pub fn ___syscall219(_ctx: &mut Ctx, _which: c_int, _varargs: VarArgs) -> c_int {
|
||||||
|
debug!("emscripten::___syscall212 (chown) {}", _which);
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
/// dup3
|
/// dup3
|
||||||
pub fn ___syscall330(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> pid_t {
|
pub fn ___syscall330(_ctx: &mut Ctx, _which: c_int, mut _varargs: VarArgs) -> pid_t {
|
||||||
debug!("emscripten::___syscall330 (dup3)");
|
debug!("emscripten::___syscall330 (dup3)");
|
||||||
-1
|
-1
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ioctl
|
/// ioctl
|
||||||
pub fn ___syscall54(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
pub fn ___syscall54(_ctx: &mut Ctx, which: c_int, mut _varargs: VarArgs) -> c_int {
|
||||||
debug!("emscripten::___syscall54 (ioctl) {}", which);
|
debug!("emscripten::___syscall54 (ioctl) {}", which);
|
||||||
|
#[cfg(not(feature = "debug"))]
|
||||||
|
let _ = which;
|
||||||
-1
|
-1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// fchmod
|
||||||
|
pub fn ___syscall94(_ctx: &mut Ctx, _which: c_int, _varargs: VarArgs) -> c_int {
|
||||||
|
debug!("emscripten::___syscall118 (fchmod) {}", _which);
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
// socketcall
|
// socketcall
|
||||||
#[allow(clippy::cast_ptr_alignment)]
|
#[allow(clippy::cast_ptr_alignment)]
|
||||||
pub fn ___syscall102(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
pub fn ___syscall102(_ctx: &mut Ctx, which: c_int, mut _varargs: VarArgs) -> c_int {
|
||||||
debug!("emscripten::___syscall102 (socketcall) {}", which);
|
debug!("emscripten::___syscall102 (socketcall) {}", which);
|
||||||
|
#[cfg(not(feature = "debug"))]
|
||||||
|
let _ = which;
|
||||||
-1
|
-1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// fsync
|
||||||
|
pub fn ___syscall118(_ctx: &mut Ctx, _which: c_int, _varargs: VarArgs) -> c_int {
|
||||||
|
debug!("emscripten::___syscall118 (fsync) {}", _which);
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
// pread
|
// pread
|
||||||
pub fn ___syscall180(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
pub fn ___syscall180(_ctx: &mut Ctx, which: c_int, mut _varargs: VarArgs) -> c_int {
|
||||||
debug!("emscripten::___syscall180 (pread) {}", which);
|
debug!("emscripten::___syscall180 (pread) {}", which);
|
||||||
|
#[cfg(not(feature = "debug"))]
|
||||||
|
let _ = which;
|
||||||
-1
|
-1
|
||||||
}
|
}
|
||||||
|
|
||||||
// pwrite
|
// pwrite
|
||||||
pub fn ___syscall181(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
pub fn ___syscall181(_ctx: &mut Ctx, which: c_int, mut _varargs: VarArgs) -> c_int {
|
||||||
debug!("emscripten::___syscall181 (pwrite) {}", which);
|
debug!("emscripten::___syscall181 (pwrite) {}", which);
|
||||||
|
#[cfg(not(feature = "debug"))]
|
||||||
|
let _ = which;
|
||||||
-1
|
-1
|
||||||
}
|
}
|
||||||
|
|
||||||
/// wait4
|
/// wait4
|
||||||
#[allow(clippy::cast_ptr_alignment)]
|
#[allow(clippy::cast_ptr_alignment)]
|
||||||
pub fn ___syscall114(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> pid_t {
|
pub fn ___syscall114(_ctx: &mut Ctx, _which: c_int, mut _varargs: VarArgs) -> pid_t {
|
||||||
debug!("emscripten::___syscall114 (wait4)");
|
debug!("emscripten::___syscall114 (wait4)");
|
||||||
-1
|
-1
|
||||||
}
|
}
|
||||||
|
|
||||||
// select
|
// select
|
||||||
#[allow(clippy::cast_ptr_alignment)]
|
#[allow(clippy::cast_ptr_alignment)]
|
||||||
pub fn ___syscall142(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
pub fn ___syscall142(_ctx: &mut Ctx, which: c_int, mut _varargs: VarArgs) -> c_int {
|
||||||
debug!("emscripten::___syscall142 (newselect) {}", which);
|
debug!("emscripten::___syscall142 (newselect) {}", which);
|
||||||
|
#[cfg(not(feature = "debug"))]
|
||||||
|
let _ = which;
|
||||||
-1
|
-1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// fdatasync
|
||||||
|
pub fn ___syscall148(_ctx: &mut Ctx, _which: c_int, _varargs: VarArgs) -> c_int {
|
||||||
|
debug!("emscripten::___syscall148 (fdatasync) {}", _which);
|
||||||
|
unimplemented!();
|
||||||
|
}
|
||||||
|
|
||||||
// setpgid
|
// setpgid
|
||||||
pub fn ___syscall57(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
pub fn ___syscall57(_ctx: &mut Ctx, which: c_int, mut _varargs: VarArgs) -> c_int {
|
||||||
debug!("emscripten::___syscall57 (setpgid) {}", which);
|
debug!("emscripten::___syscall57 (setpgid) {}", which);
|
||||||
|
#[cfg(not(feature = "debug"))]
|
||||||
|
let _ = which;
|
||||||
-1
|
-1
|
||||||
}
|
}
|
||||||
|
|
||||||
/// uname
|
/// uname
|
||||||
// NOTE: Wondering if we should return custom utsname, like Emscripten.
|
// NOTE: Wondering if we should return custom utsname, like Emscripten.
|
||||||
pub fn ___syscall122(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
pub fn ___syscall122(_ctx: &mut Ctx, which: c_int, mut _varargs: VarArgs) -> c_int {
|
||||||
debug!("emscripten::___syscall122 (uname) {}", which);
|
debug!("emscripten::___syscall122 (uname) {}", which);
|
||||||
|
#[cfg(not(feature = "debug"))]
|
||||||
|
let _ = which;
|
||||||
-1
|
-1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// lstat64
|
||||||
|
pub fn ___syscall196(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
||||||
|
debug!("emscripten::___syscall196 (lstat64) - stub");
|
||||||
|
-1
|
||||||
|
}
|
||||||
|
|
||||||
|
/// fchown
|
||||||
|
pub fn ___syscall207(_ctx: &mut Ctx, _which: c_int, _varargs: VarArgs) -> c_int {
|
||||||
|
debug!("emscripten::___syscall207 (fchown) {}", _which);
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// fallocate
|
||||||
|
pub fn ___syscall324(_ctx: &mut Ctx, _which: c_int, _varargs: VarArgs) -> c_int {
|
||||||
|
debug!("emscripten::___syscall324 (fallocate) {}", _which);
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
@ -10,6 +10,7 @@ use libc::{clockid_t, time as libc_time};
|
|||||||
use libc::time_t;
|
use libc::time_t;
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
type clockid_t = c_int;
|
type clockid_t = c_int;
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
@ -75,8 +76,10 @@ pub fn _clock_gettime(ctx: &mut Ctx, clk_id: clockid_t, tp: c_int) -> c_int {
|
|||||||
tv_nsec: i32,
|
tv_nsec: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(unreachable_patterns)]
|
||||||
let timespec = match clk_id {
|
let timespec = match clk_id {
|
||||||
CLOCK_REALTIME => time::get_time(),
|
CLOCK_REALTIME => time::get_time(),
|
||||||
|
|
||||||
CLOCK_MONOTONIC | CLOCK_MONOTONIC_COARSE => {
|
CLOCK_MONOTONIC | CLOCK_MONOTONIC_COARSE => {
|
||||||
let precise_ns = time::precise_time_ns();
|
let precise_ns = time::precise_time_ns();
|
||||||
time::Timespec::new(
|
time::Timespec::new(
|
||||||
@ -295,7 +298,7 @@ pub fn _time(ctx: &mut Ctx, time_p: u32) -> i32 {
|
|||||||
|
|
||||||
/// emscripten: _strftime
|
/// emscripten: _strftime
|
||||||
pub fn _strftime(
|
pub fn _strftime(
|
||||||
_ctx: &mut Ctx,
|
ctx: &mut Ctx,
|
||||||
s_ptr: c_int,
|
s_ptr: c_int,
|
||||||
maxsize: u32,
|
maxsize: u32,
|
||||||
format_ptr: c_int,
|
format_ptr: c_int,
|
||||||
@ -305,5 +308,67 @@ pub fn _strftime(
|
|||||||
"emscripten::_strftime {} {} {} {}",
|
"emscripten::_strftime {} {} {} {}",
|
||||||
s_ptr, maxsize, format_ptr, tm_ptr
|
s_ptr, maxsize, format_ptr, tm_ptr
|
||||||
);
|
);
|
||||||
0
|
|
||||||
|
#[allow(clippy::cast_ptr_alignment)]
|
||||||
|
let s = emscripten_memory_pointer!(ctx.memory(0), s_ptr) as *mut c_char;
|
||||||
|
#[allow(clippy::cast_ptr_alignment)]
|
||||||
|
let format = emscripten_memory_pointer!(ctx.memory(0), format_ptr) as *const c_char;
|
||||||
|
#[allow(clippy::cast_ptr_alignment)]
|
||||||
|
let tm = emscripten_memory_pointer!(ctx.memory(0), tm_ptr) as *const guest_tm;
|
||||||
|
|
||||||
|
let format_string = unsafe { std::ffi::CStr::from_ptr(format).to_str().unwrap() };
|
||||||
|
|
||||||
|
debug!("=> format_string: {:?}", format_string);
|
||||||
|
|
||||||
|
let tm = unsafe { &*tm };
|
||||||
|
|
||||||
|
let rust_tm = ::time::Tm {
|
||||||
|
tm_sec: tm.tm_sec,
|
||||||
|
tm_min: tm.tm_min,
|
||||||
|
tm_hour: tm.tm_hour,
|
||||||
|
tm_mday: tm.tm_mday,
|
||||||
|
tm_mon: tm.tm_mon,
|
||||||
|
tm_year: tm.tm_year,
|
||||||
|
tm_wday: tm.tm_wday,
|
||||||
|
tm_yday: tm.tm_yday,
|
||||||
|
tm_isdst: tm.tm_isdst,
|
||||||
|
tm_utcoff: tm.tm_gmtoff,
|
||||||
|
tm_nsec: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
let result_str = match ::time::strftime(format_string, &rust_tm) {
|
||||||
|
Ok(res_string) => res_string,
|
||||||
|
// TODO: maybe match on e in Err(e) and return different values if required
|
||||||
|
_ => return 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
// pad for null?
|
||||||
|
let bytes = result_str.chars().count();
|
||||||
|
if bytes as u32 > maxsize {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
// write output string
|
||||||
|
for (i, c) in result_str.chars().enumerate() {
|
||||||
|
unsafe { *s.add(i) = c as c_char };
|
||||||
|
}
|
||||||
|
// null terminate?
|
||||||
|
bytes as i32
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// emscripten: _strftime_l
|
||||||
|
pub fn _strftime_l(
|
||||||
|
ctx: &mut Ctx,
|
||||||
|
s_ptr: c_int,
|
||||||
|
maxsize: u32,
|
||||||
|
format_ptr: c_int,
|
||||||
|
tm_ptr: c_int,
|
||||||
|
_last: c_int,
|
||||||
|
) -> i32 {
|
||||||
|
debug!(
|
||||||
|
"emscripten::_strftime_l {} {} {} {}",
|
||||||
|
s_ptr, maxsize, format_ptr, tm_ptr
|
||||||
|
);
|
||||||
|
|
||||||
|
_strftime(ctx, s_ptr, maxsize, format_ptr, tm_ptr)
|
||||||
}
|
}
|
||||||
|
@ -90,8 +90,9 @@ pub unsafe fn allocate_cstr_on_stack<'a>(ctx: &'a mut Ctx, s: &str) -> (u32, &'a
|
|||||||
(offset, slice)
|
(offset, slice)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(target_os = "windows"))]
|
||||||
pub unsafe fn copy_terminated_array_of_cstrs(_ctx: &mut Ctx, cstrs: *mut *mut c_char) -> u32 {
|
pub unsafe fn copy_terminated_array_of_cstrs(_ctx: &mut Ctx, cstrs: *mut *mut c_char) -> u32 {
|
||||||
let total_num = {
|
let _total_num = {
|
||||||
let mut ptr = cstrs;
|
let mut ptr = cstrs;
|
||||||
let mut counter = 0;
|
let mut counter = 0;
|
||||||
while !(*ptr).is_null() {
|
while !(*ptr).is_null() {
|
||||||
@ -102,7 +103,7 @@ pub unsafe fn copy_terminated_array_of_cstrs(_ctx: &mut Ctx, cstrs: *mut *mut c_
|
|||||||
};
|
};
|
||||||
debug!(
|
debug!(
|
||||||
"emscripten::copy_terminated_array_of_cstrs::total_num: {}",
|
"emscripten::copy_terminated_array_of_cstrs::total_num: {}",
|
||||||
total_num
|
_total_num
|
||||||
);
|
);
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
@ -124,7 +125,7 @@ pub struct GuestStat {
|
|||||||
st_atime: u64,
|
st_atime: u64,
|
||||||
st_mtime: u64,
|
st_mtime: u64,
|
||||||
st_ctime: u64,
|
st_ctime: u64,
|
||||||
st_ino: u64,
|
st_ino: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::cast_ptr_alignment)]
|
#[allow(clippy::cast_ptr_alignment)]
|
||||||
@ -155,6 +156,7 @@ pub unsafe fn copy_stat_into_wasm(ctx: &mut Ctx, buf: u32, stat: &stat) {
|
|||||||
(*stat_ptr).st_ino = stat.st_ino as _;
|
(*stat_ptr).st_ino = stat.st_ino as _;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)] // it's used in `env/windows/mod.rs`.
|
||||||
pub fn read_string_from_wasm(memory: &Memory, offset: u32) -> String {
|
pub fn read_string_from_wasm(memory: &Memory, offset: u32) -> String {
|
||||||
let v: Vec<u8> = memory.view()[(offset as usize)..]
|
let v: Vec<u8> = memory.view()[(offset as usize)..]
|
||||||
.iter()
|
.iter()
|
||||||
@ -169,15 +171,40 @@ mod tests {
|
|||||||
use super::is_emscripten_module;
|
use super::is_emscripten_module;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use wabt::wat2wasm;
|
use wabt::wat2wasm;
|
||||||
use wasmer_clif_backend::CraneliftCompiler;
|
use wasmer_runtime_core::backend::Compiler;
|
||||||
use wasmer_runtime_core::compile_with;
|
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 = compile_with(&wasm_binary[..], &CraneliftCompiler::new())
|
let module =
|
||||||
.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));
|
||||||
}
|
}
|
||||||
@ -186,8 +213,8 @@ 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 = compile_with(&wasm_binary[..], &CraneliftCompiler::new())
|
let module =
|
||||||
.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));
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user