mirror of
https://github.com/mii443/wasmer.git
synced 2025-12-07 05:08:19 +00:00
Merge branch 'master' into doc-readmes
This commit is contained in:
10
.github/workflows/main.yaml
vendored
10
.github/workflows/main.yaml
vendored
@@ -15,7 +15,7 @@ jobs:
|
|||||||
uses: actions-rs/toolchain@v1
|
uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
profile: minimal
|
profile: minimal
|
||||||
toolchain: nightly-2019-12-19
|
toolchain: 1.45.0
|
||||||
override: true
|
override: true
|
||||||
components: rustfmt, clippy
|
components: rustfmt, clippy
|
||||||
- run: make lint
|
- run: make lint
|
||||||
@@ -29,7 +29,7 @@ jobs:
|
|||||||
# uses: actions-rs/toolchain@v1
|
# uses: actions-rs/toolchain@v1
|
||||||
# with:
|
# with:
|
||||||
# profile: minimal
|
# profile: minimal
|
||||||
# toolchain: nightly-2019-12-19
|
# toolchain: 1.45.0
|
||||||
# override: true
|
# override: true
|
||||||
# components: rustfmt, clippy
|
# components: rustfmt, clippy
|
||||||
# - run: make doc-local
|
# - run: make doc-local
|
||||||
@@ -44,13 +44,13 @@ jobs:
|
|||||||
include:
|
include:
|
||||||
- build: linux
|
- build: linux
|
||||||
os: ubuntu-latest
|
os: ubuntu-latest
|
||||||
rust: nightly-2019-12-19
|
rust: 1.45.0
|
||||||
- build: macos
|
- build: macos
|
||||||
os: macos-latest
|
os: macos-latest
|
||||||
rust: nightly-2019-12-19
|
rust: 1.45.0
|
||||||
- build: windows
|
- build: windows
|
||||||
os: windows-latest
|
os: windows-latest
|
||||||
rust: nightly-2019-12-19
|
rust: 1.45.0
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- name: Install Rust ${{ matrix.rust }}
|
- name: Install Rust ${{ matrix.rust }}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ We recommend trying the following commands before sending a pull request to ensu
|
|||||||
|
|
||||||
- `cargo fmt --all` Ensures all code is correctly formatted.
|
- `cargo fmt --all` Ensures all code is correctly formatted.
|
||||||
- Run `cargo test` in the crates that you are modifying.
|
- Run `cargo test` in the crates that you are modifying.
|
||||||
- Run `cargo build --all` (nightly) or `cargo build --all --exclude wasmer-singlepass-backend`
|
- Run `cargo build --all`.
|
||||||
|
|
||||||
A comprehensive CI test suite will be run by a Wasmer team member after the PR has been created.
|
A comprehensive CI test suite will be run by a Wasmer team member after the PR has been created.
|
||||||
|
|
||||||
@@ -25,9 +25,3 @@ A comprehensive CI test suite will be run by a Wasmer team member after the PR h
|
|||||||
`Didn't find usable system-wide LLVM`
|
`Didn't find usable system-wide LLVM`
|
||||||
|
|
||||||
Building Wasmer with the LLVM backend requires LLVM to be installed
|
Building Wasmer with the LLVM backend requires LLVM to be installed
|
||||||
|
|
||||||
#### Singlepass Nightly Only
|
|
||||||
|
|
||||||
`error[E0554]: #![feature] may not be used on the stable release channel`
|
|
||||||
|
|
||||||
Building Wasmer with the singlepass backend requires the nightly version of Rust
|
|
||||||
|
|||||||
20
Cargo.lock
generated
20
Cargo.lock
generated
@@ -563,14 +563,14 @@ checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dynasm"
|
name = "dynasm"
|
||||||
version = "0.6.0"
|
version = "0.7.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "48be6e89d4c88d2945d5c57d50a2d7c46325a3ae358a11cdf263c545eace97c6"
|
checksum = "6a93688d3993e998336f7e31d1272bafc078f7665c8b883bd08f140e73d2e9cd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"owning_ref",
|
"proc-macro-error",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn",
|
||||||
@@ -578,11 +578,12 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dynasmrt"
|
name = "dynasmrt"
|
||||||
version = "0.6.0"
|
version = "0.7.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7dce4800e1140e94ad07e35e789df569516fd795223600a96f3b01887a42e0da"
|
checksum = "acae550ea0de09db4dcb18d4cd49f9f7963edd34783a4571429ba2c4e13e1e09"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder",
|
"byteorder",
|
||||||
|
"dynasm",
|
||||||
"memmap",
|
"memmap",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -1165,15 +1166,6 @@ dependencies = [
|
|||||||
"sdl2",
|
"sdl2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "owning_ref"
|
|
||||||
version = "0.4.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "6ff55baddef9e4ad00f88b6c743a2a8062d4c6ade126c2a528644b8e444d52ce"
|
|
||||||
dependencies = [
|
|
||||||
"stable_deref_trait",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "parking_lot"
|
name = "parking_lot"
|
||||||
version = "0.10.2"
|
version = "0.10.2"
|
||||||
|
|||||||
@@ -53,6 +53,9 @@ cfg-if = "0.1"
|
|||||||
members = [
|
members = [
|
||||||
"lib/c-api",
|
"lib/c-api",
|
||||||
]
|
]
|
||||||
|
exclude = [
|
||||||
|
"lib/deprecated",
|
||||||
|
]
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
test-generator = { path = "tests/lib/test-generator" }
|
test-generator = { path = "tests/lib/test-generator" }
|
||||||
|
|||||||
19
Makefile
19
Makefile
@@ -10,21 +10,13 @@ endif
|
|||||||
|
|
||||||
compilers :=
|
compilers :=
|
||||||
|
|
||||||
# Singlepass is enabled
|
|
||||||
RUST_VERSION := $(shell rustc -V)
|
|
||||||
|
|
||||||
ifneq (, $(findstring nightly,$(RUST_VERSION)))
|
|
||||||
# Singlepass doesn't work yet on Windows
|
|
||||||
ifneq ($(OS), Windows_NT)
|
|
||||||
compilers += singlepass
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(ARCH), x86_64)
|
ifeq ($(ARCH), x86_64)
|
||||||
# In X64, Cranelift is enabled
|
# In X64, Cranelift is enabled
|
||||||
compilers += cranelift
|
compilers += cranelift
|
||||||
# LLVM could be enabled if not in Windows
|
# LLVM could be enabled if not in Windows
|
||||||
ifneq ($(OS), Windows_NT)
|
ifneq ($(OS), Windows_NT)
|
||||||
|
# Singlepass doesn't work yet on Windows
|
||||||
|
compilers += singlepass
|
||||||
# Autodetect LLVM from llvm-config
|
# Autodetect LLVM from llvm-config
|
||||||
ifneq (, $(shell which llvm-config))
|
ifneq (, $(shell which llvm-config))
|
||||||
LLVM_VERSION := $(shell llvm-config --version)
|
LLVM_VERSION := $(shell llvm-config --version)
|
||||||
@@ -96,7 +88,7 @@ build-capi-llvm:
|
|||||||
# Testing #
|
# Testing #
|
||||||
###########
|
###########
|
||||||
|
|
||||||
test: $(foreach compiler,$(compilers),test-$(compiler)) test-packages test-examples
|
test: $(foreach compiler,$(compilers),test-$(compiler)) test-packages test-examples test-deprecated
|
||||||
|
|
||||||
test-singlepass:
|
test-singlepass:
|
||||||
cargo test --release $(compiler_features) --features "test-singlepass"
|
cargo test --release $(compiler_features) --features "test-singlepass"
|
||||||
@@ -135,6 +127,11 @@ test-wasi-unit:
|
|||||||
test-examples:
|
test-examples:
|
||||||
cargo test --release $(compiler_features) --features wasi --examples
|
cargo test --release $(compiler_features) --features wasi --examples
|
||||||
|
|
||||||
|
test-deprecated:
|
||||||
|
cargo test --manifest-path lib/deprecated/runtime-core/Cargo.toml -p wasmer-runtime-core --release
|
||||||
|
cargo test --manifest-path lib/deprecated/runtime/Cargo.toml -p wasmer-runtime --release
|
||||||
|
cargo test --manifest-path lib/deprecated/runtime/Cargo.toml -p wasmer-runtime --release --examples
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# Packaging #
|
# Packaging #
|
||||||
#############
|
#############
|
||||||
|
|||||||
4
fuzz/.gitignore
vendored
Normal file
4
fuzz/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
target
|
||||||
|
corpus
|
||||||
|
artifacts
|
||||||
49
fuzz/Cargo.toml
Normal file
49
fuzz/Cargo.toml
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
|
||||||
|
[package]
|
||||||
|
name = "wasmer-bin-fuzz"
|
||||||
|
version = "0.0.0"
|
||||||
|
authors = ["Automatically generated"]
|
||||||
|
publish = false
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[package.metadata]
|
||||||
|
cargo-fuzz = true
|
||||||
|
|
||||||
|
[dependencies.wasmer]
|
||||||
|
path = "../lib/api"
|
||||||
|
[dependencies.wasmer-compiler-cranelift]
|
||||||
|
path = "../lib/compiler-cranelift"
|
||||||
|
[dependencies.wasmer-compiler-llvm]
|
||||||
|
path = "../lib/compiler-llvm"
|
||||||
|
[dependencies.wasmer-compiler-singlepass]
|
||||||
|
path = "../lib/compiler-singlepass"
|
||||||
|
[dependencies.wasmer-engine-jit]
|
||||||
|
path = "../lib/engine-jit"
|
||||||
|
[dependencies.wasmer-engine-native]
|
||||||
|
path = "../lib/engine-native"
|
||||||
|
[dependencies.libfuzzer-sys]
|
||||||
|
git = "https://github.com/rust-fuzz/libfuzzer-sys.git"
|
||||||
|
|
||||||
|
# Prevent this from interfering with workspaces
|
||||||
|
[workspace]
|
||||||
|
members = ["."]
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "validate"
|
||||||
|
path = "fuzz_targets/validate.rs"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "jit_cranelift"
|
||||||
|
path = "fuzz_targets/jit_cranelift.rs"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "jit_llvm"
|
||||||
|
path = "fuzz_targets/jit_llvm.rs"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "jit_singlepass"
|
||||||
|
path = "fuzz_targets/jit_singlepass.rs"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "native_cranelift"
|
||||||
|
path = "fuzz_targets/native_cranelift.rs"
|
||||||
52
fuzz/README.md
Normal file
52
fuzz/README.md
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
This directory contains the fuzz tests for wasmer. To fuzz, we use the `cargo-fuzz` package.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
You may need to install the `cargo-fuzz` package to get the `cargo fuzz` subcommand. Use
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ cargo install cargo-fuzz
|
||||||
|
```
|
||||||
|
|
||||||
|
`cargo-fuzz` is documented in the [Rust Fuzz Book](https://rust-fuzz.github.io/book/cargo-fuzz.html).
|
||||||
|
|
||||||
|
## Running a fuzzer (validate, jit_llvm, native_cranelift, ...)
|
||||||
|
|
||||||
|
Once `cargo-fuzz` is installed, you can run the `validate` fuzzer with
|
||||||
|
```sh
|
||||||
|
cargo fuzz run validate
|
||||||
|
```
|
||||||
|
or the `jit_cranelift` fuzzer
|
||||||
|
```sh
|
||||||
|
cargo fuzz run jit_cranelift
|
||||||
|
```
|
||||||
|
See the [fuzz/fuzz_targets](https://github.com/wasmerio/wasmer-reborn/tree/fuzz/fuzz_targets/) directory for the full list of targets.
|
||||||
|
|
||||||
|
You should see output that looks something like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
#1408022 NEW cov: 115073 ft: 503843 corp: 4659/1807Kb lim: 4096 exec/s: 889 rss: 857Mb L: 2588/4096 MS: 1 ChangeASCIIInt-
|
||||||
|
#1408273 NEW cov: 115073 ft: 503844 corp: 4660/1808Kb lim: 4096 exec/s: 888 rss: 857Mb L: 1197/4096 MS: 1 ShuffleBytes-
|
||||||
|
#1408534 NEW cov: 115073 ft: 503866 corp: 4661/1809Kb lim: 4096 exec/s: 886 rss: 857Mb L: 977/4096 MS: 1 ShuffleBytes-
|
||||||
|
#1408540 NEW cov: 115073 ft: 503869 corp: 4662/1811Kb lim: 4096 exec/s: 886 rss: 857Mb L: 2067/4096 MS: 1 ChangeBit-
|
||||||
|
#1408831 NEW cov: 115073 ft: 503945 corp: 4663/1811Kb lim: 4096 exec/s: 885 rss: 857Mb L: 460/4096 MS: 1 CMP- DE: "\x16\x00\x00\x00\x00\x00\x00\x00"-
|
||||||
|
#1408977 NEW cov: 115073 ft: 503946 corp: 4664/1813Kb lim: 4096 exec/s: 885 rss: 857Mb L: 1972/4096 MS: 1 ShuffleBytes-
|
||||||
|
#1408999 NEW cov: 115073 ft: 503949 corp: 4665/1814Kb lim: 4096 exec/s: 884 rss: 857Mb L: 964/4096 MS: 2 ChangeBit-ShuffleBytes-
|
||||||
|
#1409040 NEW cov: 115073 ft: 503950 corp: 4666/1814Kb lim: 4096 exec/s: 884 rss: 857Mb L: 90/4096 MS: 1 ChangeBit-
|
||||||
|
#1409042 NEW cov: 115073 ft: 503951 corp: 4667/1814Kb lim: 4096 exec/s: 884 rss: 857Mb L: 174/4096 MS: 2 ChangeByte-ChangeASCIIInt-
|
||||||
|
```
|
||||||
|
|
||||||
|
It will continue to generate random inputs forever, until it finds a bug or is terminated. The testcases for bugs it finds go into `fuzz/artifacts/jit_cranelift` and you can rerun the fuzzer on a single input by passing it on the command line `cargo fuzz run jit_cranelift my_testcase.wasm`.
|
||||||
|
|
||||||
|
## Seeding the corpus, optional
|
||||||
|
|
||||||
|
The fuzzer works best when it has examples of small Wasm files to start with. Using `wast2json` from [wabt](https://github.com/WebAssembly/wabt), we can easily produce `.wasm` files out of the WebAssembly spec tests.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
mkdir spec-test-corpus
|
||||||
|
for i in `find tests/ -name "*.wast"`; do wast2json --enable-all $i -o spec-test-corpus/$(basename $i).json; done
|
||||||
|
mv spec-test-corpus/*.wasm fuzz/corpus/validate/
|
||||||
|
rm -r spec-test-corpus
|
||||||
|
```
|
||||||
|
|
||||||
|
The corpus directory is created on the first run of the fuzzer. If it doesn't exist, run it first and then seed the corpus. The fuzzer will pick up new files added to the corpus while it is running.
|
||||||
25
fuzz/fuzz_targets/headless_cranelift.rs
Normal file
25
fuzz/fuzz_targets/headless_cranelift.rs
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
#![no_main]
|
||||||
|
#[macro_use]
|
||||||
|
extern crate libfuzzer_sys;
|
||||||
|
|
||||||
|
use wasmer::{imports, Instance, Module, Store};
|
||||||
|
use wasmer_compiler_cranelift::Cranelift;
|
||||||
|
use wasmer_engine_native::Native;
|
||||||
|
|
||||||
|
fuzz_target!(|wasm_bytes: &[u8]| {
|
||||||
|
let serialized = {
|
||||||
|
let mut compiler = Cranelift::default();
|
||||||
|
let store = Store::new(&Native::new(&mut compiler).engine());
|
||||||
|
match Module::validate(&store, wasm_bytes) {
|
||||||
|
Err(_) => return,
|
||||||
|
Ok(_) => {}
|
||||||
|
};
|
||||||
|
let module = Module::new(&store, wasm_bytes).unwrap();
|
||||||
|
module.serialize().unwrap();
|
||||||
|
};
|
||||||
|
|
||||||
|
let engine = Native::headless().engine();
|
||||||
|
let store = Store::new(&engine);
|
||||||
|
let module = unsafe { Module::deserialize(&store, serialized) };
|
||||||
|
let _instance = Instance::new(&module, &imports! {});
|
||||||
|
});
|
||||||
21
fuzz/fuzz_targets/jit_cranelift.rs
Normal file
21
fuzz/fuzz_targets/jit_cranelift.rs
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
#![no_main]
|
||||||
|
#[macro_use]
|
||||||
|
extern crate libfuzzer_sys;
|
||||||
|
|
||||||
|
use wasmer::{imports, CompilerConfig, Instance, Module, Store};
|
||||||
|
use wasmer_compiler_cranelift::Cranelift;
|
||||||
|
use wasmer_engine_jit::JIT;
|
||||||
|
|
||||||
|
fuzz_target!(|wasm_bytes: &[u8]| {
|
||||||
|
let mut compiler = Cranelift::default();
|
||||||
|
compiler.canonicalize_nans(true);
|
||||||
|
compiler.enable_verifier();
|
||||||
|
let store = Store::new(&JIT::new(&compiler).engine());
|
||||||
|
match Module::validate(&store, wasm_bytes) {
|
||||||
|
Ok(_) => {
|
||||||
|
let module = Module::new(&store, wasm_bytes).unwrap();
|
||||||
|
let _instance = Instance::new(&module, &imports! {});
|
||||||
|
}
|
||||||
|
Err(_) => {}
|
||||||
|
};
|
||||||
|
});
|
||||||
21
fuzz/fuzz_targets/jit_llvm.rs
Normal file
21
fuzz/fuzz_targets/jit_llvm.rs
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
#![no_main]
|
||||||
|
#[macro_use]
|
||||||
|
extern crate libfuzzer_sys;
|
||||||
|
|
||||||
|
use wasmer::{imports, CompilerConfig, Instance, Module, Store};
|
||||||
|
use wasmer_compiler_llvm::LLVM;
|
||||||
|
use wasmer_engine_jit::JIT;
|
||||||
|
|
||||||
|
fuzz_target!(|wasm_bytes: &[u8]| {
|
||||||
|
let mut compiler = LLVM::default();
|
||||||
|
compiler.canonicalize_nans(true);
|
||||||
|
compiler.enable_verifier();
|
||||||
|
let store = Store::new(&JIT::new(&compiler).engine());
|
||||||
|
match Module::validate(&store, wasm_bytes) {
|
||||||
|
Ok(_) => {
|
||||||
|
let module = Module::new(&store, wasm_bytes).unwrap();
|
||||||
|
let _instance = Instance::new(&module, &imports! {});
|
||||||
|
}
|
||||||
|
Err(_) => {}
|
||||||
|
};
|
||||||
|
});
|
||||||
19
fuzz/fuzz_targets/jit_singlepass.rs
Normal file
19
fuzz/fuzz_targets/jit_singlepass.rs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
#![no_main]
|
||||||
|
#[macro_use]
|
||||||
|
extern crate libfuzzer_sys;
|
||||||
|
|
||||||
|
use wasmer::{imports, Instance, Module, Store};
|
||||||
|
use wasmer_compiler_singlepass::Singlepass;
|
||||||
|
use wasmer_engine_jit::JIT;
|
||||||
|
|
||||||
|
fuzz_target!(|wasm_bytes: &[u8]| {
|
||||||
|
let compiler = Singlepass::default();
|
||||||
|
let store = Store::new(&JIT::new(&compiler).engine());
|
||||||
|
match Module::validate(&store, wasm_bytes) {
|
||||||
|
Ok(_) => {
|
||||||
|
let module = Module::new(&store, wasm_bytes).unwrap();
|
||||||
|
let _instance = Instance::new(&module, &imports! {});
|
||||||
|
}
|
||||||
|
Err(_) => {}
|
||||||
|
};
|
||||||
|
});
|
||||||
25
fuzz/fuzz_targets/native_cranelift.rs
Normal file
25
fuzz/fuzz_targets/native_cranelift.rs
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
#![no_main]
|
||||||
|
#[macro_use]
|
||||||
|
extern crate libfuzzer_sys;
|
||||||
|
|
||||||
|
use wasmer::{imports, Instance, Module, Store};
|
||||||
|
use wasmer_compiler_cranelift::Cranelift;
|
||||||
|
use wasmer_engine_native::Native;
|
||||||
|
|
||||||
|
fuzz_target!(|wasm_bytes: &[u8]| {
|
||||||
|
let serialized = {
|
||||||
|
let mut compiler = Cranelift::default();
|
||||||
|
let store = Store::new(&Native::new(&mut compiler).engine());
|
||||||
|
match Module::validate(&store, wasm_bytes) {
|
||||||
|
Err(_) => return,
|
||||||
|
Ok(_) => {}
|
||||||
|
};
|
||||||
|
let module = Module::new(&store, wasm_bytes).unwrap();
|
||||||
|
module.serialize().unwrap()
|
||||||
|
};
|
||||||
|
|
||||||
|
let engine = Native::headless().engine();
|
||||||
|
let store = Store::new(&engine);
|
||||||
|
let module = unsafe { Module::deserialize(&store, serialized.as_slice()) }.unwrap();
|
||||||
|
let _instance = Instance::new(&module, &imports! {});
|
||||||
|
});
|
||||||
13
fuzz/fuzz_targets/validate.rs
Normal file
13
fuzz/fuzz_targets/validate.rs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#![no_main]
|
||||||
|
#[macro_use]
|
||||||
|
extern crate libfuzzer_sys;
|
||||||
|
|
||||||
|
use wasmer::{imports, Instance, Module, Store};
|
||||||
|
use wasmer_compiler_cranelift::Cranelift;
|
||||||
|
use wasmer_engine_jit::JIT;
|
||||||
|
|
||||||
|
fuzz_target!(|wasm_bytes: &[u8]| {
|
||||||
|
let compiler = Cranelift::default();
|
||||||
|
let store = Store::new(&JIT::new(&compiler).engine());
|
||||||
|
Module::validate(&store, wasm_bytes);
|
||||||
|
});
|
||||||
3
lib/api/src/externals/mod.rs
vendored
3
lib/api/src/externals/mod.rs
vendored
@@ -42,7 +42,8 @@ impl Extern {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn from_export(store: &Store, export: Export) -> Extern {
|
/// Create an `Extern` from an `Export`.
|
||||||
|
pub fn from_export(store: &Store, export: Export) -> Extern {
|
||||||
match export {
|
match export {
|
||||||
Export::Function(f) => Extern::Function(Function::from_export(store, f)),
|
Export::Function(f) => Extern::Function(Function::from_export(store, f)),
|
||||||
Export::Memory(m) => Extern::Memory(Memory::from_export(store, m)),
|
Export::Memory(m) => Extern::Memory(Memory::from_export(store, m)),
|
||||||
|
|||||||
@@ -6,7 +6,10 @@
|
|||||||
intra_doc_link_resolution_failure
|
intra_doc_link_resolution_failure
|
||||||
)]
|
)]
|
||||||
#![warn(unused_import_braces)]
|
#![warn(unused_import_braces)]
|
||||||
#![cfg_attr(feature = "cargo-clippy", allow(clippy::new_without_default))]
|
#![cfg_attr(
|
||||||
|
feature = "cargo-clippy",
|
||||||
|
allow(clippy::new_without_default, vtable_address_comparisons)
|
||||||
|
)]
|
||||||
#![cfg_attr(
|
#![cfg_attr(
|
||||||
feature = "cargo-clippy",
|
feature = "cargo-clippy",
|
||||||
warn(
|
warn(
|
||||||
|
|||||||
@@ -172,17 +172,7 @@ fn memory_grow() -> Result<()> {
|
|||||||
let bad_desc = MemoryType::new(Pages(15), Some(Pages(10)), false);
|
let bad_desc = MemoryType::new(Pages(15), Some(Pages(10)), false);
|
||||||
let bad_result = Memory::new(&store, bad_desc);
|
let bad_result = Memory::new(&store, bad_desc);
|
||||||
|
|
||||||
// due to stack overflow with a modern nightly, we can't update CI to use a version of nightly which will make this work
|
assert!(matches!(bad_result, Err(MemoryError::InvalidMemory { .. })));
|
||||||
/*assert!(matches!(
|
|
||||||
bad_result,
|
|
||||||
Err(MemoryError::InvalidMemory { .. })
|
|
||||||
));*/
|
|
||||||
|
|
||||||
assert!(if let Err(MemoryError::InvalidMemory { .. }) = bad_result {
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
});
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,8 +19,8 @@ rayon = "1.3"
|
|||||||
hashbrown = { version = "0.8", optional = true }
|
hashbrown = { version = "0.8", optional = true }
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
more-asserts = "0.2"
|
more-asserts = "0.2"
|
||||||
dynasm = "0.6"
|
dynasm = "0.7"
|
||||||
dynasmrt = "0.6"
|
dynasmrt = "0.7"
|
||||||
lazy_static = "1.4"
|
lazy_static = "1.4"
|
||||||
byteorder = "1.3"
|
byteorder = "1.3"
|
||||||
smallvec = "1"
|
smallvec = "1"
|
||||||
|
|||||||
@@ -37,13 +37,7 @@ The fact that singlepass is not prone to JIT bombs and offers a very
|
|||||||
predictable compilation speed makes it ideal for **blockchains** and other
|
predictable compilation speed makes it ideal for **blockchains** and other
|
||||||
systems where fast and consistent compilation times are very critical.
|
systems where fast and consistent compilation times are very critical.
|
||||||
|
|
||||||
## Requirements
|
|
||||||
|
|
||||||
At the moment, this crate depends on Rust nightly to be compiled, as it uses
|
|
||||||
[`dynasm-rs`] which can only be compiled in Nightly.
|
|
||||||
|
|
||||||
|
|
||||||
[example]: https://github.com/wasmerio/wasmer-reborn/blob/master/examples/compiler_singlepass.rs
|
[example]: https://github.com/wasmerio/wasmer-reborn/blob/master/examples/compiler_singlepass.rs
|
||||||
[`wasmer-compiler-cranelift`]: https://github.com/wasmerio/wasmer-reborn/tree/master/lib/compiler-cranelift
|
[`wasmer-compiler-cranelift`]: https://github.com/wasmerio/wasmer-reborn/tree/master/lib/compiler-cranelift
|
||||||
[`wasmer-compiler-llvm`]: https://github.com/wasmerio/wasmer-reborn/tree/master/lib/compiler-llvm
|
[`wasmer-compiler-llvm`]: https://github.com/wasmerio/wasmer-reborn/tree/master/lib/compiler-llvm
|
||||||
[`dynasm-rs`]: https://github.com/CensoredUsername/dynasm-rs
|
|
||||||
|
|||||||
@@ -7,10 +7,6 @@
|
|||||||
//!
|
//!
|
||||||
//! Compared to Cranelift and LLVM, Singlepass compiles much faster but has worse
|
//! Compared to Cranelift and LLVM, Singlepass compiles much faster but has worse
|
||||||
//! runtime performance.
|
//! runtime performance.
|
||||||
//!
|
|
||||||
//! > Note: Singlepass currently depends on Rust nightly features.
|
|
||||||
|
|
||||||
#![feature(proc_macro_hygiene)]
|
|
||||||
|
|
||||||
mod codegen_x64;
|
mod codegen_x64;
|
||||||
mod common_decl;
|
mod common_decl;
|
||||||
|
|||||||
@@ -1,5 +1,30 @@
|
|||||||
# Wasmer deprecated packages
|
# Wasmer deprecated packages
|
||||||
|
|
||||||
We create "wrapping" crates to ease the adodption of new
|
## Important Note; Please Read
|
||||||
versions of Wasmer, with minimal or no breaking changes.
|
|
||||||
|
|
||||||
|
Thanks to users' feedbacks, collected experience and various usecases,
|
||||||
|
Wasmer has decided to entirely changed its API to offer the best user
|
||||||
|
experience and the best features to as many users as possible, just
|
||||||
|
before the 1.0 release. This new version of Wasmer includes many
|
||||||
|
improvements in terms of performance or the memory consumption, in
|
||||||
|
addition to a ton of new features and much better flexibility!
|
||||||
|
|
||||||
|
In order to help our existing users to enjoy the performance boost and
|
||||||
|
memory improvements without updating their program that much, we have
|
||||||
|
created a new version of the `wasmer-runtime-core` crate, which is now
|
||||||
|
*a port* of the new API but with the old API, as much as
|
||||||
|
possible. Indeed, it was not always possible to provide the exact same
|
||||||
|
API, but changes are subtle.
|
||||||
|
|
||||||
|
We have carefully documented most of the differences in [the
|
||||||
|
`runtime-core/CHANGES.md` document](./runtime-core/CHANGES.md).
|
||||||
|
|
||||||
|
It is important to understand the public of this port. We do not
|
||||||
|
recommend to advanced users of Wasmer to use this port. Advanced API,
|
||||||
|
like `ModuleInfo` or the `vm` module (incl. `vm::Ctx`) have not been
|
||||||
|
fully ported because it was very internals to Wasmer. For advanced
|
||||||
|
users, we highly recommend to migrate to the new version of Wasmer,
|
||||||
|
which is awesome by the way (completely neutral opinion). The public
|
||||||
|
for this port is beginners or regular users that do not necesarily
|
||||||
|
have time to update their code immediately but that want to enjoy a
|
||||||
|
performance boost and memory improvements.
|
||||||
|
|||||||
698
lib/deprecated/runtime-core/CHANGES.md
Normal file
698
lib/deprecated/runtime-core/CHANGES.md
Normal file
@@ -0,0 +1,698 @@
|
|||||||
|
# Changes between this port and the old `wasmer-runtime-core` API
|
||||||
|
|
||||||
|
This document lists *only the differences* between the old and the new
|
||||||
|
API (the port), i.e. API that didn't change are absent.
|
||||||
|
|
||||||
|
## Overall
|
||||||
|
|
||||||
|
* Host function must always take a `vm::Ctx` as first parameter
|
||||||
|
|
||||||
|
## All changes
|
||||||
|
|
||||||
|
By type name in alphabetic order.
|
||||||
|
|
||||||
|
### `Artifact`
|
||||||
|
|
||||||
|
Before:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
impl Artifact {
|
||||||
|
fn deserialize(bytes: &[u8]) -> Result<Self, Error>;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
After:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
impl Artifact {
|
||||||
|
unsafe fn deserialize(bytes: &[u8]) -> Result<Self, Error>;
|
||||||
|
fn module(self) -> Module;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The `deserialize` method is now marked as `unsafe` since it is not
|
||||||
|
checked that `bytes` represent a valid artifact.
|
||||||
|
|
||||||
|
The new `module` method is introduced to fetch the `Module` inside the
|
||||||
|
artifact.
|
||||||
|
|
||||||
|
### `DynamicFunc`
|
||||||
|
|
||||||
|
Before:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
impl DynamicFunc {
|
||||||
|
fn new<F>(signature: Arc<FuncSig>, func: F) -> Self;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
After:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
impl DynamicFunc {
|
||||||
|
fn new<F>(signature: &FuncSig, func: F) -> Self;
|
||||||
|
fn signature(&self) -> &FuncSig;
|
||||||
|
fn params(&self) -> &[Type];
|
||||||
|
fn returns(&self) -> &[Type];
|
||||||
|
fn call(&self, params: &[Value] -> Result<Box<[Value]>, RuntimeError>;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The constructor `new` no longer takes an `Arc` but a reference to
|
||||||
|
`FuncSig`.
|
||||||
|
|
||||||
|
`signature`, `params`, `returns` and `call` are new
|
||||||
|
methods. Previously, it was required to convert `DynamicFunc` into
|
||||||
|
`Func` with `Into<Func<…, …>>`. Now there is no conversion possible
|
||||||
|
between the two, and `DynamicFunc` gains its own methods.
|
||||||
|
|
||||||
|
### `DynFunc`
|
||||||
|
|
||||||
|
Before:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
impl DynFunc {
|
||||||
|
fn raw(&self) -> *const Func;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
After:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
impl DynFunc {
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The `raw` method has been removed. It was present for internal
|
||||||
|
purposes only, not sure it will impact you.
|
||||||
|
|
||||||
|
### `ExportDescriptor`
|
||||||
|
|
||||||
|
Before:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
struct ExportDescriptor<'a> {
|
||||||
|
name: &'a str,
|
||||||
|
ty: ExternDescriptor,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
After:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
struct ExportDescriptor {
|
||||||
|
name: String,
|
||||||
|
ty: ExternDescriptor,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The lifetime on `ExportDescriptor` is no longer necessary: The `name`
|
||||||
|
field now holds a `String` instead of a `&str`.
|
||||||
|
|
||||||
|
### `Export`
|
||||||
|
|
||||||
|
Before:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
impl Exports {
|
||||||
|
fn get<'a, T: Exportable<'a>>(&'a self, name: &str) -> Result<T, ResolveError>;
|
||||||
|
fn into_iter(&self) -> ExportIter;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
After:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
impl Exports {
|
||||||
|
fn get<'a, T: Exportable<'a> + Clone + 'a>(&'a self, name: &str) -> Result<T, ExportError>;
|
||||||
|
fn iter(&self) -> ExportsIterator<impl Iterator<Item = (&String, &Export)>>;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The `get` method is different. It returns a `T` where `T` implements
|
||||||
|
`Exportable<'a>` _and_ `Clone` (that the addition). The returned error
|
||||||
|
is also `ExportError` instead of `ResolveError`.
|
||||||
|
|
||||||
|
The method `into_iter` is now `iter` and returns references to the
|
||||||
|
export name and export value.
|
||||||
|
|
||||||
|
### `Func`
|
||||||
|
|
||||||
|
Before:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
impl<Args, Rets> Func<Args, Rets> {
|
||||||
|
fn params(&self) -> &'static [Type];
|
||||||
|
fn returns(&self) -> &'static [Type];
|
||||||
|
fn get_vm_func(&self) -> NonNull<Func>;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
After:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
impl<Args, Rets> Func<Args, Rets> {
|
||||||
|
fn params(&self) -> &[Type];
|
||||||
|
fn returns(&self) -> &[Type];
|
||||||
|
fn dyn_call(&self, params: &[Value]) -> Result<Box<[Value]>, RuntimeError>;
|
||||||
|
fn signature(&self) -> &FuncSig;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The `params` and `returns` return a slice of `[Type]` which has not
|
||||||
|
the `'static` lifetime.
|
||||||
|
|
||||||
|
The `get_vm_func` method has been removed. It was present for internal
|
||||||
|
purposes, it unlikely it will have an impact on your project.
|
||||||
|
|
||||||
|
In addition to the `call` method, there is now a `dyn_call` method,
|
||||||
|
that calls the function with arguments packed in a slice of `Value`.
|
||||||
|
|
||||||
|
Finally, there is a new `signature` method.
|
||||||
|
|
||||||
|
### `FuncSig`
|
||||||
|
|
||||||
|
Before:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
impl FuncSig {
|
||||||
|
fn returns(&self) -> &[Type];
|
||||||
|
fn check_param_value_types(&self, params: &[Value]) -> bool;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
After:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
impl FuncSig {
|
||||||
|
fn results(&self) -> &[Type];
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The `returns` method has been renamed `results`.
|
||||||
|
|
||||||
|
The `check_param_value_types` method has been removed, since it is now
|
||||||
|
possible to compare two `Vec<Type>`.
|
||||||
|
|
||||||
|
### `GlobalInit`
|
||||||
|
|
||||||
|
`GlobalInit` has totally changed. It was a `struct`, now it's an
|
||||||
|
`enum`:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
enum GlobalInit {
|
||||||
|
I32Const(i32),
|
||||||
|
I64Const(i64),
|
||||||
|
F32Const(f32),
|
||||||
|
F64Const(f64),
|
||||||
|
V128Const(V128),
|
||||||
|
GetGlobal(GlobalIndex),
|
||||||
|
RefNullConst,
|
||||||
|
RefFunc(FunctionIndex),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GlobalInit {
|
||||||
|
fn from_value<T>(value: Value<T>) -> Self;
|
||||||
|
fn to_value<T>(&self) -> Value<T>;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### `HostFunction`
|
||||||
|
|
||||||
|
Before:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
trait HostFunction<Kind, Args, Rets> {
|
||||||
|
fn to_raw(self) -> (NonNull<Func>, Option<NonNull<FuncEnv>>);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
After:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
trait HostFunction<Args, Rets, Kind, T> {
|
||||||
|
fn function_body_ptr(self) -> *const VMFunctionBody;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The generic parameters of the `HostFunction` trait has been re-ordered
|
||||||
|
and a new one has been introduced: `T`. In the new API, it represents
|
||||||
|
the type of the environment; in this port, it should not be used (or
|
||||||
|
at worst, use `vm::Ctx`).
|
||||||
|
|
||||||
|
The `to_raw` method, aimed at internal using, has been replaced by
|
||||||
|
`function_body_ptr`. It is subject to another change, so please don't
|
||||||
|
use it.
|
||||||
|
|
||||||
|
### `ImportDescriptor`
|
||||||
|
|
||||||
|
Before:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
struct ImportDescriptor {
|
||||||
|
namespace: String,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
After:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
struct ImportDescriptor {
|
||||||
|
module: String,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The `namespace` field has been renamed `module`.
|
||||||
|
|
||||||
|
### `ImportObject`
|
||||||
|
|
||||||
|
Before:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
impl ImportObject {
|
||||||
|
fn with_namespace<Func, InnerRet>(&self, namespace: &str, f: Func) -> Option<InnerRet>;
|
||||||
|
fn maybe_with_namespace<Func, InnerRet>(&self, namespace: &str, f: Func) -> Option<InnerRet>;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
After:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
impl ImportObject {
|
||||||
|
fn call_state_creator(&self) -> Option<(*mut c_void, fn(*mut c_void))>;
|
||||||
|
fn get_export(&self, module: &str, name: &str) -> Option<Export>;
|
||||||
|
fn clone_ref(&self) -> Self;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The `with_namespace` and `maybe_with_namespace` methods have been
|
||||||
|
removed.
|
||||||
|
|
||||||
|
The `call_state_creator` method is new, along with `get_export` and
|
||||||
|
`clone_ref`.
|
||||||
|
|
||||||
|
### `Instance`
|
||||||
|
|
||||||
|
Before:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
impl Instance {
|
||||||
|
fn load<T: Loader>(&self, loader: T) -> Result<T::Instance, T::Error>;
|
||||||
|
fn fun<Args, Rets>(&self, name: &str) -> ResolveResult<Args, Rets, Wasm>;
|
||||||
|
fn resolve_func(&self, name: &str) -> ResolveError<usize>;
|
||||||
|
fn dyn_func(&self, name: &str) -> ResolveResult<DynFunc>;
|
||||||
|
fn call(&self, name: &str, params: &[Value]) -> CallResult<Vec<Value>>;
|
||||||
|
fn context(&self) -> &Ctx;
|
||||||
|
fn context_mut(&mut self) -> &mut Ctx;
|
||||||
|
fn exports(&self) -> ExportsIter;
|
||||||
|
fn get_internal(&self, fields: &InternalField) -> u64;
|
||||||
|
fn set_internal(&self, fields: &InternalField, value: u64);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
After:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
impl Instance {
|
||||||
|
fn fun<Args, Rets>(&self, name: &str) -> Result<Func<Args, Rets>, ExportError>;
|
||||||
|
fn resolve_func(&self, name: &str) -> Result<usize, ()>;
|
||||||
|
fn dyn_func(&self, name: &str) -> Result<DynFunc, ExportError>;
|
||||||
|
fn call(&self, name: &str, params: &[Value]) -> Result<Vec<Value>, Box<dyn Error>>;
|
||||||
|
fn context(&self) -> Ref<Ctx>;
|
||||||
|
fn context_mut(&mut self) -> RefMut<Ctx>;
|
||||||
|
fn exports(&self) -> ExportsIterator<impl Iterator<Item = (&String, &Export)>>;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The `load`, `get_internal` and `set_internal` methods have been removed.
|
||||||
|
|
||||||
|
Some `Result`'s errors have changed: The `func` and `dyn_func` methods
|
||||||
|
return a `Result<…, ExportError>` instead of `ResolveResult<…>`; The
|
||||||
|
`resolve_func` method returns a `Result<usize, ()>` instead of
|
||||||
|
`ResolveError<usize>`; The `call` method returns a `Result<…, Box<dyn
|
||||||
|
Error>>` instead of `CallResult<…>`.
|
||||||
|
|
||||||
|
The `context` and `context_mut` methods respectively return a
|
||||||
|
`Ref<Ctx>` and `RefMut<Ctx>` instead of `&Ctx` and `&mut Ctx`.
|
||||||
|
|
||||||
|
The `exports` method returns an `ExportsIterator<impl Iterator<Item =
|
||||||
|
(&String, &Export)>>` instead of `ExportsIter`. That's basically the same.
|
||||||
|
|
||||||
|
### `Memory`
|
||||||
|
|
||||||
|
Before:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
impl Memory {
|
||||||
|
fn new(desc: MemoryDescriptor) -> Result<Self, CreationError>;
|
||||||
|
fn grow(&self, delta: Pages) -> Result<Pages, GrowError>;
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
After:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
impl Memory {
|
||||||
|
fn new(desc: MemoryDescriptor) -> Result<Self, MemoryError>;
|
||||||
|
fn grow(&self, delta: Pages) -> Result<Pages, MemoryError>;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Only the `Result`'s errors have changed between `new` and `grow` from
|
||||||
|
respectively `CreationError` and `GrowError` to a general
|
||||||
|
`MemoryError` type.
|
||||||
|
|
||||||
|
### `MemoryDescriptor`
|
||||||
|
|
||||||
|
Before
|
||||||
|
|
||||||
|
```rust
|
||||||
|
struct MemoryDescriptor {
|
||||||
|
memory_type: MemoryType,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
After:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
struct MemoryDescriptor {}
|
||||||
|
```
|
||||||
|
|
||||||
|
The `memory_type` field has been removed.
|
||||||
|
|
||||||
|
### `MemoryType`
|
||||||
|
|
||||||
|
Before:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
enum MemoryType {
|
||||||
|
Static,
|
||||||
|
SharedStatic,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
After:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
enum MemoryType {
|
||||||
|
Static { bound: Pages },
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The `SharedStatic` variant has been removed.
|
||||||
|
|
||||||
|
The `Static` variant is now a structure of type `Static { bound: Pages }`.
|
||||||
|
|
||||||
|
### `Module`
|
||||||
|
|
||||||
|
Before:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
impl Module {
|
||||||
|
fn instantiate(&self, import_object: &ImportObject) -> Result<Instance>;
|
||||||
|
fn cache(&self) -> Result<Artifact, CacheError>;
|
||||||
|
fn custom_sections(&self, key: impl AsRef<str>) -> Option<&[Vec<u8>]>
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
After:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
impl Module {
|
||||||
|
fn instantiate(&self, import_object: &ImportObject) -> Result<Instance, InstantiationError>;
|
||||||
|
fn cache(&self) -> Result<Artifact, Infallible>;
|
||||||
|
fn custom_sections(&self, key: impl AsRef<str>) -> Option<Vec<Vec<u8>>>;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The `Result`'s errors of `instantiate` and `cache` have changed
|
||||||
|
respectively from `Error` and `CacheError` to `InstantiationError` and
|
||||||
|
`Infallible`. For `cache`, it means that it will never fail. The
|
||||||
|
`Result` is kept to avoid a change in the API.
|
||||||
|
|
||||||
|
The `custom_sections` method returns an `Option<Vec<Vec<u8>>` instead
|
||||||
|
of `Option<&[Vec<u8>]>`.
|
||||||
|
|
||||||
|
### `ModuleInfo`
|
||||||
|
|
||||||
|
Before:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
struct ModuleInfo {
|
||||||
|
backend: String,
|
||||||
|
custom_sections: HashMap<String, Vec<Vec<u8>>>,
|
||||||
|
data_initializers: Vec<DataInitializer>,
|
||||||
|
elem_initializers: Vec<TableInitializer>,
|
||||||
|
em_symbol_map: Option<HashMap<u32, String>>,
|
||||||
|
func_assoc: Map<FuncIndex, SigIndex>,
|
||||||
|
generate_debug_info: bool,
|
||||||
|
globals: Map<LocalGlobalIndex, GlobalInit>,
|
||||||
|
imported_functions: Map<ImportedFuncIndex, ImportName>,
|
||||||
|
imported_globals: Map<ImportedGlobalIndex, (ImportName, GlobalDescriptor)>,
|
||||||
|
imported_memories: Map<ImportedMemoryIndex, (ImportName, MemoryDescriptor)>,
|
||||||
|
imported_tables: Map<ImportedTableIndex, (ImportName, TableDescriptor)>,
|
||||||
|
memories: Map<LocalMemoryIndex, MemoryDescripto>,
|
||||||
|
name_table: StringTable<NameIndex>,
|
||||||
|
namespace_table: StringTable<NamespaceIndex>,
|
||||||
|
signatures: Map<SigIndex, FuncSig>,
|
||||||
|
start_func: Option<FuncIndex>,
|
||||||
|
tables: Map<LocalTableIndex, TableDescriptor>,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
After:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
struct ModuleInfo {
|
||||||
|
custom_sections: IndexMap<String, CustomSectionIndex>,
|
||||||
|
custom_sections_data: PrimaryMap<CustomSectionIndex, Arc<[u8]>>,
|
||||||
|
func_names: HashMap<FunctionIndex, String>,
|
||||||
|
functions: PrimaryMap<FunctionIndex, SignatureIndex>,
|
||||||
|
global_initializers: PrimaryMap<LocalGlobalIndex, GlobalInit>,
|
||||||
|
globals: PrimaryMap<GlobalIndex, GlobalType>,
|
||||||
|
id: ModuleId,
|
||||||
|
imports: IndexMap<(String, String, u32), ImportIndex>,
|
||||||
|
memories: PrimaryMap<MemoryIndex, MemoryType>,
|
||||||
|
name: Option<String>,
|
||||||
|
num_imported_funcs: usize,
|
||||||
|
num_imported_globals: usize,
|
||||||
|
num_imported_memories: usize,
|
||||||
|
num_imported_tables: usize,
|
||||||
|
passive_data: HashMap<DataIndex, Arc<[u8]>>,
|
||||||
|
passive_elements: HashMap<ElemIndex, Box<[FunctionIndex]>>,
|
||||||
|
signatures: PrimaryMap<SignatureIndex, FunctionType>,
|
||||||
|
start_func: Option<FunctionIndex>,
|
||||||
|
table_elements: Vec<TableElements>,
|
||||||
|
tables: PrimaryMap<TableIndex, TableType>,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
We are not going to re-phrase the differences here, but clearly a lot
|
||||||
|
has changed.
|
||||||
|
|
||||||
|
### `Namespace`
|
||||||
|
|
||||||
|
Before:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
impl Namespace {
|
||||||
|
fn insert<S, E>(&mut self, name: S, export: E) -> Option<Box<dyn IsExport + Send>>;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
After:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
impl Namespace {
|
||||||
|
fn insert<S, E>(&mut self, name: S, export: E);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The `insert` method no longer returns a value.
|
||||||
|
|
||||||
|
### `NativeWasmType`
|
||||||
|
|
||||||
|
Before:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
trait NativeWasmType {
|
||||||
|
const TYPE: Type;
|
||||||
|
|
||||||
|
fn from_binary(bits: u64) -> Self;
|
||||||
|
fn to_binary(self) -> u64;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
After:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
trait NativeWasmType {
|
||||||
|
type Abi: Copy + std::fmt::Debug;
|
||||||
|
const WASM_TYPE: Type;
|
||||||
|
|
||||||
|
fn from_binary(binary: i128) -> Self;
|
||||||
|
fn to_binary(self) -> i128;
|
||||||
|
fn into_abi(self) -> Self::Abi;
|
||||||
|
fn from_abi(abi: Self::Abi) -> Self;
|
||||||
|
fn to_value<T>(self) -> Value<T>;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The `TYPE` constant has been renamed `WASM_TYPE`.
|
||||||
|
|
||||||
|
The `into_abi`, `from_abi` and `to_value` methods are new, in addition
|
||||||
|
to the `Abi` type.
|
||||||
|
|
||||||
|
The `to_binary` and `from_binary` methods now take a `i128` instead of
|
||||||
|
a `u64`.
|
||||||
|
|
||||||
|
### `Pages`
|
||||||
|
|
||||||
|
Before:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
impl Pages {
|
||||||
|
fn checked_add(self, rhs: Self) -> Result<Pages, PageError>;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
After:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
impl Pages {
|
||||||
|
fn checked_add(self, rhs: Self) -> Option<Self>;
|
||||||
|
const fn max_values() -> Self;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The `checked_add` method now returns an `Option<Self>` rather than a
|
||||||
|
`Result<Pages, PageError>`.
|
||||||
|
|
||||||
|
The constant `max_values` function has been introduced.
|
||||||
|
|
||||||
|
### `Table`
|
||||||
|
|
||||||
|
Before:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
impl Table {
|
||||||
|
fn new(desc: TableDescriptor) -> Result<Self, CreationError>;
|
||||||
|
fn set<T: StorableInTable>(&self, index: u32, element: T) -> Result<(), TableAccessError>;
|
||||||
|
fn grow(&self, delta: u32) -> Result<u32, GrowError>;
|
||||||
|
fn vm_local_table(&mut self) -> *mut LocalTable;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
After:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
impl Table {
|
||||||
|
fn new(desc: TableDescriptor, initial_value: Value) -> Result<Self, RuntimeError>;
|
||||||
|
fn set(&self, index: u32, element: Value) -> Result<(), RuntimeError>;
|
||||||
|
fn get(&self, index: u32) -> Option<Value>;
|
||||||
|
fn grow(&self, delta: u32, initial_value: Value) -> Result<u32, RuntimeError>;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The `new` constructor takes an `initial_value` and returns a
|
||||||
|
`RuntimeError` in case of an error instead of a `CreationError`.
|
||||||
|
|
||||||
|
The `set` method takes a `Value` rather a `T: StorableInTable`. It
|
||||||
|
also returns a `RuntimeError` rather than a `TableAccessError` in case
|
||||||
|
of an error.
|
||||||
|
|
||||||
|
The `get` method is new!
|
||||||
|
|
||||||
|
The `grow` method takes an `initial_value`, just like `new`, and also
|
||||||
|
returns a `RuntimeError` rather than a `GrowError`.
|
||||||
|
|
||||||
|
Finally, the `vm_local_table` method has been removed. It was quite an
|
||||||
|
internal API, it's unlikely it will impact your project.
|
||||||
|
|
||||||
|
### `TableDescriptor`
|
||||||
|
|
||||||
|
Before:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
struct TableDescriptor {
|
||||||
|
element: ElementType,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
After:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
struct TableDescriptor {
|
||||||
|
ty: Type,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The `element` field has been renamed `ty`.
|
||||||
|
|
||||||
|
A `new` constructor has been introduced: `fn new(ty: Type, minimum:
|
||||||
|
u32, maximum: Option<u32>) -> Self`.
|
||||||
|
|
||||||
|
### `WasmTypeList`
|
||||||
|
|
||||||
|
Before:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
trait WasmTypeList {
|
||||||
|
type RetArray: AsMut<[u64]>;
|
||||||
|
|
||||||
|
fn from_ret_array(array: Self::RetArray) -> Self;
|
||||||
|
fn empty_ret_array() -> Self::RetArray;
|
||||||
|
fn types() -> &'static [Type];
|
||||||
|
fn call<Rets>(self, f: NonNull<Func>, wasm: Wasm, ctx: *mut Ctx) -> Result<Rets, RuntimeError>;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
After:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
trait WasmTypeList {
|
||||||
|
type Array: AsMut<[i128]>;
|
||||||
|
|
||||||
|
fn from_array(array: Self::Array) -> Self;
|
||||||
|
fn empty_array(self) -> Self::Array;
|
||||||
|
fn wasm_types() -> &'static [Type];
|
||||||
|
fn from_slice(slice: &[i128]) -> Result<Self, TryFromSliceError>;
|
||||||
|
fn into_array(self) -> Self::Array;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The `RetArray` type has been renamed `Array`. The concrete type must
|
||||||
|
now implement the `AsMut<[i128]>` trait instead of `AsMut<[u64]>`.
|
||||||
|
|
||||||
|
`from_ret_array` and `empty_ret_array` have been renamed
|
||||||
|
accordingly like `from_array` and `empty_array`. Note that
|
||||||
|
`empty_array` is now a method instead of an associated function.
|
||||||
|
|
||||||
|
The `types` function has been renamed `wasm_types`.
|
||||||
|
|
||||||
|
The `call` method has been removed. It was part of an internal API,
|
||||||
|
it's unlikely it will break your code.
|
||||||
|
|
||||||
|
The `from_slice` constructor and the `into_array` method are new!
|
||||||
|
|
||||||
|
### `WasmHash`
|
||||||
|
|
||||||
|
Before:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
impl WasmHash {
|
||||||
|
fn decode(hex_str: &str) -> Result<Self, Error>;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
After:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
impl WasmHash {
|
||||||
|
fn decode(hex_str: &str) -> Result<Self, DeserializeError>;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The `Result`'s error has changed from `Error` to `DeserializeError`
|
||||||
|
for the `decode` method.
|
||||||
1314
lib/deprecated/runtime-core/Cargo.lock
generated
Normal file
1314
lib/deprecated/runtime-core/Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
39
lib/deprecated/runtime-core/Cargo.toml
Normal file
39
lib/deprecated/runtime-core/Cargo.toml
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
[package]
|
||||||
|
name = "wasmer-runtime-core"
|
||||||
|
version = "0.18.0"
|
||||||
|
description = "Wasmer runtime core library"
|
||||||
|
license = "MIT"
|
||||||
|
authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"]
|
||||||
|
repository = "https://github.com/wasmerio/wasmer"
|
||||||
|
keywords = ["wasm", "webassembly", "runtime"]
|
||||||
|
categories = ["wasm"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[badges]
|
||||||
|
maintenance = { status = "deprecated" }
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
wasm-common = { path = "../../wasm-common", version = "1.0.0-alpha.1" }
|
||||||
|
wasmer = { path = "../../api", version = "1.0.0-alpha.1" }
|
||||||
|
wasmer-cache = { path = "../../cache", version = "1.0.0-alpha.1" }
|
||||||
|
wasmer-compiler = { path = "../../compiler", version = "1.0.0-alpha.1", features = ["translator"] }
|
||||||
|
wasmer-compiler-llvm = { path = "../../compiler-llvm", version = "1.0.0-alpha.1", optional = true }
|
||||||
|
wasmer-compiler-cranelift = { path = "../../compiler-cranelift", version = "1.0.0-alpha.1", optional = true }
|
||||||
|
wasmer-compiler-singlepass = { path = "../../compiler-singlepass", version = "1.0.0-alpha.1", optional = true }
|
||||||
|
wasmer-engine = { path = "../../engine", version = "1.0.0-alpha.1" }
|
||||||
|
wasmer-engine-jit = { path = "../../engine-jit", version = "1.0.0-alpha.1" }
|
||||||
|
wasmer-vm = { path = "../../vm", version = "1.0.0-alpha.1" }
|
||||||
|
lazy_static = "1.4"
|
||||||
|
|
||||||
|
[build-dependencies]
|
||||||
|
blake3 = "0.3.4"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = ["wasmer/default"]
|
||||||
|
cranelift = ["wasmer/cranelift", "wasmer-compiler-cranelift"]
|
||||||
|
llvm = ["wasmer/llvm", "wasmer-compiler-llvm"]
|
||||||
|
singlepass = ["wasmer/singlepass", "wasmer-compiler-singlepass"]
|
||||||
|
default-backend-cranelift = ["cranelift"]
|
||||||
|
default-backend-llvm = ["llvm"]
|
||||||
|
default-backend-singlepass = ["singlepass"]
|
||||||
|
dynamicfunc-fat-closures = []
|
||||||
41
lib/deprecated/runtime-core/README.md
Normal file
41
lib/deprecated/runtime-core/README.md
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
# Wasmer Runtime Core Library [DEPRECATED]
|
||||||
|
|
||||||
|
## Important Note; Please Read
|
||||||
|
|
||||||
|
Thanks to users' feedbacks, collected experience and various usecases,
|
||||||
|
Wasmer has decided to entirely changed its API to offer the best user
|
||||||
|
experience and the best features to as many users as possible, just
|
||||||
|
before the 1.0 release. This new version of Wasmer includes many
|
||||||
|
improvements in terms of performance or the memory consumption, in
|
||||||
|
addition to a ton of new features and much better flexibility!
|
||||||
|
|
||||||
|
In order to help our existing users to enjoy the performance boost and
|
||||||
|
memory improvements without updating their program that much, we have
|
||||||
|
created a new version of the `wasmer-runtime-core` crate, which is now
|
||||||
|
*a port* of the new API but with the old API, as much as
|
||||||
|
possible. Indeed, it was not always possible to provide the exact same
|
||||||
|
API, but changes are subtle.
|
||||||
|
|
||||||
|
We have carefully documented most of the differences in [the
|
||||||
|
`CHANGES.md` document](./CHANGES.md).
|
||||||
|
|
||||||
|
It is important to understand the public of this port. We do not
|
||||||
|
recommend to advanced users of Wasmer to use this port. Advanced API,
|
||||||
|
like `ModuleInfo` or the `vm` module (incl. `vm::Ctx`) have not been
|
||||||
|
fully ported because it was very internals to Wasmer. For advanced
|
||||||
|
users, we highly recommend to migrate to the new version of Wasmer,
|
||||||
|
which is awesome by the way (completely neutral opinion). The public
|
||||||
|
for this port is beginners or regular users that do not necesarily
|
||||||
|
have time to update their code immediately but that want to enjoy a
|
||||||
|
performance boost and memory improvements.
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
|
||||||
|
The `wasmer-runtime-core` was the entry point to the Wasmer Runtime,
|
||||||
|
by providing common types to compile and to instantiate a WebAssembly
|
||||||
|
module.
|
||||||
|
|
||||||
|
Most Wasmer users should prefer the API which is re-exported by the
|
||||||
|
[`wasmer-runtime`](https://github.com/wasmerio/wasmer-reborn/tree/master/lib/deprecated/runtime)
|
||||||
|
library by default. This crate provides additional APIs which may be
|
||||||
|
useful to users that wish to customize the Wasmer runtime.
|
||||||
29
lib/deprecated/runtime-core/build.rs
Normal file
29
lib/deprecated/runtime-core/build.rs
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
use blake3::Hasher;
|
||||||
|
use std::{env, fs, io::Write, path::PathBuf};
|
||||||
|
|
||||||
|
const WASMER_VERSION: &'static str = env!("CARGO_PKG_VERSION");
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// `wasmer_version_hash.txt`
|
||||||
|
{
|
||||||
|
let mut hasher = Hasher::new();
|
||||||
|
hasher.update(WASMER_VERSION.as_bytes());
|
||||||
|
|
||||||
|
let hasher = hasher.finalize();
|
||||||
|
let hash_string = hasher.to_hex().as_str().to_owned();
|
||||||
|
|
||||||
|
let crate_dir = env::var("OUT_DIR").unwrap();
|
||||||
|
let wasmer_version_hash_file = {
|
||||||
|
let mut path = PathBuf::from(&crate_dir);
|
||||||
|
path.push("wasmer_version_hash.txt");
|
||||||
|
path
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut f_out = fs::File::create(wasmer_version_hash_file)
|
||||||
|
.expect("Could not create file for wasmer hash value");
|
||||||
|
|
||||||
|
f_out
|
||||||
|
.write_all(hash_string.as_bytes())
|
||||||
|
.expect("Could not write to file for wasmer hash value");
|
||||||
|
}
|
||||||
|
}
|
||||||
8
lib/deprecated/runtime-core/doc/new-api/artifact.rs
Normal file
8
lib/deprecated/runtime-core/doc/new-api/artifact.rs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
struct Artifact {}
|
||||||
|
|
||||||
|
impl Artifact {
|
||||||
|
unsafe fn deserialize(bytes: &[u8]) -> Result<Self, Error>;
|
||||||
|
fn info(&self) -> &ModuleInfo;
|
||||||
|
fn serialize(&self) -> Result<Vec<u8>, Error>;
|
||||||
|
fn module(self) -> Module;
|
||||||
|
}
|
||||||
1
lib/deprecated/runtime-core/doc/new-api/bytes.rs
Normal file
1
lib/deprecated/runtime-core/doc/new-api/bytes.rs
Normal file
@@ -0,0 +1 @@
|
|||||||
|
struct Bytes(pub usize);
|
||||||
9
lib/deprecated/runtime-core/doc/new-api/dynamicfunc.rs
Normal file
9
lib/deprecated/runtime-core/doc/new-api/dynamicfunc.rs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
struct DynamicFunc {}
|
||||||
|
|
||||||
|
impl DynamicFunc {
|
||||||
|
fn new<F>(signature: &FuncSig, func: F) -> Self;
|
||||||
|
fn signature(&self) -> &FuncSig;
|
||||||
|
fn params(&self) -> &[Type];
|
||||||
|
fn returns(&self) -> &[Type];
|
||||||
|
fn call(&self, params: &[Value]) -> Result<Box<[Value]>, RuntimeError>;
|
||||||
|
}
|
||||||
6
lib/deprecated/runtime-core/doc/new-api/dynfunc.rs
Normal file
6
lib/deprecated/runtime-core/doc/new-api/dynfunc.rs
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
struct DynFunc {}
|
||||||
|
|
||||||
|
impl DynFunc {
|
||||||
|
fn call(&self, params: &[Value]) -> Result<Vec<Value>, CallError>;
|
||||||
|
fn signature(&self) -> &FuncSig;
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
struct ExportDescriptor {
|
||||||
|
name: String,
|
||||||
|
ty: ExternDescriptor,
|
||||||
|
}
|
||||||
6
lib/deprecated/runtime-core/doc/new-api/exports.rs
Normal file
6
lib/deprecated/runtime-core/doc/new-api/exports.rs
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
struct Exports {}
|
||||||
|
|
||||||
|
impl Exports {
|
||||||
|
fn get<'a, T: Exportable<'a> + Clone + 'a>(&'a self, name: &str) -> Result<T, ExportError>;
|
||||||
|
fn iter(&self) -> ExportsIterator<impl Iterator<Item = (&String, &Export)>>;
|
||||||
|
}
|
||||||
10
lib/deprecated/runtime-core/doc/new-api/func.rs
Normal file
10
lib/deprecated/runtime-core/doc/new-api/func.rs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
struct Func<Args, Rets> {}
|
||||||
|
|
||||||
|
impl<Args, Rets> Func<Args, Rets> {
|
||||||
|
fn new<F>(func: F) -> Self;
|
||||||
|
fn params(&self) -> &[Type];
|
||||||
|
fn returns(&self) -> &[Type];
|
||||||
|
fn call(...) -> Result<Rets, RuntimeError>;
|
||||||
|
fn dyn_call(&self, params: &[Value]) -> Result<Box<[Value]>, RuntimeError>;
|
||||||
|
fn signature(&self) -> &FuncSig;
|
||||||
|
}
|
||||||
7
lib/deprecated/runtime-core/doc/new-api/func_sig.rs
Normal file
7
lib/deprecated/runtime-core/doc/new-api/func_sig.rs
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
struct FuncSig {}
|
||||||
|
|
||||||
|
impl FuncSig {
|
||||||
|
fn new<Params, Returns>(params: Params, returns: Returns) -> Self;
|
||||||
|
fn params(&self) -> &[Type];
|
||||||
|
fn results(&self) -> &[Type];
|
||||||
|
}
|
||||||
9
lib/deprecated/runtime-core/doc/new-api/global.rs
Normal file
9
lib/deprecated/runtime-core/doc/new-api/global.rs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
struct Global {}
|
||||||
|
|
||||||
|
impl Global {
|
||||||
|
fn new(value: Value) -> Self;
|
||||||
|
fn new_mutable(value: Value) -> Self;
|
||||||
|
fn descriptor(&self) -> GlobalDescriptor;
|
||||||
|
fn set(&self, value: Value);
|
||||||
|
fn get(&self) -> Value;
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
struct GlobalDescriptor {
|
||||||
|
mutable: bool,
|
||||||
|
ty: Type,
|
||||||
|
}
|
||||||
15
lib/deprecated/runtime-core/doc/new-api/global_init.rs
Normal file
15
lib/deprecated/runtime-core/doc/new-api/global_init.rs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
enum GlobalInit {
|
||||||
|
I32Const(i32),
|
||||||
|
I64Const(i64),
|
||||||
|
F32Const(f32),
|
||||||
|
F64Const(f64),
|
||||||
|
V128Const(V128),
|
||||||
|
GetGlobal(GlobalIndex),
|
||||||
|
RefNullConst,
|
||||||
|
RefFunc(FunctionIndex),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GlobalInit {
|
||||||
|
fn from_value<T>(value: Value<T>) -> Self;
|
||||||
|
fn to_value<T>(&self) -> Value<T>;
|
||||||
|
}
|
||||||
3
lib/deprecated/runtime-core/doc/new-api/host_function.rs
Normal file
3
lib/deprecated/runtime-core/doc/new-api/host_function.rs
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
trait HostFunction<Args, Rets, Kind, T> {
|
||||||
|
fn function_body_ptr(self) -> *const VMFunctionBody;
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
struct ImportDescriptor {
|
||||||
|
module: String,
|
||||||
|
name: String,
|
||||||
|
ty: ExternDescriptor,
|
||||||
|
}
|
||||||
11
lib/deprecated/runtime-core/doc/new-api/import_object.rs
Normal file
11
lib/deprecated/runtime-core/doc/new-api/import_object.rs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
struct ImportObject {}
|
||||||
|
|
||||||
|
impl ImportObject {
|
||||||
|
fn new() -> Self;
|
||||||
|
fn new_with_data<F>(state_creator: F) -> Self;
|
||||||
|
fn register<S, N>(&mut self, name: S, namespace: N) -> Option<Box<dyn LikeNamespace>>;
|
||||||
|
fn contains_namespace(&self, name: &str) -> bool;
|
||||||
|
fn call_state_creator(&self) -> Option<(*mut c_void, fn(*mut c_void))>;
|
||||||
|
fn get_export(&self, module: &str, name: &str) -> Option<Export>;
|
||||||
|
fn clone_ref(&self) -> Self;
|
||||||
|
}
|
||||||
14
lib/deprecated/runtime-core/doc/new-api/instance.rs
Normal file
14
lib/deprecated/runtime-core/doc/new-api/instance.rs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
struct Instance {
|
||||||
|
exports: Exports,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Instance {
|
||||||
|
fn fun<Args, Rets>(&self, name: &str) -> Result<Func<Args, Rets>, ExportError>;
|
||||||
|
fn resolve_func(&self, name: &str) -> Result<usize, ()>;
|
||||||
|
fn dyn_func(&self, name: &str) -> Result<DynFunc, ExportError>;
|
||||||
|
fn call(&self, name: &str, params: &[Value]) -> Result<Vec<Value>, Box<dyn Error>>;
|
||||||
|
fn context(&self) -> Ref<Ctx>;
|
||||||
|
fn context_mut(&mut self) -> RefMut<Ctx>;
|
||||||
|
fn exports(&self) -> ExportsIterator<impl Iterator<Item = (&String, &Export)>>;
|
||||||
|
fn module(&self) -> Module;
|
||||||
|
}
|
||||||
9
lib/deprecated/runtime-core/doc/new-api/memory.rs
Normal file
9
lib/deprecated/runtime-core/doc/new-api/memory.rs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
struct Memory {}
|
||||||
|
|
||||||
|
impl Memory {
|
||||||
|
fn new(desc: MemoryDescriptor) -> Result<Self, MemoryError>;
|
||||||
|
fn descriptor(&self) -> MemoryDescriptor;
|
||||||
|
fn grow(&self, delta: Pages) -> Result<Pages, MemoryError>;
|
||||||
|
fn size(&self) -> Pages;
|
||||||
|
fn view<T: ValueType>(&self) -> MemoryView<T>;
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
struct MemoryDescriptor {
|
||||||
|
minimum: Pages,
|
||||||
|
maximum: Option<Pages>,
|
||||||
|
shared: bool,
|
||||||
|
}
|
||||||
4
lib/deprecated/runtime-core/doc/new-api/memory_type.rs
Normal file
4
lib/deprecated/runtime-core/doc/new-api/memory_type.rs
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
enum MemoryType {
|
||||||
|
Dynamic,
|
||||||
|
Static { bound: Pages },
|
||||||
|
}
|
||||||
5
lib/deprecated/runtime-core/doc/new-api/memory_view.rs
Normal file
5
lib/deprecated/runtime-core/doc/new-api/memory_view.rs
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
struct MemoryView {}
|
||||||
|
|
||||||
|
impl MemoryView {
|
||||||
|
fn atomically(&self) -> MemoryView<'a, T::Output, Atomically>;
|
||||||
|
}
|
||||||
10
lib/deprecated/runtime-core/doc/new-api/module.rs
Normal file
10
lib/deprecated/runtime-core/doc/new-api/module.rs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
struct Module {}
|
||||||
|
|
||||||
|
impl Module {
|
||||||
|
fn instantiate(&self, import_object: &ImportObject) -> Result<Instance, InstantiationError>;
|
||||||
|
fn cache(&self) -> Result<Artifact, Infallible>;
|
||||||
|
fn info(&self) -> &ModuleInfo;
|
||||||
|
fn imports(&self) -> Vec<ImportDescriptor>;
|
||||||
|
fn exports(&self) -> Vec<ExportDescriptor>;
|
||||||
|
fn custom_sections(&self, key: impl AsRef<str>) -> Option<Vec<Vec<u8>>>;
|
||||||
|
}
|
||||||
23
lib/deprecated/runtime-core/doc/new-api/module_info.rs
Normal file
23
lib/deprecated/runtime-core/doc/new-api/module_info.rs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
struct ModuleInfo {
|
||||||
|
custom_sections: IndexMap<String, CustomSectionIndex>,
|
||||||
|
custom_sections_data: PrimaryMap<CustomSectionIndex, Arc<[u8]>>,
|
||||||
|
exports: IndexMap<String, ExportIndex>,
|
||||||
|
func_names: HashMap<FunctionIndex, String>,
|
||||||
|
functions: PrimaryMap<FunctionIndex, SignatureIndex>,
|
||||||
|
global_initializers: PrimaryMap<LocalGlobalIndex, GlobalInit>,
|
||||||
|
globals: PrimaryMap<GlobalIndex, GlobalType>,
|
||||||
|
id: ModuleId,
|
||||||
|
imports: IndexMap<(String, String, u32), ImportIndex>,
|
||||||
|
memories: PrimaryMap<MemoryIndex, MemoryType>,
|
||||||
|
name: Option<String>,
|
||||||
|
num_imported_funcs: usize,
|
||||||
|
num_imported_globals: usize,
|
||||||
|
num_imported_memories: usize,
|
||||||
|
num_imported_tables: usize,
|
||||||
|
passive_data: HashMap<DataIndex, Arc<[u8]>>,
|
||||||
|
passive_elements: HashMap<ElemIndex, Box<[FunctionIndex]>>,
|
||||||
|
signatures: PrimaryMap<SignatureIndex, FunctionType>,
|
||||||
|
start_func: Option<FunctionIndex>,
|
||||||
|
table_elements: Vec<TableElements>,
|
||||||
|
tables: PrimaryMap<TableIndex, TableType>,
|
||||||
|
}
|
||||||
7
lib/deprecated/runtime-core/doc/new-api/namespace.rs
Normal file
7
lib/deprecated/runtime-core/doc/new-api/namespace.rs
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
struct Namespace {}
|
||||||
|
|
||||||
|
impl Namespace {
|
||||||
|
fn new() -> Self;
|
||||||
|
fn insert<S, E>(&mut self, name: S, export: E);
|
||||||
|
fn contains_key<S>(&mut self, key: S) -> bool;
|
||||||
|
}
|
||||||
10
lib/deprecated/runtime-core/doc/new-api/native_wasm_type.rs
Normal file
10
lib/deprecated/runtime-core/doc/new-api/native_wasm_type.rs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
trait NativeWasmType {
|
||||||
|
type Abi: Copy + std::fmt::Debug;
|
||||||
|
const WASM_TYPE: Type;
|
||||||
|
|
||||||
|
fn from_binary(binary: i128) -> Self;
|
||||||
|
fn to_binary(self) -> i128;
|
||||||
|
fn into_abi(self) -> Self::Abi;
|
||||||
|
fn from_abi(abi: Self::Abi) -> Self;
|
||||||
|
fn to_value<T>(self) -> Value<T>;
|
||||||
|
}
|
||||||
7
lib/deprecated/runtime-core/doc/new-api/pages.rs
Normal file
7
lib/deprecated/runtime-core/doc/new-api/pages.rs
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
struct Pages(pub u32);
|
||||||
|
|
||||||
|
impl Pages {
|
||||||
|
fn checked_add(self, rhs: Self) -> Option<Self>;
|
||||||
|
fn bytes(self) -> Bytes;
|
||||||
|
const fn max_values() -> Self;
|
||||||
|
}
|
||||||
10
lib/deprecated/runtime-core/doc/new-api/table.rs
Normal file
10
lib/deprecated/runtime-core/doc/new-api/table.rs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
struct Table {}
|
||||||
|
|
||||||
|
impl Table {
|
||||||
|
fn new(desc: TableDescriptor, initial_value: Value) -> Result<Self, RuntimeError>;
|
||||||
|
fn descriptor(&self) -> TableDescriptor;
|
||||||
|
fn set(&self, index: u32, element: Value) -> Result<(), RuntimeError>;
|
||||||
|
fn get(&self, index: u32) -> Option<Value>;
|
||||||
|
fn size(&self) -> u32;
|
||||||
|
fn grow(&self, delta: u32, initial_value: Value) -> Result<u32, RuntimeError>;
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
struct TableDescriptor {
|
||||||
|
ty: Type,
|
||||||
|
minimum: u32,
|
||||||
|
maximum: Option<u32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TableDescriptor {
|
||||||
|
fn new(ty: Type, minimum: u32, maximum: Option<u32>) -> Self;
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
trait WasmExternType {
|
||||||
|
type Native: NativeWasmType;
|
||||||
|
|
||||||
|
fn from_native(native: Self::Native) -> Self;
|
||||||
|
fn to_native(self) -> Self::Native;
|
||||||
|
}
|
||||||
12
lib/deprecated/runtime-core/doc/new-api/wasm_type_list.rs
Normal file
12
lib/deprecated/runtime-core/doc/new-api/wasm_type_list.rs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
trait WasmTypeList {
|
||||||
|
type CStruct;
|
||||||
|
type Array: AsMut<[i128]>;
|
||||||
|
|
||||||
|
fn from_array(array: Self::Array) -> Self;
|
||||||
|
fn empty_array(self) -> Self::Array;
|
||||||
|
fn from_c_struct(c_struct: Self::CStruct) -> Self;
|
||||||
|
fn into_c_struct(self) -> Self::CStruct;
|
||||||
|
fn wasm_types() -> &'static [Type];
|
||||||
|
fn from_slice(slice: &[i128]) -> Result<Self, TryFromSliceError>;
|
||||||
|
fn into_array(self) -> Self::Array;
|
||||||
|
}
|
||||||
7
lib/deprecated/runtime-core/doc/new-api/wasmhash.rs
Normal file
7
lib/deprecated/runtime-core/doc/new-api/wasmhash.rs
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
struct WasmHash {}
|
||||||
|
|
||||||
|
impl WasmHash {
|
||||||
|
fn generate(wasm: &[u8]) -> Self;
|
||||||
|
fn encode(self) -> String;
|
||||||
|
fn decode(hex_str: &str) -> Result<Self, DeserializeError>;
|
||||||
|
}
|
||||||
7
lib/deprecated/runtime-core/doc/old-api/artifact.rs
Normal file
7
lib/deprecated/runtime-core/doc/old-api/artifact.rs
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
struct Artifact {}
|
||||||
|
|
||||||
|
impl Artifact {
|
||||||
|
fn deserialize(bytes: &[u8]) -> Result<Self, Error>;
|
||||||
|
fn info(&self) -> &ModuleInfo;
|
||||||
|
fn serialize(&self) -> Result<Vec<u8>, Error>;
|
||||||
|
}
|
||||||
1
lib/deprecated/runtime-core/doc/old-api/bytes.rs
Normal file
1
lib/deprecated/runtime-core/doc/old-api/bytes.rs
Normal file
@@ -0,0 +1 @@
|
|||||||
|
struct Bytes(pub usize);
|
||||||
5
lib/deprecated/runtime-core/doc/old-api/dynamicfunc.rs
Normal file
5
lib/deprecated/runtime-core/doc/old-api/dynamicfunc.rs
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
struct DynamicFunc {}
|
||||||
|
|
||||||
|
impl DynamicFunc {
|
||||||
|
fn new<F>(signature: Arc<FuncSig>, func: F) -> Self;
|
||||||
|
}
|
||||||
7
lib/deprecated/runtime-core/doc/old-api/dynfunc.rs
Normal file
7
lib/deprecated/runtime-core/doc/old-api/dynfunc.rs
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
struct DynFunc {}
|
||||||
|
|
||||||
|
impl DynFunc {
|
||||||
|
fn call(&self, params: &[Value]) -> Result<Vec<Value>, CallError>;
|
||||||
|
fn signature(&self) -> &FuncSig;
|
||||||
|
fn raw(&self) -> *const Func;
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
struct ExportDescriptor<'a> {
|
||||||
|
name: &'a str,
|
||||||
|
ty: ExternDescriptor,
|
||||||
|
}
|
||||||
6
lib/deprecated/runtime-core/doc/old-api/exports.rs
Normal file
6
lib/deprecated/runtime-core/doc/old-api/exports.rs
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
struct Exports {}
|
||||||
|
|
||||||
|
impl Exports {
|
||||||
|
fn get<'a, T: Exportable<'a>>(&'a self, name: &str) -> Result<T, ResolveError>;
|
||||||
|
fn into_iter(&self) -> ExportIter;
|
||||||
|
}
|
||||||
9
lib/deprecated/runtime-core/doc/old-api/func.rs
Normal file
9
lib/deprecated/runtime-core/doc/old-api/func.rs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
struct Func<Args, Rets> {}
|
||||||
|
|
||||||
|
impl<Args, Rets> Func<Args, Rets> {
|
||||||
|
fn new<F>(func: F) -> Self;
|
||||||
|
fn params(&self) -> &'static [Type];
|
||||||
|
fn returns(&self) -> &'static [Type];
|
||||||
|
fn call(...) -> Result<Rets, RuntimeError>;
|
||||||
|
fn get_vm_func(&self) -> NonNull<Func>;
|
||||||
|
}
|
||||||
8
lib/deprecated/runtime-core/doc/old-api/func_sig.rs
Normal file
8
lib/deprecated/runtime-core/doc/old-api/func_sig.rs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
struct FuncSig {}
|
||||||
|
|
||||||
|
impl FuncSig {
|
||||||
|
fn new<Params, Returns>(params: Params, returns: Returns) -> Self;
|
||||||
|
fn params(&self) -> &[Type];
|
||||||
|
fn returns(&self) -> &[Type];
|
||||||
|
fn check_param_value_types(&self, params: &[Value]) -> bool;
|
||||||
|
}
|
||||||
9
lib/deprecated/runtime-core/doc/old-api/global.rs
Normal file
9
lib/deprecated/runtime-core/doc/old-api/global.rs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
struct Global {}
|
||||||
|
|
||||||
|
impl Global {
|
||||||
|
fn new(value: Value) -> Self;
|
||||||
|
fn new_mutable(value: Value) -> Self;
|
||||||
|
fn descriptor(&self) -> GlobalDescriptor;
|
||||||
|
fn set(&self, value: Value);
|
||||||
|
fn get(&self) -> Value;
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
struct GlobalDescriptor {
|
||||||
|
mutable: bool,
|
||||||
|
ty: Type,
|
||||||
|
}
|
||||||
4
lib/deprecated/runtime-core/doc/old-api/global_init.rs
Normal file
4
lib/deprecated/runtime-core/doc/old-api/global_init.rs
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
struct GlobalInit {
|
||||||
|
desc: GlobalDescriptor,
|
||||||
|
init: Initializer,
|
||||||
|
}
|
||||||
3
lib/deprecated/runtime-core/doc/old-api/host_function.rs
Normal file
3
lib/deprecated/runtime-core/doc/old-api/host_function.rs
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
trait HostFunction<Kind, Args, Rets> {
|
||||||
|
fn to_raw(self) -> (NonNull<Func>, Option<NonNull<FuncEnv>>);
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
struct ImportDescriptor {
|
||||||
|
namespace: String,
|
||||||
|
name: String,
|
||||||
|
ty: ExternDescriptor,
|
||||||
|
}
|
||||||
12
lib/deprecated/runtime-core/doc/old-api/import_object.rs
Normal file
12
lib/deprecated/runtime-core/doc/old-api/import_object.rs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
struct ImportObject {
|
||||||
|
allow_missing_functions: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ImportObject {
|
||||||
|
fn new() -> Self;
|
||||||
|
fn new_with_data<F>(state_creator: F) -> Self;
|
||||||
|
fn register<S, N>(&mut self, name: S, namespace: N) -> Option<Box<dyn LikeNamespace>>;
|
||||||
|
fn with_namespace<Func, InnerRet>(&self, namespace: &str, f: Func) -> Option<InnerRet>;
|
||||||
|
fn maybe_with_namespace<Func, InnerRet>(&self, namespace: &str, f: Func) -> Option<InnerRet>;
|
||||||
|
fn contains_namespace(&self, name: &str) -> bool;
|
||||||
|
}
|
||||||
18
lib/deprecated/runtime-core/doc/old-api/instance.rs
Normal file
18
lib/deprecated/runtime-core/doc/old-api/instance.rs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
struct Instance {
|
||||||
|
module: Arc<ModuleInner>,
|
||||||
|
exports: Exports,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Instance {
|
||||||
|
fn load<T: Loader>(&self, loader: T) -> Result<T::Instance, T::Error>;
|
||||||
|
fn fun<Args, Rets>(&self, name: &str) -> ResolveResult<Args, Rets, Wasm>;
|
||||||
|
fn resolve_func(&self, name: &str) -> ResolveError<usize>;
|
||||||
|
fn dyn_func(&self, name: &str) -> ResolveResult<DynFunc>;
|
||||||
|
fn call(&self, name: &str, params: &[Value]) -> CallResult<Vec<Value>>;
|
||||||
|
fn context(&self) -> &Ctx;
|
||||||
|
fn context_mut(&mut self) -> &mut Ctx;
|
||||||
|
fn exports(&self) -> ExportsIter;
|
||||||
|
fn module(&self) -> Module;
|
||||||
|
fn get_internal(&self, fields: &InternalField) -> u64;
|
||||||
|
fn set_internal(&self, fields: &InternalField, value: u64);
|
||||||
|
}
|
||||||
9
lib/deprecated/runtime-core/doc/old-api/memory.rs
Normal file
9
lib/deprecated/runtime-core/doc/old-api/memory.rs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
struct Memory {}
|
||||||
|
|
||||||
|
impl Memory {
|
||||||
|
fn new(desc: MemoryDescriptor) -> Result<Self, CreationError>;
|
||||||
|
fn descriptor(&self) -> MemoryDescriptor;
|
||||||
|
fn grow(&self, delta: Pages) -> Result<Pages, GrowError>;
|
||||||
|
fn size(&self) -> Pages;
|
||||||
|
fn view<T: ValueType>(&self) -> MemoryView<T>;
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
struct MemoryDescriptor {
|
||||||
|
minimum: Pages,
|
||||||
|
maximum: Option<Pages>,
|
||||||
|
shared: bool,
|
||||||
|
memory_type: MemoryType,
|
||||||
|
}
|
||||||
5
lib/deprecated/runtime-core/doc/old-api/memory_type.rs
Normal file
5
lib/deprecated/runtime-core/doc/old-api/memory_type.rs
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
enum MemoryType {
|
||||||
|
Dynamic,
|
||||||
|
Static,
|
||||||
|
SharedStatic,
|
||||||
|
}
|
||||||
5
lib/deprecated/runtime-core/doc/old-api/memory_view.rs
Normal file
5
lib/deprecated/runtime-core/doc/old-api/memory_view.rs
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
struct MemoryView {}
|
||||||
|
|
||||||
|
impl MemoryView {
|
||||||
|
fn atomically(&self) -> MemoryView<'a, T::Output, Atomically>;
|
||||||
|
}
|
||||||
10
lib/deprecated/runtime-core/doc/old-api/module.rs
Normal file
10
lib/deprecated/runtime-core/doc/old-api/module.rs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
struct Module {}
|
||||||
|
|
||||||
|
impl Module {
|
||||||
|
fn instantiate(&self, import_object: &ImportObject) -> Result<Instance>;
|
||||||
|
fn cache(&self) -> Result<Artifact, CacheError>;
|
||||||
|
fn info(&self) -> &ModuleInfo;
|
||||||
|
fn imports(&self) -> Vec<ImportDescriptor>;
|
||||||
|
fn exports(&self) -> Vec<ExportDescriptor>;
|
||||||
|
fn custom_sections(&self, key: impl AsRef<str>) -> Option<&[Vec<u8>]>
|
||||||
|
}
|
||||||
21
lib/deprecated/runtime-core/doc/old-api/module_info.rs
Normal file
21
lib/deprecated/runtime-core/doc/old-api/module_info.rs
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
struct ModuleInfo {
|
||||||
|
backend: String,
|
||||||
|
custom_sections: HashMap<String, Vec<Vec<u8>>>,
|
||||||
|
data_initializers: Vec<DataInitializer>,
|
||||||
|
elem_initializers: Vec<TableInitializer>,
|
||||||
|
em_symbol_map: Option<HashMap<u32, String>>,
|
||||||
|
exports: IndexMap<String, ExportIndex>,
|
||||||
|
func_assoc: Map<FuncIndex, SigIndex>,
|
||||||
|
generate_debug_info: bool,
|
||||||
|
globals: Map<LocalGlobalIndex, GlobalInit>,
|
||||||
|
imported_functions: Map<ImportedFuncIndex, ImportName>,
|
||||||
|
imported_globals: Map<ImportedGlobalIndex, (ImportName, GlobalDescriptor)>,
|
||||||
|
imported_memories: Map<ImportedMemoryIndex, (ImportName, MemoryDescriptor)>,
|
||||||
|
imported_tables: Map<ImportedTableIndex, (ImportName, TableDescriptor)>,
|
||||||
|
memories: Map<LocalMemoryIndex, MemoryDescripto>,
|
||||||
|
name_table: StringTable<NameIndex>,
|
||||||
|
namespace_table: StringTable<NamespaceIndex>,
|
||||||
|
signatures: Map<SigIndex, FuncSig>,
|
||||||
|
start_func: Option<FuncIndex>,
|
||||||
|
tables: Map<LocalTableIndex, TableDescriptor>,
|
||||||
|
}
|
||||||
7
lib/deprecated/runtime-core/doc/old-api/namespace.rs
Normal file
7
lib/deprecated/runtime-core/doc/old-api/namespace.rs
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
struct Namespace {}
|
||||||
|
|
||||||
|
impl Namespace {
|
||||||
|
fn new() -> Self;
|
||||||
|
fn insert<S, E>(&mut self, name: S, export: E) -> Option<Box<dyn IsExport + Send>>;
|
||||||
|
fn contains_key<S>(&mut self, key: S) -> bool;
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
trait NativeWasmType {
|
||||||
|
const TYPE: Type;
|
||||||
|
|
||||||
|
fn from_binary(bits: u64) -> Self;
|
||||||
|
fn to_binary(self) -> u64;
|
||||||
|
}
|
||||||
6
lib/deprecated/runtime-core/doc/old-api/pages.rs
Normal file
6
lib/deprecated/runtime-core/doc/old-api/pages.rs
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
struct Pages(pub u32);
|
||||||
|
|
||||||
|
impl Pages {
|
||||||
|
fn checked_add(self, rhs: Self) -> Result<Pages, PageError>;
|
||||||
|
fn bytes(self) -> Bytes;
|
||||||
|
}
|
||||||
10
lib/deprecated/runtime-core/doc/old-api/table.rs
Normal file
10
lib/deprecated/runtime-core/doc/old-api/table.rs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
struct Table {}
|
||||||
|
|
||||||
|
impl Table {
|
||||||
|
fn new(desc: TableDescriptor) -> Result<Self, CreationError>;
|
||||||
|
fn descriptor(&self) -> TableDescriptor;
|
||||||
|
fn set<T: StorableInTable>(&self, index: u32, element: T) -> Result<(), TableAccessError>;
|
||||||
|
fn size(&self) -> u32;
|
||||||
|
fn grow(&self, delta: u32) -> Result<u32, GrowError>;
|
||||||
|
fn vm_local_table(&mut self) -> *mut LocalTable;
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
struct TableDescriptor {
|
||||||
|
element: ElementType,
|
||||||
|
minimum: u32,
|
||||||
|
maximum: Option<u32>,
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
trait WasmExternType {
|
||||||
|
type Native: NativeWasmType;
|
||||||
|
|
||||||
|
fn from_native(native: Self::Native) -> Self;
|
||||||
|
fn to_native(self) -> Self::Native;
|
||||||
|
}
|
||||||
11
lib/deprecated/runtime-core/doc/old-api/wasm_type_list.rs
Normal file
11
lib/deprecated/runtime-core/doc/old-api/wasm_type_list.rs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
trait WasmTypeList {
|
||||||
|
type CStruct;
|
||||||
|
type RetArray: AsMut<[u64]>;
|
||||||
|
|
||||||
|
fn from_ret_array(array: Self::RetArray) -> Self;
|
||||||
|
fn empty_ret_array() -> Self::RetArray;
|
||||||
|
fn from_c_struct(c_struct: Self::CStruct) -> Self;
|
||||||
|
fn into_c_struct(self) -> Self::CStruct;
|
||||||
|
fn types() -> &'static [Type];
|
||||||
|
fn call<Rets>(self, f: NonNull<Func>, wasm: Wasm, ctx: *mut Ctx) -> Result<Rets, RuntimeError>;
|
||||||
|
}
|
||||||
7
lib/deprecated/runtime-core/doc/old-api/wasmhash.rs
Normal file
7
lib/deprecated/runtime-core/doc/old-api/wasmhash.rs
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
struct WasmHash {}
|
||||||
|
|
||||||
|
impl WasmHash {
|
||||||
|
fn generate(wasm: &[u8]) -> Self;
|
||||||
|
fn encode(self) -> String;
|
||||||
|
fn decode(hex_str: &str) -> Result<Self, Error>;
|
||||||
|
}
|
||||||
10
lib/deprecated/runtime-core/doc/review.sh
Executable file
10
lib/deprecated/runtime-core/doc/review.sh
Executable file
@@ -0,0 +1,10 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
for i in `\ls new-api | grep "${1-.}"`; do
|
||||||
|
clear
|
||||||
|
echo -e "#######\n### ${i}\n#######\n\n\n\n"
|
||||||
|
diff --report-identical-files --unified=10 old-api/${i} new-api/${i} | diffr
|
||||||
|
|
||||||
|
echo -e "\n\n\n\nPress any key to diff the next file…"
|
||||||
|
read
|
||||||
|
done
|
||||||
84
lib/deprecated/runtime-core/src/backend.rs
Normal file
84
lib/deprecated/runtime-core/src/backend.rs
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
use crate::new;
|
||||||
|
|
||||||
|
pub use new::wasmer_compiler::{Architecture, CpuFeature as Features};
|
||||||
|
|
||||||
|
/// Enum used to select which compiler should be used to generate code.
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
|
pub enum Backend {
|
||||||
|
#[cfg(feature = "singlepass")]
|
||||||
|
/// Singlepass backend
|
||||||
|
Singlepass,
|
||||||
|
#[cfg(feature = "cranelift")]
|
||||||
|
/// Cranelift backend
|
||||||
|
Cranelift,
|
||||||
|
#[cfg(feature = "llvm")]
|
||||||
|
/// LLVM backend
|
||||||
|
LLVM,
|
||||||
|
/// Auto backend
|
||||||
|
Auto,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Backend {
|
||||||
|
/// Get a list of the currently enabled (via feature flag) backends.
|
||||||
|
pub fn variants() -> &'static [&'static str] {
|
||||||
|
&[
|
||||||
|
#[cfg(feature = "singlepass")]
|
||||||
|
"singlepass",
|
||||||
|
#[cfg(feature = "cranelift")]
|
||||||
|
"cranelift",
|
||||||
|
#[cfg(feature = "llvm")]
|
||||||
|
"llvm",
|
||||||
|
"auto",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Stable string representation of the backend.
|
||||||
|
/// It can be used as part of a cache key, for example.
|
||||||
|
pub fn to_string(&self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
#[cfg(feature = "singlepass")]
|
||||||
|
Backend::Singlepass => "singlepass",
|
||||||
|
#[cfg(feature = "cranelift")]
|
||||||
|
Backend::Cranelift => "cranelift",
|
||||||
|
#[cfg(feature = "llvm")]
|
||||||
|
Backend::LLVM => "llvm",
|
||||||
|
Backend::Auto => "auto",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Backend {
|
||||||
|
fn default() -> Self {
|
||||||
|
#[cfg(feature = "default-backend-singlepass")]
|
||||||
|
return Backend::Singlepass;
|
||||||
|
|
||||||
|
#[cfg(feature = "default-backend-cranelift")]
|
||||||
|
return Backend::Cranelift;
|
||||||
|
|
||||||
|
#[cfg(feature = "default-backend-llvm")]
|
||||||
|
return Backend::LLVM;
|
||||||
|
|
||||||
|
#[cfg(not(any(
|
||||||
|
feature = "default-backend-singlepass",
|
||||||
|
feature = "default-backend-cranelift",
|
||||||
|
feature = "default-backend-llvm",
|
||||||
|
)))]
|
||||||
|
panic!("There is no default-backend set.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::str::FromStr for Backend {
|
||||||
|
type Err = String;
|
||||||
|
fn from_str(s: &str) -> Result<Backend, String> {
|
||||||
|
match s.to_lowercase().as_str() {
|
||||||
|
#[cfg(feature = "singlepass")]
|
||||||
|
"singlepass" => Ok(Backend::Singlepass),
|
||||||
|
#[cfg(feature = "cranelift")]
|
||||||
|
"cranelift" => Ok(Backend::Cranelift),
|
||||||
|
#[cfg(feature = "llvm")]
|
||||||
|
"llvm" => Ok(Backend::LLVM),
|
||||||
|
"auto" => Ok(Backend::Auto),
|
||||||
|
_ => Err(format!("The backend {} doesn't exist", s)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
94
lib/deprecated/runtime-core/src/cache.rs
Normal file
94
lib/deprecated/runtime-core/src/cache.rs
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
//! The cache module provides the common data structures used by compiler backends to allow
|
||||||
|
//! serializing compiled wasm code to a binary format. The binary format can be persisted,
|
||||||
|
//! and loaded to allow skipping compilation and fast startup.
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
get_global_store,
|
||||||
|
module::{Module, ModuleInfo},
|
||||||
|
new,
|
||||||
|
};
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
pub use new::wasmer_cache::FileSystemCache;
|
||||||
|
|
||||||
|
/// Kinds of caching errors
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Error {
|
||||||
|
/// An error deserializing bytes into a cache data structure.
|
||||||
|
DeserializeError(new::wasmer_engine::DeserializeError),
|
||||||
|
|
||||||
|
/// An error serializing bytes from a cache data structure.
|
||||||
|
SerializeError(new::wasmer_engine::SerializeError),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Artifact are produced by caching, are serialized/deserialized to binaries, and contain
|
||||||
|
/// module info, backend metadata, and compiled code.
|
||||||
|
pub struct Artifact {
|
||||||
|
new_module: new::wasmer::Module,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Artifact {
|
||||||
|
pub(crate) fn new(new_module: new::wasmer::Module) -> Self {
|
||||||
|
Self { new_module }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Serializes the `Artifact` into a vector of bytes
|
||||||
|
pub fn serialize(&self) -> Result<Vec<u8>, Error> {
|
||||||
|
self.new_module.serialize().map_err(Error::SerializeError)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Deserializes an `Artifact` from the given byte slice.
|
||||||
|
pub unsafe fn deserialize(bytes: &[u8]) -> Result<Self, Error> {
|
||||||
|
Ok(Self::new(
|
||||||
|
new::wasmer::Module::deserialize(&get_global_store(), bytes)
|
||||||
|
.map_err(Error::DeserializeError)?,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the associated module to this artifact.
|
||||||
|
pub fn module(self) -> Module {
|
||||||
|
Module::new(self.new_module)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A reference to the `Artifact`'s stored `ModuleInfo`
|
||||||
|
pub fn info(&self) -> &ModuleInfo {
|
||||||
|
self.new_module.info()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The hash of a wasm module.
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||||
|
pub struct WasmHash {
|
||||||
|
new_hash: new::wasmer_cache::WasmHash,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WasmHash {
|
||||||
|
/// Hash a wasm module.
|
||||||
|
///
|
||||||
|
/// # Note
|
||||||
|
///
|
||||||
|
/// This does no verification that the supplied data
|
||||||
|
/// is, in fact, a wasm module.
|
||||||
|
pub fn generate(wasm_bytes: &[u8]) -> Self {
|
||||||
|
Self {
|
||||||
|
new_hash: new::wasmer_cache::WasmHash::generate(wasm_bytes),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create the hexadecimal representation of the
|
||||||
|
/// stored hash.
|
||||||
|
pub fn encode(self) -> String {
|
||||||
|
self.new_hash.to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create hash from hexadecimal representation
|
||||||
|
pub fn decode(hex_str: &str) -> Result<Self, new::wasmer_engine::DeserializeError> {
|
||||||
|
Ok(Self {
|
||||||
|
new_hash: new::wasmer_cache::WasmHash::from_str(hex_str)?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A unique ID generated from the version of Wasmer for use with cache versioning
|
||||||
|
pub const WASMER_VERSION_HASH: &'static str =
|
||||||
|
include_str!(concat!(env!("OUT_DIR"), "/wasmer_version_hash.txt"));
|
||||||
3
lib/deprecated/runtime-core/src/error.rs
Normal file
3
lib/deprecated/runtime-core/src/error.rs
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
pub use crate::new::wasmer::{ExportError, MemoryError};
|
||||||
|
pub use crate::new::wasmer_compiler::CompileError;
|
||||||
|
pub use crate::new::wasmer_engine::{InstantiationError, LinkError, RuntimeError};
|
||||||
4
lib/deprecated/runtime-core/src/export.rs
Normal file
4
lib/deprecated/runtime-core/src/export.rs
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
pub use crate::new::{
|
||||||
|
wasmer::{Exportable, Extern as Export},
|
||||||
|
wasmer_vm::Export as RuntimeExport,
|
||||||
|
};
|
||||||
110
lib/deprecated/runtime-core/src/functional_api.rs
Normal file
110
lib/deprecated/runtime-core/src/functional_api.rs
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
use crate::{
|
||||||
|
backend::Backend, cache::Artifact, get_global_store, module::Module, new,
|
||||||
|
renew_global_store_with,
|
||||||
|
};
|
||||||
|
use std::{convert::Infallible, error::Error};
|
||||||
|
|
||||||
|
pub use new::wasmer::wat2wasm;
|
||||||
|
|
||||||
|
/// Compile WebAssembly binary code into a [`Module`].
|
||||||
|
/// This function is useful if it is necessary to
|
||||||
|
/// compile a module before it can be instantiated
|
||||||
|
/// (otherwise, the [`instantiate`] function should be used).
|
||||||
|
///
|
||||||
|
/// [`Module`]: struct.Module.html
|
||||||
|
/// [`instantiate`]: fn.instantiate.html
|
||||||
|
///
|
||||||
|
/// # Params
|
||||||
|
///
|
||||||
|
/// * `wasm`: A `&[u8]` containing the
|
||||||
|
/// binary code of the wasm module you want to compile.
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
///
|
||||||
|
/// If the operation fails, the function returns `Err(error::CompileError::...)`.
|
||||||
|
///
|
||||||
|
/// This function only exists if one of `default-backend-llvm`, `default-backend-cranelift`,
|
||||||
|
/// or `default-backend-singlepass` is set.
|
||||||
|
pub fn compile(bytes: &[u8]) -> Result<Module, Box<dyn Error>> {
|
||||||
|
compile_with(bytes, Backend::Auto)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a new module from the given cache [`Artifact`]
|
||||||
|
pub fn load_cache_with(cache: Artifact) -> Result<Module, Infallible> {
|
||||||
|
Ok(cache.module())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Compile a [`Module`] using the provided compiler from
|
||||||
|
/// WebAssembly binary code. This function is useful if it
|
||||||
|
/// is necessary to a compile a module before it can be instantiated
|
||||||
|
/// and must be used if you wish to use a different backend from the default.
|
||||||
|
pub fn compile_with(bytes: &[u8], compiler: Backend) -> Result<Module, Box<dyn Error>> {
|
||||||
|
renew_global_store_with(compiler);
|
||||||
|
|
||||||
|
Ok(Module::new(new::wasmer::Module::new(
|
||||||
|
&get_global_store(),
|
||||||
|
bytes,
|
||||||
|
)?))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The same as `compile_with` but changes the compiler behavior
|
||||||
|
/// with the values in the `CompilerConfig`
|
||||||
|
///
|
||||||
|
/// # Note
|
||||||
|
///
|
||||||
|
/// The third parameter isn't used any more in the deprecated version
|
||||||
|
/// of `wasmer-runtime-core`.
|
||||||
|
pub fn compile_with_config(
|
||||||
|
bytes: &[u8],
|
||||||
|
compiler: Backend,
|
||||||
|
_compiler_config: (),
|
||||||
|
) -> Result<Module, Box<dyn Error>> {
|
||||||
|
renew_global_store_with(compiler);
|
||||||
|
|
||||||
|
Ok(Module::new(new::wasmer::Module::new(
|
||||||
|
&get_global_store(),
|
||||||
|
bytes,
|
||||||
|
)?))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Perform validation as defined by the
|
||||||
|
/// WebAssembly specification. Returns `true` if validation
|
||||||
|
/// succeeded, `false` if validation failed.
|
||||||
|
pub fn validate(bytes: &[u8]) -> bool {
|
||||||
|
new::wasmer::Module::validate(&get_global_store(), bytes).is_ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Helper macro to create a new `Func` object using the provided function pointer.
|
||||||
|
///
|
||||||
|
/// # Usage
|
||||||
|
///
|
||||||
|
/// Function pointers or closures are supported. Closures can capture
|
||||||
|
/// their environment (with `move`). The first parameter is of kind
|
||||||
|
/// `vm::Ctx`.
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use wasmer_runtime_core::{imports, func, vm};
|
||||||
|
///
|
||||||
|
/// // A host function.
|
||||||
|
/// fn func(ctx: &mut vm::Ctx, n: i32) -> i32 {
|
||||||
|
/// n
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// let i = 7;
|
||||||
|
///
|
||||||
|
/// let import_object = imports! {
|
||||||
|
/// "env" => {
|
||||||
|
/// "foo" => func!(func),
|
||||||
|
/// // A closure with a captured environment.
|
||||||
|
/// "bar" => func!(move |_: &mut vm::Ctx, n: i32| -> i32 {
|
||||||
|
/// n + i
|
||||||
|
/// }),
|
||||||
|
/// },
|
||||||
|
/// };
|
||||||
|
/// ```
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! func {
|
||||||
|
($function:expr) => {
|
||||||
|
$crate::typed_func::Func::new($function)
|
||||||
|
};
|
||||||
|
}
|
||||||
105
lib/deprecated/runtime-core/src/global.rs
Normal file
105
lib/deprecated/runtime-core/src/global.rs
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
use crate::{
|
||||||
|
error::ExportError,
|
||||||
|
get_global_store, new,
|
||||||
|
types::{GlobalDescriptor, Value},
|
||||||
|
};
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
/// A handle to a Wasm Global
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct Global {
|
||||||
|
new_global: new::wasmer::Global,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Global {
|
||||||
|
/// Create a new `Global` value.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use wasmer_runtime_core::{global::Global, types::Value};
|
||||||
|
/// let global = Global::new(Value::I32(42));
|
||||||
|
/// ```
|
||||||
|
pub fn new(value: Value) -> Self {
|
||||||
|
Self {
|
||||||
|
new_global: new::wasmer::Global::new(&get_global_store(), value),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a new, mutable `Global` value.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use wasmer_runtime_core::{global::Global, types::Value};
|
||||||
|
/// let global = Global::new_mutable(Value::I32(42));
|
||||||
|
/// ```
|
||||||
|
pub fn new_mutable(value: Value) -> Self {
|
||||||
|
Self {
|
||||||
|
new_global: new::wasmer::Global::new_mut(&get_global_store(), value),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the [`GlobalDescriptor`] generated for this global.
|
||||||
|
///
|
||||||
|
/// [`GlobalDescriptor`]: struct.GlobalDescriptor.html
|
||||||
|
pub fn descriptor(&self) -> GlobalDescriptor {
|
||||||
|
self.new_global.ty().into()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the value help by this global.
|
||||||
|
///
|
||||||
|
/// This method will panic if the value is
|
||||||
|
/// the wrong type.
|
||||||
|
pub fn set(&self, value: Value) {
|
||||||
|
self.new_global.set(value).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the value held by this global.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use wasmer_runtime_core::{global::Global, types::Value};
|
||||||
|
/// let global = Global::new_mutable(Value::I32(42));
|
||||||
|
/// assert_eq!(global.get(), Value::I32(42));
|
||||||
|
///
|
||||||
|
/// global.set(Value::I32(7));
|
||||||
|
/// assert_eq!(global.get(), Value::I32(7));
|
||||||
|
/// ```
|
||||||
|
pub fn get(&self) -> Value {
|
||||||
|
self.new_global.get()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for Global {
|
||||||
|
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(formatter, "{:?}", &self.new_global)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&new::wasmer::Global> for Global {
|
||||||
|
fn from(new_global: &new::wasmer::Global) -> Self {
|
||||||
|
Self {
|
||||||
|
new_global: new_global.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> new::wasmer::Exportable<'a> for Global {
|
||||||
|
fn to_export(&self) -> new::wasmer_vm::Export {
|
||||||
|
self.new_global.to_export()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_self_from_extern(r#extern: &'a new::wasmer::Extern) -> Result<&'a Self, ExportError> {
|
||||||
|
match r#extern {
|
||||||
|
new::wasmer::Extern::Global(global) => Ok(
|
||||||
|
// It's not ideal to call `Box::leak` here, but it
|
||||||
|
// would introduce too much changes in the
|
||||||
|
// `new::wasmer` API to support `Cow` or similar.
|
||||||
|
Box::leak(Box::<Global>::new(global.into())),
|
||||||
|
),
|
||||||
|
_ => Err(ExportError::IncompatibleType),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
215
lib/deprecated/runtime-core/src/import.rs
Normal file
215
lib/deprecated/runtime-core/src/import.rs
Normal file
@@ -0,0 +1,215 @@
|
|||||||
|
use crate::{instance::Exports, new};
|
||||||
|
|
||||||
|
pub use new::wasmer::{namespace, ImportObject, ImportObjectIterator, LikeNamespace};
|
||||||
|
|
||||||
|
pub struct Namespace {
|
||||||
|
exports: Exports,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Namespace {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
exports: Exports::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn insert<N, V>(&mut self, name: N, value: V)
|
||||||
|
where
|
||||||
|
N: Into<String>,
|
||||||
|
V: Into<new::wasmer::Extern> + 'static,
|
||||||
|
{
|
||||||
|
self.exports.new_exports.insert(name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn contains_key<N>(&mut self, name: N) -> bool
|
||||||
|
where
|
||||||
|
N: Into<String>,
|
||||||
|
{
|
||||||
|
self.exports.new_exports.contains(name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LikeNamespace for Namespace {
|
||||||
|
fn get_namespace_export(&self, name: &str) -> Option<new::wasmer_vm::Export> {
|
||||||
|
self.exports.new_exports.get_namespace_export(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_namespace_exports(&self) -> Vec<(String, new::wasmer_vm::Export)> {
|
||||||
|
self.exports.new_exports.get_namespace_exports()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[deprecated(
|
||||||
|
since = "__NEXT_VERSION__",
|
||||||
|
note = "Please use the `Exportable` trait instead."
|
||||||
|
)]
|
||||||
|
pub trait IsExport {}
|
||||||
|
|
||||||
|
/// Generate an `ImportObject` easily with the `imports!` macro.
|
||||||
|
///
|
||||||
|
/// # Usage
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use wasmer_runtime_core::{imports, func, vm::Ctx};
|
||||||
|
///
|
||||||
|
/// let import_object = imports! {
|
||||||
|
/// "env" => {
|
||||||
|
/// "foo" => func!(foo)
|
||||||
|
/// },
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// fn foo(_: &mut Ctx, n: i32) -> i32 {
|
||||||
|
/// n
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// or by passing a state creator for the import object:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use wasmer_runtime_core::{imports, func, vm::Ctx};
|
||||||
|
///
|
||||||
|
/// let import_object = imports! {
|
||||||
|
/// || (0 as _, |_a| {}),
|
||||||
|
/// "env" => {
|
||||||
|
/// "foo" => func!(foo)
|
||||||
|
/// },
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// # fn foo(_: &mut Ctx, n: i32) -> i32 {
|
||||||
|
/// # n
|
||||||
|
/// # }
|
||||||
|
/// ```
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! imports {
|
||||||
|
( $( $namespace_name:expr => $namespace:tt ),* $(,)? ) => {
|
||||||
|
{
|
||||||
|
let mut import_object = $crate::import::ImportObject::new();
|
||||||
|
|
||||||
|
$({
|
||||||
|
let namespace = $crate::import_namespace!($namespace);
|
||||||
|
|
||||||
|
import_object.register($namespace_name, namespace);
|
||||||
|
})*
|
||||||
|
|
||||||
|
import_object
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
($state_creator:expr, $( $namespace_name:expr => $namespace:tt ),* $(,)? ) => {
|
||||||
|
{
|
||||||
|
let mut import_object = $crate::import::ImportObject::new_with_data($state_creator);
|
||||||
|
|
||||||
|
$({
|
||||||
|
let namespace = $crate::import_namespace!($namespace);
|
||||||
|
|
||||||
|
import_object.register($namespace_name, namespace);
|
||||||
|
})*
|
||||||
|
|
||||||
|
import_object
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
#[doc(hidden)]
|
||||||
|
macro_rules! import_namespace {
|
||||||
|
( { $( $import_name:expr => $import_item:expr ),* $(,)? } ) => {
|
||||||
|
{
|
||||||
|
let mut namespace = $crate::import::Namespace::new();
|
||||||
|
|
||||||
|
$(
|
||||||
|
namespace.insert($import_name, $import_item);
|
||||||
|
)*
|
||||||
|
|
||||||
|
namespace
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
( $namespace:ident ) => {
|
||||||
|
$namespace
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use crate::{func, vm};
|
||||||
|
|
||||||
|
fn func(_: &mut vm::Ctx, arg: i32) -> i32 {
|
||||||
|
arg + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn imports_macro_allows_trailing_comma_and_none() {
|
||||||
|
let _ = imports! {
|
||||||
|
"env" => {
|
||||||
|
"func" => func!(func),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
let _ = imports! {
|
||||||
|
"env" => {
|
||||||
|
"func" => func!(func),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let _ = imports! {
|
||||||
|
"env" => {
|
||||||
|
"func" => func!(func),
|
||||||
|
},
|
||||||
|
"abc" => {
|
||||||
|
"def" => func!(func),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let _ = imports! {
|
||||||
|
"env" => {
|
||||||
|
"func" => func!(func)
|
||||||
|
},
|
||||||
|
};
|
||||||
|
let _ = imports! {
|
||||||
|
"env" => {
|
||||||
|
"func" => func!(func)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let _ = imports! {
|
||||||
|
"env" => {
|
||||||
|
"func1" => func!(func),
|
||||||
|
"func2" => func!(func)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let _ = imports! {
|
||||||
|
"env" => {
|
||||||
|
"func1" => func!(func),
|
||||||
|
"func2" => func!(func),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn imports_macro_allows_trailing_comma_and_none_with_state() {
|
||||||
|
use std::{ffi, ptr};
|
||||||
|
|
||||||
|
fn dtor(_arg: *mut ffi::c_void) {}
|
||||||
|
fn state_creator() -> (*mut ffi::c_void, fn(*mut ffi::c_void)) {
|
||||||
|
(ptr::null_mut() as *mut ffi::c_void, dtor)
|
||||||
|
}
|
||||||
|
let _ = imports! {
|
||||||
|
state_creator,
|
||||||
|
"env" => {
|
||||||
|
"func1" => func!(func),
|
||||||
|
"func2" => func!(func),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let _ = imports! {
|
||||||
|
state_creator,
|
||||||
|
"env" => {
|
||||||
|
"func1" => func!(func),
|
||||||
|
"func2" => func!(func)
|
||||||
|
},
|
||||||
|
};
|
||||||
|
let _ = imports! {
|
||||||
|
state_creator,
|
||||||
|
"env" => {
|
||||||
|
"func1" => func!(func),
|
||||||
|
"func2" => func!(func),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
272
lib/deprecated/runtime-core/src/instance.rs
Normal file
272
lib/deprecated/runtime-core/src/instance.rs
Normal file
@@ -0,0 +1,272 @@
|
|||||||
|
use crate::{
|
||||||
|
error::ExportError,
|
||||||
|
export::{Export, Exportable},
|
||||||
|
import::LikeNamespace,
|
||||||
|
module::{ExportIndex, Module},
|
||||||
|
new,
|
||||||
|
structures::TypedIndex,
|
||||||
|
typed_func::Func,
|
||||||
|
types::Value,
|
||||||
|
vm,
|
||||||
|
};
|
||||||
|
use std::{
|
||||||
|
cell::{Ref, RefCell, RefMut},
|
||||||
|
error::Error,
|
||||||
|
rc::Rc,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub use crate::typed_func::DynamicFunc as DynFunc;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub(crate) struct PreInstance {
|
||||||
|
pub(crate) vmctx: Rc<RefCell<vm::Ctx>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PreInstance {
|
||||||
|
pub(crate) fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
vmctx: Rc::new(RefCell::new(unsafe { vm::Ctx::new_uninit() })),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn vmctx(&self) -> Rc<RefCell<vm::Ctx>> {
|
||||||
|
self.vmctx.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn vmctx_ptr(&self) -> *mut vm::Ctx {
|
||||||
|
self.vmctx.as_ptr()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// An instantiated WebAssembly module.
|
||||||
|
///
|
||||||
|
/// An `Instance` represents a WebAssembly module that
|
||||||
|
/// has been instantiated with an [`ImportObject`] and is
|
||||||
|
/// ready to be called.
|
||||||
|
///
|
||||||
|
/// [`ImportObject`]: struct.ImportObject.html
|
||||||
|
pub struct Instance {
|
||||||
|
pre_instance: Box<PreInstance>,
|
||||||
|
/// The exports of this instance.
|
||||||
|
pub exports: Exports,
|
||||||
|
pub(crate) new_instance: new::wasmer::Instance,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Instance {
|
||||||
|
pub(crate) fn new(pre_instance: Box<PreInstance>, new_instance: new::wasmer::Instance) -> Self {
|
||||||
|
// Initialize the `vm::Ctx`
|
||||||
|
{
|
||||||
|
let mut vmctx = pre_instance.vmctx.borrow_mut();
|
||||||
|
|
||||||
|
vmctx.module_info = new_instance.module().info() as *const _;
|
||||||
|
}
|
||||||
|
|
||||||
|
Self {
|
||||||
|
pre_instance,
|
||||||
|
exports: new_instance.exports.clone().into(),
|
||||||
|
new_instance,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Through generic magic and the awe-inspiring power of traits, we bring you...
|
||||||
|
///
|
||||||
|
/// # "Func"
|
||||||
|
///
|
||||||
|
/// A [`Func`] allows you to call functions exported from wasm with
|
||||||
|
/// near zero overhead.
|
||||||
|
///
|
||||||
|
/// [`Func`]: struct.Func.html
|
||||||
|
///
|
||||||
|
/// # Usage
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # #![allow(deprecated)]
|
||||||
|
/// # use wasmer_runtime_core::{Func, Instance, error::ExportError};
|
||||||
|
/// # fn typed_func(instance: Instance) -> Result<(), ExportError> {
|
||||||
|
/// let func: Func<(i32, i32)> = instance.func("foo")?;
|
||||||
|
///
|
||||||
|
/// func.call(42, 43);
|
||||||
|
/// # Ok(())
|
||||||
|
/// # }
|
||||||
|
/// ```
|
||||||
|
#[deprecated(
|
||||||
|
since = "0.17.0",
|
||||||
|
note = "Please use `instance.exports.get(name)` instead"
|
||||||
|
)]
|
||||||
|
pub fn func<Args, Rets>(&self, name: &str) -> Result<Func<Args, Rets>, ExportError>
|
||||||
|
where
|
||||||
|
Args: new::wasmer::WasmTypeList + Clone,
|
||||||
|
Rets: new::wasmer::WasmTypeList + Clone,
|
||||||
|
{
|
||||||
|
self.exports.get(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This returns the representation of a function that can be called
|
||||||
|
/// safely.
|
||||||
|
///
|
||||||
|
/// # Usage
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # #![allow(deprecated)]
|
||||||
|
/// # use wasmer_runtime_core::{Instance};
|
||||||
|
/// # fn call_foo(instance: &mut Instance) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
/// instance
|
||||||
|
/// .dyn_func("foo")?
|
||||||
|
/// .call(&[])?;
|
||||||
|
/// # Ok(())
|
||||||
|
/// # }
|
||||||
|
/// ```
|
||||||
|
#[deprecated(
|
||||||
|
since = "0.17.0",
|
||||||
|
note = "Please use `instance.exports.get(name)` instead"
|
||||||
|
)]
|
||||||
|
pub fn dyn_func(&self, name: &str) -> Result<DynFunc, ExportError> {
|
||||||
|
self.exports.get(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Resolve an exported function by name.
|
||||||
|
pub fn resolve_func(&self, name: &str) -> Result<usize, ()> {
|
||||||
|
self.new_instance
|
||||||
|
.module()
|
||||||
|
.info()
|
||||||
|
.exports
|
||||||
|
.iter()
|
||||||
|
.find_map(|(export_name, export_index)| {
|
||||||
|
if name == export_name {
|
||||||
|
match export_index {
|
||||||
|
ExportIndex::Function(index) => Some(index.index()),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.ok_or(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Call an exported WebAssembly function given the export name.
|
||||||
|
/// Pass arguments by wrapping each one in the [`Value`] enum.
|
||||||
|
/// The returned values are also each wrapped in a [`Value`].
|
||||||
|
///
|
||||||
|
/// [`Value`]: enum.Value.html
|
||||||
|
///
|
||||||
|
/// # Note
|
||||||
|
///
|
||||||
|
/// This returns `Result<Vec<Value>, _>` in order to support
|
||||||
|
/// the future multi-value returns WebAssembly feature.
|
||||||
|
///
|
||||||
|
/// # Usage
|
||||||
|
///
|
||||||
|
/// Consider using the more explicit [`Exports::get`]` with [`DynFunc::call`]
|
||||||
|
/// instead. For example:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use wasmer_runtime_core::{types::Value, Instance, DynFunc};
|
||||||
|
/// # fn call_foo(instance: &mut Instance) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
/// // …
|
||||||
|
/// let foo: DynFunc = instance.exports.get("foo")?;
|
||||||
|
/// let results = foo.call(&[Value::I32(42)])?;
|
||||||
|
/// // …
|
||||||
|
/// # Ok(())
|
||||||
|
/// # }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Another example with `Instance::call` directly:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use wasmer_runtime_core::{types::Value, Instance};
|
||||||
|
/// # fn call_foo(instance: &mut Instance) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
/// // ...
|
||||||
|
/// let results = instance.call("foo", &[Value::I32(42)])?;
|
||||||
|
/// // ...
|
||||||
|
/// # Ok(())
|
||||||
|
/// # }
|
||||||
|
/// ```
|
||||||
|
pub fn call(&self, name: &str, params: &[Value]) -> Result<Vec<Value>, Box<dyn Error>> {
|
||||||
|
Ok(self
|
||||||
|
.new_instance
|
||||||
|
.exports
|
||||||
|
.get_function(name)?
|
||||||
|
.call(params)?
|
||||||
|
.into_vec())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The module used to instantiate this Instance.
|
||||||
|
pub fn module(&self) -> Module {
|
||||||
|
Module::new(self.new_instance.module().clone())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns an immutable reference to the
|
||||||
|
/// [`Ctx`] used by this Instance.
|
||||||
|
///
|
||||||
|
/// [`Ctx`]: struct.Ctx.html
|
||||||
|
pub fn context(&self) -> Ref<vm::Ctx> {
|
||||||
|
self.pre_instance.vmctx.borrow()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a mutable reference to the
|
||||||
|
/// [`Ctx`] used by this Instance.
|
||||||
|
///
|
||||||
|
/// [`Ctx`]: struct.Ctx.html
|
||||||
|
pub fn context_mut(&mut self) -> RefMut<vm::Ctx> {
|
||||||
|
self.pre_instance.vmctx.borrow_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns an iterator over all of the items
|
||||||
|
/// exported from this instance.
|
||||||
|
pub fn exports(
|
||||||
|
&self,
|
||||||
|
) -> new::wasmer::ExportsIterator<impl Iterator<Item = (&String, &Export)>> {
|
||||||
|
self.new_instance.exports.iter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LikeNamespace for Instance {
|
||||||
|
fn get_namespace_export(&self, name: &str) -> Option<new::wasmer_vm::Export> {
|
||||||
|
self.exports.new_exports.get_namespace_export(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_namespace_exports(&self) -> Vec<(String, new::wasmer_vm::Export)> {
|
||||||
|
self.exports.new_exports.get_namespace_exports()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct Exports {
|
||||||
|
pub(crate) new_exports: new::wasmer::Exports,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Exports {
|
||||||
|
pub(crate) fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
new_exports: new::wasmer::Exports::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get<'a, T>(&'a self, name: &str) -> Result<T, ExportError>
|
||||||
|
where
|
||||||
|
T: Exportable<'a> + Clone + 'a,
|
||||||
|
{
|
||||||
|
Ok(self.new_exports.get::<T>(name)?.clone())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn iter(&self) -> new::wasmer::ExportsIterator<impl Iterator<Item = (&String, &Export)>> {
|
||||||
|
self.new_exports.iter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LikeNamespace for Exports {
|
||||||
|
fn get_namespace_export(&self, name: &str) -> Option<new::wasmer_vm::Export> {
|
||||||
|
self.new_exports.get_namespace_export(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_namespace_exports(&self) -> Vec<(String, new::wasmer_vm::Export)> {
|
||||||
|
self.new_exports.get_namespace_exports()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<new::wasmer::Exports> for Exports {
|
||||||
|
fn from(new_exports: new::wasmer::Exports) -> Self {
|
||||||
|
Self { new_exports }
|
||||||
|
}
|
||||||
|
}
|
||||||
161
lib/deprecated/runtime-core/src/lib.rs
Normal file
161
lib/deprecated/runtime-core/src/lib.rs
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
//! Wasmer Runtime Core Library
|
||||||
|
//!
|
||||||
|
//! # Important Note; Please Read
|
||||||
|
//!
|
||||||
|
//! Wasmer has entirely changed its API (called the “new API”
|
||||||
|
//! here). This new version of Wasmer improves the performance and the
|
||||||
|
//! memory consumption, in addition to a ton of new features and much
|
||||||
|
//! more flexibility! In order to help users to enjoy the performance
|
||||||
|
//! boost and memory improvements without updating your program that
|
||||||
|
//! much, we have created a new version of the `wasmer-runtime-core`
|
||||||
|
//! crate, which is now *a port* of the new API but with the old API,
|
||||||
|
//! as much as possible. Indeed, it was not always possible to provide
|
||||||
|
//! the exact same API, but changes are subtle.
|
||||||
|
//!
|
||||||
|
//! We have carefully documented most of the differences. It is
|
||||||
|
//! important to understand the public of this port (see the
|
||||||
|
//! `CHANGES.md`) document. We do not recommend to advanced users of
|
||||||
|
//! Wasmer to use this port. Advanced API, like `ModuleInfo` or the
|
||||||
|
//! `vm` module (incl. `vm::Ctx`) have not been fully ported because
|
||||||
|
//! it was very internals to Wasmer. For advanced users, we highly
|
||||||
|
//! recommend to migrate to the new version of Wasmer, which is
|
||||||
|
//! awesome by the way (completely neutral opinion). The public for
|
||||||
|
//! this port is beginners or regular users that do not necesarily
|
||||||
|
//! have time to update their code immediately but that want to enjoy
|
||||||
|
//! a performance boost and memory improvements.
|
||||||
|
//!
|
||||||
|
//! # Introduction
|
||||||
|
//!
|
||||||
|
//! This crate provides common data structures which are shared by
|
||||||
|
//! compiler backends to implement a WebAssembly runtime.
|
||||||
|
//!
|
||||||
|
//! This crate also provides an API for users who use wasmer as an
|
||||||
|
//! embedded wasm runtime which allows operations like compiling,
|
||||||
|
//! instantiating, providing imports, access exports, memories, and
|
||||||
|
//! tables for example.
|
||||||
|
//!
|
||||||
|
//! Most wasmer users should prefer the API which is re-exported by
|
||||||
|
//! the `wasmer-runtime` library by default. This crate provides
|
||||||
|
//! additional APIs which may be useful to users that wish to
|
||||||
|
//! customize the wasmer runtime.
|
||||||
|
|
||||||
|
pub(crate) mod new {
|
||||||
|
pub use wasm_common;
|
||||||
|
pub use wasmer;
|
||||||
|
pub use wasmer_cache;
|
||||||
|
pub use wasmer_compiler;
|
||||||
|
#[cfg(feature = "cranelift")]
|
||||||
|
pub use wasmer_compiler_cranelift;
|
||||||
|
#[cfg(feature = "llvm")]
|
||||||
|
pub use wasmer_compiler_llvm;
|
||||||
|
#[cfg(feature = "singlepass")]
|
||||||
|
pub use wasmer_compiler_singlepass;
|
||||||
|
pub use wasmer_engine;
|
||||||
|
pub use wasmer_engine_jit;
|
||||||
|
pub use wasmer_vm;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub mod backend;
|
||||||
|
pub mod cache;
|
||||||
|
pub mod error;
|
||||||
|
pub mod export;
|
||||||
|
mod functional_api;
|
||||||
|
pub mod global;
|
||||||
|
pub mod import;
|
||||||
|
pub mod instance;
|
||||||
|
pub mod memory;
|
||||||
|
pub mod module;
|
||||||
|
pub mod structures;
|
||||||
|
pub mod table;
|
||||||
|
pub mod typed_func;
|
||||||
|
pub mod types;
|
||||||
|
pub mod units;
|
||||||
|
pub mod vm;
|
||||||
|
|
||||||
|
pub use crate::cache::{Artifact, WasmHash};
|
||||||
|
#[allow(deprecated)]
|
||||||
|
pub use crate::import::IsExport;
|
||||||
|
pub use crate::instance::{DynFunc, Exports, Instance};
|
||||||
|
pub use crate::module::Module;
|
||||||
|
pub use crate::new::wasmer_compiler::wasmparser;
|
||||||
|
pub use crate::typed_func::{DynamicFunc, Func};
|
||||||
|
pub use crate::units::{Bytes, Pages, WASM_MAX_PAGES, WASM_MIN_PAGES, WASM_PAGE_SIZE};
|
||||||
|
pub use functional_api::{
|
||||||
|
compile, compile_with, compile_with_config, load_cache_with, validate, wat2wasm,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub mod prelude {
|
||||||
|
pub use crate::import::{namespace, ImportObject, Namespace};
|
||||||
|
pub use crate::typed_func::{DynamicFunc, Func};
|
||||||
|
pub use crate::types::{FuncIndex, GlobalIndex, MemoryIndex, TableIndex, Type, Value};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The current version of this crate
|
||||||
|
pub const VERSION: &'static str = env!("CARGO_PKG_VERSION");
|
||||||
|
|
||||||
|
use backend::Backend;
|
||||||
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
|
struct GlobalStore {
|
||||||
|
store: Mutex<Arc<new::wasmer::Store>>,
|
||||||
|
backend: Backend,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GlobalStore {
|
||||||
|
fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
store: Mutex::new(Arc::new(Default::default())),
|
||||||
|
backend: Backend::Auto,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn renew_with(&self, compiler: backend::Backend) {
|
||||||
|
if compiler == self.backend {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(unused_variables)]
|
||||||
|
let update = |compiler_config: &dyn new::wasmer_compiler::CompilerConfig,
|
||||||
|
global_store: &GlobalStore| {
|
||||||
|
let engine = new::wasmer_engine_jit::JIT::new(compiler_config).engine();
|
||||||
|
|
||||||
|
*self.store.lock().unwrap() = Arc::new(new::wasmer::Store::new(&engine));
|
||||||
|
};
|
||||||
|
|
||||||
|
match compiler {
|
||||||
|
#[cfg(feature = "singlepass")]
|
||||||
|
Backend::Singlepass => update(
|
||||||
|
&new::wasmer_compiler_singlepass::Singlepass::default(),
|
||||||
|
&self,
|
||||||
|
),
|
||||||
|
|
||||||
|
#[cfg(feature = "cranelift")]
|
||||||
|
Backend::Cranelift => {
|
||||||
|
update(&new::wasmer_compiler_cranelift::Cranelift::default(), &self)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "llvm")]
|
||||||
|
Backend::LLVM => update(&new::wasmer_compiler_llvm::LLVM::default(), &self),
|
||||||
|
|
||||||
|
Backend::Auto => *self.store.lock().unwrap() = Arc::new(Default::default()),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn inner_store(&self) -> Arc<new::wasmer::Store> {
|
||||||
|
(*self.store.lock().unwrap()).clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lazy_static::lazy_static! {
|
||||||
|
static ref GLOBAL_STORE: GlobalStore = GlobalStore::new();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Useful if one needs to update the global store.
|
||||||
|
pub(crate) fn renew_global_store_with(backend: Backend) {
|
||||||
|
GLOBAL_STORE.renew_with(backend);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Useful if one needs to migrate to the new Wasmer's API gently.
|
||||||
|
pub fn get_global_store() -> Arc<new::wasmer::Store> {
|
||||||
|
GLOBAL_STORE.inner_store()
|
||||||
|
}
|
||||||
139
lib/deprecated/runtime-core/src/memory.rs
Normal file
139
lib/deprecated/runtime-core/src/memory.rs
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
use crate::{
|
||||||
|
error::{ExportError, MemoryError},
|
||||||
|
get_global_store, new,
|
||||||
|
types::ValueType,
|
||||||
|
units::Pages,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub mod ptr {
|
||||||
|
pub use crate::new::wasmer::{Array, Item, WasmPtr};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub use new::wasm_common::MemoryType as MemoryDescriptor;
|
||||||
|
pub use new::wasmer::{Atomically, MemoryView};
|
||||||
|
pub use new::wasmer_vm::MemoryStyle as MemoryType;
|
||||||
|
|
||||||
|
/// A Wasm linear memory.
|
||||||
|
///
|
||||||
|
/// A `Memory` represents the memory used by a Wasm instance.
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct Memory {
|
||||||
|
new_memory: new::wasmer::Memory,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Memory {
|
||||||
|
/// Create a new `Memory` from a [`MemoryDescriptor`]
|
||||||
|
///
|
||||||
|
/// [`MemoryDescriptor`]: struct.MemoryDescriptor.html
|
||||||
|
///
|
||||||
|
/// Usage:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use wasmer_runtime_core::{types::MemoryDescriptor, error::MemoryError, memory::Memory, units::Pages};
|
||||||
|
/// fn create_memory() -> Result<(), MemoryError> {
|
||||||
|
/// let descriptor = MemoryDescriptor::new(Pages(10), None, false);
|
||||||
|
///
|
||||||
|
/// let memory = Memory::new(descriptor)?;
|
||||||
|
/// Ok(())
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
pub fn new(descriptor: MemoryDescriptor) -> Result<Self, MemoryError> {
|
||||||
|
Ok(Memory {
|
||||||
|
new_memory: new::wasmer::Memory::new(&get_global_store(), descriptor)?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the [`MemoryDescriptor`] that this memory
|
||||||
|
/// was created with.
|
||||||
|
///
|
||||||
|
/// [`MemoryDescriptor`]: struct.MemoryDescriptor.html
|
||||||
|
pub fn descriptor(&self) -> MemoryDescriptor {
|
||||||
|
self.new_memory.ty().clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Grow this memory by the specified number of pages.
|
||||||
|
pub fn grow(&self, delta: Pages) -> Result<Pages, MemoryError> {
|
||||||
|
self.new_memory.grow(delta)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The size, in wasm pages, of this memory.
|
||||||
|
pub fn size(&self) -> Pages {
|
||||||
|
self.new_memory.size()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return a "view" of the currently accessible memory. By
|
||||||
|
/// default, the view is unsynchronized, using regular memory
|
||||||
|
/// accesses. You can force a memory view to use atomic accesses
|
||||||
|
/// by calling the [`atomically`] method.
|
||||||
|
///
|
||||||
|
/// [`atomically`]: struct.MemoryView.html#method.atomically
|
||||||
|
///
|
||||||
|
/// # Notes
|
||||||
|
///
|
||||||
|
/// This method is safe (as in, it won't cause the host to crash or have UB),
|
||||||
|
/// but it doesn't obey rust's rules involving data races, especially concurrent ones.
|
||||||
|
/// Therefore, if this memory is shared between multiple threads, a single memory
|
||||||
|
/// location can be mutated concurrently without synchronization.
|
||||||
|
///
|
||||||
|
/// # Usage
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use wasmer_runtime_core::memory::{Memory, MemoryView};
|
||||||
|
/// # use std::{cell::Cell, sync::atomic::Ordering};
|
||||||
|
/// # fn view_memory(memory: Memory) {
|
||||||
|
/// // Without synchronization.
|
||||||
|
/// let view: MemoryView<u8> = memory.view();
|
||||||
|
/// for byte in view[0x1000 .. 0x1010].iter().map(Cell::get) {
|
||||||
|
/// println!("byte: {}", byte);
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// // With synchronization.
|
||||||
|
/// let atomic_view = view.atomically();
|
||||||
|
/// for byte in atomic_view[0x1000 .. 0x1010].iter().map(|atom| atom.load(Ordering::SeqCst)) {
|
||||||
|
/// println!("byte: {}", byte);
|
||||||
|
/// }
|
||||||
|
/// # }
|
||||||
|
/// ```
|
||||||
|
pub fn view<T: ValueType>(&self) -> MemoryView<T> {
|
||||||
|
self.new_memory.view()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&new::wasmer::Memory> for Memory {
|
||||||
|
fn from(new_memory: &new::wasmer::Memory) -> Self {
|
||||||
|
Self {
|
||||||
|
new_memory: new_memory.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> new::wasmer::Exportable<'a> for Memory {
|
||||||
|
fn to_export(&self) -> new::wasmer_vm::Export {
|
||||||
|
self.new_memory.to_export()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_self_from_extern(r#extern: &'a new::wasmer::Extern) -> Result<&'a Self, ExportError> {
|
||||||
|
match r#extern {
|
||||||
|
new::wasmer::Extern::Memory(memory) => Ok(
|
||||||
|
// It's not ideal to call `Box::leak` here, but it
|
||||||
|
// would introduce too much changes in the
|
||||||
|
// `new::wasmer` API to support `Cow` or similar.
|
||||||
|
Box::leak(Box::<Memory>::new(memory.into())),
|
||||||
|
),
|
||||||
|
_ => Err(ExportError::IncompatibleType),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod memory_tests {
|
||||||
|
use super::{Memory, MemoryDescriptor, Pages};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_initial_memory_size() {
|
||||||
|
let memory_desc = MemoryDescriptor::new(Pages(10), Some(Pages(20)), false);
|
||||||
|
let unshared_memory = Memory::new(memory_desc).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(unshared_memory.size(), Pages(10));
|
||||||
|
}
|
||||||
|
}
|
||||||
241
lib/deprecated/runtime-core/src/module.rs
Normal file
241
lib/deprecated/runtime-core/src/module.rs
Normal file
@@ -0,0 +1,241 @@
|
|||||||
|
use crate::{
|
||||||
|
cache::Artifact,
|
||||||
|
error::{InstantiationError, RuntimeError},
|
||||||
|
import::{ImportObject, Namespace},
|
||||||
|
instance::{Instance, PreInstance},
|
||||||
|
new,
|
||||||
|
typed_func::DynamicCtx,
|
||||||
|
types::{FuncSig, Value},
|
||||||
|
vm,
|
||||||
|
};
|
||||||
|
use new::wasmer_vm::Export;
|
||||||
|
use std::{
|
||||||
|
cell::RefCell,
|
||||||
|
collections::HashMap,
|
||||||
|
convert::{AsRef, Infallible},
|
||||||
|
ptr,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub use new::wasm_common::{DataInitializer, ExportIndex};
|
||||||
|
pub use new::wasmer_vm::{
|
||||||
|
//
|
||||||
|
MemoryStyle as MemoryType,
|
||||||
|
ModuleInfo,
|
||||||
|
TableElements as TableInitializer,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// A compiled WebAssembly module.
|
||||||
|
///
|
||||||
|
/// `Module` is returned by the [`compile`] function.
|
||||||
|
///
|
||||||
|
/// [`compile`]: crate::compile
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct Module {
|
||||||
|
pub(crate) new_module: new::wasmer::Module,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Module {
|
||||||
|
pub(crate) fn new(new_module: new::wasmer::Module) -> Self {
|
||||||
|
Self { new_module }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Instantiate a WebAssembly module with the provided [`ImportObject`].
|
||||||
|
///
|
||||||
|
/// [`ImportObject`]: struct.ImportObject.html
|
||||||
|
///
|
||||||
|
/// # Note
|
||||||
|
///
|
||||||
|
/// Instantiating a `Module` will also call the function designated as `start`
|
||||||
|
/// in the WebAssembly module, if there is one.
|
||||||
|
///
|
||||||
|
/// # Usage
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use wasmer_runtime_core::{Module, imports, error::InstantiationError};
|
||||||
|
/// # fn instantiate(module: &Module) -> Result<(), InstantiationError> {
|
||||||
|
/// let import_object = imports! {
|
||||||
|
/// // ...
|
||||||
|
/// };
|
||||||
|
/// let instance = module.instantiate(&import_object)?;
|
||||||
|
/// // ...
|
||||||
|
/// # Ok(())
|
||||||
|
/// # }
|
||||||
|
/// ```
|
||||||
|
pub fn instantiate(
|
||||||
|
&self,
|
||||||
|
import_object: &ImportObject,
|
||||||
|
) -> Result<Instance, InstantiationError> {
|
||||||
|
let pre_instance = Box::new(PreInstance::new());
|
||||||
|
|
||||||
|
let import_object = {
|
||||||
|
// The problem is the following:
|
||||||
|
//
|
||||||
|
// * In the old API, `Instance` owns the host functions'
|
||||||
|
// environments of kind `vm::Ctx`, and mutably shares it
|
||||||
|
// with all host functions.
|
||||||
|
// * In the new API, every host function owns its env of
|
||||||
|
// any kind; `Instance` knows nothing about this
|
||||||
|
// environment.
|
||||||
|
//
|
||||||
|
// To reproduce the old API with the new API, host
|
||||||
|
// functions create an empty environment of kind
|
||||||
|
// `vm::Ctx`. It is stored internally behind a `VMContext`
|
||||||
|
// pointer. The hack consists of rebuilding an
|
||||||
|
// `ImportObject` (that holds all the host functions), and
|
||||||
|
// updates the `VMContext` pointer to use a shared
|
||||||
|
// `vm::Ctx` value owned by `Instance` (actually,
|
||||||
|
// `PreInstance`).
|
||||||
|
|
||||||
|
let mut new_import_object = ImportObject::new();
|
||||||
|
let mut new_namespaces: HashMap<String, Namespace> = HashMap::new();
|
||||||
|
let store = self.new_module.store();
|
||||||
|
|
||||||
|
import_object
|
||||||
|
.clone_ref()
|
||||||
|
.into_iter()
|
||||||
|
.map(|((namespace, name), export)| match export {
|
||||||
|
Export::Function(mut function) => {
|
||||||
|
{
|
||||||
|
// `function` is a static host function
|
||||||
|
// constructed with
|
||||||
|
// `new::wasmer::Function::new_env`.
|
||||||
|
if !function.address.is_null() {
|
||||||
|
// Properly drop the empty `vm::Ctx`
|
||||||
|
// created by the host function.
|
||||||
|
unsafe {
|
||||||
|
ptr::drop_in_place::<vm::Ctx>(function.vmctx as _);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the pointer to `VMContext`,
|
||||||
|
// which is actually a `vm::Ctx`
|
||||||
|
// pointer, to fallback on the
|
||||||
|
// environment hack.
|
||||||
|
function.vmctx = pre_instance.vmctx_ptr() as _;
|
||||||
|
}
|
||||||
|
// `function` is a dynamic host function
|
||||||
|
// constructed with
|
||||||
|
// `new::wasmer::Function::new_dynamic_env`.
|
||||||
|
else {
|
||||||
|
// `VMContext` holds a complex type:
|
||||||
|
// `Box<VMDynamicFunctionContext<VMDynamicFunctionWithEnv<DynamicCtx>>>`.
|
||||||
|
//
|
||||||
|
// The type `VMDynamicFunctionWithEnv`
|
||||||
|
// is private to `new::wasmer`. Let's
|
||||||
|
// replicate it, and hope the layout
|
||||||
|
// is the same!
|
||||||
|
struct VMDynamicFunctionWithEnv<Env>
|
||||||
|
where
|
||||||
|
Env: Sized + 'static,
|
||||||
|
{
|
||||||
|
#[allow(unused)]
|
||||||
|
function_type: FuncSig,
|
||||||
|
#[allow(unused)]
|
||||||
|
func: Box<
|
||||||
|
dyn Fn(
|
||||||
|
&mut Env,
|
||||||
|
&[Value],
|
||||||
|
)
|
||||||
|
-> Result<Vec<Value>, RuntimeError>
|
||||||
|
+ 'static,
|
||||||
|
>,
|
||||||
|
env: RefCell<Env>,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get back the `vmctx` as it is
|
||||||
|
// stored by
|
||||||
|
// `new::wasmer::Function::new_dynamic_env`.
|
||||||
|
let vmctx: Box<
|
||||||
|
new::wasmer_vm::VMDynamicFunctionContext<
|
||||||
|
VMDynamicFunctionWithEnv<DynamicCtx>,
|
||||||
|
>,
|
||||||
|
> = unsafe { Box::from_raw(function.vmctx as *mut _) };
|
||||||
|
|
||||||
|
// Replace the environment by ours.
|
||||||
|
vmctx.ctx.env.borrow_mut().vmctx = pre_instance.vmctx();
|
||||||
|
|
||||||
|
// … without anyone noticing…
|
||||||
|
function.vmctx = Box::into_raw(vmctx) as _;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(
|
||||||
|
(namespace, name),
|
||||||
|
new::wasmer::Extern::from_export(store, Export::Function(function)),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
export => (
|
||||||
|
(namespace, name),
|
||||||
|
new::wasmer::Extern::from_export(store, export),
|
||||||
|
),
|
||||||
|
})
|
||||||
|
.for_each(|((namespace, name), extern_)| {
|
||||||
|
if !new_namespaces.contains_key(&namespace) {
|
||||||
|
new_namespaces.insert(namespace.clone(), Namespace::new());
|
||||||
|
}
|
||||||
|
|
||||||
|
let new_namespace = new_namespaces.get_mut(&namespace).unwrap(); // it is safe because it has been verified that the key exists.
|
||||||
|
new_namespace.insert(&name, extern_);
|
||||||
|
});
|
||||||
|
|
||||||
|
new_namespaces
|
||||||
|
.into_iter()
|
||||||
|
.for_each(|(namespace_name, namespace)| {
|
||||||
|
new_import_object.register(namespace_name, namespace);
|
||||||
|
});
|
||||||
|
|
||||||
|
new_import_object
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(Instance::new(
|
||||||
|
pre_instance,
|
||||||
|
new::wasmer::Instance::new(&self.new_module, &import_object)?,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a cache artifact from this module.
|
||||||
|
pub fn cache(&self) -> Result<Artifact, Infallible> {
|
||||||
|
Ok(Artifact::new(self.new_module.clone()))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the module data for this module.
|
||||||
|
pub fn info(&self) -> &ModuleInfo {
|
||||||
|
&self.new_module.info()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the [`ImportDescriptor`]s describing the imports this [`Module`]
|
||||||
|
/// requires to be instantiated.
|
||||||
|
pub fn imports(&self) -> Vec<crate::types::ImportDescriptor> {
|
||||||
|
self.new_module.imports().collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the [`ExportDescriptor`]s of the exports this [`Module`] provides.
|
||||||
|
pub fn exports(&self) -> Vec<crate::types::ExportDescriptor> {
|
||||||
|
self.new_module.exports().collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the custom sections matching the given name.
|
||||||
|
pub fn custom_sections(&self, name: impl AsRef<str>) -> Option<Vec<Vec<u8>>> {
|
||||||
|
let custom_sections: Vec<Vec<u8>> = self
|
||||||
|
.new_module
|
||||||
|
.custom_sections(name.as_ref())
|
||||||
|
.map(|custom_section| custom_section.to_vec())
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
if custom_sections.is_empty() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(custom_sections)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub fn into_inner(&self) -> new::wasmer::Module {
|
||||||
|
self.new_module.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<new::wasmer::Module> for Module {
|
||||||
|
fn into(self) -> new::wasmer::Module {
|
||||||
|
self.into_inner()
|
||||||
|
}
|
||||||
|
}
|
||||||
1
lib/deprecated/runtime-core/src/structures.rs
Normal file
1
lib/deprecated/runtime-core/src/structures.rs
Normal file
@@ -0,0 +1 @@
|
|||||||
|
pub use crate::new::wasm_common::entity::EntityRef as TypedIndex;
|
||||||
108
lib/deprecated/runtime-core/src/table.rs
Normal file
108
lib/deprecated/runtime-core/src/table.rs
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
use crate::{
|
||||||
|
error::{ExportError, RuntimeError},
|
||||||
|
get_global_store, new,
|
||||||
|
types::{TableDescriptor, Value},
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Container with a descriptor and a reference to a table storage.
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct Table {
|
||||||
|
new_table: new::wasmer::Table,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Table {
|
||||||
|
/// Create a new `Table` from a [`TableDescriptor`]
|
||||||
|
///
|
||||||
|
/// [`TableDescriptor`]: struct.TableDescriptor.html
|
||||||
|
///
|
||||||
|
/// # Usage
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use wasmer_runtime_core::{types::{TableDescriptor, Type, Value}, table::Table, error::RuntimeError};
|
||||||
|
/// # fn create_table() -> Result<(), RuntimeError> {
|
||||||
|
/// let descriptor = TableDescriptor {
|
||||||
|
/// ty: Type::ExternRef,
|
||||||
|
/// minimum: 10,
|
||||||
|
/// maximum: None,
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// let table = Table::new(descriptor, Value::null())?;
|
||||||
|
/// # Ok(())
|
||||||
|
/// # }
|
||||||
|
/// ```
|
||||||
|
pub fn new(descriptor: TableDescriptor, initial_value: Value) -> Result<Self, RuntimeError> {
|
||||||
|
Ok(Self {
|
||||||
|
new_table: new::wasmer::Table::new(&get_global_store(), descriptor, initial_value)?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the `TableDescriptor` used to create this `Table`.
|
||||||
|
pub fn descriptor(&self) -> TableDescriptor {
|
||||||
|
self.new_table.ty().clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the element at index.
|
||||||
|
pub fn set(&self, index: u32, value: Value) -> Result<(), RuntimeError> {
|
||||||
|
self.new_table.set(index, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get(&self, index: u32) -> Option<Value> {
|
||||||
|
self.new_table.get(index)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The current size of this table.
|
||||||
|
pub fn size(&self) -> u32 {
|
||||||
|
self.new_table.size()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Grow this table by `delta`.
|
||||||
|
pub fn grow(&self, delta: u32, initial_value: Value) -> Result<u32, RuntimeError> {
|
||||||
|
self.new_table.grow(delta, initial_value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&new::wasmer::Table> for Table {
|
||||||
|
fn from(new_table: &new::wasmer::Table) -> Self {
|
||||||
|
Self {
|
||||||
|
new_table: new_table.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> new::wasmer::Exportable<'a> for Table {
|
||||||
|
fn to_export(&self) -> new::wasmer_vm::Export {
|
||||||
|
self.new_table.to_export()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_self_from_extern(r#extern: &'a new::wasmer::Extern) -> Result<&'a Self, ExportError> {
|
||||||
|
match r#extern {
|
||||||
|
new::wasmer::Extern::Table(table) => Ok(
|
||||||
|
// It's not ideal to call `Box::leak` here, but it
|
||||||
|
// would introduce too much changes in the
|
||||||
|
// `new::wasmer` API to support `Cow` or similar.
|
||||||
|
Box::leak(Box::<Table>::new(table.into())),
|
||||||
|
),
|
||||||
|
_ => Err(ExportError::IncompatibleType),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod table_tests {
|
||||||
|
use super::{Table, TableDescriptor};
|
||||||
|
use crate::types::{Type, Value};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_initial_table_size() {
|
||||||
|
let table = Table::new(
|
||||||
|
TableDescriptor {
|
||||||
|
ty: Type::FuncRef,
|
||||||
|
minimum: 10,
|
||||||
|
maximum: Some(20),
|
||||||
|
},
|
||||||
|
Value::null(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(table.size(), 10);
|
||||||
|
}
|
||||||
|
}
|
||||||
409
lib/deprecated/runtime-core/src/typed_func.rs
Normal file
409
lib/deprecated/runtime-core/src/typed_func.rs
Normal file
@@ -0,0 +1,409 @@
|
|||||||
|
use crate::{
|
||||||
|
error::{ExportError, RuntimeError},
|
||||||
|
get_global_store, new,
|
||||||
|
types::{FuncSig, NativeWasmType, Type, Value, WasmExternType},
|
||||||
|
vm,
|
||||||
|
};
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
|
pub use new::wasmer::{HostFunction, WasmTypeList};
|
||||||
|
|
||||||
|
/// Represents a function that can be used by WebAssembly.
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct Func<Args = (), Rets = ()>
|
||||||
|
where
|
||||||
|
Args: WasmTypeList,
|
||||||
|
Rets: WasmTypeList,
|
||||||
|
{
|
||||||
|
new_function: new::wasmer::Function,
|
||||||
|
_phantom: PhantomData<(Args, Rets)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Args, Rets> Func<Args, Rets>
|
||||||
|
where
|
||||||
|
Args: WasmTypeList,
|
||||||
|
Rets: WasmTypeList,
|
||||||
|
{
|
||||||
|
/// Creates a new `Func`.
|
||||||
|
pub fn new<F>(func: F) -> Self
|
||||||
|
where
|
||||||
|
F: HostFunction<Args, Rets, new::wasmer::internals::WithEnv, vm::Ctx>,
|
||||||
|
{
|
||||||
|
// Create an empty `vm::Ctx`, that is going to be overwritten by `Instance::new`.
|
||||||
|
let ctx = unsafe { vm::Ctx::new_uninit() };
|
||||||
|
|
||||||
|
Self {
|
||||||
|
new_function: new::wasmer::Function::new_env::<F, Args, Rets, vm::Ctx>(
|
||||||
|
&get_global_store(),
|
||||||
|
ctx,
|
||||||
|
func,
|
||||||
|
),
|
||||||
|
_phantom: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the full function signature.
|
||||||
|
pub fn signature(&self) -> &FuncSig {
|
||||||
|
self.new_function.ty()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the types of the function inputs.
|
||||||
|
pub fn params(&self) -> &[Type] {
|
||||||
|
self.signature().params()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the types of the function outputs.
|
||||||
|
pub fn returns(&self) -> &[Type] {
|
||||||
|
self.signature().results()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Call the function by passing all arguments in a slice of `Value`.
|
||||||
|
pub fn dyn_call(&self, params: &[Value]) -> Result<Box<[Value]>, RuntimeError> {
|
||||||
|
self.new_function.call(params)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe trait WasmExternTypeInner: WasmExternType
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl WasmExternTypeInner for i8 {}
|
||||||
|
unsafe impl WasmExternTypeInner for u8 {}
|
||||||
|
unsafe impl WasmExternTypeInner for i16 {}
|
||||||
|
unsafe impl WasmExternTypeInner for u16 {}
|
||||||
|
unsafe impl WasmExternTypeInner for i32 {}
|
||||||
|
unsafe impl WasmExternTypeInner for u32 {}
|
||||||
|
unsafe impl WasmExternTypeInner for i64 {}
|
||||||
|
unsafe impl WasmExternTypeInner for u64 {}
|
||||||
|
unsafe impl WasmExternTypeInner for f32 {}
|
||||||
|
unsafe impl WasmExternTypeInner for f64 {}
|
||||||
|
|
||||||
|
macro_rules! func_call {
|
||||||
|
( $( $x:ident ),* ) => {
|
||||||
|
#[allow(unused_parens)]
|
||||||
|
impl< $( $x, )* Rets: WasmTypeList > Func<( $( $x ),* ), Rets>
|
||||||
|
where
|
||||||
|
$( $x: WasmExternType + WasmExternTypeInner, )*
|
||||||
|
Rets: WasmTypeList
|
||||||
|
{
|
||||||
|
/// Call the function.
|
||||||
|
#[allow(non_snake_case, clippy::too_many_arguments)]
|
||||||
|
pub fn call(&self, $( $x: $x, )* ) -> Result<Rets, RuntimeError> {
|
||||||
|
// Two implementation choices:
|
||||||
|
// 1. Either by using the `NativeFunc` API, but a
|
||||||
|
// new native function must be created for each
|
||||||
|
// call,
|
||||||
|
// 2. Pack the parameters into a slice, call
|
||||||
|
// `dyn_call` with it, and unpack the results.
|
||||||
|
//
|
||||||
|
// The first implementation is the following:
|
||||||
|
//
|
||||||
|
// self.new_function.native::<( $( $x ),* ), Rets>().unwrap().call( $( $x ),* )
|
||||||
|
//
|
||||||
|
// The second implementation is the following active one:
|
||||||
|
|
||||||
|
// Pack the argument into a slice.
|
||||||
|
let params: &[Value] = &[
|
||||||
|
$(
|
||||||
|
$x.to_native().to_value()
|
||||||
|
),*
|
||||||
|
];
|
||||||
|
|
||||||
|
// Call the function with `dyn_call`, and transform the results into a vector.
|
||||||
|
let results: Vec<Value> = self.dyn_call(params)?.to_vec();
|
||||||
|
|
||||||
|
// Map the results into their binary form.
|
||||||
|
let rets: Vec<i128> = results
|
||||||
|
.iter()
|
||||||
|
.map(|value| {
|
||||||
|
Ok(match value {
|
||||||
|
Value::I32(value) => <i32 as WasmExternType>::from_native(*value).to_binary(),
|
||||||
|
Value::I64(value) => <i64 as WasmExternType>::from_native(*value).to_binary(),
|
||||||
|
Value::F32(value) => <f32 as WasmExternType>::from_native(*value).to_binary(),
|
||||||
|
Value::F64(value) => <f64 as WasmExternType>::from_native(*value).to_binary(),
|
||||||
|
value => return Err(RuntimeError::new(format!(
|
||||||
|
"value `{:?}` is not supported as a returned value of a host function for the moment; please use `dyn_call` or the new API",
|
||||||
|
value
|
||||||
|
))),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.collect::<Result<_, _>>()?;
|
||||||
|
|
||||||
|
// Convert `Vec<i128>` into a `WasmTypeList`.
|
||||||
|
let rets: Rets = Rets::from_slice(rets.as_slice()).map_err(|_| {
|
||||||
|
RuntimeError::new(format!(
|
||||||
|
"returned values (`{:?}`) do not match the expected returned type (`{:?}`)",
|
||||||
|
results,
|
||||||
|
Rets::wasm_types()
|
||||||
|
))
|
||||||
|
})?;
|
||||||
|
|
||||||
|
Ok(rets)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func_call!();
|
||||||
|
func_call!(A1);
|
||||||
|
func_call!(A1, A2);
|
||||||
|
func_call!(A1, A2, A3);
|
||||||
|
func_call!(A1, A2, A3, A4);
|
||||||
|
func_call!(A1, A2, A3, A4, A5);
|
||||||
|
func_call!(A1, A2, A3, A4, A5, A6);
|
||||||
|
func_call!(A1, A2, A3, A4, A5, A6, A7);
|
||||||
|
func_call!(A1, A2, A3, A4, A5, A6, A7, A8);
|
||||||
|
func_call!(A1, A2, A3, A4, A5, A6, A7, A8, A9);
|
||||||
|
func_call!(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10);
|
||||||
|
func_call!(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11);
|
||||||
|
func_call!(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12);
|
||||||
|
func_call!(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13);
|
||||||
|
func_call!(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14);
|
||||||
|
func_call!(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15);
|
||||||
|
func_call!(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16);
|
||||||
|
func_call!(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17);
|
||||||
|
func_call!(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18);
|
||||||
|
func_call!(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19);
|
||||||
|
func_call!(
|
||||||
|
A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20
|
||||||
|
);
|
||||||
|
|
||||||
|
impl<Args, Rets> From<Func<Args, Rets>> for new::wasmer::Extern
|
||||||
|
where
|
||||||
|
Args: WasmTypeList,
|
||||||
|
Rets: WasmTypeList,
|
||||||
|
{
|
||||||
|
fn from(func: Func<Args, Rets>) -> Self {
|
||||||
|
new::wasmer::Extern::Function(func.new_function)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Args, Rets> From<&new::wasmer::Function> for Func<Args, Rets>
|
||||||
|
where
|
||||||
|
Args: WasmTypeList,
|
||||||
|
Rets: WasmTypeList,
|
||||||
|
{
|
||||||
|
fn from(new_function: &new::wasmer::Function) -> Self {
|
||||||
|
Self {
|
||||||
|
new_function: new_function.clone(),
|
||||||
|
_phantom: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, Args, Rets> new::wasmer::Exportable<'a> for Func<Args, Rets>
|
||||||
|
where
|
||||||
|
Args: WasmTypeList,
|
||||||
|
Rets: WasmTypeList,
|
||||||
|
{
|
||||||
|
fn to_export(&self) -> new::wasmer_vm::Export {
|
||||||
|
self.new_function.to_export()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_self_from_extern(r#extern: &'a new::wasmer::Extern) -> Result<&'a Self, ExportError> {
|
||||||
|
match r#extern {
|
||||||
|
new::wasmer::Extern::Function(func) => Ok(
|
||||||
|
// It's not ideal to call `Box::leak` here, but it
|
||||||
|
// would introduce too much changes in the
|
||||||
|
// `new::wasmer` API to support `Cow` or similar.
|
||||||
|
Box::leak(Box::<Func<Args, Rets>>::new(func.into())),
|
||||||
|
),
|
||||||
|
_ => Err(ExportError::IncompatibleType),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Represents a type-erased function provided by either the host or the WebAssembly program.
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct DynamicFunc {
|
||||||
|
new_function: new::wasmer::Function,
|
||||||
|
}
|
||||||
|
|
||||||
|
use std::{
|
||||||
|
cell::{RefCell, RefMut},
|
||||||
|
ops::DerefMut,
|
||||||
|
rc::Rc,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Specific context for `DynamicFunc`. It's a hack.
|
||||||
|
///
|
||||||
|
/// Initially, it holds an empty `vm::Ctx`, but it is replaced by the
|
||||||
|
/// `vm::Ctx` from `instance::PreInstance` in
|
||||||
|
/// `module::Module::instantiate`.
|
||||||
|
pub(crate) struct DynamicCtx {
|
||||||
|
pub(crate) vmctx: Rc<RefCell<vm::Ctx>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DynamicFunc {
|
||||||
|
/// Create a new `DynamicFunc`.
|
||||||
|
pub fn new<F>(signature: &FuncSig, func: F) -> Self
|
||||||
|
where
|
||||||
|
F: Fn(&mut vm::Ctx, &[Value]) -> Result<Vec<Value>, RuntimeError> + 'static,
|
||||||
|
{
|
||||||
|
// Create an empty `vm::Ctx`, that is going to be overwritten by `Instance::new`.
|
||||||
|
let ctx = DynamicCtx {
|
||||||
|
vmctx: Rc::new(RefCell::new(unsafe { vm::Ctx::new_uninit() })),
|
||||||
|
};
|
||||||
|
|
||||||
|
Self {
|
||||||
|
new_function: new::wasmer::Function::new_dynamic_env(
|
||||||
|
&get_global_store(),
|
||||||
|
signature,
|
||||||
|
ctx,
|
||||||
|
// Wrapper to safely extract a `&mut vm::Ctx` to pass
|
||||||
|
// to `func`.
|
||||||
|
move |dyn_ctx: &mut DynamicCtx,
|
||||||
|
params: &[Value]|
|
||||||
|
-> Result<Vec<Value>, RuntimeError> {
|
||||||
|
let cell: Rc<RefCell<vm::Ctx>> = dyn_ctx.vmctx.clone();
|
||||||
|
let mut vmctx: RefMut<vm::Ctx> = cell.borrow_mut();
|
||||||
|
|
||||||
|
func(vmctx.deref_mut(), params)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the full function signature.
|
||||||
|
pub fn signature(&self) -> &FuncSig {
|
||||||
|
self.new_function.ty()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the types of the function inputs.
|
||||||
|
pub fn params(&self) -> &[Type] {
|
||||||
|
self.signature().params()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the types of the function outputs.
|
||||||
|
pub fn returns(&self) -> &[Type] {
|
||||||
|
self.signature().results()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Call the function. In this case, it's an alias to `dyn_call`.
|
||||||
|
pub fn call(&self, params: &[Value]) -> Result<Box<[Value]>, RuntimeError> {
|
||||||
|
self.dyn_call(params)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Call the function.
|
||||||
|
pub fn dyn_call(&self, params: &[Value]) -> Result<Box<[Value]>, RuntimeError> {
|
||||||
|
self.new_function.call(params)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<DynamicFunc> for new::wasmer::Extern {
|
||||||
|
fn from(dynamic_func: DynamicFunc) -> Self {
|
||||||
|
new::wasmer::Extern::Function(dynamic_func.new_function)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&new::wasmer::Function> for DynamicFunc {
|
||||||
|
fn from(new_function: &new::wasmer::Function) -> Self {
|
||||||
|
Self {
|
||||||
|
new_function: new_function.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> new::wasmer::Exportable<'a> for DynamicFunc {
|
||||||
|
fn to_export(&self) -> new::wasmer_vm::Export {
|
||||||
|
self.new_function.to_export()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_self_from_extern(r#extern: &'a new::wasmer::Extern) -> Result<&'a Self, ExportError> {
|
||||||
|
match r#extern {
|
||||||
|
new::wasmer::Extern::Function(dynamic_func) => Ok(
|
||||||
|
// It's not ideal to call `Box::leak` here, but it
|
||||||
|
// would introduce too much changes in the
|
||||||
|
// `new::wasmer` API to support `Cow` or similar.
|
||||||
|
Box::leak(Box::<DynamicFunc>::new(dynamic_func.into())),
|
||||||
|
),
|
||||||
|
_ => Err(ExportError::IncompatibleType),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
macro_rules! test_func_arity_n {
|
||||||
|
($test_name:ident, $($x:ident),*) => {
|
||||||
|
#[test]
|
||||||
|
fn $test_name() {
|
||||||
|
use crate::vm;
|
||||||
|
|
||||||
|
fn with_vmctx(_: &mut vm::Ctx, $($x: i32),*) -> i32 {
|
||||||
|
vec![$($x),*].iter().sum()
|
||||||
|
}
|
||||||
|
|
||||||
|
let _ = Func::new(with_vmctx);
|
||||||
|
let _ = Func::new(|_: &mut vm::Ctx, $($x: i32),*| -> i32 {
|
||||||
|
vec![$($x),*].iter().sum()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_func_arity_0() {
|
||||||
|
fn foo(_: &mut vm::Ctx) -> i32 {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
|
let _ = Func::new(foo);
|
||||||
|
let _ = Func::new(|_: &mut vm::Ctx| -> i32 { 0 });
|
||||||
|
}
|
||||||
|
|
||||||
|
test_func_arity_n!(test_func_arity_1, a);
|
||||||
|
test_func_arity_n!(test_func_arity_2, a, b);
|
||||||
|
test_func_arity_n!(test_func_arity_3, a, b, c);
|
||||||
|
test_func_arity_n!(test_func_arity_4, a, b, c, d);
|
||||||
|
test_func_arity_n!(test_func_arity_5, a, b, c, d, e);
|
||||||
|
test_func_arity_n!(test_func_arity_6, a, b, c, d, e, f);
|
||||||
|
test_func_arity_n!(test_func_arity_7, a, b, c, d, e, f, g);
|
||||||
|
test_func_arity_n!(test_func_arity_8, a, b, c, d, e, f, g, h);
|
||||||
|
test_func_arity_n!(test_func_arity_9, a, b, c, d, e, f, g, h, i);
|
||||||
|
test_func_arity_n!(test_func_arity_10, a, b, c, d, e, f, g, h, i, j);
|
||||||
|
test_func_arity_n!(test_func_arity_11, a, b, c, d, e, f, g, h, i, j, k);
|
||||||
|
test_func_arity_n!(test_func_arity_12, a, b, c, d, e, f, g, h, i, j, k, l);
|
||||||
|
test_func_arity_n!(test_func_arity_13, a, b, c, d, e, f, g, h, i, j, k, l, m);
|
||||||
|
test_func_arity_n!(test_func_arity_14, a, b, c, d, e, f, g, h, i, j, k, l, m, n);
|
||||||
|
#[rustfmt::skip] test_func_arity_n!(test_func_arity_15, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o);
|
||||||
|
#[rustfmt::skip] test_func_arity_n!(test_func_arity_16, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p);
|
||||||
|
#[rustfmt::skip] test_func_arity_n!(test_func_arity_17, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q);
|
||||||
|
#[rustfmt::skip] test_func_arity_n!(test_func_arity_18, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r);
|
||||||
|
#[rustfmt::skip] test_func_arity_n!(test_func_arity_19, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s);
|
||||||
|
#[rustfmt::skip] test_func_arity_n!(test_func_arity_20, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t);
|
||||||
|
#[rustfmt::skip] test_func_arity_n!(test_func_arity_21, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u);
|
||||||
|
#[rustfmt::skip] test_func_arity_n!(test_func_arity_22, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v);
|
||||||
|
#[rustfmt::skip] test_func_arity_n!(test_func_arity_23, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w);
|
||||||
|
#[rustfmt::skip] test_func_arity_n!(test_func_arity_24, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x);
|
||||||
|
#[rustfmt::skip] test_func_arity_n!(test_func_arity_25, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y);
|
||||||
|
#[rustfmt::skip] test_func_arity_n!(test_func_arity_26, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z);
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_call() {
|
||||||
|
fn foo(_ctx: &mut vm::Ctx, a: i32, b: i32) -> (i32, i32) {
|
||||||
|
(a, b)
|
||||||
|
}
|
||||||
|
|
||||||
|
let _f = Func::new(foo);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_imports() {
|
||||||
|
use crate::{func, imports};
|
||||||
|
|
||||||
|
fn foo(_ctx: &mut vm::Ctx, a: i32) -> i32 {
|
||||||
|
a
|
||||||
|
}
|
||||||
|
|
||||||
|
let _import_object = imports! {
|
||||||
|
"env" => {
|
||||||
|
"foo" => func!(foo),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
99
lib/deprecated/runtime-core/src/types.rs
Normal file
99
lib/deprecated/runtime-core/src/types.rs
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
use crate::new;
|
||||||
|
|
||||||
|
pub use new::wasm_common::{
|
||||||
|
//
|
||||||
|
ExportType as ExportDescriptor,
|
||||||
|
ExternType as ExternDescriptor,
|
||||||
|
FunctionIndex as FuncIndex,
|
||||||
|
FunctionIndex as ImportedFuncIndex,
|
||||||
|
FunctionType as FuncDescriptor,
|
||||||
|
FunctionType as FuncSig,
|
||||||
|
GlobalIndex as ImportedGlobalIndex,
|
||||||
|
GlobalIndex,
|
||||||
|
GlobalInit,
|
||||||
|
ImportType as ImportDescriptor,
|
||||||
|
LocalFunctionIndex as LocalFuncIndex,
|
||||||
|
LocalGlobalIndex,
|
||||||
|
LocalMemoryIndex,
|
||||||
|
LocalTableIndex,
|
||||||
|
MemoryIndex as ImportedMemoryIndex,
|
||||||
|
MemoryIndex,
|
||||||
|
MemoryType as MemoryDescriptor,
|
||||||
|
NativeWasmType,
|
||||||
|
SignatureIndex as SigIndex,
|
||||||
|
TableIndex as ImportedTableIndex,
|
||||||
|
TableIndex,
|
||||||
|
TableType as TableDescriptor,
|
||||||
|
Type,
|
||||||
|
ValueType,
|
||||||
|
};
|
||||||
|
pub use new::wasmer::{FromToNativeWasmType as WasmExternType, Val as Value};
|
||||||
|
|
||||||
|
/// Describes the mutability and type of a Global
|
||||||
|
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||||
|
pub struct GlobalDescriptor {
|
||||||
|
pub mutable: bool,
|
||||||
|
pub ty: Type,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&new::wasm_common::GlobalType> for GlobalDescriptor {
|
||||||
|
fn from(value: &new::wasm_common::GlobalType) -> Self {
|
||||||
|
Self {
|
||||||
|
mutable: value.mutability.into(),
|
||||||
|
ty: value.ty,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_native_types_round_trip() {
|
||||||
|
assert_eq!(
|
||||||
|
42i32,
|
||||||
|
i32::from_native(i32::from_binary((42i32).to_native().to_binary()))
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
-42i32,
|
||||||
|
i32::from_native(i32::from_binary((-42i32).to_native().to_binary()))
|
||||||
|
);
|
||||||
|
|
||||||
|
use std::i64;
|
||||||
|
let xi64 = i64::MAX;
|
||||||
|
assert_eq!(
|
||||||
|
xi64,
|
||||||
|
i64::from_native(i64::from_binary((xi64).to_native().to_binary()))
|
||||||
|
);
|
||||||
|
let yi64 = i64::MIN;
|
||||||
|
assert_eq!(
|
||||||
|
yi64,
|
||||||
|
i64::from_native(i64::from_binary((yi64).to_native().to_binary()))
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
16.5f32,
|
||||||
|
f32::from_native(f32::from_binary((16.5f32).to_native().to_binary()))
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
-16.5f32,
|
||||||
|
f32::from_native(f32::from_binary((-16.5f32).to_native().to_binary()))
|
||||||
|
);
|
||||||
|
|
||||||
|
use std::f64;
|
||||||
|
let xf64: f64 = f64::MAX;
|
||||||
|
assert_eq!(
|
||||||
|
xf64,
|
||||||
|
f64::from_native(f64::from_binary((xf64).to_native().to_binary()))
|
||||||
|
);
|
||||||
|
|
||||||
|
let yf64: f64 = f64::MIN;
|
||||||
|
assert_eq!(
|
||||||
|
yf64,
|
||||||
|
f64::from_native(f64::from_binary((yf64).to_native().to_binary()))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user