mirror of
https://github.com/fluencelabs/wasmer
synced 2024-12-12 22:05: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
|
||||
|
||||
# Do not build feature branch with open Pull Requests
|
||||
skip_branch_with_pr: true
|
||||
branches:
|
||||
only:
|
||||
- staging
|
||||
- trying
|
||||
|
||||
environment:
|
||||
matrix:
|
||||
@ -14,30 +16,51 @@ environment:
|
||||
|
||||
cache:
|
||||
- 'C:\Users\appveyor\.cargo'
|
||||
- target
|
||||
|
||||
install:
|
||||
- appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe
|
||||
- rustup-init.exe -yv --default-host %target%
|
||||
- set PATH=%PATH%;%USERPROFILE%\.cargo\bin
|
||||
# # Install LLVM
|
||||
# - mkdir C:\projects\deps
|
||||
# - cd C:\projects\deps
|
||||
# - appveyor DownloadFile http://prereleases.llvm.org/win-snapshots/LLVM-7.0.0-r336178-win64.exe -FileName llvm.exe
|
||||
# - 7z x llvm.exe -oC:\projects\deps\llvm
|
||||
# # - set "PATH=%PATH%;C:\projects\deps\llvm\bin"
|
||||
# - set "LLD_LINK=C:\projects\deps\llvm\bin\lld-link.exe"
|
||||
# - set "LLVM_SYS_70_PREFIX=C:\projects\deps\llvm"
|
||||
# - cd "%APPVEYOR_BUILD_FOLDER%"
|
||||
|
||||
# Install Rust
|
||||
# uncomment these lines if the cache is cleared, or if we must re-install rust for some reason
|
||||
# - appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe
|
||||
# - rustup-init.exe -yv --default-host %target%
|
||||
- set PATH=%PATH%;C:\\Libraries\\llvm-5.0.0\\bin;%USERPROFILE%\.cargo\bin
|
||||
- rustup default stable-%target%
|
||||
- rustup update
|
||||
- rustc -vV
|
||||
- cargo -vV
|
||||
|
||||
# Install InnoSetup
|
||||
- appveyor-retry appveyor DownloadFile https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/2017-08-22-is.exe
|
||||
- 2017-08-22-is.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /SP-
|
||||
- set PATH="C:\Program Files (x86)\Inno Setup 5";%PATH%
|
||||
# uncomment to RDP to appveyor
|
||||
# - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
||||
|
||||
build_script:
|
||||
- cargo build --verbose
|
||||
- cargo build --release --verbose
|
||||
|
||||
test_script:
|
||||
- set RUST_BACKTRACE=1
|
||||
- cd ./lib/spectests && cargo test -- --test-threads 1 && cd ../..
|
||||
- cargo test --manifest-path lib/spectests/Cargo.toml --features clif
|
||||
|
||||
before_deploy:
|
||||
- cd ./src/installer
|
||||
- iscc wasmer.iss
|
||||
- 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:
|
||||
- path: WasmerInstaller-%APPVEYOR_REPO_TAG_NAME%.exe
|
||||
name: WasmerInstaller.exe
|
||||
matrix:
|
||||
fast_finish: true
|
||||
|
||||
deploy:
|
||||
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
|
||||
jobs:
|
||||
changelog:
|
||||
docker:
|
||||
- image: docker:stable-git
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
command: ! git diff --exit-code CHANGELOG.md
|
||||
|
||||
# Job used for testing
|
||||
lint:
|
||||
docker:
|
||||
- image: circleci/rust:latest
|
||||
<<: *run_with_build_env_vars
|
||||
steps:
|
||||
- checkout
|
||||
- restore_cache:
|
||||
keys:
|
||||
- v6-lint-{{ arch }}-{{ checksum "Cargo.lock" }}
|
||||
- run:
|
||||
name: Install dependencies
|
||||
command: |
|
||||
sudo apt-get install -y cmake
|
||||
- v8-lint-{{ arch }}-{{ checksum "Cargo.lock" }}
|
||||
- v8-lint-{{ arch }}
|
||||
- <<: *run_install_dependencies
|
||||
- run:
|
||||
name: Install lint deps
|
||||
command: |
|
||||
git config --global --unset url."ssh://git@github.com".insteadOf || true
|
||||
rustup toolchain install nightly-2019-02-27
|
||||
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:
|
||||
name: Execute lints
|
||||
command: make lint
|
||||
command: |
|
||||
make lint
|
||||
- save_cache:
|
||||
paths:
|
||||
- /usr/local/cargo/registry
|
||||
- target/debug/.fingerprint
|
||||
- target/debug/build
|
||||
- target/debug/deps
|
||||
key: v6-lint-{{ arch }}-{{ checksum "Cargo.lock" }}
|
||||
key: v8-lint-{{ arch }}-{{ checksum "Cargo.lock" }}
|
||||
|
||||
test:
|
||||
docker:
|
||||
- image: circleci/rust:latest
|
||||
<<: *run_with_build_env_vars
|
||||
steps:
|
||||
- checkout
|
||||
- restore_cache:
|
||||
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:
|
||||
name: Install dependencies
|
||||
name: Tests
|
||||
command: make test
|
||||
- run:
|
||||
name: Emscripten Tests
|
||||
command: |
|
||||
sudo apt-get install -y cmake
|
||||
- run: make test
|
||||
- run: make integration-tests
|
||||
make test-emscripten-clif
|
||||
make test-emscripten-llvm
|
||||
- run:
|
||||
name: Integration Tests
|
||||
command: make integration-tests
|
||||
- save_cache:
|
||||
paths:
|
||||
- /usr/local/cargo/registry
|
||||
- target/debug/.fingerprint
|
||||
- target/debug/build
|
||||
- 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:
|
||||
macos:
|
||||
@ -58,7 +88,8 @@ jobs:
|
||||
- checkout
|
||||
- restore_cache:
|
||||
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:
|
||||
name: Install crate dependencies
|
||||
command: |
|
||||
@ -66,6 +97,9 @@ jobs:
|
||||
curl -O https://cmake.org/files/v3.4/cmake-3.4.1-Darwin-x86_64.tar.gz
|
||||
tar xf cmake-3.4.1-Darwin-x86_64.tar.gz
|
||||
export PATH="`pwd`/cmake-3.4.1-Darwin-x86_64/CMake.app/Contents/bin:$PATH"
|
||||
# Installing LLVM outside of brew
|
||||
curl -O https://releases.llvm.org/7.0.0/clang+llvm-7.0.0-x86_64-apple-darwin.tar.xz
|
||||
tar xf clang+llvm-7.0.0-x86_64-apple-darwin.tar.xz
|
||||
- run:
|
||||
name: Install Rust
|
||||
command: |
|
||||
@ -73,19 +107,32 @@ jobs:
|
||||
export PATH="$HOME/.cargo/bin:$PATH"
|
||||
cargo --version
|
||||
- run:
|
||||
name: Execute tests
|
||||
name: Tests
|
||||
command: |
|
||||
export PATH="$HOME/.cargo/bin:$PATH"
|
||||
export PATH="`pwd`/cmake-3.4.1-Darwin-x86_64/CMake.app/Contents/bin:$PATH"
|
||||
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
|
||||
- run:
|
||||
name: Execute integration tests
|
||||
name: Emscripten Tests
|
||||
command: |
|
||||
export PATH="$HOME/.cargo/bin:$PATH"
|
||||
export PATH="`pwd`/cmake-3.4.1-Darwin-x86_64/CMake.app/Contents/bin:$PATH"
|
||||
export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-apple-darwin/"
|
||||
# We increase the ulimit for fixing cargo unclosed files in mac
|
||||
ulimit -n 8000
|
||||
sudo sysctl -w kern.maxfiles=655360 kern.maxfilesperproc=327680
|
||||
make test-emscripten-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
|
||||
- save_cache:
|
||||
paths:
|
||||
@ -96,7 +143,7 @@ jobs:
|
||||
- target/release/.fingerprint
|
||||
- target/release/build
|
||||
- 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:
|
||||
docker:
|
||||
@ -105,24 +152,43 @@ jobs:
|
||||
- checkout
|
||||
- restore_cache:
|
||||
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:
|
||||
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
|
||||
# Use rust nightly (for singlepass, for now)
|
||||
- run: rustup default nightly-2019-04-11
|
||||
- run:
|
||||
name: Execute tests
|
||||
command: make test
|
||||
- run:
|
||||
name: Make release build
|
||||
name: Tests
|
||||
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
|
||||
VERSION=$(cargo pkgid | cut -d# -f2 | cut -d: -f2)
|
||||
# GIT_VERSION=$(git describe --exact-match --tags)
|
||||
echo "${VERSION}" >> artifacts/version
|
||||
echo "${CIRCLE_TAG}" >> artifacts/git_version
|
||||
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:
|
||||
root: .
|
||||
paths:
|
||||
@ -136,7 +202,7 @@ jobs:
|
||||
- target/release/.fingerprint
|
||||
- target/release/build
|
||||
- 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:
|
||||
macos:
|
||||
@ -145,7 +211,8 @@ jobs:
|
||||
- checkout
|
||||
- restore_cache:
|
||||
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:
|
||||
name: Install crate dependencies
|
||||
command: |
|
||||
@ -153,31 +220,54 @@ jobs:
|
||||
curl -O https://cmake.org/files/v3.4/cmake-3.4.1-Darwin-x86_64.tar.gz
|
||||
tar xf cmake-3.4.1-Darwin-x86_64.tar.gz
|
||||
export PATH="`pwd`/cmake-3.4.1-Darwin-x86_64/CMake.app/Contents/bin:$PATH"
|
||||
# Installing LLVM outside of brew
|
||||
curl -O https://releases.llvm.org/7.0.0/clang+llvm-7.0.0-x86_64-apple-darwin.tar.xz
|
||||
tar xf clang+llvm-7.0.0-x86_64-apple-darwin.tar.xz
|
||||
- run:
|
||||
name: Install Rust
|
||||
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"
|
||||
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:
|
||||
name: Execute tests
|
||||
name: Tests
|
||||
command: |
|
||||
export PATH="`pwd`/cmake-3.4.1-Darwin-x86_64/CMake.app/Contents/bin:$PATH"
|
||||
export PATH="$HOME/.cargo/bin:$PATH"
|
||||
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
|
||||
- run:
|
||||
name: Make release build
|
||||
name: Emscripten Tests
|
||||
command: |
|
||||
export PATH="`pwd`/cmake-3.4.1-Darwin-x86_64/CMake.app/Contents/bin:$PATH"
|
||||
export PATH="$HOME/.cargo/bin:$PATH"
|
||||
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
|
||||
make build-install
|
||||
cp ./wasmer.tar.gz ./artifacts/$(./binary-name.sh)
|
||||
# VERSION=$(cargo pkgid | cut -d# -f2 | cut -d: -f2)
|
||||
# echo "${VERSION}" >> artifacts/version
|
||||
cp ./target/release/wasmer ./artifacts/$(./binary-name.sh)
|
||||
- persist_to_workspace:
|
||||
root: .
|
||||
paths:
|
||||
@ -191,7 +281,7 @@ jobs:
|
||||
- target/release/.fingerprint
|
||||
- target/release/build
|
||||
- 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:
|
||||
docker:
|
||||
@ -200,20 +290,28 @@ jobs:
|
||||
- checkout
|
||||
- restore_cache:
|
||||
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:
|
||||
name: Install dependencies
|
||||
command: |
|
||||
sudo apt-get install -y cmake
|
||||
- run: rustup default nightly
|
||||
- run: make test
|
||||
curl -O https://releases.llvm.org/7.0.0/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz
|
||||
tar xf clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz
|
||||
- run: 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:
|
||||
paths:
|
||||
- /usr/local/cargo/registry
|
||||
- target/debug/.fingerprint
|
||||
- target/debug/build
|
||||
- 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:
|
||||
docker:
|
||||
@ -240,32 +338,57 @@ jobs:
|
||||
# echo "Versions don't match. Wasmer output version (wasmer --version) is ${VERSION} while Git tag is ${VERSION_TAG}"
|
||||
# exit 1
|
||||
#fi
|
||||
trigger-benchmark-build:
|
||||
docker:
|
||||
- image: circleci/rust:latest
|
||||
steps:
|
||||
- run:
|
||||
name: "Trigger Benchmark Build"
|
||||
command: |
|
||||
if [[ -z "${CIRCLE_API_USER_TOKEN}" ]]; then
|
||||
echo "CIRCLE_API_USER_TOKEN environment variable not set"
|
||||
exit 1
|
||||
else
|
||||
echo "Triggering benchmark build"
|
||||
curl -u ${CIRCLE_API_USER_TOKEN} \
|
||||
-d build_parameters[CIRCLE_JOB]=bench \
|
||||
https://circleci.com/api/v1.1/project/github/wasmerio/wasmer-bench/tree/master
|
||||
fi
|
||||
|
||||
workflows:
|
||||
version: 2
|
||||
main:
|
||||
jobs:
|
||||
- changelog
|
||||
- lint
|
||||
- test:
|
||||
filters:
|
||||
branches:
|
||||
ignore: master
|
||||
only:
|
||||
- trying
|
||||
- staging
|
||||
- test-macos:
|
||||
filters:
|
||||
branches:
|
||||
ignore: master
|
||||
only:
|
||||
- trying
|
||||
- staging
|
||||
- test-and-build:
|
||||
filters:
|
||||
branches:
|
||||
only: master
|
||||
only:
|
||||
- master
|
||||
- test-and-build-macos:
|
||||
filters:
|
||||
branches:
|
||||
only: master
|
||||
only:
|
||||
- master
|
||||
- test-rust-nightly:
|
||||
filters:
|
||||
branches:
|
||||
only: master
|
||||
only:
|
||||
- trying
|
||||
- staging
|
||||
- publish-github-release:
|
||||
requires:
|
||||
- lint
|
||||
@ -274,3 +397,10 @@ workflows:
|
||||
filters:
|
||||
branches:
|
||||
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
|
||||
.DS_Store
|
||||
.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]
|
||||
name = "wasmer"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0"
|
||||
authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"]
|
||||
edition = "2018"
|
||||
repository = "https://github.com/wasmerio/wasmer"
|
||||
@ -19,24 +19,33 @@ include = [
|
||||
]
|
||||
|
||||
[dependencies]
|
||||
errno = "0.2.4"
|
||||
structopt = "0.2.11"
|
||||
wabt = "0.7.2"
|
||||
hashbrown = "0.1.8"
|
||||
wasmer-clif-backend = { path = "lib/clif-backend" }
|
||||
wasmer-singlepass-backend = { path = "lib/singlepass-backend", optional = true }
|
||||
wasmer-runtime = { path = "lib/runtime" }
|
||||
wasmer-runtime-abi = { path = "lib/runtime-abi", optional = true }
|
||||
wasmer-runtime-core = { path = "lib/runtime-core" }
|
||||
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]
|
||||
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]
|
||||
wabt = "0.7.2"
|
||||
glob = "0.2.11"
|
||||
rustc_version = "0.2.3"
|
||||
|
||||
[features]
|
||||
default = ["fast-tests"]
|
||||
|
||||
debug = []
|
||||
default = ["fast-tests", "wasi"]
|
||||
debug = ["wasmer-clif-backend/debug", "wasmer-runtime-core/debug"]
|
||||
# This feature will allow cargo test to run much faster
|
||||
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
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
44
Makefile
44
Makefile
@ -12,14 +12,11 @@ spectests:
|
||||
emtests:
|
||||
WASM_EMSCRIPTEN_GENERATE_EMTESTS=1 cargo build -p wasmer-emscripten
|
||||
|
||||
capi:
|
||||
WASM_EMSCRIPTEN_GENERATE_C_API_HEADERS=1 cargo build --manifest-path lib/runtime-c-api/Cargo.toml --features generate-c-api-headers
|
||||
|
||||
# clean:
|
||||
# rm -rf artifacts
|
||||
|
||||
build:
|
||||
cargo build
|
||||
cargo build --features debug
|
||||
|
||||
install:
|
||||
cargo install --path .
|
||||
@ -31,22 +28,57 @@ integration-tests: release
|
||||
|
||||
lint:
|
||||
cargo fmt --all -- --check
|
||||
cargo clippy --all
|
||||
cargo +nightly-2019-02-27 clippy --all
|
||||
|
||||
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:
|
||||
# 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 --manifest-path lib/spectests/Cargo.toml --features clif
|
||||
cargo test --manifest-path lib/spectests/Cargo.toml --features llvm
|
||||
cargo build -p wasmer-runtime-c-api
|
||||
cargo test -p wasmer-runtime-c-api -- --nocapture
|
||||
|
||||
test-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:
|
||||
# If you are in OS-X, you will need mingw-w64 for cross compiling to windows
|
||||
# brew install mingw-w64
|
||||
cargo build --release
|
||||
|
||||
production-release:
|
||||
cargo build --release --features backend:singlepass,backend:llvm
|
||||
|
||||
debug-release:
|
||||
cargo build --release --features "debug"
|
||||
|
||||
|
36
README.md
36
README.md
@ -18,7 +18,7 @@
|
||||
|
||||
## 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:
|
||||
|
||||
@ -26,19 +26,29 @@ Install Wasmer with:
|
||||
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
|
||||
|
||||
Wasmer can execute both the standard binary format (`.wasm`) and the text
|
||||
format defined by the WebAssembly reference interpreter (`.wat`).
|
||||
|
||||
Once installed, you will be able to run any WebAssembly files (_including nginx and Lua!_):
|
||||
Once installed, you will be able to run any WebAssembly files (_including Lua, PHP, SQLite and nginx!_):
|
||||
|
||||
```sh
|
||||
# Run Lua
|
||||
wasmer run examples/lua.wasm
|
||||
|
||||
# Run PHP
|
||||
wasmer run examples/php.wasm
|
||||
|
||||
# Run SQLite
|
||||
wasmer run examples/sqlite.wasm
|
||||
|
||||
# Run nginx
|
||||
wasmer run examples/nginx/nginx.wasm -- -p examples/nginx -c nginx.conf
|
||||
```
|
||||
@ -70,6 +80,7 @@ Please select your operating system:
|
||||
|
||||
- [macOS](#macos)
|
||||
- [Debian-based Linuxes](#debian-based-linuxes)
|
||||
- [FreeBSD](#freebsd)
|
||||
- [Microsoft Windows](#windows-msvc)
|
||||
|
||||
#### macOS
|
||||
@ -92,18 +103,30 @@ sudo port install cmake
|
||||
sudo apt install cmake
|
||||
```
|
||||
|
||||
#### FreeBSD
|
||||
|
||||
```sh
|
||||
pkg install cmake
|
||||
```
|
||||
|
||||
#### Windows (MSVC)
|
||||
|
||||
Windows support is _highly experimental_. Only simple Wasm programs may be run, and no syscalls are allowed. This means
|
||||
nginx and Lua do not work on Windows. See [this issue](https://github.com/wasmerio/wasmer/issues/176) regarding Emscripten syscall polyfills for Windows.
|
||||
|
||||
1. Install [Python for Windows](https://www.python.org/downloads/release/python-2714/). The Windows x86-64 MSI installer is fine.
|
||||
1. Install [Visual Studio](https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/?sku=Community&rel=15)
|
||||
|
||||
2. Install [Rust for Windows](https://win.rustup.rs)
|
||||
|
||||
3. Install [Python for Windows](https://www.python.org/downloads/release/python-2714/). The Windows x86-64 MSI installer is fine.
|
||||
Make sure to enable "Add python.exe to Path" during installation.
|
||||
|
||||
2. Install [Git for Windows](https://git-scm.com/download/win). Allow it to add `git.exe` to your PATH (default
|
||||
4. Install [Git for Windows](https://git-scm.com/download/win). Allow it to add `git.exe` to your PATH (default
|
||||
settings for the installer are fine).
|
||||
|
||||
3. Install [CMake](https://cmake.org/download/). Ensure CMake is in your PATH.
|
||||
5. Install [CMake](https://cmake.org/download/). Ensure CMake is in your PATH.
|
||||
|
||||
6. Install [LLVM 7.0](https://prereleases.llvm.org/win-snapshots/LLVM-7.0.0-r336178-win64.exe)
|
||||
|
||||
## Building
|
||||
|
||||
@ -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 fast _(partially achieved)_
|
||||
- [ ] Support WASI _(in the works)_
|
||||
- [ ] Support Emscripten calls _(in the works)_
|
||||
- [ ] Support Rust ABI calls
|
||||
- [ ] Support Go ABI calls
|
||||
|
@ -23,8 +23,8 @@ initOS() {
|
||||
darwin) OS='darwin';;
|
||||
linux) OS='linux';;
|
||||
freebsd) OS='freebsd';;
|
||||
mingw*) OS='windows';;
|
||||
msys*) OS='windows';;
|
||||
# mingw*) OS='windows';;
|
||||
# msys*) OS='windows';;
|
||||
*) echo "OS ${OS} is not supported by this installation script"; exit 1;;
|
||||
esac
|
||||
}
|
||||
@ -34,11 +34,11 @@ initArch
|
||||
initOS
|
||||
|
||||
# determine install directory if required
|
||||
BINARY="wasmer-${OS}-${ARCH}"
|
||||
BINARY="wasmer-${OS}-${ARCH}.tar.gz"
|
||||
|
||||
# add .exe if on windows
|
||||
if [ "$OS" = "windows" ]; then
|
||||
BINARY="$BINARY.exe"
|
||||
fi
|
||||
# if [ "$OS" = "windows" ]; then
|
||||
# BINARY="$BINARY.exe"
|
||||
# fi
|
||||
|
||||
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"
|
||||
dim="\e[2m"
|
||||
|
||||
# Warning: Remove this on the public repo
|
||||
RELEASES_URL="https://github.com/wasmerio/wasmer/releases"
|
||||
|
||||
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"
|
||||
|
||||
# We create the wasmer.sh file
|
||||
echo "$SOURCE_STR" > "$HOME/.wasmer/wasmer.sh"
|
||||
printf "$SOURCE_STR" > "$HOME/.wasmer/wasmer.sh"
|
||||
|
||||
if [ -z "${WASMER_PROFILE-}" ] ; then
|
||||
printf "${red}Profile not found. Tried:\n* ${WASMER_PROFILE} (as defined in \$PROFILE)\n* ~/.bashrc\n* ~/.bash_profile\n* ~/.zshrc\n* ~/.profile.\n"
|
||||
@ -369,12 +370,12 @@ wasmer_download() {
|
||||
WASMER=INSTALL_DIRECTORY
|
||||
|
||||
# assemble expected release artifact name
|
||||
BINARY="wasmer-${OS}-${ARCH}"
|
||||
BINARY="wasmer-${OS}-${ARCH}.tar.gz"
|
||||
|
||||
# add .exe if on windows
|
||||
if [ "$OS" = "windows" ]; then
|
||||
BINARY="$BINARY.exe"
|
||||
fi
|
||||
# if [ "$OS" = "windows" ]; then
|
||||
# BINARY="$BINARY.exe"
|
||||
# fi
|
||||
|
||||
# if WASMER_RELEASE_TAG was not provided, assume latest
|
||||
if [ -z "$WASMER_RELEASE_TAG" ]; then
|
||||
@ -417,9 +418,6 @@ wasmer_download() {
|
||||
printf "\033[K\n\033[1A"
|
||||
# printf "\033[1A$cyan> Downloaded$reset\033[K\n"
|
||||
# echo "Setting executable permissions."
|
||||
chmod +x "$DOWNLOAD_FILE"
|
||||
|
||||
INSTALL_NAME="wasmer"
|
||||
|
||||
# windows not supported yet
|
||||
# if [ "$OS" = "windows" ]; then
|
||||
@ -428,8 +426,9 @@ wasmer_download() {
|
||||
|
||||
# echo "Moving executable to $INSTALL_DIRECTORY/$INSTALL_NAME"
|
||||
|
||||
mkdir -p $INSTALL_DIRECTORY/bin
|
||||
mv "$DOWNLOAD_FILE" "$INSTALL_DIRECTORY/bin/$INSTALL_NAME"
|
||||
mkdir -p $INSTALL_DIRECTORY
|
||||
# Untar the wasmer contents in the install directory
|
||||
tar -C $INSTALL_DIRECTORY -zxvf $DOWNLOAD_FILE
|
||||
}
|
||||
|
||||
wasmer_verify_or_quit() {
|
||||
|
@ -1,7 +1,6 @@
|
||||
#! /bin/bash
|
||||
|
||||
nohup ./target/release/wasmer run examples/lua.wasm &
|
||||
sleep 3s
|
||||
nohup ./target/release/wasmer run examples/lua.wasm --disable-cache -- -v
|
||||
|
||||
if grep "Lua 5.4.0 Copyright (C) 1994-2018 Lua.org, PUC-Rio" ./nohup.out
|
||||
then
|
||||
|
@ -1,22 +1,14 @@
|
||||
#! /bin/bash
|
||||
|
||||
nohup ./target/release/wasmer run examples/nginx/nginx.wasm -- -p integration_tests/nginx/ -c nginx.conf &
|
||||
sleep 3s
|
||||
nohup ./target/release/wasmer run examples/nginx/nginx.wasm --disable-cache -- -v
|
||||
|
||||
curl localhost:8080 > ./nginx.out
|
||||
|
||||
|
||||
if grep "wasmer" ./nginx.out
|
||||
if grep "nginx version: nginx/1.15.3" ./nohup.out
|
||||
then
|
||||
echo "nginx integration test succeeded"
|
||||
rm ./nohup.out
|
||||
rm ./nginx.out
|
||||
rm -rf ./integration_tests/nginx/*_temp
|
||||
exit 0
|
||||
else
|
||||
echo "nginx integration test failed"
|
||||
rm ./nohup.out
|
||||
rm ./nginx.out
|
||||
rm -rf ./integration_tests/nginx/*_temp
|
||||
exit -1
|
||||
fi
|
||||
|
@ -22,7 +22,8 @@ The integration builds on the Wasmer runtime and allow us to run WebAssembly fil
|
||||
|
||||
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? ✋_
|
||||
- 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
|
||||
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]
|
||||
name = "wasmer-clif-backend"
|
||||
version = "0.1.2"
|
||||
version = "0.3.0"
|
||||
description = "Wasmer runtime Cranelift compiler backend"
|
||||
license = "MIT"
|
||||
authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"]
|
||||
@ -8,17 +8,18 @@ repository = "https://github.com/wasmerio/wasmer"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
wasmer-runtime-core = { path = "../runtime-core", version = "0.1.2" }
|
||||
cranelift-native = "0.26.0"
|
||||
cranelift-codegen = "0.26.0"
|
||||
cranelift-entity = "0.26.0"
|
||||
cranelift-wasm = "0.26.0"
|
||||
wasmer-runtime-core = { path = "../runtime-core", version = "0.3.0" }
|
||||
cranelift-native = "0.30.0"
|
||||
cranelift-codegen = "0.30.0"
|
||||
cranelift-entity = "0.30.0"
|
||||
cranelift-wasm = "0.30.0"
|
||||
hashbrown = "0.1"
|
||||
target-lexicon = "0.2.0"
|
||||
target-lexicon = "0.3.0"
|
||||
wasmparser = "0.23.0"
|
||||
byteorder = "1"
|
||||
nix = "0.13.0"
|
||||
libc = "0.2.48"
|
||||
libc = "0.2.49"
|
||||
rayon = "1.0"
|
||||
|
||||
# Dependencies for caching.
|
||||
[dependencies.serde]
|
||||
@ -32,7 +33,7 @@ version = "0.0.7"
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
winapi = { version = "0.3", features = ["errhandlingapi", "minwindef", "minwinbase", "winnt"] }
|
||||
wasmer-win-exception-handler = { path = "../win-exception-handler", version = "0.0.1" }
|
||||
wasmer-win-exception-handler = { path = "../win-exception-handler", version = "0.3.0" }
|
||||
|
||||
[features]
|
||||
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 {
|
||||
fn generate_cache(
|
||||
&self,
|
||||
module: &ModuleInner,
|
||||
) -> Result<(Box<ModuleInfo>, Box<[u8]>, Memory), Error> {
|
||||
let info = Box::new(module.info.clone());
|
||||
|
||||
fn generate_cache(&self) -> Result<(Box<[u8]>, Memory), Error> {
|
||||
// Clone the memory to a new location. This could take a long time,
|
||||
// depending on the throughput of your memcpy implementation.
|
||||
let compiled_code = (*self.memory).clone();
|
||||
|
||||
Ok((
|
||||
info,
|
||||
self.backend_cache.into_backend_data()?.into_boxed_slice(),
|
||||
compiled_code,
|
||||
))
|
||||
|
@ -445,6 +445,12 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
||||
|
||||
pos.ins().symbol_value(ir::types::I64, sig_index_global)
|
||||
|
||||
// let dynamic_sigindices_array_ptr = pos.ins().load(
|
||||
// ptr_type,
|
||||
// mflags,
|
||||
|
||||
// )
|
||||
|
||||
// let expected_sig = pos.ins().iconst(ir::types::I32, sig_index.index() as i64);
|
||||
|
||||
// self.env.deduplicated[clif_sig_index]
|
||||
@ -477,9 +483,10 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
||||
call_args: &[ir::Value],
|
||||
) -> cranelift_wasm::WasmResult<ir::Inst> {
|
||||
let callee_index: FuncIndex = Converter(clif_callee_index).into();
|
||||
let ptr_type = self.pointer_type();
|
||||
|
||||
match callee_index.local_or_import(&self.env.module.info) {
|
||||
LocalOrImport::Local(_) => {
|
||||
LocalOrImport::Local(local_function_index) => {
|
||||
// this is an internal function
|
||||
let vmctx = pos
|
||||
.func
|
||||
@ -490,10 +497,28 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
||||
args.push(vmctx);
|
||||
args.extend(call_args.iter().cloned());
|
||||
|
||||
Ok(pos.ins().call(callee, &args))
|
||||
let sig_ref = pos.func.dfg.ext_funcs[callee].signature;
|
||||
let function_ptr = {
|
||||
let mflags = ir::MemFlags::trusted();
|
||||
|
||||
let function_array_ptr = pos.ins().load(
|
||||
ptr_type,
|
||||
mflags,
|
||||
vmctx,
|
||||
vm::Ctx::offset_local_functions() as i32,
|
||||
);
|
||||
|
||||
pos.ins().load(
|
||||
ptr_type,
|
||||
mflags,
|
||||
function_array_ptr,
|
||||
(local_function_index.index() as i32) * 8,
|
||||
)
|
||||
};
|
||||
|
||||
Ok(pos.ins().call_indirect(sig_ref, function_ptr, &args))
|
||||
}
|
||||
LocalOrImport::Import(imported_func_index) => {
|
||||
let ptr_type = self.pointer_type();
|
||||
// this is an imported function
|
||||
let vmctx = pos.func.create_global_value(ir::GlobalValueData::VMContext);
|
||||
|
||||
|
@ -16,7 +16,7 @@ use target_lexicon::Triple;
|
||||
|
||||
use wasmer_runtime_core::cache::{Artifact, Error as CacheError};
|
||||
use wasmer_runtime_core::{
|
||||
backend::{Compiler, Token},
|
||||
backend::{Compiler, CompilerConfig, Token},
|
||||
error::{CompileError, CompileResult},
|
||||
module::ModuleInner,
|
||||
};
|
||||
@ -24,6 +24,7 @@ use wasmer_runtime_core::{
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
extern crate rayon;
|
||||
extern crate serde;
|
||||
|
||||
use wasmparser::{self, WasmDecoder};
|
||||
@ -38,12 +39,17 @@ impl CraneliftCompiler {
|
||||
|
||||
impl Compiler for CraneliftCompiler {
|
||||
/// 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)?;
|
||||
|
||||
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 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::{
|
||||
backend::Backend,
|
||||
backend::{Backend, CompilerConfig},
|
||||
error::CompileResult,
|
||||
module::{ModuleInfo, ModuleInner, StringTable},
|
||||
structures::{Map, TypedIndex},
|
||||
@ -25,7 +25,7 @@ pub struct Module {
|
||||
}
|
||||
|
||||
impl Module {
|
||||
pub fn new(wasm: &[u8]) -> Self {
|
||||
pub fn new(compiler_config: &CompilerConfig) -> Self {
|
||||
Self {
|
||||
info: ModuleInfo {
|
||||
memories: Map::new(),
|
||||
@ -50,6 +50,9 @@ impl Module {
|
||||
|
||||
namespace_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(),
|
||||
)?;
|
||||
|
||||
let protected_caller = Caller::new(&self.info, handler_data, trampolines);
|
||||
|
||||
let cache_gen = Box::new(CacheGenerator::new(
|
||||
backend_cache,
|
||||
Arc::clone(&func_resolver.memory),
|
||||
));
|
||||
|
||||
let runnable_module = Caller::new(handler_data, trampolines, func_resolver);
|
||||
|
||||
Ok(ModuleInner {
|
||||
func_resolver: Box::new(func_resolver),
|
||||
protected_caller: Box::new(protected_caller),
|
||||
runnable_module: Box::new(runnable_module),
|
||||
cache_gen,
|
||||
|
||||
info: self.info,
|
||||
@ -100,16 +102,15 @@ impl Module {
|
||||
)
|
||||
.map_err(|e| CacheError::Unknown(format!("{:?}", e)))?;
|
||||
|
||||
let protected_caller = Caller::new(&info, handler_data, trampolines);
|
||||
|
||||
let cache_gen = Box::new(CacheGenerator::new(
|
||||
backend_cache,
|
||||
Arc::clone(&func_resolver.memory),
|
||||
));
|
||||
|
||||
let runnable_module = Caller::new(handler_data, trampolines, func_resolver);
|
||||
|
||||
Ok(ModuleInner {
|
||||
func_resolver: Box::new(func_resolver),
|
||||
protected_caller: Box::new(protected_caller),
|
||||
runnable_module: Box::new(runnable_module),
|
||||
cache_gen,
|
||||
|
||||
info,
|
||||
@ -148,8 +149,8 @@ convert_clif_to_runtime_index![
|
||||
(SignatureIndex: SigIndex),
|
||||
];
|
||||
|
||||
impl<'a> From<Converter<&'a ir::Signature>> for FuncSig {
|
||||
fn from(signature: Converter<&'a ir::Signature>) -> Self {
|
||||
impl From<Converter<ir::Signature>> for FuncSig {
|
||||
fn from(signature: Converter<ir::Signature>) -> Self {
|
||||
FuncSig::new(
|
||||
signature
|
||||
.0
|
||||
|
@ -4,7 +4,6 @@ use crate::{
|
||||
};
|
||||
use cranelift_codegen::{ir, isa};
|
||||
use cranelift_wasm::{self, translate_module, FuncTranslator, ModuleEnvironment};
|
||||
use std::sync::Arc;
|
||||
use wasmer_runtime_core::{
|
||||
error::{CompileError, CompileResult},
|
||||
module::{
|
||||
@ -51,6 +50,20 @@ impl<'module, 'isa> ModuleEnv<'module, 'isa> {
|
||||
|
||||
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> {
|
||||
@ -60,17 +73,9 @@ impl<'module, 'isa, 'data> ModuleEnvironment<'data> for ModuleEnv<'module, 'isa>
|
||||
}
|
||||
|
||||
/// Declares a function signature to the environment.
|
||||
fn declare_signature(&mut self, sig: &ir::Signature) {
|
||||
fn declare_signature(&mut self, sig: ir::Signature) {
|
||||
self.signatures.push(sig.clone());
|
||||
self.module
|
||||
.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()]
|
||||
self.module.info.signatures.push(Converter(sig).into());
|
||||
}
|
||||
|
||||
/// 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.
|
||||
fn declare_func_type(&mut self, clif_sig_index: cranelift_wasm::SignatureIndex) {
|
||||
// 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);
|
||||
}
|
||||
|
||||
/// 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.
|
||||
fn declare_global(&mut self, global: cranelift_wasm::Global) {
|
||||
let desc = GlobalDescriptor {
|
||||
@ -184,11 +175,6 @@ impl<'module, 'isa, 'data> ModuleEnvironment<'data> for ModuleEnv<'module, 'isa>
|
||||
self.globals.push(global);
|
||||
}
|
||||
|
||||
/// Return the global for the given global index.
|
||||
fn get_global(&self, global_index: cranelift_wasm::GlobalIndex) -> &cranelift_wasm::Global {
|
||||
&self.globals[Converter(global_index).into()]
|
||||
}
|
||||
|
||||
/// Declares a table to the environment.
|
||||
fn declare_table(&mut self, table: cranelift_wasm::Table) {
|
||||
use cranelift_wasm::TableElementType;
|
||||
@ -242,7 +228,7 @@ impl<'module, 'isa, 'data> ModuleEnvironment<'data> for ModuleEnv<'module, 'isa>
|
||||
table_index: cranelift_wasm::TableIndex,
|
||||
base: Option<cranelift_wasm::GlobalIndex>,
|
||||
offset: usize,
|
||||
elements: Vec<cranelift_wasm::FuncIndex>,
|
||||
elements: Box<[cranelift_wasm::FuncIndex]>,
|
||||
) {
|
||||
// Convert Cranelift GlobalIndex to wamser GlobalIndex
|
||||
// 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.
|
||||
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 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);
|
||||
|
||||
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")]
|
||||
{
|
||||
@ -534,7 +524,10 @@ impl<'module, 'isa, 'data> ModuleEnvironment<'data> for ModuleEnv<'module, 'isa>
|
||||
.special_param(ir::ArgumentPurpose::VMContext)
|
||||
.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]);
|
||||
|
||||
|
@ -224,6 +224,7 @@ pub enum TrapCode {
|
||||
IntegerDivisionByZero,
|
||||
BadConversionToInteger,
|
||||
Interrupt,
|
||||
UnreachableCodeReached,
|
||||
User(u16),
|
||||
}
|
||||
|
||||
@ -297,6 +298,7 @@ impl binemit::TrapSink for LocalTrapSink {
|
||||
ir::TrapCode::IntegerDivisionByZero => TrapCode::IntegerDivisionByZero,
|
||||
ir::TrapCode::BadConversionToInteger => TrapCode::BadConversionToInteger,
|
||||
ir::TrapCode::Interrupt => TrapCode::Interrupt,
|
||||
ir::TrapCode::UnreachableCodeReached => TrapCode::UnreachableCodeReached,
|
||||
ir::TrapCode::User(x) => TrapCode::User(x),
|
||||
};
|
||||
|
||||
|
@ -7,6 +7,7 @@ use crate::{
|
||||
},
|
||||
signal::HandlerData,
|
||||
};
|
||||
use rayon::prelude::*;
|
||||
|
||||
use byteorder::{ByteOrder, LittleEndian};
|
||||
use cranelift_codegen::{ir, isa, Context};
|
||||
@ -20,7 +21,6 @@ use wasmer_runtime_core::cache::Error as CacheError;
|
||||
use wasmer_runtime_core::{
|
||||
self,
|
||||
backend::{
|
||||
self,
|
||||
sys::{Memory, Protect},
|
||||
SigRegistry,
|
||||
},
|
||||
@ -92,25 +92,44 @@ impl FuncResolverBuilder {
|
||||
function_bodies: Map<LocalFuncIndex, ir::Function>,
|
||||
info: &ModuleInfo,
|
||||
) -> CompileResult<(Self, HandlerData)> {
|
||||
let mut compiled_functions: Vec<Vec<u8>> = Vec::with_capacity(function_bodies.len());
|
||||
let mut local_relocs = Map::with_capacity(function_bodies.len());
|
||||
let mut external_relocs = Map::new();
|
||||
let num_func_bodies = function_bodies.len();
|
||||
let mut local_relocs = Map::with_capacity(num_func_bodies);
|
||||
let mut external_relocs = Map::with_capacity(num_func_bodies);
|
||||
|
||||
let mut trap_sink = TrapSink::new();
|
||||
let mut local_trap_sink = LocalTrapSink::new();
|
||||
|
||||
let mut ctx = Context::new();
|
||||
let compiled_functions: Result<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();
|
||||
|
||||
ctx.compile_and_emit(
|
||||
isa,
|
||||
&mut code_buf,
|
||||
&mut reloc_sink,
|
||||
&mut local_trap_sink,
|
||||
)
|
||||
.map_err(|e| CompileError::InternalError { msg: e.to_string() })?;
|
||||
ctx.clear();
|
||||
Ok((code_buf, (reloc_sink, local_trap_sink)))
|
||||
},
|
||||
)
|
||||
.collect();
|
||||
|
||||
let compiled_functions = compiled_functions?;
|
||||
let mut total_size = 0;
|
||||
|
||||
for (_, func) in function_bodies {
|
||||
ctx.func = func;
|
||||
let mut code_buf = Vec::new();
|
||||
let mut reloc_sink = RelocSink::new();
|
||||
|
||||
ctx.compile_and_emit(isa, &mut code_buf, &mut reloc_sink, &mut local_trap_sink)
|
||||
.map_err(|e| CompileError::InternalError { msg: e.to_string() })?;
|
||||
ctx.clear();
|
||||
|
||||
// We separate into two iterators, one iterable and one into iterable
|
||||
let (code_bufs, sinks): (Vec<Vec<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
|
||||
// into a single location.
|
||||
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.
|
||||
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());
|
||||
external_relocs.push(reloc_sink.external_relocs.into_boxed_slice());
|
||||
}
|
||||
@ -145,10 +163,10 @@ impl FuncResolverBuilder {
|
||||
*i = 0xCC;
|
||||
}
|
||||
|
||||
let mut map = Map::with_capacity(compiled_functions.len());
|
||||
let mut map = Map::with_capacity(num_func_bodies);
|
||||
|
||||
let mut previous_end = 0;
|
||||
for compiled in compiled_functions.iter() {
|
||||
for compiled in code_bufs.iter() {
|
||||
let new_end = previous_end + round_up(compiled.len(), mem::size_of::<usize>());
|
||||
unsafe {
|
||||
memory.as_slice_mut()[previous_end..previous_end + compiled.len()]
|
||||
@ -202,7 +220,7 @@ impl FuncResolverBuilder {
|
||||
|
||||
pub fn finalize(
|
||||
mut self,
|
||||
signatures: &SliceMap<SigIndex, Arc<FuncSig>>,
|
||||
signatures: &SliceMap<SigIndex, FuncSig>,
|
||||
trampolines: Arc<Trampolines>,
|
||||
handler_data: HandlerData,
|
||||
) -> CompileResult<(FuncResolver, BackendCache)> {
|
||||
@ -269,8 +287,8 @@ impl FuncResolverBuilder {
|
||||
},
|
||||
},
|
||||
RelocationType::Signature(sig_index) => {
|
||||
let sig_index =
|
||||
SigRegistry.lookup_sig_index(Arc::clone(&signatures[sig_index]));
|
||||
let signature = SigRegistry.lookup_signature_ref(&signatures[sig_index]);
|
||||
let sig_index = SigRegistry.lookup_sig_index(signature);
|
||||
sig_index.index() as _
|
||||
}
|
||||
};
|
||||
@ -338,13 +356,8 @@ pub struct FuncResolver {
|
||||
pub(crate) memory: Arc<Memory>,
|
||||
}
|
||||
|
||||
// Implements FuncResolver trait.
|
||||
impl backend::FuncResolver for FuncResolver {
|
||||
fn get(
|
||||
&self,
|
||||
_module: &wasmer_runtime_core::module::ModuleInner,
|
||||
index: LocalFuncIndex,
|
||||
) -> Option<NonNull<vm::Func>> {
|
||||
impl FuncResolver {
|
||||
pub fn lookup(&self, index: LocalFuncIndex) -> Option<NonNull<vm::Func>> {
|
||||
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) {
|
||||
print!(" i32: {},", n);
|
||||
eprint!(" i32: {},", n);
|
||||
}
|
||||
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) {
|
||||
print!(" f32: {},", n);
|
||||
eprint!(" f32: {},", n);
|
||||
}
|
||||
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) {
|
||||
print!("func ({}), args: [", func_index);
|
||||
extern "C" fn start_debug(ctx: &mut vm::Ctx, func_index: u32) {
|
||||
if let Some(symbol_map) = unsafe { ctx.borrow_symbol_map() } {
|
||||
if let Some(fn_name) = symbol_map.get(&func_index) {
|
||||
eprint!("func ({} ({})), args: [", fn_name, func_index);
|
||||
return;
|
||||
}
|
||||
}
|
||||
eprint!("func ({}), args: [", func_index);
|
||||
}
|
||||
extern "C" fn end_debug(_ctx: &mut vm::Ctx) {
|
||||
println!(" ]");
|
||||
eprintln!(" ]");
|
||||
}
|
||||
|
@ -1,15 +1,14 @@
|
||||
use crate::relocation::{TrapData, TrapSink};
|
||||
use crate::resolver::FuncResolver;
|
||||
use crate::trampoline::Trampolines;
|
||||
use hashbrown::HashSet;
|
||||
use libc::c_void;
|
||||
use std::{cell::Cell, sync::Arc};
|
||||
use std::{any::Any, cell::Cell, ptr::NonNull, sync::Arc};
|
||||
use wasmer_runtime_core::{
|
||||
backend::{ProtectedCaller, Token, UserTrapper},
|
||||
error::RuntimeResult,
|
||||
export::Context,
|
||||
module::{ExportIndex, ModuleInfo, ModuleInner},
|
||||
types::{FuncIndex, FuncSig, LocalOrImport, SigIndex, Type, Value},
|
||||
vm::{self, ImportBacking},
|
||||
backend::RunnableModule,
|
||||
module::ModuleInfo,
|
||||
typed_func::{Wasm, WasmTrapInfo},
|
||||
types::{LocalFuncIndex, SigIndex},
|
||||
vm,
|
||||
};
|
||||
|
||||
#[cfg(unix)]
|
||||
@ -25,167 +24,78 @@ pub use self::unix::*;
|
||||
pub use self::windows::*;
|
||||
|
||||
thread_local! {
|
||||
pub static TRAP_EARLY_DATA: Cell<Option<String>> = 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 static TRAP_EARLY_DATA: Cell<Option<Box<dyn Any>>> = Cell::new(None);
|
||||
}
|
||||
|
||||
pub struct Caller {
|
||||
func_export_set: HashSet<FuncIndex>,
|
||||
handler_data: HandlerData,
|
||||
trampolines: Arc<Trampolines>,
|
||||
resolver: FuncResolver,
|
||||
}
|
||||
|
||||
impl Caller {
|
||||
pub fn new(
|
||||
module: &ModuleInfo,
|
||||
handler_data: HandlerData,
|
||||
trampolines: Arc<Trampolines>,
|
||||
resolver: FuncResolver,
|
||||
) -> Self {
|
||||
let mut func_export_set = HashSet::new();
|
||||
for export_index in module.exports.values() {
|
||||
if let ExportIndex::Func(func_index) = export_index {
|
||||
func_export_set.insert(*func_index);
|
||||
}
|
||||
}
|
||||
if let Some(start_func_index) = module.start_func {
|
||||
func_export_set.insert(start_func_index);
|
||||
}
|
||||
|
||||
Self {
|
||||
func_export_set,
|
||||
handler_data,
|
||||
trampolines,
|
||||
resolver,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ProtectedCaller for Caller {
|
||||
fn call(
|
||||
&self,
|
||||
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);
|
||||
impl RunnableModule for Caller {
|
||||
fn get_func(&self, _: &ModuleInfo, func_index: LocalFuncIndex) -> Option<NonNull<vm::Func>> {
|
||||
self.resolver.lookup(func_index)
|
||||
}
|
||||
|
||||
let vmctx_ptr = match ctx {
|
||||
Context::External(external_vmctx) => external_vmctx,
|
||||
Context::Internal => vmctx,
|
||||
};
|
||||
fn get_trampoline(&self, _: &ModuleInfo, sig_index: SigIndex) -> Option<Wasm> {
|
||||
unsafe extern "C" fn invoke(
|
||||
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));
|
||||
|
||||
assert!(
|
||||
signature.returns().len() <= 1,
|
||||
"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(),
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
let res = call_protected(handler_data, || {
|
||||
// Leap of faith.
|
||||
trampoline(ctx, func, args, rets);
|
||||
})
|
||||
.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
|
||||
.trampolines
|
||||
.lookup(sig_index)
|
||||
.expect("that trampoline doesn't exist");
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
call_protected(&self.handler_data, || unsafe {
|
||||
// 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,
|
||||
vmctx_ptr,
|
||||
func_ptr,
|
||||
param_vec.as_ptr(),
|
||||
return_vec.as_mut_ptr(),
|
||||
)?;
|
||||
|
||||
Ok(return_vec
|
||||
.iter()
|
||||
.zip(signature.returns().iter())
|
||||
.map(|(&x, ty)| match ty {
|
||||
Type::I32 => Value::I32(x as i32),
|
||||
Type::I64 => Value::I64(x as i64),
|
||||
Type::F32 => Value::F32(f32::from_bits(x as u32)),
|
||||
Type::F64 => Value::F64(f64::from_bits(x as u64)),
|
||||
})
|
||||
.collect())
|
||||
}
|
||||
|
||||
fn get_early_trapper(&self) -> Box<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),
|
||||
Some(unsafe {
|
||||
Wasm::from_raw_parts(
|
||||
trampoline,
|
||||
invoke,
|
||||
Some(NonNull::from(&self.handler_data).cast()),
|
||||
)
|
||||
}
|
||||
};
|
||||
})
|
||||
}
|
||||
|
||||
let signature = Arc::clone(&module.info.signatures[sig_index]);
|
||||
|
||||
(func_ptr, ctx, signature, sig_index)
|
||||
unsafe fn do_early_trap(&self, data: Box<dyn Any>) -> ! {
|
||||
TRAP_EARLY_DATA.with(|cell| cell.set(Some(data)));
|
||||
trigger_trap()
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl Send for HandlerData {}
|
||||
|
@ -18,11 +18,7 @@ use nix::sys::signal::{
|
||||
use std::cell::{Cell, UnsafeCell};
|
||||
use std::ptr;
|
||||
use std::sync::Once;
|
||||
use wasmer_runtime_core::{
|
||||
error::{RuntimeError, RuntimeResult},
|
||||
structures::TypedIndex,
|
||||
types::{MemoryIndex, TableIndex},
|
||||
};
|
||||
use wasmer_runtime_core::error::{RuntimeError, RuntimeResult};
|
||||
|
||||
extern "C" fn signal_trap_handler(
|
||||
signum: ::nix::libc::c_int,
|
||||
@ -79,8 +75,8 @@ pub fn call_protected<T>(handler_data: &HandlerData, f: impl FnOnce() -> T) -> R
|
||||
if signum != 0 {
|
||||
*jmp_buf = prev_jmp_buf;
|
||||
|
||||
if let Some(msg) = super::TRAP_EARLY_DATA.with(|cell| cell.replace(None)) {
|
||||
Err(RuntimeError::User { msg })
|
||||
if let Some(data) = super::TRAP_EARLY_DATA.with(|cell| cell.replace(None)) {
|
||||
Err(RuntimeError::Panic { data })
|
||||
} else {
|
||||
let (faulting_addr, inst_ptr) = CAUGHT_ADDRESSES.with(|cell| cell.get());
|
||||
|
||||
@ -91,28 +87,28 @@ pub fn call_protected<T>(handler_data: &HandlerData, f: impl FnOnce() -> T) -> R
|
||||
{
|
||||
Err(match Signal::from_c_int(signum) {
|
||||
Ok(SIGILL) => match trapcode {
|
||||
TrapCode::BadSignature => RuntimeError::IndirectCallSignature {
|
||||
table: TableIndex::new(0),
|
||||
TrapCode::BadSignature => RuntimeError::Trap {
|
||||
msg: "incorrect call_indirect signature".into(),
|
||||
},
|
||||
TrapCode::IndirectCallToNull => RuntimeError::IndirectCallToNull {
|
||||
table: TableIndex::new(0),
|
||||
TrapCode::IndirectCallToNull => RuntimeError::Trap {
|
||||
msg: "indirect call to null".into(),
|
||||
},
|
||||
TrapCode::HeapOutOfBounds => RuntimeError::OutOfBoundsAccess {
|
||||
memory: MemoryIndex::new(0),
|
||||
addr: None,
|
||||
TrapCode::HeapOutOfBounds => RuntimeError::Trap {
|
||||
msg: "memory out-of-bounds access".into(),
|
||||
},
|
||||
TrapCode::TableOutOfBounds => RuntimeError::TableOutOfBounds {
|
||||
table: TableIndex::new(0),
|
||||
TrapCode::TableOutOfBounds => RuntimeError::Trap {
|
||||
msg: "table out-of-bounds access".into(),
|
||||
},
|
||||
_ => RuntimeError::Unknown {
|
||||
msg: "unknown trap".to_string(),
|
||||
_ => RuntimeError::Trap {
|
||||
msg: "unknown trap".into(),
|
||||
},
|
||||
},
|
||||
Ok(SIGSEGV) | Ok(SIGBUS) => RuntimeError::OutOfBoundsAccess {
|
||||
memory: MemoryIndex::new(0),
|
||||
addr: None,
|
||||
Ok(SIGSEGV) | Ok(SIGBUS) => RuntimeError::Trap {
|
||||
msg: "memory out-of-bounds access".into(),
|
||||
},
|
||||
Ok(SIGFPE) => RuntimeError::Trap {
|
||||
msg: "illegal arithmetic operation".into(),
|
||||
},
|
||||
Ok(SIGFPE) => RuntimeError::IllegalArithmeticOperation,
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
.into())
|
||||
@ -126,8 +122,8 @@ pub fn call_protected<T>(handler_data: &HandlerData, f: impl FnOnce() -> T) -> R
|
||||
_ => "unkown trapped signal",
|
||||
};
|
||||
// When the trap-handler is fully implemented, this will return more information.
|
||||
Err(RuntimeError::Unknown {
|
||||
msg: format!("trap at {:p} - {}", faulting_addr, signal),
|
||||
Err(RuntimeError::Trap {
|
||||
msg: format!("unknown trap at {:p} - {}", faulting_addr, signal).into(),
|
||||
}
|
||||
.into())
|
||||
}
|
||||
|
@ -3,14 +3,10 @@ use crate::signal::HandlerData;
|
||||
use crate::trampoline::Trampoline;
|
||||
use std::cell::Cell;
|
||||
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::Func;
|
||||
use wasmer_runtime_core::{
|
||||
error::{RuntimeError, RuntimeResult},
|
||||
structures::TypedIndex,
|
||||
types::{MemoryIndex, TableIndex},
|
||||
};
|
||||
use wasmer_win_exception_handler::CallProtectedData;
|
||||
pub use wasmer_win_exception_handler::_call_protected;
|
||||
use winapi::shared::minwindef::DWORD;
|
||||
@ -29,7 +25,7 @@ pub fn call_protected(
|
||||
handler_data: &HandlerData,
|
||||
trampoline: Trampoline,
|
||||
ctx: *mut Ctx,
|
||||
func: *const Func,
|
||||
func: NonNull<Func>,
|
||||
param_vec: *const u64,
|
||||
return_vec: *mut u64,
|
||||
) -> RuntimeResult<()> {
|
||||
@ -47,8 +43,8 @@ pub fn call_protected(
|
||||
|
||||
let CallProtectedData {
|
||||
code: signum,
|
||||
exceptionAddress: exception_address,
|
||||
instructionPointer: instruction_pointer,
|
||||
exception_address,
|
||||
instruction_pointer,
|
||||
} = result.unwrap_err();
|
||||
|
||||
if let Some(TrapData {
|
||||
@ -57,35 +53,34 @@ pub fn call_protected(
|
||||
}) = handler_data.lookup(instruction_pointer as _)
|
||||
{
|
||||
Err(match signum as DWORD {
|
||||
EXCEPTION_ACCESS_VIOLATION => RuntimeError::OutOfBoundsAccess {
|
||||
memory: MemoryIndex::new(0),
|
||||
addr: None,
|
||||
EXCEPTION_ACCESS_VIOLATION => RuntimeError::Trap {
|
||||
msg: "memory out-of-bounds access".into(),
|
||||
},
|
||||
EXCEPTION_ILLEGAL_INSTRUCTION => match trapcode {
|
||||
TrapCode::BadSignature => RuntimeError::IndirectCallSignature {
|
||||
table: TableIndex::new(0),
|
||||
TrapCode::BadSignature => RuntimeError::Trap {
|
||||
msg: "incorrect call_indirect signature".into(),
|
||||
},
|
||||
TrapCode::IndirectCallToNull => RuntimeError::IndirectCallToNull {
|
||||
table: TableIndex::new(0),
|
||||
TrapCode::IndirectCallToNull => RuntimeError::Trap {
|
||||
msg: "indirect call to null".into(),
|
||||
},
|
||||
TrapCode::HeapOutOfBounds => RuntimeError::OutOfBoundsAccess {
|
||||
memory: MemoryIndex::new(0),
|
||||
addr: None,
|
||||
TrapCode::HeapOutOfBounds => RuntimeError::Trap {
|
||||
msg: "memory out-of-bounds access".into(),
|
||||
},
|
||||
TrapCode::TableOutOfBounds => RuntimeError::TableOutOfBounds {
|
||||
table: TableIndex::new(0),
|
||||
TrapCode::TableOutOfBounds => RuntimeError::Trap {
|
||||
msg: "table out-of-bounds access".into(),
|
||||
},
|
||||
_ => RuntimeError::Unknown {
|
||||
msg: "unknown trap".to_string(),
|
||||
_ => RuntimeError::Trap {
|
||||
msg: "unknown trap".into(),
|
||||
},
|
||||
},
|
||||
EXCEPTION_STACK_OVERFLOW => RuntimeError::Unknown {
|
||||
msg: "unknown trap".to_string(),
|
||||
EXCEPTION_STACK_OVERFLOW => RuntimeError::Trap {
|
||||
msg: "stack overflow trap".into(),
|
||||
},
|
||||
EXCEPTION_INT_DIVIDE_BY_ZERO => RuntimeError::IllegalArithmeticOperation,
|
||||
EXCEPTION_INT_OVERFLOW => RuntimeError::IllegalArithmeticOperation,
|
||||
_ => RuntimeError::Unknown {
|
||||
msg: "unknown trap".to_string(),
|
||||
EXCEPTION_INT_DIVIDE_BY_ZERO | EXCEPTION_INT_OVERFLOW => RuntimeError::Trap {
|
||||
msg: "illegal arithmetic operation".into(),
|
||||
},
|
||||
_ => RuntimeError::Trap {
|
||||
msg: "unknown trap".into(),
|
||||
},
|
||||
}
|
||||
.into())
|
||||
@ -103,8 +98,8 @@ pub fn call_protected(
|
||||
_ => "unkown trapped signal",
|
||||
};
|
||||
|
||||
Err(RuntimeError::Unknown {
|
||||
msg: format!("trap at {} - {}", exception_address, signal),
|
||||
Err(RuntimeError::Trap {
|
||||
msg: format!("unknown trap at {} - {}", exception_address, signal).into(),
|
||||
}
|
||||
.into())
|
||||
}
|
||||
|
@ -6,8 +6,7 @@ use cranelift_codegen::{
|
||||
isa, Context,
|
||||
};
|
||||
use hashbrown::HashMap;
|
||||
use std::ffi::c_void;
|
||||
use std::{iter, mem};
|
||||
use std::{iter, mem, ptr::NonNull};
|
||||
use wasmer_runtime_core::{
|
||||
backend::sys::{Memory, Protect},
|
||||
module::{ExportIndex, ModuleInfo},
|
||||
@ -23,8 +22,7 @@ impl RelocSink for NullRelocSink {
|
||||
fn reloc_jt(&mut self, _: u32, _: Reloc, _: ir::JumpTable) {}
|
||||
}
|
||||
|
||||
pub type Trampoline =
|
||||
unsafe extern "C" fn(*mut vm::Ctx, *const vm::Func, *const u64, *mut u64) -> c_void;
|
||||
pub type Trampoline = unsafe extern "C" fn(*mut vm::Ctx, NonNull<vm::Func>, *const u64, *mut u64);
|
||||
|
||||
pub struct Trampolines {
|
||||
memory: Memory,
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "wasmer-emscripten"
|
||||
version = "0.1.0"
|
||||
version = "0.3.0"
|
||||
description = "Wasmer runtime emscripten implementation library"
|
||||
license = "MIT"
|
||||
authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"]
|
||||
@ -9,18 +9,26 @@ edition = "2018"
|
||||
build = "build/mod.rs"
|
||||
|
||||
[dependencies]
|
||||
wasmer-runtime-core = { path = "../runtime-core", version = "0.1.0" }
|
||||
wasmer-runtime-core = { path = "../runtime-core", version = "0.3.0" }
|
||||
lazy_static = "1.2.0"
|
||||
libc = { git = "https://github.com/rust-lang/libc" }
|
||||
libc = "0.2.49"
|
||||
byteorder = "1"
|
||||
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]
|
||||
rand = "0.6"
|
||||
|
||||
[dev-dependencies]
|
||||
wasmer-clif-backend = { path = "../clif-backend", version = "0.1.0" }
|
||||
wabt = "0.7.2"
|
||||
|
||||
[build-dependencies]
|
||||
glob = "0.2.11"
|
||||
|
||||
[features]
|
||||
clif = []
|
||||
llvm = ["wasmer-llvm-backend"]
|
||||
singlepass = ["wasmer-singlepass-backend"]
|
||||
debug = ["wasmer-clif-backend/debug", "wasmer-runtime-core/debug"]
|
||||
|
@ -46,26 +46,42 @@ pub fn compile(file: &str, ignores: &Vec<String>) -> Option<String> {
|
||||
output_path.set_extension("js");
|
||||
let output_str = output_path.to_str().unwrap();
|
||||
|
||||
// Compile to wasm
|
||||
let _wasm_compilation = Command::new("emcc")
|
||||
.arg(file)
|
||||
.arg("-s")
|
||||
.arg("WASM=1")
|
||||
.arg("-o")
|
||||
.arg(output_str)
|
||||
.output()
|
||||
.expect("failed to execute process");
|
||||
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
|
||||
}
|
||||
};
|
||||
|
||||
// panic!("{:?}", wasm_compilation);
|
||||
// if output.stderr {
|
||||
// panic!("{}", output.stderr);
|
||||
// }
|
||||
// Remove js file
|
||||
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
|
||||
let _wasm_compilation = Command::new("emcc")
|
||||
.arg(file)
|
||||
.arg("-s")
|
||||
.arg("WASM=1")
|
||||
.arg("-o")
|
||||
.arg(output_str)
|
||||
.output()
|
||||
.expect("failed to execute process");
|
||||
|
||||
if Path::new(output_str).is_file() {
|
||||
fs::remove_file(output_str).unwrap();
|
||||
} else {
|
||||
println!("Output JS not found: {}", output_str);
|
||||
// panic!("{:?}", wasm_compilation);
|
||||
// if output.stderr {
|
||||
// panic!("{}", output.stderr);
|
||||
// }
|
||||
// Remove js file
|
||||
|
||||
if Path::new(output_str).is_file() {
|
||||
fs::remove_file(output_str).unwrap();
|
||||
} else {
|
||||
println!("Output JS not found: {}", output_str);
|
||||
}
|
||||
}
|
||||
|
||||
let mut output_path = PathBuf::from(file);
|
||||
|
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_varargs
|
||||
test_llvm_intrinsics
|
||||
test_longjmp2
|
||||
test_longjmp3
|
||||
test_longjmp4
|
||||
test_longjmp
|
||||
test_longjmp_exc
|
||||
test_longjmp_funcptr
|
||||
test_longjmp_repeat
|
||||
test_longjmp_stacked
|
||||
test_longjmp_throw
|
||||
test_longjmp_unwind
|
||||
test_lower_intrinsics
|
||||
test_main_thread_async_em_asm
|
||||
test_mainenv
|
||||
@ -72,3 +63,46 @@ test_std_cout_new
|
||||
test_strptime_reentrant
|
||||
test_gmtime
|
||||
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;
|
||||
#[cfg(target_os = "linux")]
|
||||
use libc::getdtablesize;
|
||||
use wasmer_runtime_core::vm::Ctx;
|
||||
|
||||
pub fn setTempRet0(ctx: &mut Ctx, a: i32) {
|
||||
debug!("emscripten::setTempRet0");
|
||||
pub fn setTempRet0(ctx: &mut Ctx, val: i32) {
|
||||
debug!("emscripten::setTempRet0: {}", val);
|
||||
get_emscripten_data(ctx).temp_ret_0 = val;
|
||||
}
|
||||
|
||||
pub fn getTempRet0(ctx: &mut Ctx) -> i32 {
|
||||
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 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 {
|
||||
|
||||
pub fn __Unwind_Backtrace(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
|
||||
debug!("emscripten::__Unwind_Backtrace");
|
||||
0
|
||||
}
|
||||
pub fn __Unwind_FindEnclosingFunction(ctx: &mut Ctx, a: i32) -> i32 {
|
||||
pub fn __Unwind_FindEnclosingFunction(_ctx: &mut Ctx, _a: i32) -> i32 {
|
||||
debug!("emscripten::__Unwind_FindEnclosingFunction");
|
||||
0
|
||||
}
|
||||
pub fn __Unwind_GetIPInfo(ctx: &mut Ctx, a: i32, b: i32) -> i32 {
|
||||
pub fn __Unwind_GetIPInfo(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
|
||||
debug!("emscripten::__Unwind_GetIPInfo");
|
||||
0
|
||||
}
|
||||
pub fn ___cxa_find_matching_catch_2(ctx: &mut Ctx) -> i32 {
|
||||
pub fn ___cxa_find_matching_catch_2(_ctx: &mut Ctx) -> i32 {
|
||||
debug!("emscripten::___cxa_find_matching_catch_2");
|
||||
0
|
||||
}
|
||||
pub fn ___cxa_find_matching_catch_3(ctx: &mut Ctx, a: i32) -> i32 {
|
||||
pub fn ___cxa_find_matching_catch_3(_ctx: &mut Ctx, _a: i32) -> i32 {
|
||||
debug!("emscripten::___cxa_find_matching_catch_3");
|
||||
0
|
||||
}
|
||||
pub fn ___cxa_free_exception(ctx: &mut Ctx, a: i32) {
|
||||
pub fn ___cxa_free_exception(_ctx: &mut Ctx, _a: i32) {
|
||||
debug!("emscripten::___cxa_free_exception");
|
||||
}
|
||||
pub fn ___resumeException(ctx: &mut Ctx, a: i32) {
|
||||
pub fn ___resumeException(_ctx: &mut Ctx, _a: i32) {
|
||||
debug!("emscripten::___resumeException");
|
||||
}
|
||||
pub fn _dladdr(ctx: &mut Ctx, a: i32, b: i32) -> i32 {
|
||||
pub fn _dladdr(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
|
||||
debug!("emscripten::_dladdr");
|
||||
0
|
||||
}
|
||||
pub fn _pthread_cond_destroy(ctx: &mut Ctx, a: i32) -> i32 {
|
||||
pub fn _pthread_cond_destroy(_ctx: &mut Ctx, _a: i32) -> i32 {
|
||||
debug!("emscripten::_pthread_cond_destroy");
|
||||
0
|
||||
}
|
||||
pub fn _pthread_cond_init(ctx: &mut Ctx, a: i32, b: i32) -> i32 {
|
||||
pub fn _pthread_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");
|
||||
0
|
||||
}
|
||||
pub fn _pthread_cond_signal(ctx: &mut Ctx, a: i32) -> i32 {
|
||||
pub fn _pthread_cond_signal(_ctx: &mut Ctx, _a: i32) -> i32 {
|
||||
debug!("emscripten::_pthread_cond_signal");
|
||||
0
|
||||
}
|
||||
pub fn _pthread_cond_wait(ctx: &mut Ctx, a: i32, b: i32) -> i32 {
|
||||
pub fn _pthread_cond_wait(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
|
||||
debug!("emscripten::_pthread_cond_wait");
|
||||
0
|
||||
}
|
||||
pub fn _pthread_condattr_destroy(ctx: &mut Ctx, a: i32) -> i32 {
|
||||
pub fn _pthread_condattr_destroy(_ctx: &mut Ctx, _a: i32) -> i32 {
|
||||
debug!("emscripten::_pthread_condattr_destroy");
|
||||
0
|
||||
}
|
||||
pub fn _pthread_condattr_init(ctx: &mut Ctx, a: i32) -> i32 {
|
||||
pub fn _pthread_condattr_init(_ctx: &mut Ctx, _a: i32) -> i32 {
|
||||
debug!("emscripten::_pthread_condattr_init");
|
||||
0
|
||||
}
|
||||
pub fn _pthread_condattr_setclock(ctx: &mut Ctx, a: i32, b: i32) -> i32 {
|
||||
pub fn _pthread_condattr_setclock(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
|
||||
debug!("emscripten::_pthread_condattr_setclock");
|
||||
0
|
||||
}
|
||||
pub fn _pthread_mutex_destroy(ctx: &mut Ctx, a: i32) -> i32 {
|
||||
pub fn _pthread_mutex_destroy(_ctx: &mut Ctx, _a: i32) -> i32 {
|
||||
debug!("emscripten::_pthread_mutex_destroy");
|
||||
0
|
||||
}
|
||||
pub fn _pthread_mutex_init(ctx: &mut Ctx, a: i32, b: i32) -> i32 {
|
||||
pub fn _pthread_mutex_init(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
|
||||
debug!("emscripten::_pthread_mutex_init");
|
||||
0
|
||||
}
|
||||
pub fn _pthread_mutexattr_destroy(ctx: &mut Ctx, a: i32) -> i32 {
|
||||
pub fn _pthread_mutexattr_destroy(_ctx: &mut Ctx, _a: i32) -> i32 {
|
||||
debug!("emscripten::_pthread_mutexattr_destroy");
|
||||
0
|
||||
}
|
||||
pub fn _pthread_mutexattr_init(ctx: &mut Ctx, a: i32) -> i32 {
|
||||
pub fn _pthread_mutexattr_init(_ctx: &mut Ctx, _a: i32) -> i32 {
|
||||
debug!("emscripten::_pthread_mutexattr_init");
|
||||
0
|
||||
}
|
||||
pub fn _pthread_mutexattr_settype(ctx: &mut Ctx, a: i32, b: i32) -> i32 {
|
||||
pub fn _pthread_mutexattr_settype(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
|
||||
debug!("emscripten::_pthread_mutexattr_settype");
|
||||
0
|
||||
}
|
||||
pub fn _pthread_rwlock_rdlock(ctx: &mut Ctx, a: i32) -> i32 {
|
||||
pub fn _pthread_rwlock_rdlock(_ctx: &mut Ctx, _a: i32) -> i32 {
|
||||
debug!("emscripten::_pthread_rwlock_rdlock");
|
||||
0
|
||||
}
|
||||
pub fn _pthread_rwlock_unlock(ctx: &mut Ctx, a: i32) -> i32 {
|
||||
pub fn _pthread_rwlock_unlock(_ctx: &mut Ctx, _a: i32) -> i32 {
|
||||
debug!("emscripten::_pthread_rwlock_unlock");
|
||||
0
|
||||
}
|
||||
pub fn ___gxx_personality_v0(ctx: &mut Ctx, a: i32, b: i32, c: i32, d: i32, e: i32, f: i32) -> i32 {
|
||||
pub fn _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");
|
||||
0
|
||||
}
|
||||
// round 2
|
||||
pub fn nullFunc_dii(ctx: &mut Ctx, index: i32) {
|
||||
debug!("emscripten::nullFunc_dii");
|
||||
#[cfg(target_os = "linux")]
|
||||
pub fn _getdtablesize(_ctx: &mut Ctx) -> i32 {
|
||||
debug!("emscripten::getdtablesize");
|
||||
unsafe { getdtablesize() }
|
||||
}
|
||||
pub fn nullFunc_diiii(ctx: &mut Ctx, index: i32) {
|
||||
debug!("emscripten::nullFunc_diiii");
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
pub fn _getdtablesize(_ctx: &mut Ctx) -> i32 {
|
||||
debug!("emscripten::getdtablesize");
|
||||
-1
|
||||
}
|
||||
pub fn nullFunc_iiji(ctx: &mut Ctx, index: i32) {
|
||||
debug!("emscripten::nullFunc_iiji");
|
||||
pub fn _gethostbyaddr(_ctx: &mut Ctx, _addr: i32, _addrlen: i32, _atype: i32) -> i32 {
|
||||
debug!("emscripten::gethostbyaddr");
|
||||
0
|
||||
}
|
||||
pub fn nullFunc_j(ctx: &mut Ctx, index: i32) {
|
||||
debug!("emscripten::nullFunc_j");
|
||||
pub fn _gethostbyname_r(
|
||||
_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) {
|
||||
debug!("emscripten::nullFunc_jij");
|
||||
// NOTE: php.js has proper impl; libc has proper impl for linux
|
||||
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");
|
||||
macro_rules! invoke_no_return {
|
||||
($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_viiiiiii(ctx: &mut Ctx, index: i32) {
|
||||
debug!("emscripten::nullFunc_viiiiiii");
|
||||
|
||||
// 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_viiiiiiii(ctx: &mut Ctx, index: i32) {
|
||||
debug!("emscripten::nullFunc_viiiiiiii");
|
||||
pub fn invoke_ii(ctx: &mut Ctx, index: i32, a1: i32) -> i32 {
|
||||
debug!("emscripten::invoke_ii");
|
||||
invoke!(ctx, dyn_call_ii, index, a1)
|
||||
}
|
||||
pub fn nullFunc_viiiiiiiii(ctx: &mut Ctx, index: i32) {
|
||||
debug!("emscripten::nullFunc_viiiiiiiii");
|
||||
pub fn invoke_iii(ctx: &mut Ctx, index: i32, a1: i32, a2: i32) -> i32 {
|
||||
debug!("emscripten::invoke_iii");
|
||||
invoke!(ctx, dyn_call_iii, index, a1, a2)
|
||||
}
|
||||
pub fn nullFunc_viiij(ctx: &mut Ctx, index: i32) {
|
||||
debug!("emscripten::nullFunc_viiij");
|
||||
pub fn invoke_iiii(ctx: &mut Ctx, index: i32, a1: i32, a2: i32, a3: i32) -> i32 {
|
||||
debug!("emscripten::invoke_iiii");
|
||||
invoke!(ctx, dyn_call_iiii, index, a1, a2, a3)
|
||||
}
|
||||
pub fn nullFunc_viiijiiii(ctx: &mut Ctx, index: i32) {
|
||||
debug!("emscripten::nullFunc_viiijiiii");
|
||||
pub fn invoke_iifi(ctx: &mut Ctx, index: i32, a1: i32, a2: f64, a3: i32) -> i32 {
|
||||
debug!("emscripten::invoke_iifi");
|
||||
invoke!(ctx, dyn_call_iifi, index, a1, a2, a3)
|
||||
}
|
||||
pub fn nullFunc_viiijiiiiii(ctx: &mut Ctx, index: i32) {
|
||||
debug!("emscripten::nullFunc_viiijiiiiii");
|
||||
pub fn invoke_v(ctx: &mut Ctx, index: i32) {
|
||||
debug!("emscripten::invoke_v");
|
||||
invoke_no_return!(ctx, dyn_call_v, index);
|
||||
}
|
||||
pub fn nullFunc_viij(ctx: &mut Ctx, index: i32) {
|
||||
debug!("emscripten::nullFunc_viij");
|
||||
pub fn invoke_vi(ctx: &mut Ctx, index: i32, a1: i32) {
|
||||
debug!("emscripten::invoke_vi");
|
||||
invoke_no_return!(ctx, dyn_call_vi, index, a1);
|
||||
}
|
||||
pub fn nullFunc_viiji(ctx: &mut Ctx, index: i32) {
|
||||
debug!("emscripten::nullFunc_viiji");
|
||||
pub fn invoke_vii(ctx: &mut Ctx, index: i32, a1: i32, a2: i32) {
|
||||
debug!("emscripten::invoke_vii");
|
||||
invoke_no_return!(ctx, dyn_call_vii, index, a1, a2);
|
||||
}
|
||||
pub fn nullFunc_viijiii(ctx: &mut Ctx, index: i32) {
|
||||
debug!("emscripten::nullFunc_viijiii");
|
||||
|
||||
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_viijj(ctx: &mut Ctx, index: i32) {
|
||||
debug!("emscripten::nullFunc_viijj");
|
||||
}
|
||||
pub fn nullFunc_vij(ctx: &mut Ctx, index: i32) {
|
||||
debug!("emscripten::nullFunc_vij");
|
||||
}
|
||||
pub fn nullFunc_viji(ctx: &mut Ctx, index: i32) {
|
||||
debug!("emscripten::nullFunc_viji");
|
||||
}
|
||||
pub fn nullFunc_vijiii(ctx: &mut Ctx, index: i32) {
|
||||
debug!("emscripten::nullFunc_vijiii");
|
||||
}
|
||||
pub fn nullFunc_vijj(ctx: &mut Ctx, index: i32) {
|
||||
debug!("emscripten::nullFunc_vijj");
|
||||
pub fn invoke_viiii(ctx: &mut Ctx, index: i32, a1: i32, a2: i32, a3: i32, a4: i32) {
|
||||
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 {
|
||||
debug!("emscripten::invoke_dii");
|
||||
if let Some(dyn_call_dii) = &get_emscripten_data(ctx).dyn_call_dii {
|
||||
dyn_call_dii.call(index, a1, a2).unwrap()
|
||||
} else {
|
||||
panic!("dyn_call_dii is set to None");
|
||||
}
|
||||
invoke!(ctx, dyn_call_dii, index, a1, a2)
|
||||
}
|
||||
pub fn invoke_diiii(ctx: &mut Ctx, index: i32, a1: i32, a2: i32, a3: i32, a4: i32) -> f64 {
|
||||
debug!("emscripten::invoke_diiii");
|
||||
if let Some(dyn_call_diiii) = &get_emscripten_data(ctx).dyn_call_diiii {
|
||||
dyn_call_diiii.call(index, a1, a2, a3, a4).unwrap()
|
||||
} else {
|
||||
panic!("dyn_call_diiii is set to None");
|
||||
}
|
||||
invoke!(ctx, dyn_call_diiii, index, a1, a2, a3, a4)
|
||||
}
|
||||
pub fn invoke_iiiii(ctx: &mut Ctx, index: i32, a1: i32, a2: i32, a3: i32, a4: i32) -> i32 {
|
||||
debug!("emscripten::invoke_iiiii");
|
||||
if let Some(dyn_call_iiiii) = &get_emscripten_data(ctx).dyn_call_iiiii {
|
||||
dyn_call_iiiii.call(index, a1, a2, a3, a4).unwrap()
|
||||
} else {
|
||||
panic!("dyn_call_iiiii is set to None");
|
||||
}
|
||||
invoke!(ctx, dyn_call_iiiii, index, a1, a2, a3, a4)
|
||||
}
|
||||
pub fn invoke_iiiiii(
|
||||
ctx: &mut Ctx,
|
||||
@ -271,27 +273,129 @@ pub fn invoke_iiiiii(
|
||||
a5: i32,
|
||||
) -> i32 {
|
||||
debug!("emscripten::invoke_iiiiii");
|
||||
if let Some(dyn_call_iiiiii) = &get_emscripten_data(ctx).dyn_call_iiiiii {
|
||||
dyn_call_iiiiii.call(index, a1, a2, a3, a4, a5).unwrap()
|
||||
} else {
|
||||
panic!("dyn_call_iiiiii is set to None");
|
||||
}
|
||||
invoke!(ctx, dyn_call_iiiiii, index, a1, a2, a3, a4, a5)
|
||||
}
|
||||
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) {
|
||||
debug!("emscripten::invoke_vd");
|
||||
if let Some(dyn_call_vd) = &get_emscripten_data(ctx).dyn_call_vd {
|
||||
dyn_call_vd.call(index, a1).unwrap();
|
||||
} else {
|
||||
panic!("dyn_call_vd is set to None");
|
||||
}
|
||||
invoke_no_return!(ctx, dyn_call_vd, index, a1)
|
||||
}
|
||||
pub fn invoke_viiiii(ctx: &mut Ctx, index: i32, a1: i32, a2: i32, a3: i32, a4: i32, a5: i32) {
|
||||
debug!("emscripten::invoke_viiiii");
|
||||
if let Some(dyn_call_viiiii) = &get_emscripten_data(ctx).dyn_call_viiiii {
|
||||
dyn_call_viiiii.call(index, a1, a2, a3, a4, a5).unwrap();
|
||||
} else {
|
||||
panic!("dyn_call_viiiii is set to None");
|
||||
}
|
||||
invoke_no_return!(ctx, dyn_call_viiiii, index, a1, a2, a3, a4, a5)
|
||||
}
|
||||
pub fn invoke_viiiiii(
|
||||
ctx: &mut Ctx,
|
||||
@ -304,13 +408,7 @@ pub fn invoke_viiiiii(
|
||||
a6: i32,
|
||||
) {
|
||||
debug!("emscripten::invoke_viiiiii");
|
||||
if let Some(dyn_call_viiiiii) = &get_emscripten_data(ctx).dyn_call_viiiiii {
|
||||
dyn_call_viiiiii
|
||||
.call(index, a1, a2, a3, a4, a5, a6)
|
||||
.unwrap();
|
||||
} else {
|
||||
panic!("dyn_call_viiiiii is set to None");
|
||||
}
|
||||
invoke_no_return!(ctx, dyn_call_viiiiii, index, a1, a2, a3, a4, a5, a6)
|
||||
}
|
||||
pub fn invoke_viiiiiii(
|
||||
ctx: &mut Ctx,
|
||||
@ -324,13 +422,7 @@ pub fn invoke_viiiiiii(
|
||||
a7: i32,
|
||||
) {
|
||||
debug!("emscripten::invoke_viiiiiii");
|
||||
if let Some(dyn_call_viiiiiii) = &get_emscripten_data(ctx).dyn_call_viiiiiii {
|
||||
dyn_call_viiiiiii
|
||||
.call(index, a1, a2, a3, a4, a5, a6, a7)
|
||||
.unwrap();
|
||||
} else {
|
||||
panic!("dyn_call_viiiiiii is set to None");
|
||||
}
|
||||
invoke_no_return!(ctx, dyn_call_viiiiiii, index, a1, a2, a3, a4, a5, a6, a7)
|
||||
}
|
||||
pub fn invoke_viiiiiiii(
|
||||
ctx: &mut Ctx,
|
||||
@ -345,13 +437,19 @@ pub fn invoke_viiiiiiii(
|
||||
a8: i32,
|
||||
) {
|
||||
debug!("emscripten::invoke_viiiiiiii");
|
||||
if let Some(dyn_call_viiiiiiii) = &get_emscripten_data(ctx).dyn_call_viiiiiiii {
|
||||
dyn_call_viiiiiiii
|
||||
.call(index, a1, a2, a3, a4, a5, a6, a7, a8)
|
||||
.unwrap();
|
||||
} else {
|
||||
panic!("dyn_call_viiiiiiii is set to None");
|
||||
}
|
||||
invoke_no_return!(
|
||||
ctx,
|
||||
dyn_call_viiiiiiii,
|
||||
index,
|
||||
a1,
|
||||
a2,
|
||||
a3,
|
||||
a4,
|
||||
a5,
|
||||
a6,
|
||||
a7,
|
||||
a8
|
||||
)
|
||||
}
|
||||
pub fn invoke_viiiiiiiii(
|
||||
ctx: &mut Ctx,
|
||||
@ -367,21 +465,75 @@ pub fn invoke_viiiiiiiii(
|
||||
a9: i32,
|
||||
) {
|
||||
debug!("emscripten::invoke_viiiiiiiii");
|
||||
if let Some(dyn_call_viiiiiiiii) = &get_emscripten_data(ctx).dyn_call_viiiiiiiii {
|
||||
dyn_call_viiiiiiiii
|
||||
.call(index, a1, a2, a3, a4, a5, a6, a7, a8, a9)
|
||||
.unwrap();
|
||||
} else {
|
||||
panic!("dyn_call_viiiiiiiii is set to None");
|
||||
}
|
||||
invoke_no_return!(
|
||||
ctx,
|
||||
dyn_call_viiiiiiiii,
|
||||
index,
|
||||
a1,
|
||||
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 {
|
||||
debug!("emscripten::invoke_iiji");
|
||||
if let Some(dyn_call_iiji) = &get_emscripten_data(ctx).dyn_call_iiji {
|
||||
dyn_call_iiji.call(index, a1, a2, a3, a4).unwrap()
|
||||
} else {
|
||||
panic!("dyn_call_iiji is set to None");
|
||||
}
|
||||
invoke!(ctx, dyn_call_iiji, index, a1, a2, a3, a4)
|
||||
}
|
||||
|
||||
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 {
|
||||
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");
|
||||
}
|
||||
}
|
||||
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 {
|
||||
debug!("emscripten::invoke_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");
|
||||
}
|
||||
}
|
||||
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) {
|
||||
debug!("emscripten::invoke_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");
|
||||
}
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
pub fn _times(ctx: &mut Ctx, buffer: u32) -> u32 {
|
||||
if buffer != 0 {
|
||||
call_memset(ctx, buffer, 0, 16);
|
||||
}
|
||||
0
|
||||
}
|
||||
|
||||
#[allow(clippy::cast_ptr_alignment)]
|
||||
pub fn ___build_environment(ctx: &mut Ctx, environ: c_int) {
|
||||
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) {
|
||||
debug!("emscripten::___assert_fail {} {} {} {}", a, b, c, d);
|
||||
pub fn ___assert_fail(_ctx: &mut Ctx, _a: c_int, _b: c_int, _c: c_int, _d: c_int) {
|
||||
debug!("emscripten::___assert_fail {} {} {} {}", _a, _b, _c, _d);
|
||||
// TODO: Implement like emscripten expects regarding memory/page size
|
||||
// TODO raise an error
|
||||
}
|
||||
|
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)]
|
||||
pub fn _getpwnam(ctx: &mut Ctx, name_ptr: c_int) -> c_int {
|
||||
debug!("emscripten::_getpwnam {}", name_ptr);
|
||||
#[cfg(feature = "debug")]
|
||||
let _ = name_ptr;
|
||||
|
||||
#[repr(C)]
|
||||
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::utils::{copy_cstr_into_wasm, read_string_from_wasm};
|
||||
use std::ffi::CStr;
|
||||
use wasmer_runtime_core::vm::Ctx;
|
||||
|
||||
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);
|
||||
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");
|
||||
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
|
||||
let name = read_string_from_wasm(ctx.memory(0), name);
|
||||
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);
|
||||
pub fn _putenv(ctx: &mut Ctx, name: c_int) -> c_int {
|
||||
debug!("emscripten::_putenv");
|
||||
|
||||
let name_addr = emscripten_memory_pointer!(ctx.memory(0), name) as *const c_char;
|
||||
|
||||
debug!("=> name({:?})", unsafe { CStr::from_ptr(name_addr) });
|
||||
debug!("=> name({:?})", unsafe {
|
||||
std::ffi::CStr::from_ptr(name_addr)
|
||||
});
|
||||
unsafe { putenv(name_addr) }
|
||||
}
|
||||
|
||||
/// emscripten: _unsetenv // (name: *const char);
|
||||
pub fn _unsetenv(ctx: &mut Ctx, name: u32) -> c_int {
|
||||
debug!("emscripten::_unsetenv");
|
||||
let name_addr = emscripten_memory_pointer!(ctx.memory(0), name);
|
||||
let name = read_string_from_wasm(ctx.memory(0), name);
|
||||
// no unsetenv on windows, so use putenv with an empty value
|
||||
let unsetenv_string = format!("{}=", name);
|
||||
@ -70,6 +66,8 @@ pub fn _unsetenv(ctx: &mut Ctx, name: u32) -> c_int {
|
||||
#[allow(clippy::cast_ptr_alignment)]
|
||||
pub fn _getpwnam(ctx: &mut Ctx, name_ptr: c_int) -> c_int {
|
||||
debug!("emscripten::_getpwnam {}", name_ptr);
|
||||
#[cfg(not(feature = "debug"))]
|
||||
let _ = name_ptr;
|
||||
|
||||
#[repr(C)]
|
||||
struct GuestPasswd {
|
||||
@ -102,6 +100,8 @@ pub fn _getpwnam(ctx: &mut Ctx, name_ptr: c_int) -> c_int {
|
||||
#[allow(clippy::cast_ptr_alignment)]
|
||||
pub fn _getgrnam(ctx: &mut Ctx, name_ptr: c_int) -> c_int {
|
||||
debug!("emscripten::_getgrnam {}", name_ptr);
|
||||
#[cfg(not(feature = "debug"))]
|
||||
let _ = name_ptr;
|
||||
|
||||
#[repr(C)]
|
||||
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 {
|
||||
debug!("emscripten::_sysconf {}", name);
|
||||
#[cfg(not(feature = "debug"))]
|
||||
let _ = name;
|
||||
// stub because sysconf is not valid on windows
|
||||
0
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
// use std::collections::HashMap;
|
||||
use wasmer_runtime_core::vm::Ctx;
|
||||
|
||||
pub fn ___seterrno(_ctx: &mut Ctx, value: i32) {
|
||||
debug!("emscripten::___seterrno {}", value);
|
||||
pub fn ___seterrno(_ctx: &mut Ctx, _value: i32) {
|
||||
debug!("emscripten::___seterrno {}", _value);
|
||||
// TODO: Incomplete impl
|
||||
eprintln!("failed to set errno!");
|
||||
// value
|
||||
|
@ -14,3 +14,17 @@ pub fn ___cxa_throw(ctx: &mut Ctx, _ptr: u32, _ty: u32, _destructor: u32) {
|
||||
debug!("emscripten::___cxa_throw");
|
||||
_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)]
|
||||
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;
|
||||
|
||||
/// putchar
|
||||
pub fn putchar(ctx: &mut Ctx, chr: i32) {
|
||||
pub fn putchar(_ctx: &mut Ctx, chr: i32) {
|
||||
unsafe { libc::putchar(chr) };
|
||||
}
|
||||
|
||||
@ -15,3 +15,16 @@ pub fn printf(ctx: &mut Ctx, memory_offset: i32, extra: i32) -> i32 {
|
||||
_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;
|
||||
|
||||
// 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
|
||||
pub fn putchar(ctx: &mut Ctx, chr: i32) {
|
||||
pub fn putchar(_ctx: &mut Ctx, chr: i32) {
|
||||
unsafe { libc::putchar(chr) };
|
||||
}
|
||||
|
||||
/// 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);
|
||||
#[cfg(not(feature = "debug"))]
|
||||
{
|
||||
let _ = memory_offset;
|
||||
let _ = extra;
|
||||
}
|
||||
// unsafe {
|
||||
// let addr = emscripten_memory_pointer!(ctx.memory(0), memory_offset) as _;
|
||||
// _printf(addr, extra)
|
||||
// }
|
||||
-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 libc::{c_int, c_void};
|
||||
use std::cell::UnsafeCell;
|
||||
use super::process::abort_with_message;
|
||||
use libc::c_int;
|
||||
// use std::cell::UnsafeCell;
|
||||
use wasmer_runtime_core::vm::Ctx;
|
||||
|
||||
/// 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)");
|
||||
unsafe {
|
||||
// Rather than using the env as the holder of the jump buffer pointer,
|
||||
// we use the environment address to store the index relative to jumps
|
||||
// so the address of the jump it's outside the wasm memory itself.
|
||||
let jump_index = emscripten_memory_pointer!(ctx.memory(0), env_addr) as *mut i8;
|
||||
// We create the jump buffer outside of the wasm memory
|
||||
let jump_buf: UnsafeCell<[u32; 27]> = UnsafeCell::new([0; 27]);
|
||||
let jumps = &mut get_emscripten_data(ctx).jumps;
|
||||
let result = setjmp(jump_buf.get() as _);
|
||||
// We set the jump index to be the last 3value of jumps
|
||||
*jump_index = jumps.len() as _;
|
||||
// We hold the reference of the jump buffer
|
||||
jumps.push(jump_buf);
|
||||
result
|
||||
}
|
||||
abort_with_message(ctx, "missing function: _longjmp");
|
||||
unreachable!()
|
||||
// unsafe {
|
||||
// // Rather than using the env as the holder of the jump buffer pointer,
|
||||
// // we use the environment address to store the index relative to jumps
|
||||
// // so the address of the jump it's outside the wasm memory itself.
|
||||
// let jump_index = emscripten_memory_pointer!(ctx.memory(0), env_addr) as *mut i8;
|
||||
// // We create the jump buffer outside of the wasm memory
|
||||
// let jump_buf: UnsafeCell<[u32; 27]> = UnsafeCell::new([0; 27]);
|
||||
// let jumps = &mut get_emscripten_data(ctx).jumps;
|
||||
// let result = setjmp(jump_buf.get() as _);
|
||||
// // We set the jump index to be the last 3value of jumps
|
||||
// *jump_index = jumps.len() as _;
|
||||
// // We hold the reference of the jump buffer
|
||||
// jumps.push(jump_buf);
|
||||
// result
|
||||
// }
|
||||
}
|
||||
|
||||
/// longjmp
|
||||
#[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)");
|
||||
unsafe {
|
||||
// We retrieve the jump index from the env address
|
||||
let jump_index = emscripten_memory_pointer!(ctx.memory(0), env_addr) as *mut i8;
|
||||
let jumps = &mut get_emscripten_data(ctx).jumps;
|
||||
// We get the real jump buffer from the jumps vector, using the retrieved index
|
||||
let jump_buf = &jumps[*jump_index as usize];
|
||||
longjmp(jump_buf.get() as _, val)
|
||||
};
|
||||
abort_with_message(ctx, "missing function: _longjmp");
|
||||
// unsafe {
|
||||
// // We retrieve the jump index from the env address
|
||||
// let jump_index = emscripten_memory_pointer!(ctx.memory(0), env_addr) as *mut i8;
|
||||
// let jumps = &mut get_emscripten_data(ctx).jumps;
|
||||
// // We get the real jump buffer from the jumps vector, using the retrieved index
|
||||
// let jump_buf = &jumps[*jump_index as usize];
|
||||
// longjmp(jump_buf.get() as _, val)
|
||||
// };
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
fn setjmp(env: *mut c_void) -> c_int;
|
||||
fn longjmp(env: *mut c_void, val: c_int) -> !;
|
||||
/// _longjmp
|
||||
// This function differs from the js implementation, it should return Result<(), &'static str>
|
||||
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;
|
||||
|
||||
// EMSCRIPTEN APIS
|
||||
mod bitwise;
|
||||
mod emscripten_target;
|
||||
mod env;
|
||||
mod errno;
|
||||
mod exception;
|
||||
mod exec;
|
||||
mod exit;
|
||||
mod io;
|
||||
mod jmp;
|
||||
mod linking;
|
||||
mod lock;
|
||||
mod math;
|
||||
mod memory;
|
||||
mod nullfunc;
|
||||
mod process;
|
||||
mod signal;
|
||||
mod storage;
|
||||
@ -54,8 +56,6 @@ pub use self::utils::{
|
||||
|
||||
// TODO: Magic number - how is this calculated?
|
||||
const TOTAL_STACK: u32 = 5_242_880;
|
||||
// TODO: Magic number - how is this calculated?
|
||||
const DYNAMICTOP_PTR_DIFF: u32 = 1088;
|
||||
// TODO: make this variable
|
||||
const STATIC_BUMP: u32 = 215_536;
|
||||
|
||||
@ -71,22 +71,6 @@ lazy_static! {
|
||||
const GLOBAL_BASE: u32 = 1024;
|
||||
const STATIC_BASE: u32 = GLOBAL_BASE;
|
||||
|
||||
fn stacktop(static_bump: u32) -> u32 {
|
||||
align_memory(dynamictop_ptr(static_bump) + 4)
|
||||
}
|
||||
|
||||
fn stack_max(static_bump: u32) -> u32 {
|
||||
stacktop(static_bump) + TOTAL_STACK
|
||||
}
|
||||
|
||||
fn dynamic_base(static_bump: u32) -> u32 {
|
||||
align_memory(stack_max(static_bump))
|
||||
}
|
||||
|
||||
fn dynamictop_ptr(static_bump: u32) -> u32 {
|
||||
static_bump + DYNAMICTOP_PTR_DIFF
|
||||
}
|
||||
|
||||
pub struct EmscriptenData<'a> {
|
||||
pub malloc: Func<'a, u32, u32>,
|
||||
pub free: Func<'a, u32>,
|
||||
@ -99,6 +83,7 @@ pub struct EmscriptenData<'a> {
|
||||
pub dyn_call_ii: Option<Func<'a, (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_iifi: Option<Func<'a, (i32, i32, f64, i32), i32>>,
|
||||
pub dyn_call_v: Option<Func<'a, (i32)>>,
|
||||
pub dyn_call_vi: Option<Func<'a, (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_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_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_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_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_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_iiijj: Option<Func<'a, (i32, i32, i32, i32, i32, i32, i32), i32>>,
|
||||
pub dyn_call_j: Option<Func<'a, 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_jjj: 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_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_vj: Option<Func<'a, (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_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_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> {
|
||||
@ -151,6 +158,7 @@ impl<'a> EmscriptenData<'a> {
|
||||
let dyn_call_ii = instance.func("dynCall_ii").ok();
|
||||
let dyn_call_iii = instance.func("dynCall_iii").ok();
|
||||
let dyn_call_iiii = instance.func("dynCall_iiii").ok();
|
||||
let dyn_call_iifi = instance.func("dynCall_iifi").ok();
|
||||
let dyn_call_v = instance.func("dynCall_v").ok();
|
||||
let dyn_call_vi = instance.func("dynCall_vi").ok();
|
||||
let dyn_call_vii = instance.func("dynCall_vii").ok();
|
||||
@ -162,15 +170,24 @@ impl<'a> EmscriptenData<'a> {
|
||||
let dyn_call_diiii = instance.func("dynCall_diiii").ok();
|
||||
let dyn_call_iiiii = instance.func("dynCall_iiiii").ok();
|
||||
let dyn_call_iiiiii = instance.func("dynCall_iiiiii").ok();
|
||||
let dyn_call_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_viiiii = instance.func("dynCall_viiiii").ok();
|
||||
let dyn_call_viiiiii = instance.func("dynCall_viiiiii").ok();
|
||||
let dyn_call_viiiiiii = instance.func("dynCall_viiiiiii").ok();
|
||||
let dyn_call_viiiiiiii = instance.func("dynCall_viiiiiiii").ok();
|
||||
let dyn_call_viiiiiiiii = instance.func("dynCall_viiiiiiiii").ok();
|
||||
let dyn_call_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_iiijj = instance.func("dynCall_iiijj").ok();
|
||||
let dyn_call_j = instance.func("dynCall_j").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_jjj = instance.func("dynCall_jjj").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_viijiii = instance.func("dynCall_viijiii").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_viji = instance.func("dynCall_viji").ok();
|
||||
let dyn_call_vijiii = instance.func("dynCall_vijiii").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 {
|
||||
malloc,
|
||||
@ -196,6 +221,7 @@ impl<'a> EmscriptenData<'a> {
|
||||
dyn_call_ii,
|
||||
dyn_call_iii,
|
||||
dyn_call_iiii,
|
||||
dyn_call_iifi,
|
||||
dyn_call_v,
|
||||
dyn_call_vi,
|
||||
dyn_call_vii,
|
||||
@ -207,15 +233,24 @@ impl<'a> EmscriptenData<'a> {
|
||||
dyn_call_diiii,
|
||||
dyn_call_iiiii,
|
||||
dyn_call_iiiiii,
|
||||
dyn_call_iiiiiii,
|
||||
dyn_call_iiiiiiii,
|
||||
dyn_call_iiiiiiiii,
|
||||
dyn_call_iiiiiiiiii,
|
||||
dyn_call_iiiiiiiiiii,
|
||||
dyn_call_vd,
|
||||
dyn_call_viiiii,
|
||||
dyn_call_viiiiii,
|
||||
dyn_call_viiiiiii,
|
||||
dyn_call_viiiiiiii,
|
||||
dyn_call_viiiiiiiii,
|
||||
dyn_call_viiiiiiiiii,
|
||||
dyn_call_iij,
|
||||
dyn_call_iiji,
|
||||
dyn_call_iiijj,
|
||||
dyn_call_j,
|
||||
dyn_call_ji,
|
||||
dyn_call_jii,
|
||||
dyn_call_jij,
|
||||
dyn_call_jjj,
|
||||
dyn_call_viiij,
|
||||
@ -225,10 +260,19 @@ impl<'a> EmscriptenData<'a> {
|
||||
dyn_call_viiji,
|
||||
dyn_call_viijiii,
|
||||
dyn_call_viijj,
|
||||
dyn_call_vj,
|
||||
dyn_call_vij,
|
||||
dyn_call_viji,
|
||||
dyn_call_vijiii,
|
||||
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;
|
||||
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") {
|
||||
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);
|
||||
Ok(())
|
||||
}
|
||||
@ -309,10 +359,6 @@ pub struct EmscriptenGlobalsData {
|
||||
table_base: u32,
|
||||
temp_double_ptr: u32,
|
||||
use_old_abort_on_cannot_grow_memory: bool,
|
||||
|
||||
// Global namespace
|
||||
infinity: f64,
|
||||
nan: f64,
|
||||
}
|
||||
|
||||
pub struct EmscriptenGlobals {
|
||||
@ -323,6 +369,7 @@ pub struct EmscriptenGlobals {
|
||||
pub table: Table,
|
||||
pub memory_min: Pages,
|
||||
pub memory_max: Option<Pages>,
|
||||
pub null_func_names: Vec<String>,
|
||||
}
|
||||
|
||||
impl EmscriptenGlobals {
|
||||
@ -341,7 +388,7 @@ impl EmscriptenGlobals {
|
||||
if name == "abortOnCannotGrowMemory" && namespace == "env" {
|
||||
let sig_index = module.info().func_assoc[index.convert_up(module.info())];
|
||||
let expected_sig = &module.info().signatures[sig_index];
|
||||
if **expected_sig == *OLD_ABORT_ON_CANNOT_GROW_MEMORY_SIG {
|
||||
if *expected_sig == *OLD_ABORT_ON_CANNOT_GROW_MEMORY_SIG {
|
||||
use_old_abort_on_cannot_grow_memory = true;
|
||||
}
|
||||
break;
|
||||
@ -364,22 +411,22 @@ impl EmscriptenGlobals {
|
||||
minimum: table_min,
|
||||
maximum: table_max,
|
||||
};
|
||||
let mut table = Table::new(table_type).unwrap();
|
||||
let table = Table::new(table_type).unwrap();
|
||||
|
||||
let data = {
|
||||
let static_bump = STATIC_BUMP;
|
||||
|
||||
let mut STATIC_TOP = STATIC_BASE + static_bump;
|
||||
let mut static_top = STATIC_BASE + static_bump;
|
||||
|
||||
let memory_base = STATIC_BASE;
|
||||
let table_base = 0;
|
||||
|
||||
let temp_double_ptr = STATIC_TOP;
|
||||
STATIC_TOP += 16;
|
||||
let temp_double_ptr = static_top;
|
||||
static_top += 16;
|
||||
|
||||
let dynamictop_ptr = static_alloc(&mut STATIC_TOP, 4);
|
||||
let dynamictop_ptr = static_alloc(&mut static_top, 4);
|
||||
|
||||
let stacktop = align_memory(STATIC_TOP);
|
||||
let stacktop = align_memory(static_top);
|
||||
let stack_max = stacktop + TOTAL_STACK;
|
||||
|
||||
EmscriptenGlobalsData {
|
||||
@ -391,20 +438,34 @@ impl EmscriptenGlobals {
|
||||
table_base,
|
||||
temp_double_ptr,
|
||||
use_old_abort_on_cannot_grow_memory,
|
||||
|
||||
infinity: std::f64::INFINITY,
|
||||
nan: std::f64::NAN,
|
||||
}
|
||||
};
|
||||
|
||||
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 {
|
||||
data,
|
||||
memory,
|
||||
table,
|
||||
memory_min,
|
||||
memory_max,
|
||||
null_func_names,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -416,291 +477,349 @@ pub fn generate_emscripten_env(globals: &mut EmscriptenGlobals) -> ImportObject
|
||||
func!(crate::memory::abort_on_cannot_grow_memory).to_export()
|
||||
};
|
||||
|
||||
imports! {
|
||||
"env" => {
|
||||
"memory" => Export::Memory(globals.memory.clone()),
|
||||
"table" => Export::Table(globals.table.clone()),
|
||||
let mut env_ns = namespace! {
|
||||
"memory" => Export::Memory(globals.memory.clone()),
|
||||
"table" => Export::Table(globals.table.clone()),
|
||||
|
||||
// Globals
|
||||
"STACKTOP" => Global::new(Value::I32(globals.data.stacktop as i32)),
|
||||
"STACK_MAX" => Global::new(Value::I32(globals.data.stack_max as i32)),
|
||||
"DYNAMICTOP_PTR" => Global::new(Value::I32(globals.data.dynamictop_ptr as i32)),
|
||||
"tableBase" => Global::new(Value::I32(globals.data.table_base as i32)),
|
||||
"__table_base" => Global::new(Value::I32(globals.data.table_base as i32)),
|
||||
"ABORT" => Global::new(Value::I32(globals.data.abort as i32)),
|
||||
"memoryBase" => Global::new(Value::I32(globals.data.memory_base as i32)),
|
||||
"__memory_base" => Global::new(Value::I32(globals.data.memory_base as i32)),
|
||||
"tempDoublePtr" => Global::new(Value::I32(globals.data.temp_double_ptr as i32)),
|
||||
// Globals
|
||||
"STACKTOP" => Global::new(Value::I32(globals.data.stacktop as i32)),
|
||||
"STACK_MAX" => Global::new(Value::I32(globals.data.stack_max as i32)),
|
||||
"DYNAMICTOP_PTR" => Global::new(Value::I32(globals.data.dynamictop_ptr as i32)),
|
||||
"tableBase" => Global::new(Value::I32(globals.data.table_base as i32)),
|
||||
"__table_base" => Global::new(Value::I32(globals.data.table_base as i32)),
|
||||
"ABORT" => Global::new(Value::I32(globals.data.abort as i32)),
|
||||
"memoryBase" => Global::new(Value::I32(globals.data.memory_base as i32)),
|
||||
"__memory_base" => Global::new(Value::I32(globals.data.memory_base as i32)),
|
||||
"tempDoublePtr" => Global::new(Value::I32(globals.data.temp_double_ptr as i32)),
|
||||
|
||||
// IO
|
||||
"printf" => func!(crate::io::printf),
|
||||
"putchar" => func!(crate::io::putchar),
|
||||
"___lock" => func!(crate::lock::___lock),
|
||||
"___unlock" => func!(crate::lock::___unlock),
|
||||
"___wait" => func!(crate::lock::___wait),
|
||||
// IO
|
||||
"printf" => func!(crate::io::printf),
|
||||
"putchar" => func!(crate::io::putchar),
|
||||
"___lock" => func!(crate::lock::___lock),
|
||||
"___unlock" => func!(crate::lock::___unlock),
|
||||
"___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),
|
||||
|
||||
// Env
|
||||
"___assert_fail" => func!(crate::env::___assert_fail),
|
||||
"_getenv" => func!(crate::env::_getenv),
|
||||
"_setenv" => func!(crate::env::_setenv),
|
||||
"_putenv" => func!(crate::env::_putenv),
|
||||
"_unsetenv" => func!(crate::env::_unsetenv),
|
||||
"_getpwnam" => func!(crate::env::_getpwnam),
|
||||
"_getgrnam" => func!(crate::env::_getgrnam),
|
||||
"___buildEnvironment" => func!(crate::env::___build_environment),
|
||||
"___setErrNo" => func!(crate::errno::___seterrno),
|
||||
"_getpagesize" => func!(crate::env::_getpagesize),
|
||||
"_sysconf" => func!(crate::env::_sysconf),
|
||||
"_getaddrinfo" => func!(crate::env::_getaddrinfo),
|
||||
// exec
|
||||
"_execvp" => func!(crate::exec::execvp),
|
||||
"_execl" => func!(crate::exec::execl),
|
||||
"_execle" => func!(crate::exec::execle),
|
||||
|
||||
// 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),
|
||||
// exit
|
||||
"__exit" => func!(crate::exit::exit),
|
||||
|
||||
// Syscalls
|
||||
"___syscall1" => func!(crate::syscalls::___syscall1),
|
||||
"___syscall3" => func!(crate::syscalls::___syscall3),
|
||||
"___syscall4" => func!(crate::syscalls::___syscall4),
|
||||
"___syscall5" => func!(crate::syscalls::___syscall5),
|
||||
"___syscall6" => func!(crate::syscalls::___syscall6),
|
||||
"___syscall10" => func!(crate::syscalls::___syscall10),
|
||||
"___syscall12" => func!(crate::syscalls::___syscall12),
|
||||
"___syscall15" => func!(crate::syscalls::___syscall15),
|
||||
"___syscall20" => func!(crate::syscalls::___syscall20),
|
||||
"___syscall39" => func!(crate::syscalls::___syscall39),
|
||||
"___syscall38" => func!(crate::syscalls::___syscall38),
|
||||
"___syscall40" => func!(crate::syscalls::___syscall40),
|
||||
"___syscall54" => func!(crate::syscalls::___syscall54),
|
||||
"___syscall57" => func!(crate::syscalls::___syscall57),
|
||||
"___syscall60" => func!(crate::syscalls::___syscall60),
|
||||
"___syscall63" => func!(crate::syscalls::___syscall63),
|
||||
"___syscall64" => func!(crate::syscalls::___syscall64),
|
||||
"___syscall66" => func!(crate::syscalls::___syscall66),
|
||||
"___syscall75" => func!(crate::syscalls::___syscall75),
|
||||
"___syscall85" => func!(crate::syscalls::___syscall85),
|
||||
"___syscall91" => func!(crate::syscalls::___syscall191),
|
||||
"___syscall97" => func!(crate::syscalls::___syscall97),
|
||||
"___syscall102" => func!(crate::syscalls::___syscall102),
|
||||
"___syscall110" => func!(crate::syscalls::___syscall110),
|
||||
"___syscall114" => func!(crate::syscalls::___syscall114),
|
||||
"___syscall122" => func!(crate::syscalls::___syscall122),
|
||||
"___syscall140" => func!(crate::syscalls::___syscall140),
|
||||
"___syscall142" => func!(crate::syscalls::___syscall142),
|
||||
"___syscall145" => func!(crate::syscalls::___syscall145),
|
||||
"___syscall146" => func!(crate::syscalls::___syscall146),
|
||||
"___syscall168" => func!(crate::syscalls::___syscall168),
|
||||
"___syscall180" => func!(crate::syscalls::___syscall180),
|
||||
"___syscall181" => func!(crate::syscalls::___syscall181),
|
||||
"___syscall191" => func!(crate::syscalls::___syscall191),
|
||||
"___syscall192" => func!(crate::syscalls::___syscall192),
|
||||
"___syscall194" => func!(crate::syscalls::___syscall194),
|
||||
"___syscall195" => func!(crate::syscalls::___syscall195),
|
||||
"___syscall196" => func!(crate::syscalls::___syscall196),
|
||||
"___syscall197" => func!(crate::syscalls::___syscall197),
|
||||
"___syscall199" => func!(crate::syscalls::___syscall199),
|
||||
"___syscall201" => func!(crate::syscalls::___syscall201),
|
||||
"___syscall202" => func!(crate::syscalls::___syscall202),
|
||||
"___syscall212" => func!(crate::syscalls::___syscall212),
|
||||
"___syscall220" => func!(crate::syscalls::___syscall220),
|
||||
"___syscall221" => func!(crate::syscalls::___syscall221),
|
||||
"___syscall268" => func!(crate::syscalls::___syscall268),
|
||||
"___syscall272" => func!(crate::syscalls::___syscall272),
|
||||
"___syscall295" => func!(crate::syscalls::___syscall295),
|
||||
"___syscall300" => func!(crate::syscalls::___syscall300),
|
||||
"___syscall330" => func!(crate::syscalls::___syscall330),
|
||||
"___syscall334" => func!(crate::syscalls::___syscall334),
|
||||
"___syscall340" => func!(crate::syscalls::___syscall340),
|
||||
// Env
|
||||
"___assert_fail" => func!(crate::env::___assert_fail),
|
||||
"_getenv" => func!(crate::env::_getenv),
|
||||
"_setenv" => func!(crate::env::_setenv),
|
||||
"_putenv" => func!(crate::env::_putenv),
|
||||
"_unsetenv" => func!(crate::env::_unsetenv),
|
||||
"_getpwnam" => func!(crate::env::_getpwnam),
|
||||
"_getgrnam" => func!(crate::env::_getgrnam),
|
||||
"___buildEnvironment" => func!(crate::env::___build_environment),
|
||||
"___setErrNo" => func!(crate::errno::___seterrno),
|
||||
"_getpagesize" => func!(crate::env::_getpagesize),
|
||||
"_sysconf" => func!(crate::env::_sysconf),
|
||||
"_getaddrinfo" => func!(crate::env::_getaddrinfo),
|
||||
"_times" => func!(crate::env::_times),
|
||||
|
||||
// Process
|
||||
"abort" => func!(crate::process::em_abort),
|
||||
"_abort" => func!(crate::process::_abort),
|
||||
"abortStackOverflow" => func!(crate::process::abort_stack_overflow),
|
||||
"_llvm_trap" => func!(crate::process::_llvm_trap),
|
||||
"_fork" => func!(crate::process::_fork),
|
||||
"_exit" => func!(crate::process::_exit),
|
||||
"_system" => func!(crate::process::_system),
|
||||
"_popen" => func!(crate::process::_popen),
|
||||
"_endgrent" => func!(crate::process::_endgrent),
|
||||
"_execve" => func!(crate::process::_execve),
|
||||
"_kill" => func!(crate::process::_kill),
|
||||
"_llvm_stackrestore" => func!(crate::process::_llvm_stackrestore),
|
||||
"_llvm_stacksave" => func!(crate::process::_llvm_stacksave),
|
||||
"_raise" => func!(crate::process::_raise),
|
||||
"_sem_init" => func!(crate::process::_sem_init),
|
||||
"_sem_post" => func!(crate::process::_sem_post),
|
||||
"_sem_wait" => func!(crate::process::_sem_wait),
|
||||
"_getgrent" => func!(crate::process::_getgrent),
|
||||
"_sched_yield" => func!(crate::process::_sched_yield),
|
||||
"_setgrent" => func!(crate::process::_setgrent),
|
||||
"_setgroups" => func!(crate::process::_setgroups),
|
||||
"_setitimer" => func!(crate::process::_setitimer),
|
||||
"_usleep" => func!(crate::process::_usleep),
|
||||
"_utimes" => func!(crate::process::_utimes),
|
||||
"_waitpid" => func!(crate::process::_waitpid),
|
||||
// Syscalls
|
||||
"___syscall1" => func!(crate::syscalls::___syscall1),
|
||||
"___syscall3" => func!(crate::syscalls::___syscall3),
|
||||
"___syscall4" => func!(crate::syscalls::___syscall4),
|
||||
"___syscall5" => func!(crate::syscalls::___syscall5),
|
||||
"___syscall6" => func!(crate::syscalls::___syscall6),
|
||||
"___syscall9" => func!(crate::syscalls::___syscall9),
|
||||
"___syscall10" => func!(crate::syscalls::___syscall10),
|
||||
"___syscall12" => func!(crate::syscalls::___syscall12),
|
||||
"___syscall15" => func!(crate::syscalls::___syscall15),
|
||||
"___syscall20" => func!(crate::syscalls::___syscall20),
|
||||
"___syscall33" => func!(crate::syscalls::___syscall33),
|
||||
"___syscall34" => func!(crate::syscalls::___syscall34),
|
||||
"___syscall39" => func!(crate::syscalls::___syscall39),
|
||||
"___syscall38" => func!(crate::syscalls::___syscall38),
|
||||
"___syscall40" => func!(crate::syscalls::___syscall40),
|
||||
"___syscall41" => func!(crate::syscalls::___syscall41),
|
||||
"___syscall42" => func!(crate::syscalls::___syscall42),
|
||||
"___syscall54" => func!(crate::syscalls::___syscall54),
|
||||
"___syscall57" => func!(crate::syscalls::___syscall57),
|
||||
"___syscall60" => func!(crate::syscalls::___syscall60),
|
||||
"___syscall63" => func!(crate::syscalls::___syscall63),
|
||||
"___syscall64" => func!(crate::syscalls::___syscall64),
|
||||
"___syscall66" => func!(crate::syscalls::___syscall66),
|
||||
"___syscall75" => func!(crate::syscalls::___syscall75),
|
||||
"___syscall77" => func!(crate::syscalls::___syscall77),
|
||||
"___syscall83" => func!(crate::syscalls::___syscall83),
|
||||
"___syscall85" => func!(crate::syscalls::___syscall85),
|
||||
"___syscall91" => func!(crate::syscalls::___syscall91),
|
||||
"___syscall94" => func!(crate::syscalls::___syscall94),
|
||||
"___syscall97" => func!(crate::syscalls::___syscall97),
|
||||
"___syscall102" => func!(crate::syscalls::___syscall102),
|
||||
"___syscall110" => func!(crate::syscalls::___syscall110),
|
||||
"___syscall114" => func!(crate::syscalls::___syscall114),
|
||||
"___syscall118" => func!(crate::syscalls::___syscall118),
|
||||
"___syscall122" => func!(crate::syscalls::___syscall122),
|
||||
"___syscall140" => func!(crate::syscalls::___syscall140),
|
||||
"___syscall142" => func!(crate::syscalls::___syscall142),
|
||||
"___syscall145" => func!(crate::syscalls::___syscall145),
|
||||
"___syscall146" => func!(crate::syscalls::___syscall146),
|
||||
"___syscall148" => func!(crate::syscalls::___syscall148),
|
||||
"___syscall168" => func!(crate::syscalls::___syscall168),
|
||||
"___syscall180" => func!(crate::syscalls::___syscall180),
|
||||
"___syscall181" => func!(crate::syscalls::___syscall181),
|
||||
"___syscall183" => func!(crate::syscalls::___syscall183),
|
||||
"___syscall191" => func!(crate::syscalls::___syscall191),
|
||||
"___syscall192" => func!(crate::syscalls::___syscall192),
|
||||
"___syscall194" => func!(crate::syscalls::___syscall194),
|
||||
"___syscall195" => func!(crate::syscalls::___syscall195),
|
||||
"___syscall196" => func!(crate::syscalls::___syscall196),
|
||||
"___syscall197" => func!(crate::syscalls::___syscall197),
|
||||
"___syscall198" => func!(crate::syscalls::___syscall198),
|
||||
"___syscall199" => func!(crate::syscalls::___syscall199),
|
||||
"___syscall200" => func!(crate::syscalls::___syscall200),
|
||||
"___syscall201" => func!(crate::syscalls::___syscall201),
|
||||
"___syscall202" => func!(crate::syscalls::___syscall202),
|
||||
"___syscall205" => func!(crate::syscalls::___syscall205),
|
||||
"___syscall207" => func!(crate::syscalls::___syscall207),
|
||||
"___syscall212" => func!(crate::syscalls::___syscall212),
|
||||
"___syscall219" => func!(crate::syscalls::___syscall219),
|
||||
"___syscall220" => func!(crate::syscalls::___syscall220),
|
||||
"___syscall221" => func!(crate::syscalls::___syscall221),
|
||||
"___syscall268" => func!(crate::syscalls::___syscall268),
|
||||
"___syscall272" => func!(crate::syscalls::___syscall272),
|
||||
"___syscall295" => func!(crate::syscalls::___syscall295),
|
||||
"___syscall300" => func!(crate::syscalls::___syscall300),
|
||||
"___syscall324" => func!(crate::syscalls::___syscall324),
|
||||
"___syscall330" => func!(crate::syscalls::___syscall330),
|
||||
"___syscall334" => func!(crate::syscalls::___syscall334),
|
||||
"___syscall340" => func!(crate::syscalls::___syscall340),
|
||||
|
||||
// Process
|
||||
"abort" => func!(crate::process::em_abort),
|
||||
"_abort" => func!(crate::process::_abort),
|
||||
"abortStackOverflow" => func!(crate::process::abort_stack_overflow),
|
||||
"_llvm_trap" => func!(crate::process::_llvm_trap),
|
||||
"_fork" => func!(crate::process::_fork),
|
||||
"_exit" => func!(crate::process::_exit),
|
||||
"_system" => func!(crate::process::_system),
|
||||
"_popen" => func!(crate::process::_popen),
|
||||
"_endgrent" => func!(crate::process::_endgrent),
|
||||
"_execve" => func!(crate::process::_execve),
|
||||
"_kill" => func!(crate::process::_kill),
|
||||
"_llvm_stackrestore" => func!(crate::process::_llvm_stackrestore),
|
||||
"_llvm_stacksave" => func!(crate::process::_llvm_stacksave),
|
||||
"_llvm_eh_typeid_for" => func!(crate::process::_llvm_eh_typeid_for),
|
||||
"_raise" => func!(crate::process::_raise),
|
||||
"_sem_init" => func!(crate::process::_sem_init),
|
||||
"_sem_post" => func!(crate::process::_sem_post),
|
||||
"_sem_wait" => func!(crate::process::_sem_wait),
|
||||
"_getgrent" => func!(crate::process::_getgrent),
|
||||
"_sched_yield" => func!(crate::process::_sched_yield),
|
||||
"_setgrent" => func!(crate::process::_setgrent),
|
||||
"_setgroups" => func!(crate::process::_setgroups),
|
||||
"_setitimer" => func!(crate::process::_setitimer),
|
||||
"_usleep" => func!(crate::process::_usleep),
|
||||
"_nanosleep" => func!(crate::process::_nanosleep),
|
||||
"_utimes" => func!(crate::process::_utimes),
|
||||
"_waitpid" => func!(crate::process::_waitpid),
|
||||
|
||||
|
||||
// Signal
|
||||
"_sigemptyset" => func!(crate::signal::_sigemptyset),
|
||||
"_sigaddset" => func!(crate::signal::_sigaddset),
|
||||
"_sigprocmask" => func!(crate::signal::_sigprocmask),
|
||||
"_sigaction" => func!(crate::signal::_sigaction),
|
||||
"_signal" => func!(crate::signal::_signal),
|
||||
"_sigsuspend" => func!(crate::signal::_sigsuspend),
|
||||
// Signal
|
||||
"_sigemptyset" => func!(crate::signal::_sigemptyset),
|
||||
"_sigaddset" => func!(crate::signal::_sigaddset),
|
||||
"_sigprocmask" => func!(crate::signal::_sigprocmask),
|
||||
"_sigaction" => func!(crate::signal::_sigaction),
|
||||
"_signal" => func!(crate::signal::_signal),
|
||||
"_sigsuspend" => func!(crate::signal::_sigsuspend),
|
||||
|
||||
// Memory
|
||||
"abortOnCannotGrowMemory" => abort_on_cannot_grow_memory_export,
|
||||
"_emscripten_memcpy_big" => func!(crate::memory::_emscripten_memcpy_big),
|
||||
"_emscripten_get_heap_size" => func!(crate::memory::_emscripten_get_heap_size),
|
||||
"_emscripten_resize_heap" => func!(crate::memory::_emscripten_resize_heap),
|
||||
"enlargeMemory" => func!(crate::memory::enlarge_memory),
|
||||
"getTotalMemory" => func!(crate::memory::get_total_memory),
|
||||
"___map_file" => func!(crate::memory::___map_file),
|
||||
// Memory
|
||||
"abortOnCannotGrowMemory" => abort_on_cannot_grow_memory_export,
|
||||
"_emscripten_memcpy_big" => func!(crate::memory::_emscripten_memcpy_big),
|
||||
"_emscripten_get_heap_size" => func!(crate::memory::_emscripten_get_heap_size),
|
||||
"_emscripten_resize_heap" => func!(crate::memory::_emscripten_resize_heap),
|
||||
"enlargeMemory" => func!(crate::memory::enlarge_memory),
|
||||
"getTotalMemory" => func!(crate::memory::get_total_memory),
|
||||
"___map_file" => func!(crate::memory::___map_file),
|
||||
|
||||
// Exception
|
||||
"___cxa_allocate_exception" => func!(crate::exception::___cxa_allocate_exception),
|
||||
"___cxa_throw" => func!(crate::exception::___cxa_throw),
|
||||
// Exception
|
||||
"___cxa_allocate_exception" => func!(crate::exception::___cxa_allocate_exception),
|
||||
"___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
|
||||
"_gettimeofday" => func!(crate::time::_gettimeofday),
|
||||
"_clock_gettime" => func!(crate::time::_clock_gettime),
|
||||
"___clock_gettime" => func!(crate::time::_clock_gettime),
|
||||
"_clock" => func!(crate::time::_clock),
|
||||
"_difftime" => func!(crate::time::_difftime),
|
||||
"_asctime" => func!(crate::time::_asctime),
|
||||
"_asctime_r" => func!(crate::time::_asctime_r),
|
||||
"_localtime" => func!(crate::time::_localtime),
|
||||
"_time" => func!(crate::time::_time),
|
||||
"_strftime" => func!(crate::time::_strftime),
|
||||
"_localtime_r" => func!(crate::time::_localtime_r),
|
||||
"_gmtime_r" => func!(crate::time::_gmtime_r),
|
||||
"_mktime" => func!(crate::time::_mktime),
|
||||
"_gmtime" => func!(crate::time::_gmtime),
|
||||
// Time
|
||||
"_gettimeofday" => func!(crate::time::_gettimeofday),
|
||||
"_clock_gettime" => func!(crate::time::_clock_gettime),
|
||||
"___clock_gettime" => func!(crate::time::_clock_gettime),
|
||||
"_clock" => func!(crate::time::_clock),
|
||||
"_difftime" => func!(crate::time::_difftime),
|
||||
"_asctime" => func!(crate::time::_asctime),
|
||||
"_asctime_r" => func!(crate::time::_asctime_r),
|
||||
"_localtime" => func!(crate::time::_localtime),
|
||||
"_time" => func!(crate::time::_time),
|
||||
"_strftime" => func!(crate::time::_strftime),
|
||||
"_strftime_l" => func!(crate::time::_strftime_l),
|
||||
"_localtime_r" => func!(crate::time::_localtime_r),
|
||||
"_gmtime_r" => func!(crate::time::_gmtime_r),
|
||||
"_mktime" => func!(crate::time::_mktime),
|
||||
"_gmtime" => func!(crate::time::_gmtime),
|
||||
|
||||
// Math
|
||||
"f64-rem" => func!(crate::math::f64_rem),
|
||||
"_llvm_log10_f64" => func!(crate::math::_llvm_log10_f64),
|
||||
"_llvm_log2_f64" => func!(crate::math::_llvm_log2_f64),
|
||||
"_llvm_log10_f32" => func!(crate::math::_llvm_log10_f32),
|
||||
"_llvm_log2_f32" => func!(crate::math::_llvm_log2_f64),
|
||||
"_emscripten_random" => func!(crate::math::_emscripten_random),
|
||||
// Math
|
||||
"f64-rem" => func!(crate::math::f64_rem),
|
||||
"_llvm_log10_f64" => func!(crate::math::_llvm_log10_f64),
|
||||
"_llvm_log2_f64" => func!(crate::math::_llvm_log2_f64),
|
||||
"_llvm_log10_f32" => func!(crate::math::_llvm_log10_f32),
|
||||
"_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),
|
||||
|
||||
// Jump
|
||||
"__setjmp" => func!(crate::jmp::__setjmp),
|
||||
"__longjmp" => func!(crate::jmp::__longjmp),
|
||||
// Jump
|
||||
"__setjmp" => func!(crate::jmp::__setjmp),
|
||||
"__longjmp" => func!(crate::jmp::__longjmp),
|
||||
"_longjmp" => func!(crate::jmp::_longjmp),
|
||||
"_emscripten_longjmp" => func!(crate::jmp::_longjmp),
|
||||
|
||||
// Linking
|
||||
"_dlclose" => func!(crate::linking::_dlclose),
|
||||
"_dlerror" => func!(crate::linking::_dlerror),
|
||||
"_dlopen" => func!(crate::linking::_dlopen),
|
||||
"_dlsym" => func!(crate::linking::_dlsym),
|
||||
// Bitwise
|
||||
"_llvm_bswap_i64" => func!(crate::bitwise::_llvm_bswap_i64),
|
||||
|
||||
// wasm32-unknown-emscripten
|
||||
"setTempRet0" => func!(crate::emscripten_target::setTempRet0),
|
||||
"getTempRet0" => func!(crate::emscripten_target::getTempRet0),
|
||||
"nullFunc_ji" => func!(crate::emscripten_target::nullFunc_ji),
|
||||
"invoke_i" => func!(crate::emscripten_target::invoke_i),
|
||||
"invoke_ii" => func!(crate::emscripten_target::invoke_ii),
|
||||
"invoke_iii" => func!(crate::emscripten_target::invoke_iii),
|
||||
"invoke_iiii" => func!(crate::emscripten_target::invoke_iiii),
|
||||
"invoke_v" => func!(crate::emscripten_target::invoke_v),
|
||||
"invoke_vi" => func!(crate::emscripten_target::invoke_vi),
|
||||
"invoke_vii" => func!(crate::emscripten_target::invoke_vii),
|
||||
"invoke_viii" => func!(crate::emscripten_target::invoke_viii),
|
||||
"invoke_viiii" => func!(crate::emscripten_target::invoke_viiii),
|
||||
"__Unwind_Backtrace" => func!(crate::emscripten_target::__Unwind_Backtrace),
|
||||
"__Unwind_FindEnclosingFunction" => func!(crate::emscripten_target::__Unwind_FindEnclosingFunction),
|
||||
"__Unwind_GetIPInfo" => func!(crate::emscripten_target::__Unwind_GetIPInfo),
|
||||
"___cxa_find_matching_catch_2" => func!(crate::emscripten_target::___cxa_find_matching_catch_2),
|
||||
"___cxa_find_matching_catch_3" => func!(crate::emscripten_target::___cxa_find_matching_catch_3),
|
||||
"___cxa_free_exception" => func!(crate::emscripten_target::___cxa_free_exception),
|
||||
"___resumeException" => func!(crate::emscripten_target::___resumeException),
|
||||
"_dladdr" => func!(crate::emscripten_target::_dladdr),
|
||||
"_pthread_cond_destroy" => func!(crate::emscripten_target::_pthread_cond_destroy),
|
||||
"_pthread_cond_init" => func!(crate::emscripten_target::_pthread_cond_init),
|
||||
"_pthread_cond_signal" => func!(crate::emscripten_target::_pthread_cond_signal),
|
||||
"_pthread_cond_wait" => func!(crate::emscripten_target::_pthread_cond_wait),
|
||||
"_pthread_condattr_destroy" => func!(crate::emscripten_target::_pthread_condattr_destroy),
|
||||
"_pthread_condattr_init" => func!(crate::emscripten_target::_pthread_condattr_init),
|
||||
"_pthread_condattr_setclock" => func!(crate::emscripten_target::_pthread_condattr_setclock),
|
||||
"_pthread_mutex_destroy" => func!(crate::emscripten_target::_pthread_mutex_destroy),
|
||||
"_pthread_mutex_init" => func!(crate::emscripten_target::_pthread_mutex_init),
|
||||
"_pthread_mutexattr_destroy" => func!(crate::emscripten_target::_pthread_mutexattr_destroy),
|
||||
"_pthread_mutexattr_init" => func!(crate::emscripten_target::_pthread_mutexattr_init),
|
||||
"_pthread_mutexattr_settype" => func!(crate::emscripten_target::_pthread_mutexattr_settype),
|
||||
"_pthread_rwlock_rdlock" => func!(crate::emscripten_target::_pthread_rwlock_rdlock),
|
||||
"_pthread_rwlock_unlock" => func!(crate::emscripten_target::_pthread_rwlock_unlock),
|
||||
"___gxx_personality_v0" => func!(crate::emscripten_target::___gxx_personality_v0),
|
||||
// round 2
|
||||
"nullFunc_dii" => func!(crate::emscripten_target::nullFunc_dii),
|
||||
"nullFunc_diiii" => func!(crate::emscripten_target::nullFunc_diiii),
|
||||
"nullFunc_iiji" => func!(crate::emscripten_target::nullFunc_iiji),
|
||||
"nullFunc_j" => func!(crate::emscripten_target::nullFunc_j),
|
||||
"nullFunc_jij" => func!(crate::emscripten_target::nullFunc_jij),
|
||||
"nullFunc_jjj" => func!(crate::emscripten_target::nullFunc_jjj),
|
||||
"nullFunc_vd" => func!(crate::emscripten_target::nullFunc_vd),
|
||||
"nullFunc_viiiiiii" => func!(crate::emscripten_target::nullFunc_viiiiiii),
|
||||
"nullFunc_viiiiiiii" => func!(crate::emscripten_target::nullFunc_viiiiiiii),
|
||||
"nullFunc_viiiiiiiii" => func!(crate::emscripten_target::nullFunc_viiiiiiiii),
|
||||
"nullFunc_viiij" => func!(crate::emscripten_target::nullFunc_viiij),
|
||||
"nullFunc_viiijiiii" => func!(crate::emscripten_target::nullFunc_viiijiiii),
|
||||
"nullFunc_viiijiiiiii" => func!(crate::emscripten_target::nullFunc_viiijiiiiii),
|
||||
"nullFunc_viij" => func!(crate::emscripten_target::nullFunc_viij),
|
||||
"nullFunc_viiji" => func!(crate::emscripten_target::nullFunc_viiji),
|
||||
"nullFunc_viijiii" => func!(crate::emscripten_target::nullFunc_viijiii),
|
||||
"nullFunc_viijj" => func!(crate::emscripten_target::nullFunc_viijj),
|
||||
"nullFunc_vij" => func!(crate::emscripten_target::nullFunc_vij),
|
||||
"nullFunc_viji" => func!(crate::emscripten_target::nullFunc_viji),
|
||||
"nullFunc_vijiii" => func!(crate::emscripten_target::nullFunc_vijiii),
|
||||
"nullFunc_vijj" => func!(crate::emscripten_target::nullFunc_vijj),
|
||||
"invoke_dii" => func!(crate::emscripten_target::invoke_dii),
|
||||
"invoke_diiii" => func!(crate::emscripten_target::invoke_diiii),
|
||||
"invoke_iiiii" => func!(crate::emscripten_target::invoke_iiiii),
|
||||
"invoke_iiiiii" => func!(crate::emscripten_target::invoke_iiiiii),
|
||||
"invoke_vd" => func!(crate::emscripten_target::invoke_vd),
|
||||
"invoke_viiiii" => func!(crate::emscripten_target::invoke_viiiii),
|
||||
"invoke_viiiiii" => func!(crate::emscripten_target::invoke_viiiiii),
|
||||
"invoke_viiiiiii" => func!(crate::emscripten_target::invoke_viiiiiii),
|
||||
"invoke_viiiiiiii" => func!(crate::emscripten_target::invoke_viiiiiiii),
|
||||
"invoke_viiiiiiiii" => func!(crate::emscripten_target::invoke_viiiiiiiii),
|
||||
"invoke_iiji" => func!(crate::emscripten_target::invoke_iiji),
|
||||
"invoke_j" => func!(crate::emscripten_target::invoke_j),
|
||||
"invoke_ji" => func!(crate::emscripten_target::invoke_ji),
|
||||
"invoke_jij" => func!(crate::emscripten_target::invoke_jij),
|
||||
"invoke_jjj" => func!(crate::emscripten_target::invoke_jjj),
|
||||
"invoke_viiij" => func!(crate::emscripten_target::invoke_viiij),
|
||||
"invoke_viiijiiii" => func!(crate::emscripten_target::invoke_viiijiiii),
|
||||
"invoke_viiijiiiiii" => func!(crate::emscripten_target::invoke_viiijiiiiii),
|
||||
"invoke_viij" => func!(crate::emscripten_target::invoke_viij),
|
||||
"invoke_viiji" => func!(crate::emscripten_target::invoke_viiji),
|
||||
"invoke_viijiii" => func!(crate::emscripten_target::invoke_viijiii),
|
||||
"invoke_viijj" => func!(crate::emscripten_target::invoke_viijj),
|
||||
"invoke_vij" => func!(crate::emscripten_target::invoke_vij),
|
||||
"invoke_viji" => func!(crate::emscripten_target::invoke_viji),
|
||||
"invoke_vijiii" => func!(crate::emscripten_target::invoke_vijiii),
|
||||
"invoke_vijj" => func!(crate::emscripten_target::invoke_vijj),
|
||||
},
|
||||
// Linking
|
||||
"_dlclose" => func!(crate::linking::_dlclose),
|
||||
"_dlerror" => func!(crate::linking::_dlerror),
|
||||
"_dlopen" => func!(crate::linking::_dlopen),
|
||||
"_dlsym" => func!(crate::linking::_dlsym),
|
||||
|
||||
// wasm32-unknown-emscripten
|
||||
"setTempRet0" => func!(crate::emscripten_target::setTempRet0),
|
||||
"getTempRet0" => func!(crate::emscripten_target::getTempRet0),
|
||||
"invoke_i" => func!(crate::emscripten_target::invoke_i),
|
||||
"invoke_ii" => func!(crate::emscripten_target::invoke_ii),
|
||||
"invoke_iii" => func!(crate::emscripten_target::invoke_iii),
|
||||
"invoke_iiii" => func!(crate::emscripten_target::invoke_iiii),
|
||||
"invoke_iifi" => func!(crate::emscripten_target::invoke_iifi),
|
||||
"invoke_v" => func!(crate::emscripten_target::invoke_v),
|
||||
"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_viii" => func!(crate::emscripten_target::invoke_viii),
|
||||
"invoke_viiii" => func!(crate::emscripten_target::invoke_viiii),
|
||||
"__Unwind_Backtrace" => func!(crate::emscripten_target::__Unwind_Backtrace),
|
||||
"__Unwind_FindEnclosingFunction" => func!(crate::emscripten_target::__Unwind_FindEnclosingFunction),
|
||||
"__Unwind_GetIPInfo" => func!(crate::emscripten_target::__Unwind_GetIPInfo),
|
||||
"___cxa_find_matching_catch_2" => func!(crate::emscripten_target::___cxa_find_matching_catch_2),
|
||||
"___cxa_find_matching_catch_3" => func!(crate::emscripten_target::___cxa_find_matching_catch_3),
|
||||
"___cxa_free_exception" => func!(crate::emscripten_target::___cxa_free_exception),
|
||||
"___resumeException" => func!(crate::emscripten_target::___resumeException),
|
||||
"_dladdr" => func!(crate::emscripten_target::_dladdr),
|
||||
"_pthread_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_init" => func!(crate::emscripten_target::_pthread_cond_init),
|
||||
"_pthread_cond_signal" => func!(crate::emscripten_target::_pthread_cond_signal),
|
||||
"_pthread_cond_wait" => func!(crate::emscripten_target::_pthread_cond_wait),
|
||||
"_pthread_condattr_destroy" => func!(crate::emscripten_target::_pthread_condattr_destroy),
|
||||
"_pthread_condattr_init" => func!(crate::emscripten_target::_pthread_condattr_init),
|
||||
"_pthread_condattr_setclock" => func!(crate::emscripten_target::_pthread_condattr_setclock),
|
||||
"_pthread_mutex_destroy" => func!(crate::emscripten_target::_pthread_mutex_destroy),
|
||||
"_pthread_mutex_init" => func!(crate::emscripten_target::_pthread_mutex_init),
|
||||
"_pthread_mutexattr_destroy" => func!(crate::emscripten_target::_pthread_mutexattr_destroy),
|
||||
"_pthread_mutexattr_init" => func!(crate::emscripten_target::_pthread_mutexattr_init),
|
||||
"_pthread_mutexattr_settype" => func!(crate::emscripten_target::_pthread_mutexattr_settype),
|
||||
"_pthread_rwlock_rdlock" => func!(crate::emscripten_target::_pthread_rwlock_rdlock),
|
||||
"_pthread_rwlock_unlock" => func!(crate::emscripten_target::_pthread_rwlock_unlock),
|
||||
"_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),
|
||||
"_getdtablesize" => func!(crate::emscripten_target::_getdtablesize),
|
||||
"_gethostbyaddr" => func!(crate::emscripten_target::_gethostbyaddr),
|
||||
"_gethostbyname_r" => func!(crate::emscripten_target::_gethostbyname_r),
|
||||
"_getloadavg" => func!(crate::emscripten_target::_getloadavg),
|
||||
"invoke_dii" => func!(crate::emscripten_target::invoke_dii),
|
||||
"invoke_diiii" => func!(crate::emscripten_target::invoke_diiii),
|
||||
"invoke_iiiii" => func!(crate::emscripten_target::invoke_iiiii),
|
||||
"invoke_iiiiii" => func!(crate::emscripten_target::invoke_iiiiii),
|
||||
"invoke_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_viiiii" => func!(crate::emscripten_target::invoke_viiiii),
|
||||
"invoke_viiiiii" => func!(crate::emscripten_target::invoke_viiiiii),
|
||||
"invoke_viiiiiii" => func!(crate::emscripten_target::invoke_viiiiiii),
|
||||
"invoke_viiiiiiii" => func!(crate::emscripten_target::invoke_viiiiiiii),
|
||||
"invoke_viiiiiiiii" => func!(crate::emscripten_target::invoke_viiiiiiiii),
|
||||
"invoke_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_iiijj" => func!(crate::emscripten_target::invoke_iiijj),
|
||||
"invoke_j" => func!(crate::emscripten_target::invoke_j),
|
||||
"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_jjj" => func!(crate::emscripten_target::invoke_jjj),
|
||||
"invoke_viiij" => func!(crate::emscripten_target::invoke_viiij),
|
||||
"invoke_viiijiiii" => func!(crate::emscripten_target::invoke_viiijiiii),
|
||||
"invoke_viiijiiiiii" => func!(crate::emscripten_target::invoke_viiijiiiiii),
|
||||
"invoke_viij" => func!(crate::emscripten_target::invoke_viij),
|
||||
"invoke_viiji" => func!(crate::emscripten_target::invoke_viiji),
|
||||
"invoke_viijiii" => func!(crate::emscripten_target::invoke_viijiii),
|
||||
"invoke_viijj" => func!(crate::emscripten_target::invoke_viijj),
|
||||
"invoke_vij" => func!(crate::emscripten_target::invoke_vij),
|
||||
"invoke_viji" => func!(crate::emscripten_target::invoke_viji),
|
||||
"invoke_vijiii" => func!(crate::emscripten_target::invoke_vijiii),
|
||||
"invoke_vijj" => func!(crate::emscripten_target::invoke_vijj),
|
||||
"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" => {
|
||||
"NaN" => Global::new(Value::F64(f64::NAN)),
|
||||
"Infinity" => Global::new(Value::F64(f64::INFINITY)),
|
||||
},
|
||||
"global.Math" => {
|
||||
"pow" => func!(crate::math::pow),
|
||||
"exp" => func!(crate::math::exp),
|
||||
"log" => func!(crate::math::log),
|
||||
},
|
||||
"asm2wasm" => {
|
||||
"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
|
||||
|
@ -2,16 +2,21 @@ use libc::c_int;
|
||||
use wasmer_runtime_core::vm::Ctx;
|
||||
|
||||
// NOTE: Not implemented by Emscripten
|
||||
pub fn ___lock(_ctx: &mut Ctx, what: c_int) {
|
||||
debug!("emscripten::___lock {}", what);
|
||||
pub fn ___lock(_ctx: &mut Ctx, _what: c_int) {
|
||||
debug!("emscripten::___lock {}", _what);
|
||||
}
|
||||
|
||||
// NOTE: Not implemented by Emscripten
|
||||
pub fn ___unlock(_ctx: &mut Ctx, what: c_int) {
|
||||
debug!("emscripten::___unlock {}", what);
|
||||
pub fn ___unlock(_ctx: &mut Ctx, _what: c_int) {
|
||||
debug!("emscripten::___unlock {}", _what);
|
||||
}
|
||||
|
||||
// NOTE: Not implemented by Emscripten
|
||||
pub fn ___wait(_ctx: &mut Ctx, _which: u32, _varargs: u32, _three: u32, _four: u32) {
|
||||
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()
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
debug!("emscripten::_llvm_log10_f32");
|
||||
-1.0
|
||||
@ -22,12 +34,22 @@ pub fn _llvm_log2_f32(_ctx: &mut Ctx, _value: f64) -> f64 {
|
||||
-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 {
|
||||
debug!("emscripten::_emscripten_random");
|
||||
-1.0
|
||||
}
|
||||
|
||||
// emscripten: f64-rem
|
||||
// emscripten: asm2wasm.f64-rem
|
||||
pub fn f64_rem(_ctx: &mut Ctx, x: f64, y: f64) -> f64 {
|
||||
debug!("emscripten::f64-rem");
|
||||
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 {
|
||||
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 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
|
||||
pub fn _emscripten_memcpy_big(ctx: &mut Ctx, dest: u32, src: u32, len: u32) -> u32 {
|
||||
@ -19,15 +22,44 @@ pub fn _emscripten_memcpy_big(ctx: &mut Ctx, dest: u32, src: u32, len: u32) -> u
|
||||
/// emscripten: _emscripten_get_heap_size
|
||||
pub fn _emscripten_get_heap_size(ctx: &mut Ctx) -> u32 {
|
||||
debug!("emscripten::_emscripten_get_heap_size",);
|
||||
// TODO: Fix implementation
|
||||
16_777_216
|
||||
ctx.memory(0).size().bytes().0 as u32
|
||||
}
|
||||
|
||||
// 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
|
||||
/// Note: this function only allows growing the size of heap
|
||||
pub fn _emscripten_resize_heap(ctx: &mut Ctx, requested_size: u32) -> u32 {
|
||||
debug!("emscripten::_emscripten_resize_heap {}", requested_size);
|
||||
// TODO: Fix implementation
|
||||
0
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
/// emscripten: getTotalMemory
|
||||
@ -35,7 +67,7 @@ pub fn get_total_memory(_ctx: &mut Ctx) -> u32 {
|
||||
debug!("emscripten::get_total_memory");
|
||||
// instance.memories[0].current_pages()
|
||||
// TODO: Fix implementation
|
||||
16_777_216
|
||||
_ctx.memory(0).size().bytes().0 as u32
|
||||
}
|
||||
|
||||
/// emscripten: enlargeMemory
|
||||
@ -47,8 +79,11 @@ pub fn enlarge_memory(_ctx: &mut Ctx) -> u32 {
|
||||
}
|
||||
|
||||
/// emscripten: abortOnCannotGrowMemory
|
||||
pub fn abort_on_cannot_grow_memory(ctx: &mut Ctx, requested_size: u32) -> u32 {
|
||||
debug!("emscripten::abort_on_cannot_grow_memory {}", requested_size);
|
||||
pub fn abort_on_cannot_grow_memory(ctx: &mut Ctx, _requested_size: u32) -> u32 {
|
||||
debug!(
|
||||
"emscripten::abort_on_cannot_grow_memory {}",
|
||||
_requested_size
|
||||
);
|
||||
abort_with_message(ctx, "Cannot enlarge memory arrays!");
|
||||
0
|
||||
}
|
||||
|
@ -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};
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
use libc::pid_t;
|
||||
|
||||
type PidT = libc::pid_t;
|
||||
#[cfg(target_os = "windows")]
|
||||
type pid_t = c_int;
|
||||
type PidT = c_int;
|
||||
|
||||
use std::ffi::CStr;
|
||||
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");
|
||||
// unsafe {
|
||||
// fork()
|
||||
@ -98,7 +97,7 @@ pub fn _sem_wait(_ctx: &mut Ctx, _one: i32) -> i32 {
|
||||
}
|
||||
|
||||
#[allow(clippy::cast_ptr_alignment)]
|
||||
pub fn _getgrent(ctx: &mut Ctx) -> c_int {
|
||||
pub fn _getgrent(_ctx: &mut Ctx) -> c_int {
|
||||
debug!("emscripten::_getgrent");
|
||||
-1
|
||||
}
|
||||
@ -122,6 +121,11 @@ pub fn _usleep(_ctx: &mut Ctx, _one: i32) -> i32 {
|
||||
-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 {
|
||||
debug!("emscripten::_utimes");
|
||||
-1
|
||||
@ -146,6 +150,11 @@ pub fn _llvm_trap(ctx: &mut Ctx) {
|
||||
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 {
|
||||
debug!("emscripten::_system");
|
||||
// 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
|
||||
}
|
||||
|
||||
pub fn _sigaction(_ctx: &mut Ctx, signum: u32, act: u32, oldact: u32) -> i32 {
|
||||
debug!("emscripten::_sigaction {}, {}, {}", signum, act, oldact);
|
||||
pub fn _sigaction(_ctx: &mut Ctx, _signum: u32, _act: u32, _oldact: u32) -> i32 {
|
||||
debug!("emscripten::_sigaction {}, {}, {}", _signum, _act, _oldact);
|
||||
0
|
||||
}
|
||||
|
||||
@ -36,7 +36,7 @@ pub fn _sigprocmask(_ctx: &mut Ctx, _one: i32, _two: i32, _three: i32) -> i32 {
|
||||
0
|
||||
}
|
||||
|
||||
pub fn _signal(_ctx: &mut Ctx, sig: u32, _two: i32) -> i32 {
|
||||
debug!("emscripten::_signal ({})", sig);
|
||||
pub fn _signal(_ctx: &mut Ctx, _sig: u32, _two: i32) -> i32 {
|
||||
debug!("emscripten::_signal ({})", _sig);
|
||||
0
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ pub struct StdioCapturer {
|
||||
use libc::{STDERR_FILENO, STDOUT_FILENO};
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
const STDIN_FILENO: libc::c_int = 0;
|
||||
const _STDIN_FILENO: libc::c_int = 0;
|
||||
#[cfg(target_os = "windows")]
|
||||
const STDOUT_FILENO: libc::c_int = 1;
|
||||
#[cfg(target_os = "windows")]
|
||||
|
@ -28,6 +28,7 @@ use libc::{
|
||||
getpid,
|
||||
// iovec,
|
||||
lseek,
|
||||
off_t,
|
||||
// open,
|
||||
read,
|
||||
// readv,
|
||||
@ -40,20 +41,15 @@ use libc::{
|
||||
use wasmer_runtime_core::vm::Ctx;
|
||||
|
||||
use super::env;
|
||||
use std::cell::Cell;
|
||||
#[allow(unused_imports)]
|
||||
use std::io::Error;
|
||||
use std::mem;
|
||||
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
|
||||
pub fn ___syscall1(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) {
|
||||
debug!("emscripten::___syscall1 (exit) {}", which);
|
||||
pub fn ___syscall1(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) {
|
||||
debug!("emscripten::___syscall1 (exit) {}", _which);
|
||||
let status: i32 = varargs.get(ctx);
|
||||
unsafe {
|
||||
exit(status);
|
||||
@ -61,47 +57,47 @@ pub fn ___syscall1(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) {
|
||||
}
|
||||
|
||||
/// read
|
||||
pub fn ___syscall3(ctx: &mut Ctx, which: i32, mut varargs: VarArgs) -> i32 {
|
||||
pub fn ___syscall3(ctx: &mut Ctx, _which: i32, mut varargs: VarArgs) -> i32 {
|
||||
// -> ssize_t
|
||||
debug!("emscripten::___syscall3 (read) {}", which);
|
||||
debug!("emscripten::___syscall3 (read) {}", _which);
|
||||
let fd: i32 = varargs.get(ctx);
|
||||
let buf: u32 = varargs.get(ctx);
|
||||
let count = varargs.get(ctx);
|
||||
let count: i32 = varargs.get(ctx);
|
||||
debug!("=> fd: {}, buf_offset: {}, count: {}", fd, buf, count);
|
||||
let buf_addr = emscripten_memory_pointer!(ctx.memory(0), buf) as *mut c_void;
|
||||
let ret = unsafe { read(fd, buf_addr, count) };
|
||||
let ret = unsafe { read(fd, buf_addr, count as _) };
|
||||
debug!("=> ret: {}", ret);
|
||||
ret as _
|
||||
}
|
||||
|
||||
/// write
|
||||
pub fn ___syscall4(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall4 (write) {}", which);
|
||||
pub fn ___syscall4(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall4 (write) {}", _which);
|
||||
let fd: i32 = varargs.get(ctx);
|
||||
let buf: u32 = varargs.get(ctx);
|
||||
let count = varargs.get(ctx);
|
||||
let count: i32 = varargs.get(ctx);
|
||||
debug!("=> fd: {}, buf: {}, count: {}", fd, buf, count);
|
||||
let buf_addr = emscripten_memory_pointer!(ctx.memory(0), buf) as *const c_void;
|
||||
unsafe { write(fd, buf_addr, count) as i32 }
|
||||
unsafe { write(fd, buf_addr, count as _) as i32 }
|
||||
}
|
||||
|
||||
/// close
|
||||
pub fn ___syscall6(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall6 (close) {}", which);
|
||||
pub fn ___syscall6(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall6 (close) {}", _which);
|
||||
let fd: i32 = varargs.get(ctx);
|
||||
debug!("fd: {}", fd);
|
||||
unsafe { close(fd) }
|
||||
}
|
||||
|
||||
// chdir
|
||||
pub fn ___syscall12(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall12 (chdir) {}", which);
|
||||
pub fn ___syscall12(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall12 (chdir) {}", _which);
|
||||
let path_addr: i32 = varargs.get(ctx);
|
||||
unsafe {
|
||||
let path_ptr = emscripten_memory_pointer!(ctx.memory(0), path_addr) as *const i8;
|
||||
let path = std::ffi::CStr::from_ptr(path_ptr);
|
||||
let _path = std::ffi::CStr::from_ptr(path_ptr);
|
||||
let ret = chdir(path_ptr);
|
||||
debug!("=> path: {:?}, ret: {}", path, ret);
|
||||
debug!("=> path: {:?}, ret: {}", _path, ret);
|
||||
ret
|
||||
}
|
||||
}
|
||||
@ -135,14 +131,40 @@ pub fn ___syscall40(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int
|
||||
unsafe { rmdir(pathname_addr) }
|
||||
}
|
||||
|
||||
// pipe
|
||||
pub fn ___syscall42(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall42 (pipe)");
|
||||
// offset to a file descriptor, which contains a read end and write end, 2 integers
|
||||
let fd_offset: u32 = varargs.get(ctx);
|
||||
|
||||
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 {
|
||||
debug!("emscripten::___syscall60");
|
||||
-1
|
||||
}
|
||||
|
||||
// dup2
|
||||
pub fn ___syscall63(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall63 (dup2) {}", which);
|
||||
pub fn ___syscall63(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall63 (dup2) {}", _which);
|
||||
|
||||
let src: i32 = varargs.get(ctx);
|
||||
let dst: i32 = varargs.get(ctx);
|
||||
@ -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 {
|
||||
debug!("emscripten::___syscall91");
|
||||
-1
|
||||
debug!("emscripten::___syscall91 - stub");
|
||||
0
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
// 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
|
||||
pub fn ___syscall192(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall192 (mmap2) {}", which);
|
||||
let addr: i32 = varargs.get(ctx);
|
||||
pub fn ___syscall192(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall192 (mmap2) {}", _which);
|
||||
let _addr: i32 = varargs.get(ctx);
|
||||
let len: u32 = varargs.get(ctx);
|
||||
let prot: i32 = varargs.get(ctx);
|
||||
let flags: i32 = varargs.get(ctx);
|
||||
let _prot: i32 = varargs.get(ctx);
|
||||
let _flags: i32 = varargs.get(ctx);
|
||||
let fd: i32 = varargs.get(ctx);
|
||||
let off: i32 = varargs.get(ctx);
|
||||
let _off: i32 = varargs.get(ctx);
|
||||
debug!(
|
||||
"=> addr: {}, len: {}, prot: {}, flags: {}, fd: {}, off: {}",
|
||||
addr, len, prot, flags, fd, off
|
||||
_addr, len, _prot, _flags, fd, _off
|
||||
);
|
||||
|
||||
if fd == -1 {
|
||||
@ -213,27 +256,39 @@ pub fn ___syscall192(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int
|
||||
}
|
||||
|
||||
/// lseek
|
||||
pub fn ___syscall140(ctx: &mut Ctx, which: i32, mut varargs: VarArgs) -> i32 {
|
||||
pub fn ___syscall140(ctx: &mut Ctx, _which: i32, mut varargs: VarArgs) -> i32 {
|
||||
// -> c_int
|
||||
debug!("emscripten::___syscall140 (lseek) {}", which);
|
||||
debug!("emscripten::___syscall140 (lseek) {}", _which);
|
||||
let fd: i32 = varargs.get(ctx);
|
||||
let offset = 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);
|
||||
debug!("=> fd: {}, offset: {}, whence = {}", fd, offset, whence);
|
||||
unsafe { lseek(fd, offset, whence) as _ }
|
||||
let offset = offset_low as off_t;
|
||||
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
|
||||
#[allow(clippy::cast_ptr_alignment)]
|
||||
pub fn ___syscall145(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> i32 {
|
||||
pub fn ___syscall145(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> i32 {
|
||||
// -> ssize_t
|
||||
debug!("emscripten::___syscall145 (readv) {}", which);
|
||||
// let fd: i32 = varargs.get(ctx);
|
||||
// let iov: u32 = varargs.get(ctx);
|
||||
// let iovcnt: i32 = varargs.get(ctx);
|
||||
// debug!("=> fd: {}, iov: {}, iovcnt = {}", fd, iov, iovcnt);
|
||||
// let iov_addr = emscripten_memory_pointer!(ctx.memory(0), iov) as *mut iovec;
|
||||
// unsafe { readv(fd, iov_addr, iovcnt) }
|
||||
debug!("emscripten::___syscall145 (readv) {}", _which);
|
||||
|
||||
let fd: i32 = varargs.get(ctx);
|
||||
let iov: i32 = varargs.get(ctx);
|
||||
@ -268,9 +323,9 @@ pub fn ___syscall145(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> i32 {
|
||||
|
||||
// writev
|
||||
#[allow(clippy::cast_ptr_alignment)]
|
||||
pub fn ___syscall146(ctx: &mut Ctx, which: i32, mut varargs: VarArgs) -> i32 {
|
||||
pub fn ___syscall146(ctx: &mut Ctx, _which: i32, mut varargs: VarArgs) -> i32 {
|
||||
// -> ssize_t
|
||||
debug!("emscripten::___syscall146 (writev) {}", which);
|
||||
debug!("emscripten::___syscall146 (writev) {}", _which);
|
||||
let fd: i32 = varargs.get(ctx);
|
||||
let iov: i32 = varargs.get(ctx);
|
||||
let iovcnt: i32 = varargs.get(ctx);
|
||||
@ -312,24 +367,14 @@ pub fn ___syscall191(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
||||
-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 {
|
||||
debug!("emscripten::___syscall199 - stub");
|
||||
-1
|
||||
}
|
||||
|
||||
// stat64
|
||||
pub fn ___syscall195(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall195 (stat64) {}", which);
|
||||
pub fn ___syscall195(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall195 (stat64) {}", _which);
|
||||
let pathname: u32 = varargs.get(ctx);
|
||||
let buf: u32 = varargs.get(ctx);
|
||||
|
||||
@ -338,7 +383,14 @@ pub fn ___syscall195(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int
|
||||
unsafe {
|
||||
let mut _stat: stat = std::mem::zeroed();
|
||||
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 {
|
||||
return ret;
|
||||
}
|
||||
@ -348,8 +400,8 @@ pub fn ___syscall195(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int
|
||||
}
|
||||
|
||||
// fstat64
|
||||
pub fn ___syscall197(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall197 (fstat64) {}", which);
|
||||
pub fn ___syscall197(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall197 (fstat64) {}", _which);
|
||||
let fd: c_int = varargs.get(ctx);
|
||||
let buf: u32 = varargs.get(ctx);
|
||||
|
||||
@ -372,13 +424,19 @@ pub fn ___syscall220(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
||||
}
|
||||
|
||||
// fcntl64
|
||||
pub fn ___syscall221(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall221 (fcntl64) {}", which);
|
||||
pub fn ___syscall221(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall221 (fcntl64) {}", _which);
|
||||
// fcntl64
|
||||
let _fd: i32 = varargs.get(ctx);
|
||||
let cmd: u32 = varargs.get(ctx);
|
||||
// (FAPPEND - 0x08
|
||||
// |FASYNC - 0x40
|
||||
// |FFSYNC - 0x80
|
||||
// |FNONBLOCK - 0x04
|
||||
debug!("=> fd: {}, cmd: {}", _fd, cmd);
|
||||
match cmd {
|
||||
2 => 0,
|
||||
13 | 14 => 0, // pretend file locking worked
|
||||
_ => -1,
|
||||
}
|
||||
}
|
||||
@ -409,8 +467,8 @@ pub fn ___syscall334(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
||||
}
|
||||
|
||||
// prlimit64
|
||||
pub fn ___syscall340(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall340 (prlimit64), {}", which);
|
||||
pub fn ___syscall340(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall340 (prlimit64), {}", _which);
|
||||
// NOTE: Doesn't really matter. Wasm modules cannot exceed WASM_PAGE_SIZE anyway.
|
||||
let _pid: i32 = varargs.get(ctx);
|
||||
let _resource: i32 = varargs.get(ctx);
|
||||
|
@ -3,27 +3,40 @@ use crate::varargs::VarArgs;
|
||||
/// Syscall list: https://www.cs.utexas.edu/~bismith/test/syscalls/syscalls32.html
|
||||
use libc::{
|
||||
accept,
|
||||
access,
|
||||
bind,
|
||||
// ENOTTY,
|
||||
c_char,
|
||||
c_int,
|
||||
c_void,
|
||||
chown,
|
||||
// fcntl, setsockopt, getppid
|
||||
connect,
|
||||
dup,
|
||||
dup2,
|
||||
fchmod,
|
||||
fchown,
|
||||
fcntl,
|
||||
// ENOTTY,
|
||||
fsync,
|
||||
getgid,
|
||||
getgroups,
|
||||
getpeername,
|
||||
getrusage,
|
||||
getsockname,
|
||||
getsockopt,
|
||||
gid_t,
|
||||
in_addr_t,
|
||||
in_port_t,
|
||||
ioctl,
|
||||
lchown,
|
||||
link,
|
||||
// iovec,
|
||||
listen,
|
||||
mkdir,
|
||||
mode_t,
|
||||
msghdr,
|
||||
nice,
|
||||
off_t,
|
||||
open,
|
||||
pid_t,
|
||||
pread,
|
||||
@ -40,9 +53,13 @@ use libc::{
|
||||
sendto,
|
||||
setpgid,
|
||||
setsockopt,
|
||||
size_t,
|
||||
sockaddr,
|
||||
socket,
|
||||
socklen_t,
|
||||
stat,
|
||||
symlink,
|
||||
uid_t,
|
||||
uname,
|
||||
utsname,
|
||||
EINVAL,
|
||||
@ -57,6 +74,9 @@ use libc::{
|
||||
};
|
||||
use wasmer_runtime_core::vm::Ctx;
|
||||
|
||||
use crate::utils;
|
||||
#[allow(unused_imports)]
|
||||
use std::io::Error;
|
||||
use std::mem;
|
||||
|
||||
// Linking to functions that are not provided by rust libc
|
||||
@ -64,10 +84,13 @@ use std::mem;
|
||||
#[link(name = "c")]
|
||||
extern "C" {
|
||||
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"))]
|
||||
use libc::wait4;
|
||||
use libc::{fallocate, fdatasync, ftruncate64, lstat, madvise, wait4};
|
||||
|
||||
// Another conditional constant for name resolution: Macos et iOS use
|
||||
// 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;
|
||||
|
||||
/// open
|
||||
pub fn ___syscall5(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall5 (open) {}", which);
|
||||
pub fn ___syscall5(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall5 (open) {}", _which);
|
||||
let pathname: u32 = varargs.get(ctx);
|
||||
let flags: i32 = varargs.get(ctx);
|
||||
let mode: u32 = varargs.get(ctx);
|
||||
let pathname_addr = emscripten_memory_pointer!(ctx.memory(0), pathname) as *const i8;
|
||||
let path_str = unsafe { std::ffi::CStr::from_ptr(pathname_addr).to_str().unwrap() };
|
||||
let _path_str = unsafe { std::ffi::CStr::from_ptr(pathname_addr).to_str().unwrap() };
|
||||
let fd = unsafe { open(pathname_addr, flags, mode) };
|
||||
debug!(
|
||||
"=> pathname: {}, flags: {}, mode: {} = fd: {}\npath: {}",
|
||||
pathname, flags, mode, fd, path_str
|
||||
"=> pathname: {}, flags: {}, mode: {} = fd: {}\npath: {}\nlast os error: {}",
|
||||
pathname,
|
||||
flags,
|
||||
mode,
|
||||
fd,
|
||||
_path_str,
|
||||
Error::last_os_error(),
|
||||
);
|
||||
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
|
||||
pub fn ___syscall212(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall212 (chown) {}", which);
|
||||
pub fn ___syscall212(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall212 (chown) {}", _which);
|
||||
|
||||
let pathname: u32 = varargs.get(ctx);
|
||||
let owner: u32 = varargs.get(ctx);
|
||||
@ -106,15 +230,63 @@ pub fn ___syscall212(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int
|
||||
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
|
||||
pub fn ___syscall39(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall39 (mkdir) {}", which);
|
||||
pub fn ___syscall39(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall39 (mkdir) {}", _which);
|
||||
let pathname: u32 = varargs.get(ctx);
|
||||
let mode: u32 = varargs.get(ctx);
|
||||
let pathname_addr = emscripten_memory_pointer!(ctx.memory(0), pathname) as *const i8;
|
||||
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
|
||||
pub fn ___syscall201(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
||||
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
|
||||
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
|
||||
@ -169,8 +350,8 @@ pub fn ___syscall330(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> pid_
|
||||
}
|
||||
|
||||
/// ioctl
|
||||
pub fn ___syscall54(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall54 (ioctl) {}", which);
|
||||
pub fn ___syscall54(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall54 (ioctl) {}", _which);
|
||||
let fd: i32 = varargs.get(ctx);
|
||||
let request: u32 = varargs.get(ctx);
|
||||
debug!("fd: {}, op: {}", fd, request);
|
||||
@ -212,8 +393,8 @@ pub fn ___syscall54(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int
|
||||
|
||||
// socketcall
|
||||
#[allow(clippy::cast_ptr_alignment)]
|
||||
pub fn ___syscall102(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall102 (socketcall) {}", which);
|
||||
pub fn ___syscall102(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall102 (socketcall) {}", _which);
|
||||
let call: u32 = varargs.get(ctx);
|
||||
let mut socket_varargs: VarArgs = varargs.get(ctx);
|
||||
|
||||
@ -279,13 +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;
|
||||
|
||||
// Debug received address
|
||||
unsafe {
|
||||
let proper_address = address as *const GuestSockaddrIn;
|
||||
debug!(
|
||||
let _proper_address = address as *const GuestSockaddrIn;
|
||||
debug!(
|
||||
"=> address.sin_family: {:?}, address.sin_port: {:?}, address.sin_addr.s_addr: {:?}",
|
||||
(*proper_address).sin_family, (*proper_address).sin_port, (*proper_address).sin_addr.s_addr
|
||||
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) };
|
||||
// debug!("=> status: {}", status);
|
||||
@ -464,8 +643,8 @@ pub fn ___syscall102(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int
|
||||
}
|
||||
|
||||
// pread
|
||||
pub fn ___syscall180(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall180 (pread) {}", which);
|
||||
pub fn ___syscall180(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall180 (pread) {}", _which);
|
||||
let fd: i32 = varargs.get(ctx);
|
||||
let buf: u32 = varargs.get(ctx);
|
||||
let count: u32 = varargs.get(ctx);
|
||||
@ -481,8 +660,8 @@ pub fn ___syscall180(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int
|
||||
}
|
||||
|
||||
// pwrite
|
||||
pub fn ___syscall181(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall181 (pwrite) {}", which);
|
||||
pub fn ___syscall181(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall181 (pwrite) {}", _which);
|
||||
let fd: i32 = varargs.get(ctx);
|
||||
let buf: u32 = varargs.get(ctx);
|
||||
let count: u32 = varargs.get(ctx);
|
||||
@ -501,6 +680,14 @@ pub fn ___syscall181(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int
|
||||
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
|
||||
#[allow(clippy::cast_ptr_alignment)]
|
||||
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 rusage: u32 = varargs.get(ctx);
|
||||
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 res = unsafe { wait4(pid, status_addr, options, rusage_addr) };
|
||||
debug!(
|
||||
@ -519,10 +707,17 @@ pub fn ___syscall114(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> pid_
|
||||
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
|
||||
#[allow(clippy::cast_ptr_alignment)]
|
||||
pub fn ___syscall142(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall142 (newselect) {}", which);
|
||||
pub fn ___syscall142(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall142 (newselect) {}", _which);
|
||||
|
||||
let nfds: i32 = varargs.get(ctx);
|
||||
let readfds: u32 = varargs.get(ctx);
|
||||
@ -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 _) }
|
||||
}
|
||||
|
||||
/// 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
|
||||
pub fn ___syscall57(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall57 (setpgid) {}", which);
|
||||
pub fn ___syscall57(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall57 (setpgid) {}", _which);
|
||||
let pid: i32 = varargs.get(ctx);
|
||||
let pgid: i32 = varargs.get(ctx);
|
||||
unsafe { setpgid(pid, pgid) }
|
||||
@ -549,10 +753,55 @@ pub fn ___syscall57(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int
|
||||
|
||||
/// uname
|
||||
// NOTE: Wondering if we should return custom utsname, like Emscripten.
|
||||
pub fn ___syscall122(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall122 (uname) {}", which);
|
||||
pub fn ___syscall122(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall122 (uname) {}", _which);
|
||||
let buf: u32 = varargs.get(ctx);
|
||||
debug!("=> buf: {}", buf);
|
||||
let buf_addr = emscripten_memory_pointer!(ctx.memory(0), buf) as *mut utsname;
|
||||
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::read_string_from_wasm;
|
||||
use crate::varargs::VarArgs;
|
||||
use libc::mkdir;
|
||||
use libc::open;
|
||||
use rand::Rng;
|
||||
use std::env;
|
||||
use std::ffi::CStr;
|
||||
use std::ffi::CString;
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
use std::os::raw::c_int;
|
||||
use wasmer_runtime_core::vm::Ctx;
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
type pid_t = c_int;
|
||||
|
||||
/// open
|
||||
pub fn ___syscall5(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall5 (open) {}", which);
|
||||
#[cfg(not(feature = "debug"))]
|
||||
let _ = which;
|
||||
let pathname: u32 = varargs.get(ctx);
|
||||
let flags: i32 = 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();
|
||||
// create some random bytes and put them into the file
|
||||
let random_bytes = rand::thread_rng().gen::<[u8; 32]>();
|
||||
urandom_file.write_all(&random_bytes);
|
||||
let _ = urandom_file.write_all(&random_bytes).unwrap();
|
||||
// put the file path string into wasm memory
|
||||
let urandom_file_offset = unsafe { copy_cstr_into_wasm(ctx, ptr) };
|
||||
let raw_pointer_to_urandom_file =
|
||||
emscripten_memory_pointer!(ctx.memory(0), urandom_file_offset) as *const i8;
|
||||
let fd = unsafe { open(raw_pointer_to_urandom_file, flags, mode) };
|
||||
debug!(
|
||||
"=> pathname: {}, flags: {}, mode: {} = fd: {}\npath: {}",
|
||||
pathname, flags, mode, fd, s
|
||||
"=> pathname: {}, flags: {}, mode: {} = fd: {}",
|
||||
pathname, flags, mode, 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
|
||||
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);
|
||||
#[cfg(not(feature = "debug"))]
|
||||
let _ = which;
|
||||
-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
|
||||
pub fn ___syscall39(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall39 (mkdir) {}", which);
|
||||
#[cfg(not(feature = "debug"))]
|
||||
let _ = which;
|
||||
let pathname: u32 = varargs.get(ctx);
|
||||
let mode: u32 = varargs.get(ctx);
|
||||
let pathname_addr = emscripten_memory_pointer!(ctx.memory(0), pathname) as *const i8;
|
||||
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
|
||||
pub fn ___syscall201(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
||||
debug!("emscripten::___syscall201 (getgid)");
|
||||
@ -85,60 +143,122 @@ pub fn ___syscall202(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
||||
-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
|
||||
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)");
|
||||
-1
|
||||
}
|
||||
|
||||
/// 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);
|
||||
#[cfg(not(feature = "debug"))]
|
||||
let _ = which;
|
||||
-1
|
||||
}
|
||||
|
||||
/// fchmod
|
||||
pub fn ___syscall94(_ctx: &mut Ctx, _which: c_int, _varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall118 (fchmod) {}", _which);
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
// socketcall
|
||||
#[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);
|
||||
#[cfg(not(feature = "debug"))]
|
||||
let _ = which;
|
||||
-1
|
||||
}
|
||||
|
||||
/// fsync
|
||||
pub fn ___syscall118(_ctx: &mut Ctx, _which: c_int, _varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall118 (fsync) {}", _which);
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
// 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);
|
||||
#[cfg(not(feature = "debug"))]
|
||||
let _ = which;
|
||||
-1
|
||||
}
|
||||
|
||||
// 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);
|
||||
#[cfg(not(feature = "debug"))]
|
||||
let _ = which;
|
||||
-1
|
||||
}
|
||||
|
||||
/// wait4
|
||||
#[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)");
|
||||
-1
|
||||
}
|
||||
|
||||
// select
|
||||
#[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);
|
||||
#[cfg(not(feature = "debug"))]
|
||||
let _ = which;
|
||||
-1
|
||||
}
|
||||
|
||||
/// fdatasync
|
||||
pub fn ___syscall148(_ctx: &mut Ctx, _which: c_int, _varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall148 (fdatasync) {}", _which);
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
// 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);
|
||||
#[cfg(not(feature = "debug"))]
|
||||
let _ = which;
|
||||
-1
|
||||
}
|
||||
|
||||
/// uname
|
||||
// NOTE: Wondering if we should return custom utsname, like Emscripten.
|
||||
pub fn ___syscall122(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
pub fn ___syscall122(_ctx: &mut Ctx, which: c_int, mut _varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall122 (uname) {}", which);
|
||||
#[cfg(not(feature = "debug"))]
|
||||
let _ = which;
|
||||
-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;
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
#[allow(non_camel_case_types)]
|
||||
type clockid_t = c_int;
|
||||
|
||||
#[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,
|
||||
}
|
||||
|
||||
#[allow(unreachable_patterns)]
|
||||
let timespec = match clk_id {
|
||||
CLOCK_REALTIME => time::get_time(),
|
||||
|
||||
CLOCK_MONOTONIC | CLOCK_MONOTONIC_COARSE => {
|
||||
let precise_ns = time::precise_time_ns();
|
||||
time::Timespec::new(
|
||||
@ -295,7 +298,7 @@ pub fn _time(ctx: &mut Ctx, time_p: u32) -> i32 {
|
||||
|
||||
/// emscripten: _strftime
|
||||
pub fn _strftime(
|
||||
_ctx: &mut Ctx,
|
||||
ctx: &mut Ctx,
|
||||
s_ptr: c_int,
|
||||
maxsize: u32,
|
||||
format_ptr: c_int,
|
||||
@ -305,5 +308,67 @@ pub fn _strftime(
|
||||
"emscripten::_strftime {} {} {} {}",
|
||||
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)
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
pub unsafe fn copy_terminated_array_of_cstrs(_ctx: &mut Ctx, cstrs: *mut *mut c_char) -> u32 {
|
||||
let total_num = {
|
||||
let _total_num = {
|
||||
let mut ptr = cstrs;
|
||||
let mut counter = 0;
|
||||
while !(*ptr).is_null() {
|
||||
@ -102,7 +103,7 @@ pub unsafe fn copy_terminated_array_of_cstrs(_ctx: &mut Ctx, cstrs: *mut *mut c_
|
||||
};
|
||||
debug!(
|
||||
"emscripten::copy_terminated_array_of_cstrs::total_num: {}",
|
||||
total_num
|
||||
_total_num
|
||||
);
|
||||
0
|
||||
}
|
||||
@ -124,7 +125,7 @@ pub struct GuestStat {
|
||||
st_atime: u64,
|
||||
st_mtime: u64,
|
||||
st_ctime: u64,
|
||||
st_ino: u64,
|
||||
st_ino: u32,
|
||||
}
|
||||
|
||||
#[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 _;
|
||||
}
|
||||
|
||||
#[allow(dead_code)] // it's used in `env/windows/mod.rs`.
|
||||
pub fn read_string_from_wasm(memory: &Memory, offset: u32) -> String {
|
||||
let v: Vec<u8> = memory.view()[(offset as usize)..]
|
||||
.iter()
|
||||
@ -169,15 +171,40 @@ mod tests {
|
||||
use super::is_emscripten_module;
|
||||
use std::sync::Arc;
|
||||
use wabt::wat2wasm;
|
||||
use wasmer_clif_backend::CraneliftCompiler;
|
||||
use wasmer_runtime_core::backend::Compiler;
|
||||
use wasmer_runtime_core::compile_with;
|
||||
|
||||
#[cfg(feature = "clif")]
|
||||
fn get_compiler() -> impl Compiler {
|
||||
use wasmer_clif_backend::CraneliftCompiler;
|
||||
CraneliftCompiler::new()
|
||||
}
|
||||
|
||||
#[cfg(feature = "llvm")]
|
||||
fn get_compiler() -> impl Compiler {
|
||||
use wasmer_llvm_backend::LLVMCompiler;
|
||||
LLVMCompiler::new()
|
||||
}
|
||||
|
||||
#[cfg(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]
|
||||
fn should_detect_emscripten_files() {
|
||||
const WAST_BYTES: &[u8] = include_bytes!("tests/is_emscripten_true.wast");
|
||||
let wasm_binary = wat2wasm(WAST_BYTES.to_vec()).expect("Can't convert to wasm");
|
||||
let module = compile_with(&wasm_binary[..], &CraneliftCompiler::new())
|
||||
.expect("WASM can't be compiled");
|
||||
let module =
|
||||
compile_with(&wasm_binary[..], &get_compiler()).expect("WASM can't be compiled");
|
||||
let module = Arc::new(module);
|
||||
assert!(is_emscripten_module(&module));
|
||||
}
|
||||
@ -186,8 +213,8 @@ mod tests {
|
||||
fn should_detect_non_emscripten_files() {
|
||||
const WAST_BYTES: &[u8] = include_bytes!("tests/is_emscripten_false.wast");
|
||||
let wasm_binary = wat2wasm(WAST_BYTES.to_vec()).expect("Can't convert to wasm");
|
||||
let module = compile_with(&wasm_binary[..], &CraneliftCompiler::new())
|
||||
.expect("WASM can't be compiled");
|
||||
let module =
|
||||
compile_with(&wasm_binary[..], &get_compiler()).expect("WASM can't be compiled");
|
||||
let module = Arc::new(module);
|
||||
assert!(!is_emscripten_module(&module));
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user