mirror of
https://github.com/fluencelabs/wasmer
synced 2025-06-25 22:51:32 +00:00
Merge upstream/master into feature/llvm-feature
This commit is contained in:
@ -12,6 +12,9 @@ environment:
|
|||||||
ABI: msvc
|
ABI: msvc
|
||||||
TARGET: x86_64-pc-windows-msvc
|
TARGET: x86_64-pc-windows-msvc
|
||||||
|
|
||||||
|
cache:
|
||||||
|
- 'C:\Users\appveyor\.cargo'
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe
|
- appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe
|
||||||
- rustup-init.exe -yv --default-host %target%
|
- rustup-init.exe -yv --default-host %target%
|
||||||
@ -27,9 +30,9 @@ test_script:
|
|||||||
- cd ./lib/spectests && cargo test -- --test-threads 1 && cd ../..
|
- cd ./lib/spectests && cargo test -- --test-threads 1 && cd ../..
|
||||||
|
|
||||||
before_deploy:
|
before_deploy:
|
||||||
- cd installer
|
- cd ./src/installer
|
||||||
- iscc wasmer.iss
|
- iscc wasmer.iss
|
||||||
- copy /y .\WasmerInstaller.exe ..\WasmerInstaller-%APPVEYOR_REPO_TAG_NAME%.exe
|
- copy /y .\WasmerInstaller.exe ..\..\WasmerInstaller-%APPVEYOR_REPO_TAG_NAME%.exe
|
||||||
- appveyor PushArtifact WasmerInstaller-%APPVEYOR_REPO_TAG_NAME%.exe
|
- appveyor PushArtifact WasmerInstaller-%APPVEYOR_REPO_TAG_NAME%.exe
|
||||||
|
|
||||||
artifacts:
|
artifacts:
|
||||||
|
@ -2,19 +2,19 @@
|
|||||||
|
|
||||||
Wasmer uses the following components:
|
Wasmer uses the following components:
|
||||||
|
|
||||||
- [Cranelift](https://github.com/cranestation/cranelift): for compiling WASM function binaries into Machine IR
|
- [Cranelift](https://github.com/cranestation/cranelift): for compiling Wasm binaries to machine code
|
||||||
- [wabt](https://github.com/pepyakin/wabt-rs): for transforming `.wast` files to `.wasm` and also to run WebAssembly spectests
|
- [wabt](https://github.com/pepyakin/wabt-rs): for transforming `.wast` files to `.wasm` and running WebAssembly spec tests
|
||||||
- [wasmparser](https://github.com/yurydelendik/wasmparser.rs): for parsing the `.wasm` files and translating them into WebAssembly Modules
|
- [wasmparser](https://github.com/yurydelendik/wasmparser.rs): for parsing the `.wasm` files and translating them into WebAssembly modules
|
||||||
|
|
||||||
## How Wasmer works?
|
## How Wasmer works
|
||||||
|
|
||||||
The first time you run `wasmer run myfile.wasm`, wasmer will:
|
The first time you run `wasmer run myfile.wasm`, Wasmer will:
|
||||||
|
|
||||||
- Check if is a `.wast` file. If so, transform it to `.wasm`
|
- Check if is a `.wast` file, and if so, transform it to `.wasm`
|
||||||
- Check that the provided binary is a valid WebAssembly one. That means, that its binary format starts with `\0asm`.
|
- Check that the provided binary is a valid WebAssembly one, i.e. its binary format starts with `\0asm`.
|
||||||
- If it looks like a WebAssembly file, try to parse it with `wasmparser` and generate a `Module` from it
|
- Parse it with `wasmparser` and generate a `Module` from it
|
||||||
- Once a `Module` is generated, an `Instance` is created with the proper `import_object` (that means, if is detected as an emscripten file, it will add the emscripten expected imports)
|
- Generate an `Instance` with the proper `import_object` (that means, if is detected to be an Emscripten file, it will add the Emscripten expected imports)
|
||||||
- Try to call the WebAssembly start function, or if unexistent try to search for the one that is exported as `main`.
|
- Try to call the WebAssembly `start` function, or if it does not exist, try to search for the function that is exported as `main`
|
||||||
|
|
||||||
Find a more detailed explanation of the process below:
|
Find a more detailed explanation of the process below:
|
||||||
|
|
||||||
@ -22,7 +22,7 @@ Find a more detailed explanation of the process below:
|
|||||||
|
|
||||||
As the WebAssembly file is being parsed, it will read the sections in the WebAssembly file (memory, table, function, global and element definitions) using the `Module` (or `ModuleEnvironment`) as the structure to hold this information.
|
As the WebAssembly file is being parsed, it will read the sections in the WebAssembly file (memory, table, function, global and element definitions) using the `Module` (or `ModuleEnvironment`) as the structure to hold this information.
|
||||||
|
|
||||||
However, the real IR initialization happens while a function body is being parsed/created. That means, when the parser reads the section `(func ...)`.
|
However, the real IR initialization happens while a function body is being parsed/created, i.e. when the parser reads the section `(func ...)`.
|
||||||
While the function body is being parsed the corresponding `FuncEnvironment` methods will be called.
|
While the function body is being parsed the corresponding `FuncEnvironment` methods will be called.
|
||||||
|
|
||||||
So for example, if the function is using a table, the `make_table` method within that `FuncEnvironment` will be called.
|
So for example, if the function is using a table, the `make_table` method within that `FuncEnvironment` will be called.
|
||||||
@ -41,15 +41,14 @@ Once we have the compiled values, we will push them to memory and mark them as e
|
|||||||
|
|
||||||
#### Relocations
|
#### Relocations
|
||||||
|
|
||||||
Sometimes the functions that we generated will need to call other functions.
|
Sometimes the functions that we generate will need to call other functions, but the generated code has no idea how to link these functions together.
|
||||||
However the generated code have no idea how to link this functions together.
|
|
||||||
|
|
||||||
For example, if a function `A` is calling function `B` (that means is having a `(call b)` on it's body) while compiling `A` we will have no idea where the function `B` lives on memory (as `B` is not yet compiled nor pushed into memory).
|
For example, if a function `A` is calling function `B` (that means is having a `(call b)` on its body) while compiling `A` we will have no idea where the function `B` lives on memory (as `B` is not yet compiled nor pushed into memory).
|
||||||
|
|
||||||
For that reason, we will start collecting all the calls that function `A` will need to do under the hood, and save it's offsets.
|
For that reason, we will start collecting all the calls that function `A` will need to do under the hood, and save it's offsets.
|
||||||
We do that, so we can patch the function calls after compilation, to point to the correct memory address.
|
We do that, so we can patch the function calls after compilation, to point to the correct memory address.
|
||||||
|
|
||||||
Note: Sometimes this functions rather than living in the same WebAssembly module, they will be provided as import values.
|
Note: sometimes this functions rather than living in the same WebAssembly module, they will be provided as import values.
|
||||||
|
|
||||||
#### Traps
|
#### Traps
|
||||||
|
|
||||||
@ -66,5 +65,5 @@ Once that's finished, we will have a `Instance` function that will be ready to e
|
|||||||
|
|
||||||
## Emscripten
|
## Emscripten
|
||||||
|
|
||||||
The Wasmer Emscripten integration tries to wrap (and emulate) all the different syscalls that Emscripten needs.
|
Wasmer's Emscripten integration tries to wrap (and emulate) all the different syscalls that Emscripten needs.
|
||||||
We provide this integration by filling the `import_object` with the emscripten functions, while instantiating the WebAssembly Instance.
|
We provide this integration by filling the `import_object` with the Emscripten functions, while instantiating the WebAssembly Instance.
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
Wasmer is a community effort.
|
Wasmer is a community effort.
|
||||||
In order to build the best WebAssembly runtime it's our duty to see how other runtimes are approaching the same space
|
In order to build the best WebAssembly runtime it's our duty to see how other runtimes are approaching the same space
|
||||||
and get inspired from them on the things that they got right, so wasmer and its community can benefit from a solid
|
and get inspired from them on the things that they got right, so Wasmer and its community can benefit from a solid
|
||||||
foundation.
|
foundation.
|
||||||
|
|
||||||
These are the different project that we used as inspiration:
|
These are the different project that we used as inspiration:
|
||||||
@ -10,9 +10,9 @@ These are the different project that we used as inspiration:
|
|||||||
- [Nebulet](https://github.com/nebulet/nebulet): as the base for creating a great Rust WebAssembly runtime
|
- [Nebulet](https://github.com/nebulet/nebulet): as the base for creating a great Rust WebAssembly runtime
|
||||||
- [WAVM](https://github.com/wavm/wavm): for their great integration and testing framework
|
- [WAVM](https://github.com/wavm/wavm): for their great integration and testing framework
|
||||||
- [greenwasm](https://github.com/Kimundi/greenwasm): for their [spectests framework](https://github.com/Kimundi/greenwasm/tree/master/greenwasm-spectest)
|
- [greenwasm](https://github.com/Kimundi/greenwasm): for their [spectests framework](https://github.com/Kimundi/greenwasm/tree/master/greenwasm-spectest)
|
||||||
- [wasmtime](/wasmtime): on their [mmap implementation](https://github.com/CraneStation/wasmtime/blob/3f24098edc81cd9bf0f877fb7fba018cad0f039e/lib/runtime/src/mmap.rs).
|
- [wasmtime](https://github.com/CraneStation/wasmtime): for their [mmap implementation](https://github.com/CraneStation/wasmtime/blob/3f24098edc81cd9bf0f877fb7fba018cad0f039e/lib/runtime/src/mmap.rs)
|
||||||
- [stackoverflow](https://stackoverflow.com/a/45795699/1072990): to create an efficient HashMap with pair keys.
|
- [stackoverflow](https://stackoverflow.com/a/45795699/1072990): to create an efficient HashMap with pair keys
|
||||||
- [Emscripten](https://github.com/kripken/emscripten): for emtests test sources to ensure compatibility.
|
- [Emscripten](https://github.com/kripken/emscripten): for emtests test sources to ensure compatibility
|
||||||
|
|
||||||
We would love to hear from you if you think we can take inspiration from other projects that we haven't covered here.
|
We would love to hear from you if you think we can take inspiration from other projects that we haven't covered here.
|
||||||
😊
|
😊
|
||||||
@ -21,10 +21,10 @@ We would love to hear from you if you think we can take inspiration from other p
|
|||||||
|
|
||||||
### Nebulet
|
### Nebulet
|
||||||
|
|
||||||
```
|
```text
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2018
|
Copyright (c) 2018
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -47,7 +47,7 @@ SOFTWARE.
|
|||||||
|
|
||||||
### WAVM
|
### WAVM
|
||||||
|
|
||||||
```
|
```text
|
||||||
Copyright (c) 2018, Andrew Scheidecker
|
Copyright (c) 2018, Andrew Scheidecker
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
@ -69,7 +69,7 @@ The contents of [Test/spec](Test/spec) is covered by the license in [Test/spec/L
|
|||||||
|
|
||||||
### Greenwasm
|
### Greenwasm
|
||||||
|
|
||||||
```
|
```text
|
||||||
Apache License
|
Apache License
|
||||||
Version 2.0, January 2004
|
Version 2.0, January 2004
|
||||||
http://www.apache.org/licenses/
|
http://www.apache.org/licenses/
|
||||||
@ -275,7 +275,7 @@ limitations under the License.
|
|||||||
|
|
||||||
### Wasmtime
|
### Wasmtime
|
||||||
|
|
||||||
```
|
```text
|
||||||
Apache License
|
Apache License
|
||||||
Version 2.0, January 2004
|
Version 2.0, January 2004
|
||||||
http://www.apache.org/licenses/
|
http://www.apache.org/licenses/
|
||||||
@ -497,7 +497,7 @@ Software.
|
|||||||
```
|
```
|
||||||
|
|
||||||
### Emscripten
|
### Emscripten
|
||||||
```
|
```text
|
||||||
Emscripten is available under 2 licenses, the MIT license and the
|
Emscripten is available under 2 licenses, the MIT license and the
|
||||||
University of Illinois/NCSA Open Source License.
|
University of Illinois/NCSA Open Source License.
|
||||||
|
|
||||||
@ -557,7 +557,7 @@ the following conditions:
|
|||||||
Neither the names of Mozilla,
|
Neither the names of Mozilla,
|
||||||
nor the names of its contributors may be used to endorse
|
nor the names of its contributors may be used to endorse
|
||||||
or promote products derived from this Software without specific prior
|
or promote products derived from this Software without specific prior
|
||||||
written permission.
|
written permission.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
72
Cargo.lock
generated
72
Cargo.lock
generated
@ -111,6 +111,21 @@ name = "cast"
|
|||||||
version = "0.2.2"
|
version = "0.2.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cbindgen"
|
||||||
|
version = "0.7.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"serde_json 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"tempfile 3.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.0.29"
|
version = "1.0.29"
|
||||||
@ -373,6 +388,11 @@ dependencies = [
|
|||||||
"unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hex"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "humantime"
|
name = "humantime"
|
||||||
version = "1.2.0"
|
version = "1.2.0"
|
||||||
@ -761,6 +781,14 @@ dependencies = [
|
|||||||
"ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "remove_dir_all"
|
||||||
|
version = "0.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc-demangle"
|
name = "rustc-demangle"
|
||||||
version = "0.1.13"
|
version = "0.1.13"
|
||||||
@ -820,6 +848,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.87"
|
version = "1.0.87"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde-bench"
|
name = "serde-bench"
|
||||||
@ -956,6 +987,19 @@ dependencies = [
|
|||||||
"serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tempfile"
|
||||||
|
version = "3.0.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "termcolor"
|
name = "termcolor"
|
||||||
version = "1.0.4"
|
version = "1.0.4"
|
||||||
@ -1000,6 +1044,14 @@ dependencies = [
|
|||||||
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml"
|
||||||
|
version = "0.4.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "typenum"
|
name = "typenum"
|
||||||
version = "1.10.0"
|
version = "1.10.0"
|
||||||
@ -1122,6 +1174,8 @@ dependencies = [
|
|||||||
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
"glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc 0.2.49 (git+https://github.com/rust-lang/libc)",
|
"libc 0.2.49 (git+https://github.com/rust-lang/libc)",
|
||||||
|
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
"time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"wasmer-clif-backend 0.1.2",
|
"wasmer-clif-backend 0.1.2",
|
||||||
@ -1133,10 +1187,21 @@ name = "wasmer-runtime"
|
|||||||
version = "0.1.4"
|
version = "0.1.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"wasmer-clif-backend 0.1.2",
|
"wasmer-clif-backend 0.1.2",
|
||||||
"wasmer-runtime-core 0.1.2",
|
"wasmer-runtime-core 0.1.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasmer-runtime-c-api"
|
||||||
|
version = "0.1.4"
|
||||||
|
dependencies = [
|
||||||
|
"cbindgen 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"wasmer-runtime 0.1.4",
|
||||||
|
"wasmer-runtime-core 0.1.2",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasmer-runtime-core"
|
name = "wasmer-runtime-core"
|
||||||
version = "0.1.2"
|
version = "0.1.2"
|
||||||
@ -1144,10 +1209,10 @@ dependencies = [
|
|||||||
"errno 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"errno 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"field-offset 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"field-offset 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"nix 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"nix 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"page_size 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"page_size 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -1267,6 +1332,7 @@ dependencies = [
|
|||||||
"checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb"
|
"checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb"
|
||||||
"checksum cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "926013f2860c46252efceabb19f4a6b308197505082c609025aa6706c011d427"
|
"checksum cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "926013f2860c46252efceabb19f4a6b308197505082c609025aa6706c011d427"
|
||||||
"checksum cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)" = "4390a3b5f4f6bce9c1d0c00128379df433e53777fdd30e92f16a529332baec4e"
|
"checksum cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)" = "4390a3b5f4f6bce9c1d0c00128379df433e53777fdd30e92f16a529332baec4e"
|
||||||
|
"checksum cbindgen 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "32e01024aaf5390d6a8145047371a4f5b0063a14c1e411bc731353bd2278ca44"
|
||||||
"checksum cexpr 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "644d693ecfa91955ed32dcc7eda4914e1be97a641fb6f0645a37348e20b230da"
|
"checksum cexpr 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "644d693ecfa91955ed32dcc7eda4914e1be97a641fb6f0645a37348e20b230da"
|
||||||
"checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4"
|
"checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4"
|
||||||
"checksum clang-sys 0.26.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6ef0c1bcf2e99c649104bd7a7012d8f8802684400e03db0ec0af48583c6fa0e4"
|
"checksum clang-sys 0.26.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6ef0c1bcf2e99c649104bd7a7012d8f8802684400e03db0ec0af48583c6fa0e4"
|
||||||
@ -1297,6 +1363,7 @@ dependencies = [
|
|||||||
"checksum goblin 0.0.20 (registry+https://github.com/rust-lang/crates.io-index)" = "84473a5302fa5094d3d9911c2f312f522f9a37462a777f195f63fae1bf7faf4d"
|
"checksum goblin 0.0.20 (registry+https://github.com/rust-lang/crates.io-index)" = "84473a5302fa5094d3d9911c2f312f522f9a37462a777f195f63fae1bf7faf4d"
|
||||||
"checksum hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3bae29b6653b3412c2e71e9d486db9f9df5d701941d86683005efb9f2d28e3da"
|
"checksum hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3bae29b6653b3412c2e71e9d486db9f9df5d701941d86683005efb9f2d28e3da"
|
||||||
"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
|
"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
|
||||||
|
"checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77"
|
||||||
"checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114"
|
"checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114"
|
||||||
"checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d"
|
"checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d"
|
||||||
"checksum inkwell 0.1.0 (git+https://github.com/TheDan64/inkwell?branch=llvm7-0)" = "<none>"
|
"checksum inkwell 0.1.0 (git+https://github.com/TheDan64/inkwell?branch=llvm7-0)" = "<none>"
|
||||||
@ -1342,6 +1409,7 @@ dependencies = [
|
|||||||
"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
|
"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
|
||||||
"checksum regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "37e7cbbd370869ce2e8dff25c7018702d10b21a20ef7135316f8daecd6c25b7f"
|
"checksum regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "37e7cbbd370869ce2e8dff25c7018702d10b21a20ef7135316f8daecd6c25b7f"
|
||||||
"checksum regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8c2f35eedad5295fdf00a63d7d4b238135723f92b434ec06774dad15c7ab0861"
|
"checksum regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8c2f35eedad5295fdf00a63d7d4b238135723f92b434ec06774dad15c7ab0861"
|
||||||
|
"checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5"
|
||||||
"checksum rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "adacaae16d02b6ec37fdc7acfcddf365978de76d1983d3ee22afc260e1ca9619"
|
"checksum rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "adacaae16d02b6ec37fdc7acfcddf365978de76d1983d3ee22afc260e1ca9619"
|
||||||
"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
|
"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
|
||||||
"checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7"
|
"checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7"
|
||||||
@ -1366,11 +1434,13 @@ dependencies = [
|
|||||||
"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
|
"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
|
||||||
"checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015"
|
"checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015"
|
||||||
"checksum target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4af5e2227f0b887d591d3724b796a96eff04226104d872f5b3883fcd427d64b9"
|
"checksum target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4af5e2227f0b887d591d3724b796a96eff04226104d872f5b3883fcd427d64b9"
|
||||||
|
"checksum tempfile 3.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "37daa55a7240c4931c84559f03b3cad7d19535840d1c4a0cc4e9b2fb0dcf70ff"
|
||||||
"checksum termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f"
|
"checksum termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f"
|
||||||
"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096"
|
"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096"
|
||||||
"checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6"
|
"checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6"
|
||||||
"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
|
"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
|
||||||
"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f"
|
"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f"
|
||||||
|
"checksum toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "758664fc71a3a69038656bee8b6be6477d2a6c315a6b81f7081f591bffa4111f"
|
||||||
"checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169"
|
"checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169"
|
||||||
"checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86"
|
"checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86"
|
||||||
"checksum unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa6024fc12ddfd1c6dbc14a80fa2324d4568849869b779f6bd37e5e4c03344d1"
|
"checksum unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa6024fc12ddfd1c6dbc14a80fa2324d4568849869b779f6bd37e5e4c03344d1"
|
||||||
|
@ -27,7 +27,7 @@ wasmer-runtime-core = { path = "lib/runtime-core" }
|
|||||||
wasmer-emscripten = { path = "lib/emscripten" }
|
wasmer-emscripten = { path = "lib/emscripten" }
|
||||||
|
|
||||||
[workspace]
|
[workspace]
|
||||||
members = ["lib/clif-backend", "lib/runtime", "lib/runtime-core", "lib/emscripten", "lib/spectests", "lib/win-exception-handler", "lib/llvm-backend"]
|
members = ["lib/clif-backend", "lib/runtime", "lib/runtime-core", "lib/emscripten", "lib/spectests", "lib/win-exception-handler", "lib/runtime-c-api", "lib/llvm-backend"]
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
wabt = "0.7.2"
|
wabt = "0.7.2"
|
||||||
|
4
LICENSE
4
LICENSE
@ -1,6 +1,4 @@
|
|||||||
The MIT License (MIT)
|
Copyright (c) 2019 Syrus Akbary
|
||||||
|
|
||||||
Copyright (c) 2018-Present Syrus Akbary
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
8
Makefile
8
Makefile
@ -12,6 +12,9 @@ spectests:
|
|||||||
emtests:
|
emtests:
|
||||||
WASM_EMSCRIPTEN_GENERATE_EMTESTS=1 cargo build -p wasmer-emscripten
|
WASM_EMSCRIPTEN_GENERATE_EMTESTS=1 cargo build -p wasmer-emscripten
|
||||||
|
|
||||||
|
capi:
|
||||||
|
WASM_EMSCRIPTEN_GENERATE_C_API_HEADERS=1 cargo build --manifest-path lib/runtime-c-api/Cargo.toml --features generate-c-api-headers
|
||||||
|
|
||||||
# clean:
|
# clean:
|
||||||
# rm -rf artifacts
|
# rm -rf artifacts
|
||||||
|
|
||||||
@ -34,9 +37,10 @@ precommit: lint test
|
|||||||
|
|
||||||
test:
|
test:
|
||||||
# We use one thread so the emscripten stdouts doesn't collide
|
# We use one thread so the emscripten stdouts doesn't collide
|
||||||
cargo test --all -- --test-threads=1 $(runargs)
|
cargo test --all --exclude wasmer-runtime-c-api -- --test-threads=1 $(runargs)
|
||||||
# cargo test --all --exclude wasmer-emscripten -- --test-threads=1 $(runargs)
|
# cargo test --all --exclude wasmer-emscripten -- --test-threads=1 $(runargs)
|
||||||
# cargo test -p wasmer-spectests -- --test-threads=1 $(runargs)
|
cargo build -p wasmer-runtime-c-api
|
||||||
|
cargo test -p wasmer-runtime-c-api -- --nocapture
|
||||||
|
|
||||||
release:
|
release:
|
||||||
# If you are in OS-X, you will need mingw-w64 for cross compiling to windows
|
# If you are in OS-X, you will need mingw-w64 for cross compiling to windows
|
||||||
|
64
README.md
64
README.md
@ -1,16 +1,24 @@
|
|||||||
<p align="center"><a href="https://wasmer.io" target="_blank" rel="noopener noreferrer"><img width="400" src="https://raw.githubusercontent.com/wasmerio/wasmer/master/logo.png" alt="Wasmer logo"></a></p>
|
<p align="center">
|
||||||
|
<a href="https://wasmer.io" target="_blank" rel="noopener noreferrer">
|
||||||
|
<img width="400" src="https://raw.githubusercontent.com/wasmerio/wasmer/master/logo.png" alt="Wasmer logo">
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://circleci.com/gh/wasmerio/wasmer/"><img src="https://img.shields.io/circleci/project/github/wasmerio/wasmer/master.svg" alt="Build Status"></a>
|
<a href="https://circleci.com/gh/wasmerio/wasmer/">
|
||||||
<a href="https://github.com/wasmerio/wasmer/blob/master/LICENSE"><img src="https://img.shields.io/github/license/wasmerio/wasmer.svg" alt="License"></a>
|
<img src="https://img.shields.io/circleci/project/github/wasmerio/wasmer/master.svg" alt="Build Status">
|
||||||
|
</a>
|
||||||
|
<a href="https://github.com/wasmerio/wasmer/blob/master/LICENSE">
|
||||||
|
<img src="https://img.shields.io/github/license/wasmerio/wasmer.svg" alt="License">
|
||||||
|
</a>
|
||||||
<a href="https://spectrum.chat/wasmer">
|
<a href="https://spectrum.chat/wasmer">
|
||||||
<img alt="Join the Wasmer Community" src="https://withspectrum.github.io/badge/badge.svg" />
|
<img src="https://withspectrum.github.io/badge/badge.svg" alt="Join the Wasmer Community">
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
## Introduction
|
## Introduction
|
||||||
|
|
||||||
[Wasmer](https://wasmer.io/) is a Standalone JIT WebAssembly runtime, aiming to be fully compatible with Emscripten, Rust and Go.
|
[Wasmer](https://wasmer.io/) is a standalone JIT WebAssembly runtime, aiming to be fully compatible with Emscripten, Rust and Go.
|
||||||
|
|
||||||
Install Wasmer with:
|
Install Wasmer with:
|
||||||
|
|
||||||
@ -18,20 +26,20 @@ Install Wasmer with:
|
|||||||
curl https://get.wasmer.io -sSfL | sh
|
curl https://get.wasmer.io -sSfL | sh
|
||||||
```
|
```
|
||||||
|
|
||||||
_**NEW ✨**: Now you can also embed Wasmer in your Rust application, check our [example repo](https://github.com/wasmerio/wasmer-rust-example) to see how to do it!_
|
_**NEW ✨**: You can now embed Wasmer in your Rust application, check our [example repo](https://github.com/wasmerio/wasmer-rust-example) to see how!_
|
||||||
|
|
||||||
### Usage
|
### Usage
|
||||||
|
|
||||||
`wasmer` can execute both the standard binary format (`.wasm`) and the text
|
Wasmer can execute both the standard binary format (`.wasm`) and the text
|
||||||
format defined by the WebAssembly reference interpreter (`.wat`).
|
format defined by the WebAssembly reference interpreter (`.wat`).
|
||||||
|
|
||||||
Once installed, you will be able to run any WebAssembly files (_including Nginx, and Lua!_):
|
Once installed, you will be able to run any WebAssembly files (_including nginx and Lua!_):
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
# Run Lua
|
# Run Lua
|
||||||
wasmer run examples/lua.wasm
|
wasmer run examples/lua.wasm
|
||||||
|
|
||||||
# Run Nginx
|
# Run nginx
|
||||||
wasmer run examples/nginx/nginx.wasm -- -p examples/nginx -c nginx.conf
|
wasmer run examples/nginx/nginx.wasm -- -p examples/nginx -c nginx.conf
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -39,13 +47,13 @@ wasmer run examples/nginx/nginx.wasm -- -p examples/nginx -c nginx.conf
|
|||||||
|
|
||||||
Wasmer is structured into different directories:
|
Wasmer is structured into different directories:
|
||||||
|
|
||||||
- [`src`](./src): code related to the wasmer excutable binary itself
|
- [`src`](./src): code related to the Wasmer executable itself
|
||||||
- [`lib`](./lib): modularized libraries that Wasmer uses under the hood
|
- [`lib`](./lib): modularized libraries that Wasmer uses under the hood
|
||||||
- [`examples`](./examples): some useful examples to getting started with wasmer
|
- [`examples`](./examples): some useful examples to getting started with Wasmer
|
||||||
|
|
||||||
## Dependencies
|
## Dependencies
|
||||||
|
|
||||||
Building wasmer requires [rustup](https://rustup.rs/).
|
Building Wasmer requires [rustup](https://rustup.rs/).
|
||||||
|
|
||||||
To build on Windows, download and run [`rustup-init.exe`](https://win.rustup.rs/)
|
To build on Windows, download and run [`rustup-init.exe`](https://win.rustup.rs/)
|
||||||
then follow the onscreen instructions.
|
then follow the onscreen instructions.
|
||||||
@ -66,13 +74,13 @@ Please select your operating system:
|
|||||||
|
|
||||||
#### macOS
|
#### macOS
|
||||||
|
|
||||||
If you have [homebrew](https://brew.sh/) installed:
|
If you have [Homebrew](https://brew.sh/) installed:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
brew install cmake
|
brew install cmake
|
||||||
```
|
```
|
||||||
|
|
||||||
Or, in case you have [ports](https://www.macports.org/install.php):
|
Or, in case you have [MacPorts](https://www.macports.org/install.php):
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
sudo port install cmake
|
sudo port install cmake
|
||||||
@ -86,16 +94,16 @@ sudo apt install cmake
|
|||||||
|
|
||||||
#### Windows (MSVC)
|
#### Windows (MSVC)
|
||||||
|
|
||||||
Windows support is _highly experimental_. Only simple wasm programs may be run, and no syscalls are allowed. This means
|
Windows support is _highly experimental_. Only simple Wasm programs may be run, and no syscalls are allowed. This means
|
||||||
nginx and lua do not work on Windows. See [this issue for ongoing Emscripten syscall polyfills for Windows](https://github.com/wasmerio/wasmer/pull/176).
|
nginx and Lua do not work on Windows. See [this issue](https://github.com/wasmerio/wasmer/issues/176) regarding Emscripten syscall polyfills for Windows.
|
||||||
|
|
||||||
1. Install Python for Windows (https://www.python.org/downloads/release/python-2714/). The Windows x86-64 MSI installer is fine.
|
1. Install [Python for Windows](https://www.python.org/downloads/release/python-2714/). The Windows x86-64 MSI installer is fine.
|
||||||
You should change the installation to install the "Add python.exe to Path" feature.
|
Make sure to enable "Add python.exe to Path" during installation.
|
||||||
|
|
||||||
2. Install Git for Windows (https://git-scm.com/download/win). DO allow it to add git.exe to the PATH (default
|
2. Install [Git for Windows](https://git-scm.com/download/win). Allow it to add `git.exe` to your PATH (default
|
||||||
settings for the installer are fine).
|
settings for the installer are fine).
|
||||||
|
|
||||||
3. Install CMake (https://cmake.org/download/). Ensure CMake is in the PATH.
|
3. Install [CMake](https://cmake.org/download/). Ensure CMake is in your PATH.
|
||||||
|
|
||||||
## Building
|
## Building
|
||||||
|
|
||||||
@ -113,7 +121,7 @@ cargo install --path .
|
|||||||
|
|
||||||
## Testing
|
## Testing
|
||||||
|
|
||||||
Thanks to [spectests](https://github.com/wasmerio/wasmer/tree/master/lib/runtime-core/spectests) we can assure 100% compatibility with the WebAssembly spec test suite.
|
Thanks to [spec tests](https://github.com/wasmerio/wasmer/tree/master/lib/spectests/spectests) we can ensure 100% compatibility with the WebAssembly spec test suite.
|
||||||
|
|
||||||
Tests can be run with:
|
Tests can be run with:
|
||||||
|
|
||||||
@ -121,7 +129,7 @@ Tests can be run with:
|
|||||||
make test
|
make test
|
||||||
```
|
```
|
||||||
|
|
||||||
If you need to re-generate the Rust tests from the spectests
|
If you need to regenerate the Rust tests from the spec tests
|
||||||
you can run:
|
you can run:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
@ -138,20 +146,20 @@ make integration-tests
|
|||||||
|
|
||||||
Wasmer is an open project guided by strong principles, aiming to be modular, flexible and fast. It is open to the community to help set its direction.
|
Wasmer is an open project guided by strong principles, aiming to be modular, flexible and fast. It is open to the community to help set its direction.
|
||||||
|
|
||||||
Below are some of the goals (written with order) of this project:
|
Below are some of the goals of this project (in order of priority):
|
||||||
|
|
||||||
- [x] It should be 100% compatible with the [WebAssembly Spectest](https://github.com/wasmerio/wasmer/tree/master/spectests)
|
- [x] It should be 100% compatible with the [WebAssembly spec tests](https://github.com/wasmerio/wasmer/tree/master/lib/spectests/spectests)
|
||||||
- [x] It should be fast _(partially achieved)_
|
- [x] It should be fast _(partially achieved)_
|
||||||
- [ ] Support Emscripten calls _(in the works)_
|
- [ ] Support Emscripten calls _(in the works)_
|
||||||
- [ ] Support Rust ABI calls
|
- [ ] Support Rust ABI calls
|
||||||
- [ ] Support GO ABI calls
|
- [ ] Support Go ABI calls
|
||||||
|
|
||||||
## Architecture
|
## Architecture
|
||||||
|
|
||||||
If you would like to know how Wasmer works under the hood, please visit our [ARCHITECTURE](https://github.com/wasmerio/wasmer/blob/master/ARCHITECTURE.md) document.
|
If you would like to know how Wasmer works under the hood, please see [ARCHITECTURE.md](./ARCHITECTURE.md).
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
MIT/Apache-2.0
|
Wasmer is primarily distributed under the terms of the [MIT license](http://opensource.org/licenses/MIT) ([LICENSE](./LICENSE)).
|
||||||
|
|
||||||
<small>[Attributions](./ATTRIBUTIONS.md)</small>.
|
[ATTRIBUTIONS](./ATTRIBUTIONS.md)
|
||||||
|
@ -130,7 +130,7 @@ wasmer_link() {
|
|||||||
printf "$cyan> Adding to bash profile...$reset\n"
|
printf "$cyan> Adding to bash profile...$reset\n"
|
||||||
WASMER_PROFILE="$(wasmer_detect_profile)"
|
WASMER_PROFILE="$(wasmer_detect_profile)"
|
||||||
LOAD_STR="\n# Wasmer\nexport WASMER_DIR=\"\$HOME/.wasmer\"\n[ -s \"\$WASMER_DIR/wasmer.sh\" ] && source \"\$WASMER_DIR/wasmer.sh\" # This loads wasmer\n"
|
LOAD_STR="\n# Wasmer\nexport WASMER_DIR=\"\$HOME/.wasmer\"\n[ -s \"\$WASMER_DIR/wasmer.sh\" ] && source \"\$WASMER_DIR/wasmer.sh\" # This loads wasmer\n"
|
||||||
SOURCE_STR="# Wasmer config\nexport WASMER_DIR=\"\$HOME/.wasmer\"\nexport PATH=\"\$HOME/.wasmer/bin:\$PATH\"\n"
|
SOURCE_STR="# Wasmer config\nexport WASMER_DIR=\"\$HOME/.wasmer\"\nexport WASMER_CACHE_DIR=\"\$WASMER_DIR/cache\"\nexport PATH=\"\$HOME/.wasmer/bin:\$PATH\"\n"
|
||||||
|
|
||||||
# We create the wasmer.sh file
|
# We create the wasmer.sh file
|
||||||
echo "$SOURCE_STR" > "$HOME/.wasmer/wasmer.sh"
|
echo "$SOURCE_STR" > "$HOME/.wasmer/wasmer.sh"
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
# `lua` integration test
|
# `lua` integration test
|
||||||
|
|
||||||
|
|
||||||
This starts wasmer with the lua wasm file. The test asserts on
|
This starts Wasmer with the Lua Wasm file. The test makes assertions on
|
||||||
the output of wasmer. Run test with:
|
the output of Wasmer. Run test with:
|
||||||
|
|
||||||
```
|
```
|
||||||
> ./integration_tests/lua/test.sh
|
> ./integration_tests/lua/test.sh
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
# `nginx` integration test
|
# `nginx` integration test
|
||||||
|
|
||||||
|
|
||||||
This starts wasmer with the nginx wasm file and serves an html
|
This starts Wasmer with the nginx Wasm file and serves an HTML
|
||||||
file with some simple text to assert on. The test script does
|
file with some simple text to assert on. The test script does
|
||||||
the assertion.
|
the assertion.
|
||||||
|
|
||||||
Run test with:
|
Run test with:
|
||||||
|
|
||||||
```
|
```
|
||||||
> ./integration_tests/nginx/test.sh
|
> ./integration_tests/nginx/test.sh
|
||||||
|
@ -2,34 +2,34 @@
|
|||||||
|
|
||||||
Wasmer is modularized into different libraries, separated into three main sections:
|
Wasmer is modularized into different libraries, separated into three main sections:
|
||||||
|
|
||||||
- [Runtime](#Runtime)
|
- [Runtime](#runtime)
|
||||||
- [Integrations](#Integrations)
|
- [Integrations](#integrations)
|
||||||
- [Backends](#Backends)
|
- [Backends](#backends)
|
||||||
|
|
||||||
## Runtime
|
## Runtime
|
||||||
|
|
||||||
The core of Wasmer is the runtime, which provides the necessary
|
The core of Wasmer is the runtime, which provides the necessary
|
||||||
abstractions to create a good user-experience when embedding.
|
abstractions to create a good user experience when embedding.
|
||||||
|
|
||||||
The runtime is divided into two main libraries:
|
The runtime is divided into two main libraries:
|
||||||
|
|
||||||
- [runtime-core](./runtime-core/): The main implementation of the runtime.
|
- [runtime-core](./runtime-core/): The main implementation of the runtime.
|
||||||
- [runtime](./runtime/): Easy-to-use api on top of runtime-core.
|
- [runtime](./runtime/): Easy-to-use API on top of `runtime-core`.
|
||||||
|
|
||||||
## Integrations
|
## Integrations
|
||||||
|
|
||||||
The intergration run on-top of the Wasmer runtime and allow us to run WebAssembly files compiled for different environments.
|
The integration builds on the Wasmer runtime and allow us to run WebAssembly files compiled for different environments.
|
||||||
|
|
||||||
Wasmer intends to support different integrations:
|
Wasmer intends to support different integrations:
|
||||||
|
|
||||||
- [emscripten](./emscripten): run emscripten-generated WebAssembly files, such as [Lua](../examples/lua.wasm) or [Nginx](../examples/nginx/nginx.wasm).
|
- [emscripten](./emscripten): run Emscripten-generated WebAssembly files, such as [Lua](../examples/lua.wasm) or [nginx](../examples/nginx/nginx.wasm).
|
||||||
- Go ABI: _we will work on this soon! Want to give us a hand? ✋_
|
- Go ABI: _we will work on this soon! Want to give us a hand? ✋_
|
||||||
- Blazor: _researching period, see [tracking issue](https://github.com/wasmerio/wasmer/issues/97)_
|
- Blazor: _research period, see [tracking issue](https://github.com/wasmerio/wasmer/issues/97)_
|
||||||
|
|
||||||
## Backends
|
## Backends
|
||||||
|
|
||||||
The Wasmer [runtime](./runtime) is designed to support multiple compiler backends, allowing the user
|
The Wasmer [runtime](./runtime) is designed to support multiple compiler backends, allowing the user
|
||||||
to tune the codegen properties (compile speed, performance, etc) to fit your usecase best.
|
to tune the codegen properties (compile speed, performance, etc) to best fit their use case.
|
||||||
|
|
||||||
Currently, we support a Cranelift compiler backend:
|
Currently, we support a Cranelift compiler backend:
|
||||||
|
|
||||||
|
@ -23,24 +23,16 @@ libc = "0.2.48"
|
|||||||
# Dependencies for caching.
|
# Dependencies for caching.
|
||||||
[dependencies.serde]
|
[dependencies.serde]
|
||||||
version = "1.0"
|
version = "1.0"
|
||||||
optional = true
|
|
||||||
[dependencies.serde_derive]
|
[dependencies.serde_derive]
|
||||||
version = "1.0"
|
version = "1.0"
|
||||||
optional = true
|
|
||||||
[dependencies.serde_bytes]
|
[dependencies.serde_bytes]
|
||||||
version = "0.10"
|
version = "0.10"
|
||||||
optional = true
|
|
||||||
# [dependencies.bincode]
|
|
||||||
# version = "1.0.1"
|
|
||||||
# optional = true
|
|
||||||
[dependencies.serde-bench]
|
[dependencies.serde-bench]
|
||||||
version = "0.0.7"
|
version = "0.0.7"
|
||||||
optional = true
|
|
||||||
|
|
||||||
[target.'cfg(windows)'.dependencies]
|
[target.'cfg(windows)'.dependencies]
|
||||||
winapi = { version = "0.3", features = ["errhandlingapi", "minwindef", "minwinbase", "winnt"] }
|
winapi = { version = "0.3", features = ["errhandlingapi", "minwindef", "minwinbase", "winnt"] }
|
||||||
wasmer-win-exception-handler = { path = "../win-exception-handler", version = "0.0.1" }
|
wasmer-win-exception-handler = { path = "../win-exception-handler", version = "0.0.1" }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
cache = ["serde", "serde_derive", "serde_bytes", "serde-bench", "wasmer-runtime-core/cache"]
|
|
||||||
debug = ["wasmer-runtime-core/debug"]
|
debug = ["wasmer-runtime-core/debug"]
|
||||||
|
@ -1,16 +1,50 @@
|
|||||||
use crate::relocation::{ExternalRelocation, TrapSink};
|
use crate::relocation::{ExternalRelocation, TrapSink};
|
||||||
|
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
|
use std::sync::Arc;
|
||||||
use wasmer_runtime_core::{
|
use wasmer_runtime_core::{
|
||||||
backend::sys::Memory,
|
backend::{sys::Memory, CacheGen},
|
||||||
cache::{Cache, Error},
|
cache::{Artifact, Error},
|
||||||
module::ModuleInfo,
|
module::{ModuleInfo, ModuleInner},
|
||||||
structures::Map,
|
structures::Map,
|
||||||
types::{LocalFuncIndex, SigIndex},
|
types::{LocalFuncIndex, SigIndex},
|
||||||
};
|
};
|
||||||
|
|
||||||
use serde_bench::{deserialize, serialize};
|
use serde_bench::{deserialize, serialize};
|
||||||
|
|
||||||
|
pub struct CacheGenerator {
|
||||||
|
backend_cache: BackendCache,
|
||||||
|
memory: Arc<Memory>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CacheGenerator {
|
||||||
|
pub fn new(backend_cache: BackendCache, memory: Arc<Memory>) -> Self {
|
||||||
|
Self {
|
||||||
|
backend_cache,
|
||||||
|
memory,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CacheGen for CacheGenerator {
|
||||||
|
fn generate_cache(
|
||||||
|
&self,
|
||||||
|
module: &ModuleInner,
|
||||||
|
) -> Result<(Box<ModuleInfo>, Box<[u8]>, Memory), Error> {
|
||||||
|
let info = Box::new(module.info.clone());
|
||||||
|
|
||||||
|
// Clone the memory to a new location. This could take a long time,
|
||||||
|
// depending on the throughput of your memcpy implementation.
|
||||||
|
let compiled_code = (*self.memory).clone();
|
||||||
|
|
||||||
|
Ok((
|
||||||
|
info,
|
||||||
|
self.backend_cache.into_backend_data()?.into_boxed_slice(),
|
||||||
|
compiled_code,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct TrampolineCache {
|
pub struct TrampolineCache {
|
||||||
#[serde(with = "serde_bytes")]
|
#[serde(with = "serde_bytes")]
|
||||||
@ -22,24 +56,24 @@ pub struct TrampolineCache {
|
|||||||
pub struct BackendCache {
|
pub struct BackendCache {
|
||||||
pub external_relocs: Map<LocalFuncIndex, Box<[ExternalRelocation]>>,
|
pub external_relocs: Map<LocalFuncIndex, Box<[ExternalRelocation]>>,
|
||||||
pub offsets: Map<LocalFuncIndex, usize>,
|
pub offsets: Map<LocalFuncIndex, usize>,
|
||||||
pub trap_sink: TrapSink,
|
pub trap_sink: Arc<TrapSink>,
|
||||||
pub trampolines: TrampolineCache,
|
pub trampolines: TrampolineCache,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BackendCache {
|
impl BackendCache {
|
||||||
pub fn from_cache(cache: Cache) -> Result<(ModuleInfo, Memory, Self), Error> {
|
pub fn from_cache(cache: Artifact) -> Result<(ModuleInfo, Memory, Self), Error> {
|
||||||
let (info, backend_data, compiled_code) = cache.consume();
|
let (info, backend_data, compiled_code) = cache.consume();
|
||||||
|
|
||||||
let backend_cache = deserialize(backend_data.as_slice())
|
let backend_cache =
|
||||||
.map_err(|e| Error::DeserializeError(e.to_string()))?;
|
deserialize(&backend_data).map_err(|e| Error::DeserializeError(e.to_string()))?;
|
||||||
|
|
||||||
Ok((info, compiled_code, backend_cache))
|
Ok((info, compiled_code, backend_cache))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn into_backend_data(self) -> Result<Vec<u8>, Error> {
|
pub fn into_backend_data(&self) -> Result<Vec<u8>, Error> {
|
||||||
let mut buffer = Vec::new();
|
let mut buffer = Vec::new();
|
||||||
|
|
||||||
serialize(&mut buffer, &self).map_err(|e| Error::SerializeError(e.to_string()))?;
|
serialize(&mut buffer, self).map_err(|e| Error::SerializeError(e.to_string()))?;
|
||||||
|
|
||||||
Ok(buffer)
|
Ok(buffer)
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
#[cfg(feature = "cache")]
|
|
||||||
mod cache;
|
mod cache;
|
||||||
mod func_env;
|
mod func_env;
|
||||||
mod libcalls;
|
mod libcalls;
|
||||||
@ -14,21 +13,17 @@ use cranelift_codegen::{
|
|||||||
settings::{self, Configurable},
|
settings::{self, Configurable},
|
||||||
};
|
};
|
||||||
use target_lexicon::Triple;
|
use target_lexicon::Triple;
|
||||||
#[cfg(feature = "cache")]
|
|
||||||
use wasmer_runtime_core::{
|
use wasmer_runtime_core::cache::{Artifact, Error as CacheError};
|
||||||
backend::sys::Memory,
|
|
||||||
cache::{Cache, Error as CacheError},
|
|
||||||
module::ModuleInfo,
|
|
||||||
};
|
|
||||||
use wasmer_runtime_core::{
|
use wasmer_runtime_core::{
|
||||||
backend::{Compiler, Token},
|
backend::{Compiler, Token},
|
||||||
error::{CompileError, CompileResult},
|
error::{CompileError, CompileResult},
|
||||||
module::ModuleInner,
|
module::ModuleInner,
|
||||||
};
|
};
|
||||||
#[cfg(feature = "cache")]
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate serde_derive;
|
extern crate serde_derive;
|
||||||
#[cfg(feature = "cache")]
|
|
||||||
extern crate serde;
|
extern crate serde;
|
||||||
|
|
||||||
use wasmparser::{self, WasmDecoder};
|
use wasmparser::{self, WasmDecoder};
|
||||||
@ -48,7 +43,7 @@ impl Compiler for CraneliftCompiler {
|
|||||||
|
|
||||||
let isa = get_isa();
|
let isa = get_isa();
|
||||||
|
|
||||||
let mut module = module::Module::empty();
|
let mut module = module::Module::new(wasm);
|
||||||
let module_env = module_env::ModuleEnv::new(&mut module, &*isa);
|
let module_env = module_env::ModuleEnv::new(&mut module, &*isa);
|
||||||
|
|
||||||
let func_bodies = module_env.translate(wasm)?;
|
let func_bodies = module_env.translate(wasm)?;
|
||||||
@ -57,41 +52,41 @@ impl Compiler for CraneliftCompiler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Create a wasmer Module from an already-compiled cache.
|
/// Create a wasmer Module from an already-compiled cache.
|
||||||
#[cfg(feature = "cache")]
|
|
||||||
unsafe fn from_cache(&self, cache: Cache, _: Token) -> Result<ModuleInner, CacheError> {
|
unsafe fn from_cache(&self, cache: Artifact, _: Token) -> Result<ModuleInner, CacheError> {
|
||||||
module::Module::from_cache(cache)
|
module::Module::from_cache(cache)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "cache")]
|
//
|
||||||
fn compile_to_backend_cache_data(
|
// fn compile_to_backend_cache_data(
|
||||||
&self,
|
// &self,
|
||||||
wasm: &[u8],
|
// wasm: &[u8],
|
||||||
_: Token,
|
// _: Token,
|
||||||
) -> CompileResult<(Box<ModuleInfo>, Vec<u8>, Memory)> {
|
// ) -> CompileResult<(Box<ModuleInfo>, Vec<u8>, Memory)> {
|
||||||
validate(wasm)?;
|
// validate(wasm)?;
|
||||||
|
|
||||||
let isa = get_isa();
|
// let isa = get_isa();
|
||||||
|
|
||||||
let mut module = module::Module::empty();
|
// let mut module = module::Module::new(wasm);
|
||||||
let module_env = module_env::ModuleEnv::new(&mut module, &*isa);
|
// let module_env = module_env::ModuleEnv::new(&mut module, &*isa);
|
||||||
|
|
||||||
let func_bodies = module_env.translate(wasm)?;
|
// let func_bodies = module_env.translate(wasm)?;
|
||||||
|
|
||||||
let (info, backend_cache, compiled_code) = module
|
// let (info, backend_cache, compiled_code) = module
|
||||||
.compile_to_backend_cache(&*isa, func_bodies)
|
// .compile_to_backend_cache(&*isa, func_bodies)
|
||||||
.map_err(|e| CompileError::InternalError {
|
// .map_err(|e| CompileError::InternalError {
|
||||||
msg: format!("{:?}", e),
|
// msg: format!("{:?}", e),
|
||||||
})?;
|
// })?;
|
||||||
|
|
||||||
let buffer =
|
// let buffer =
|
||||||
backend_cache
|
// backend_cache
|
||||||
.into_backend_data()
|
// .into_backend_data()
|
||||||
.map_err(|e| CompileError::InternalError {
|
// .map_err(|e| CompileError::InternalError {
|
||||||
msg: format!("{:?}", e),
|
// msg: format!("{:?}", e),
|
||||||
})?;
|
// })?;
|
||||||
|
|
||||||
Ok((Box::new(info), buffer, compiled_code))
|
// Ok((Box::new(info), buffer, compiled_code))
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_isa() -> Box<isa::TargetIsa> {
|
fn get_isa() -> Box<isa::TargetIsa> {
|
||||||
|
@ -1,178 +1,122 @@
|
|||||||
#[cfg(feature = "cache")]
|
use crate::cache::{BackendCache, CacheGenerator};
|
||||||
use crate::cache::BackendCache;
|
|
||||||
use crate::{resolver::FuncResolverBuilder, signal::Caller, trampoline::Trampolines};
|
use crate::{resolver::FuncResolverBuilder, signal::Caller, trampoline::Trampolines};
|
||||||
|
|
||||||
use cranelift_codegen::{ir, isa};
|
use cranelift_codegen::{ir, isa};
|
||||||
use cranelift_entity::EntityRef;
|
use cranelift_entity::EntityRef;
|
||||||
use cranelift_wasm;
|
use cranelift_wasm;
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
use std::{
|
use std::sync::Arc;
|
||||||
ops::{Deref, DerefMut},
|
|
||||||
ptr::NonNull,
|
use wasmer_runtime_core::cache::{Artifact, Error as CacheError, WasmHash};
|
||||||
};
|
|
||||||
#[cfg(feature = "cache")]
|
|
||||||
use wasmer_runtime_core::{
|
use wasmer_runtime_core::{
|
||||||
backend::sys::Memory,
|
backend::Backend,
|
||||||
cache::{Cache, Error as CacheError},
|
error::CompileResult,
|
||||||
};
|
|
||||||
use wasmer_runtime_core::{
|
|
||||||
backend::{Backend, FuncResolver, ProtectedCaller, Token, UserTrapper},
|
|
||||||
error::{CompileResult, RuntimeResult},
|
|
||||||
module::{ModuleInfo, ModuleInner, StringTable},
|
module::{ModuleInfo, ModuleInner, StringTable},
|
||||||
structures::{Map, TypedIndex},
|
structures::{Map, TypedIndex},
|
||||||
types::{
|
types::{
|
||||||
FuncIndex, FuncSig, GlobalIndex, LocalFuncIndex, MemoryIndex, SigIndex, TableIndex, Type,
|
FuncIndex, FuncSig, GlobalIndex, LocalFuncIndex, MemoryIndex, SigIndex, TableIndex, Type,
|
||||||
Value,
|
|
||||||
},
|
},
|
||||||
vm::{self, ImportBacking},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Placeholder;
|
|
||||||
|
|
||||||
impl FuncResolver for Placeholder {
|
|
||||||
fn get(
|
|
||||||
&self,
|
|
||||||
_module: &ModuleInner,
|
|
||||||
_local_func_index: LocalFuncIndex,
|
|
||||||
) -> Option<NonNull<vm::Func>> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ProtectedCaller for Placeholder {
|
|
||||||
fn call(
|
|
||||||
&self,
|
|
||||||
_module: &ModuleInner,
|
|
||||||
_func_index: FuncIndex,
|
|
||||||
_params: &[Value],
|
|
||||||
_import_backing: &ImportBacking,
|
|
||||||
_vmctx: *mut vm::Ctx,
|
|
||||||
_: Token,
|
|
||||||
) -> RuntimeResult<Vec<Value>> {
|
|
||||||
Ok(vec![])
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_early_trapper(&self) -> Box<dyn UserTrapper> {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This contains all of the items in a `ModuleInner` except the `func_resolver`.
|
/// This contains all of the items in a `ModuleInner` except the `func_resolver`.
|
||||||
pub struct Module {
|
pub struct Module {
|
||||||
pub module: ModuleInner,
|
pub info: ModuleInfo,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Module {
|
impl Module {
|
||||||
pub fn empty() -> Self {
|
pub fn new(wasm: &[u8]) -> Self {
|
||||||
Self {
|
Self {
|
||||||
module: ModuleInner {
|
info: ModuleInfo {
|
||||||
// this is a placeholder
|
memories: Map::new(),
|
||||||
func_resolver: Box::new(Placeholder),
|
globals: Map::new(),
|
||||||
protected_caller: Box::new(Placeholder),
|
tables: Map::new(),
|
||||||
|
|
||||||
info: ModuleInfo {
|
imported_functions: Map::new(),
|
||||||
memories: Map::new(),
|
imported_memories: Map::new(),
|
||||||
globals: Map::new(),
|
imported_tables: Map::new(),
|
||||||
tables: Map::new(),
|
imported_globals: Map::new(),
|
||||||
|
|
||||||
imported_functions: Map::new(),
|
exports: HashMap::new(),
|
||||||
imported_memories: Map::new(),
|
|
||||||
imported_tables: Map::new(),
|
|
||||||
imported_globals: Map::new(),
|
|
||||||
|
|
||||||
exports: HashMap::new(),
|
data_initializers: Vec::new(),
|
||||||
|
elem_initializers: Vec::new(),
|
||||||
|
|
||||||
data_initializers: Vec::new(),
|
start_func: None,
|
||||||
elem_initializers: Vec::new(),
|
|
||||||
|
|
||||||
start_func: None,
|
func_assoc: Map::new(),
|
||||||
|
signatures: Map::new(),
|
||||||
|
backend: Backend::Cranelift,
|
||||||
|
|
||||||
func_assoc: Map::new(),
|
namespace_table: StringTable::new(),
|
||||||
signatures: Map::new(),
|
name_table: StringTable::new(),
|
||||||
backend: Backend::Cranelift,
|
|
||||||
|
|
||||||
namespace_table: StringTable::new(),
|
|
||||||
name_table: StringTable::new(),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compile(
|
pub fn compile(
|
||||||
mut self,
|
self,
|
||||||
isa: &isa::TargetIsa,
|
isa: &isa::TargetIsa,
|
||||||
functions: Map<LocalFuncIndex, ir::Function>,
|
functions: Map<LocalFuncIndex, ir::Function>,
|
||||||
) -> CompileResult<ModuleInner> {
|
) -> CompileResult<ModuleInner> {
|
||||||
let (func_resolver_builder, handler_data) =
|
let (func_resolver_builder, handler_data) =
|
||||||
FuncResolverBuilder::new(isa, functions, &self.module.info)?;
|
FuncResolverBuilder::new(isa, functions, &self.info)?;
|
||||||
|
|
||||||
self.module.func_resolver =
|
let trampolines = Arc::new(Trampolines::new(isa, &self.info));
|
||||||
Box::new(func_resolver_builder.finalize(&self.module.info.signatures)?);
|
|
||||||
|
|
||||||
let trampolines = Trampolines::new(isa, &self.module.info);
|
let (func_resolver, backend_cache) = func_resolver_builder.finalize(
|
||||||
|
&self.info.signatures,
|
||||||
|
Arc::clone(&trampolines),
|
||||||
|
handler_data.clone(),
|
||||||
|
)?;
|
||||||
|
|
||||||
self.module.protected_caller =
|
let protected_caller = Caller::new(&self.info, handler_data, trampolines);
|
||||||
Box::new(Caller::new(&self.module.info, handler_data, trampolines));
|
|
||||||
|
|
||||||
Ok(self.module)
|
let cache_gen = Box::new(CacheGenerator::new(
|
||||||
|
backend_cache,
|
||||||
|
Arc::clone(&func_resolver.memory),
|
||||||
|
));
|
||||||
|
|
||||||
|
Ok(ModuleInner {
|
||||||
|
func_resolver: Box::new(func_resolver),
|
||||||
|
protected_caller: Box::new(protected_caller),
|
||||||
|
cache_gen,
|
||||||
|
|
||||||
|
info: self.info,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "cache")]
|
pub fn from_cache(cache: Artifact) -> Result<ModuleInner, CacheError> {
|
||||||
pub fn compile_to_backend_cache(
|
|
||||||
self,
|
|
||||||
isa: &isa::TargetIsa,
|
|
||||||
functions: Map<LocalFuncIndex, ir::Function>,
|
|
||||||
) -> CompileResult<(ModuleInfo, BackendCache, Memory)> {
|
|
||||||
let (func_resolver_builder, handler_data) =
|
|
||||||
FuncResolverBuilder::new(isa, functions, &self.module.info)?;
|
|
||||||
|
|
||||||
let trampolines = Trampolines::new(isa, &self.module.info);
|
|
||||||
|
|
||||||
let trampoline_cache = trampolines.to_trampoline_cache();
|
|
||||||
|
|
||||||
let (backend_cache, compiled_code) =
|
|
||||||
func_resolver_builder.to_backend_cache(trampoline_cache, handler_data);
|
|
||||||
|
|
||||||
Ok((self.module.info, backend_cache, compiled_code))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "cache")]
|
|
||||||
pub fn from_cache(cache: Cache) -> Result<ModuleInner, CacheError> {
|
|
||||||
let (info, compiled_code, backend_cache) = BackendCache::from_cache(cache)?;
|
let (info, compiled_code, backend_cache) = BackendCache::from_cache(cache)?;
|
||||||
|
|
||||||
let (func_resolver_builder, trampolines, handler_data) =
|
let (func_resolver_builder, trampolines, handler_data) =
|
||||||
FuncResolverBuilder::new_from_backend_cache(backend_cache, compiled_code, &info)?;
|
FuncResolverBuilder::new_from_backend_cache(backend_cache, compiled_code, &info)?;
|
||||||
|
|
||||||
let func_resolver = Box::new(
|
let (func_resolver, backend_cache) = func_resolver_builder
|
||||||
func_resolver_builder
|
.finalize(
|
||||||
.finalize(&info.signatures)
|
&info.signatures,
|
||||||
.map_err(|e| CacheError::Unknown(format!("{:?}", e)))?,
|
Arc::clone(&trampolines),
|
||||||
);
|
handler_data.clone(),
|
||||||
|
)
|
||||||
|
.map_err(|e| CacheError::Unknown(format!("{:?}", e)))?;
|
||||||
|
|
||||||
let protected_caller = Box::new(Caller::new(&info, handler_data, trampolines));
|
let protected_caller = Caller::new(&info, handler_data, trampolines);
|
||||||
|
|
||||||
|
let cache_gen = Box::new(CacheGenerator::new(
|
||||||
|
backend_cache,
|
||||||
|
Arc::clone(&func_resolver.memory),
|
||||||
|
));
|
||||||
|
|
||||||
Ok(ModuleInner {
|
Ok(ModuleInner {
|
||||||
func_resolver,
|
func_resolver: Box::new(func_resolver),
|
||||||
protected_caller,
|
protected_caller: Box::new(protected_caller),
|
||||||
|
cache_gen,
|
||||||
|
|
||||||
info,
|
info,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Deref for Module {
|
|
||||||
type Target = ModuleInner;
|
|
||||||
|
|
||||||
fn deref(&self) -> &ModuleInner {
|
|
||||||
&self.module
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DerefMut for Module {
|
|
||||||
fn deref_mut(&mut self) -> &mut ModuleInner {
|
|
||||||
&mut self.module
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Converter<T>(pub T);
|
pub struct Converter<T>(pub T);
|
||||||
|
|
||||||
macro_rules! convert_clif_to_runtime_index {
|
macro_rules! convert_clif_to_runtime_index {
|
||||||
|
@ -386,7 +386,7 @@ impl<'module, 'isa, 'data> ModuleEnvironment<'data> for ModuleEnv<'module, 'isa>
|
|||||||
let name = ir::ExternalName::user(0, func_index.index() as u32);
|
let name = ir::ExternalName::user(0, func_index.index() as u32);
|
||||||
|
|
||||||
let sig = func_env.generate_signature(
|
let sig = func_env.generate_signature(
|
||||||
self.get_func_type(Converter(func_index.convert_up(self.module)).into()),
|
self.get_func_type(Converter(func_index.convert_up(&self.module.info)).into()),
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut func = ir::Function::with_name_signature(name, sig);
|
let mut func = ir::Function::with_name_signature(name, sig);
|
||||||
|
@ -22,16 +22,14 @@ pub mod call_names {
|
|||||||
pub const DYNAMIC_MEM_SIZE: u32 = 5;
|
pub const DYNAMIC_MEM_SIZE: u32 = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "cache", derive(Serialize, Deserialize))]
|
#[derive(Serialize, Deserialize, Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
|
||||||
pub enum Reloc {
|
pub enum Reloc {
|
||||||
Abs8,
|
Abs8,
|
||||||
X86PCRel4,
|
X86PCRel4,
|
||||||
X86CallPCRel4,
|
X86CallPCRel4,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "cache", derive(Serialize, Deserialize))]
|
#[derive(Serialize, Deserialize, Debug, Copy, Clone)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
|
||||||
pub enum LibCall {
|
pub enum LibCall {
|
||||||
Probestack,
|
Probestack,
|
||||||
CeilF32,
|
CeilF32,
|
||||||
@ -44,8 +42,7 @@ pub enum LibCall {
|
|||||||
NearestF64,
|
NearestF64,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "cache", derive(Serialize, Deserialize))]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct ExternalRelocation {
|
pub struct ExternalRelocation {
|
||||||
/// The relocation code.
|
/// The relocation code.
|
||||||
pub reloc: Reloc,
|
pub reloc: Reloc,
|
||||||
@ -66,8 +63,7 @@ pub struct LocalRelocation {
|
|||||||
pub target: FuncIndex,
|
pub target: FuncIndex,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "cache", derive(Serialize, Deserialize))]
|
#[derive(Serialize, Deserialize, Debug, Clone, Copy)]
|
||||||
#[derive(Debug, Clone, Copy)]
|
|
||||||
pub enum VmCallKind {
|
pub enum VmCallKind {
|
||||||
StaticMemoryGrow,
|
StaticMemoryGrow,
|
||||||
StaticMemorySize,
|
StaticMemorySize,
|
||||||
@ -79,16 +75,14 @@ pub enum VmCallKind {
|
|||||||
DynamicMemorySize,
|
DynamicMemorySize,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "cache", derive(Serialize, Deserialize))]
|
#[derive(Serialize, Deserialize, Debug, Clone, Copy)]
|
||||||
#[derive(Debug, Clone, Copy)]
|
|
||||||
pub enum VmCall {
|
pub enum VmCall {
|
||||||
Local(VmCallKind),
|
Local(VmCallKind),
|
||||||
Import(VmCallKind),
|
Import(VmCallKind),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Specify the type of relocation
|
/// Specify the type of relocation
|
||||||
#[cfg_attr(feature = "cache", derive(Serialize, Deserialize))]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub enum RelocationType {
|
pub enum RelocationType {
|
||||||
Intrinsic(String),
|
Intrinsic(String),
|
||||||
LibCall(LibCall),
|
LibCall(LibCall),
|
||||||
@ -218,8 +212,7 @@ impl binemit::RelocSink for RelocSink {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "cache", derive(Serialize, Deserialize))]
|
#[derive(Serialize, Deserialize, Debug, Clone, Copy)]
|
||||||
#[derive(Debug, Clone, Copy)]
|
|
||||||
pub enum TrapCode {
|
pub enum TrapCode {
|
||||||
StackOverflow,
|
StackOverflow,
|
||||||
HeapOutOfBounds,
|
HeapOutOfBounds,
|
||||||
@ -244,8 +237,7 @@ impl RelocSink {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "cache", derive(Serialize, Deserialize))]
|
#[derive(Serialize, Deserialize, Debug, Clone, Copy)]
|
||||||
#[derive(Debug, Clone, Copy)]
|
|
||||||
pub struct TrapData {
|
pub struct TrapData {
|
||||||
pub trapcode: TrapCode,
|
pub trapcode: TrapCode,
|
||||||
pub srcloc: u32,
|
pub srcloc: u32,
|
||||||
@ -253,7 +245,7 @@ pub struct TrapData {
|
|||||||
|
|
||||||
/// Simple implementation of a TrapSink
|
/// Simple implementation of a TrapSink
|
||||||
/// that saves the info for later.
|
/// that saves the info for later.
|
||||||
#[cfg_attr(feature = "cache", derive(Serialize, Deserialize))]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct TrapSink {
|
pub struct TrapSink {
|
||||||
trap_datas: Vec<(usize, TrapData)>,
|
trap_datas: Vec<(usize, TrapData)>,
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,4 @@
|
|||||||
#[cfg(feature = "cache")]
|
use crate::{cache::BackendCache, trampoline::Trampolines};
|
||||||
use crate::{
|
|
||||||
cache::{BackendCache, TrampolineCache},
|
|
||||||
trampoline::Trampolines,
|
|
||||||
};
|
|
||||||
use crate::{
|
use crate::{
|
||||||
libcalls,
|
libcalls,
|
||||||
relocation::{
|
relocation::{
|
||||||
@ -19,7 +15,7 @@ use std::{
|
|||||||
ptr::{write_unaligned, NonNull},
|
ptr::{write_unaligned, NonNull},
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
};
|
};
|
||||||
#[cfg(feature = "cache")]
|
|
||||||
use wasmer_runtime_core::cache::Error as CacheError;
|
use wasmer_runtime_core::cache::Error as CacheError;
|
||||||
use wasmer_runtime_core::{
|
use wasmer_runtime_core::{
|
||||||
self,
|
self,
|
||||||
@ -42,21 +38,32 @@ extern "C" {
|
|||||||
pub fn __chkstk();
|
pub fn __chkstk();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn lookup_func(
|
||||||
|
map: &SliceMap<LocalFuncIndex, usize>,
|
||||||
|
memory: &Memory,
|
||||||
|
local_func_index: LocalFuncIndex,
|
||||||
|
) -> Option<NonNull<vm::Func>> {
|
||||||
|
let offset = *map.get(local_func_index)?;
|
||||||
|
let ptr = unsafe { memory.as_ptr().add(offset) };
|
||||||
|
|
||||||
|
NonNull::new(ptr).map(|nonnull| nonnull.cast())
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub struct FuncResolverBuilder {
|
pub struct FuncResolverBuilder {
|
||||||
resolver: FuncResolver,
|
map: Map<LocalFuncIndex, usize>,
|
||||||
|
memory: Memory,
|
||||||
local_relocs: Map<LocalFuncIndex, Box<[LocalRelocation]>>,
|
local_relocs: Map<LocalFuncIndex, Box<[LocalRelocation]>>,
|
||||||
external_relocs: Map<LocalFuncIndex, Box<[ExternalRelocation]>>,
|
external_relocs: Map<LocalFuncIndex, Box<[ExternalRelocation]>>,
|
||||||
import_len: usize,
|
import_len: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FuncResolverBuilder {
|
impl FuncResolverBuilder {
|
||||||
#[cfg(feature = "cache")]
|
|
||||||
pub fn new_from_backend_cache(
|
pub fn new_from_backend_cache(
|
||||||
backend_cache: BackendCache,
|
backend_cache: BackendCache,
|
||||||
mut code: Memory,
|
mut code: Memory,
|
||||||
info: &ModuleInfo,
|
info: &ModuleInfo,
|
||||||
) -> Result<(Self, Trampolines, HandlerData), CacheError> {
|
) -> Result<(Self, Arc<Trampolines>, HandlerData), CacheError> {
|
||||||
unsafe {
|
unsafe {
|
||||||
code.protect(.., Protect::ReadWrite)
|
code.protect(.., Protect::ReadWrite)
|
||||||
.map_err(|e| CacheError::Unknown(e.to_string()))?;
|
.map_err(|e| CacheError::Unknown(e.to_string()))?;
|
||||||
@ -67,37 +74,19 @@ impl FuncResolverBuilder {
|
|||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
Self {
|
Self {
|
||||||
resolver: FuncResolver {
|
map: backend_cache.offsets,
|
||||||
map: backend_cache.offsets,
|
memory: code,
|
||||||
memory: code,
|
|
||||||
},
|
|
||||||
local_relocs: Map::new(),
|
local_relocs: Map::new(),
|
||||||
external_relocs: backend_cache.external_relocs,
|
external_relocs: backend_cache.external_relocs,
|
||||||
import_len: info.imported_functions.len(),
|
import_len: info.imported_functions.len(),
|
||||||
},
|
},
|
||||||
Trampolines::from_trampoline_cache(backend_cache.trampolines),
|
Arc::new(Trampolines::from_trampoline_cache(
|
||||||
|
backend_cache.trampolines,
|
||||||
|
)),
|
||||||
handler_data,
|
handler_data,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "cache")]
|
|
||||||
pub fn to_backend_cache(
|
|
||||||
mut self,
|
|
||||||
trampolines: TrampolineCache,
|
|
||||||
handler_data: HandlerData,
|
|
||||||
) -> (BackendCache, Memory) {
|
|
||||||
self.relocate_locals();
|
|
||||||
(
|
|
||||||
BackendCache {
|
|
||||||
external_relocs: self.external_relocs,
|
|
||||||
offsets: self.resolver.map,
|
|
||||||
trap_sink: handler_data.trap_data,
|
|
||||||
trampolines,
|
|
||||||
},
|
|
||||||
self.resolver.memory,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new(
|
pub fn new(
|
||||||
isa: &isa::TargetIsa,
|
isa: &isa::TargetIsa,
|
||||||
function_bodies: Map<LocalFuncIndex, ir::Function>,
|
function_bodies: Map<LocalFuncIndex, ir::Function>,
|
||||||
@ -169,10 +158,12 @@ impl FuncResolverBuilder {
|
|||||||
previous_end = new_end;
|
previous_end = new_end;
|
||||||
}
|
}
|
||||||
|
|
||||||
let handler_data = HandlerData::new(trap_sink, memory.as_ptr() as _, memory.size());
|
let handler_data =
|
||||||
|
HandlerData::new(Arc::new(trap_sink), memory.as_ptr() as _, memory.size());
|
||||||
|
|
||||||
let mut func_resolver_builder = Self {
|
let mut func_resolver_builder = Self {
|
||||||
resolver: FuncResolver { map, memory },
|
map,
|
||||||
|
memory,
|
||||||
local_relocs,
|
local_relocs,
|
||||||
external_relocs,
|
external_relocs,
|
||||||
import_len: info.imported_functions.len(),
|
import_len: info.imported_functions.len(),
|
||||||
@ -187,12 +178,15 @@ impl FuncResolverBuilder {
|
|||||||
for (index, relocs) in self.local_relocs.iter() {
|
for (index, relocs) in self.local_relocs.iter() {
|
||||||
for ref reloc in relocs.iter() {
|
for ref reloc in relocs.iter() {
|
||||||
let local_func_index = LocalFuncIndex::new(reloc.target.index() - self.import_len);
|
let local_func_index = LocalFuncIndex::new(reloc.target.index() - self.import_len);
|
||||||
let target_func_address =
|
let target_func_address = lookup_func(&self.map, &self.memory, local_func_index)
|
||||||
self.resolver.lookup(local_func_index).unwrap().as_ptr() as usize;
|
.unwrap()
|
||||||
|
.as_ptr() as usize;
|
||||||
|
|
||||||
// We need the address of the current function
|
// We need the address of the current function
|
||||||
// because these calls are relative.
|
// because these calls are relative.
|
||||||
let func_addr = self.resolver.lookup(index).unwrap().as_ptr() as usize;
|
let func_addr = lookup_func(&self.map, &self.memory, index)
|
||||||
|
.unwrap()
|
||||||
|
.as_ptr() as usize;
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let reloc_address = func_addr + reloc.offset as usize;
|
let reloc_address = func_addr + reloc.offset as usize;
|
||||||
@ -208,8 +202,10 @@ impl FuncResolverBuilder {
|
|||||||
|
|
||||||
pub fn finalize(
|
pub fn finalize(
|
||||||
mut self,
|
mut self,
|
||||||
signatures: &SliceMap<SigIndex, FuncSig>,
|
signatures: &SliceMap<SigIndex, Arc<FuncSig>>,
|
||||||
) -> CompileResult<FuncResolver> {
|
trampolines: Arc<Trampolines>,
|
||||||
|
handler_data: HandlerData,
|
||||||
|
) -> CompileResult<(FuncResolver, BackendCache)> {
|
||||||
for (index, relocs) in self.external_relocs.iter() {
|
for (index, relocs) in self.external_relocs.iter() {
|
||||||
for ref reloc in relocs.iter() {
|
for ref reloc in relocs.iter() {
|
||||||
let target_func_address: isize = match reloc.target {
|
let target_func_address: isize = match reloc.target {
|
||||||
@ -281,7 +277,9 @@ impl FuncResolverBuilder {
|
|||||||
|
|
||||||
// We need the address of the current function
|
// We need the address of the current function
|
||||||
// because some of these calls are relative.
|
// because some of these calls are relative.
|
||||||
let func_addr = self.resolver.lookup(index).unwrap().as_ptr();
|
let func_addr = lookup_func(&self.map, &self.memory, index)
|
||||||
|
.unwrap()
|
||||||
|
.as_ptr() as usize;
|
||||||
|
|
||||||
// Determine relocation type and apply relocation.
|
// Determine relocation type and apply relocation.
|
||||||
match reloc.reloc {
|
match reloc.reloc {
|
||||||
@ -289,9 +287,9 @@ impl FuncResolverBuilder {
|
|||||||
let ptr_to_write = (target_func_address as u64)
|
let ptr_to_write = (target_func_address as u64)
|
||||||
.checked_add(reloc.addend as u64)
|
.checked_add(reloc.addend as u64)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let empty_space_offset = self.resolver.map[index] + reloc.offset as usize;
|
let empty_space_offset = self.map[index] + reloc.offset as usize;
|
||||||
let ptr_slice = unsafe {
|
let ptr_slice = unsafe {
|
||||||
&mut self.resolver.memory.as_slice_mut()
|
&mut self.memory.as_slice_mut()
|
||||||
[empty_space_offset..empty_space_offset + 8]
|
[empty_space_offset..empty_space_offset + 8]
|
||||||
};
|
};
|
||||||
LittleEndian::write_u64(ptr_slice, ptr_to_write);
|
LittleEndian::write_u64(ptr_slice, ptr_to_write);
|
||||||
@ -309,29 +307,35 @@ impl FuncResolverBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
self.resolver
|
self.memory
|
||||||
.memory
|
|
||||||
.protect(.., Protect::ReadExec)
|
.protect(.., Protect::ReadExec)
|
||||||
.map_err(|e| CompileError::InternalError { msg: e.to_string() })?;
|
.map_err(|e| CompileError::InternalError { msg: e.to_string() })?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(self.resolver)
|
let backend_cache = BackendCache {
|
||||||
|
external_relocs: self.external_relocs.clone(),
|
||||||
|
offsets: self.map.clone(),
|
||||||
|
trap_sink: handler_data.trap_data,
|
||||||
|
trampolines: trampolines.to_trampoline_cache(),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok((
|
||||||
|
FuncResolver {
|
||||||
|
map: self.map,
|
||||||
|
memory: Arc::new(self.memory),
|
||||||
|
},
|
||||||
|
backend_cache,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe impl Sync for FuncResolver {}
|
||||||
|
unsafe impl Send for FuncResolver {}
|
||||||
|
|
||||||
/// Resolves a function index to a function address.
|
/// Resolves a function index to a function address.
|
||||||
pub struct FuncResolver {
|
pub struct FuncResolver {
|
||||||
map: Map<LocalFuncIndex, usize>,
|
map: Map<LocalFuncIndex, usize>,
|
||||||
memory: Memory,
|
pub(crate) memory: Arc<Memory>,
|
||||||
}
|
|
||||||
|
|
||||||
impl FuncResolver {
|
|
||||||
fn lookup(&self, local_func_index: LocalFuncIndex) -> Option<NonNull<vm::Func>> {
|
|
||||||
let offset = *self.map.get(local_func_index)?;
|
|
||||||
let ptr = unsafe { self.memory.as_ptr().add(offset) };
|
|
||||||
|
|
||||||
NonNull::new(ptr).map(|nonnull| nonnull.cast())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements FuncResolver trait.
|
// Implements FuncResolver trait.
|
||||||
@ -341,7 +345,7 @@ impl backend::FuncResolver for FuncResolver {
|
|||||||
_module: &wasmer_runtime_core::module::ModuleInner,
|
_module: &wasmer_runtime_core::module::ModuleInner,
|
||||||
index: LocalFuncIndex,
|
index: LocalFuncIndex,
|
||||||
) -> Option<NonNull<vm::Func>> {
|
) -> Option<NonNull<vm::Func>> {
|
||||||
self.lookup(index)
|
lookup_func(&self.map, &self.memory, index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,11 +40,15 @@ impl UserTrapper for Trapper {
|
|||||||
pub struct Caller {
|
pub struct Caller {
|
||||||
func_export_set: HashSet<FuncIndex>,
|
func_export_set: HashSet<FuncIndex>,
|
||||||
handler_data: HandlerData,
|
handler_data: HandlerData,
|
||||||
trampolines: Trampolines,
|
trampolines: Arc<Trampolines>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Caller {
|
impl Caller {
|
||||||
pub fn new(module: &ModuleInfo, handler_data: HandlerData, trampolines: Trampolines) -> Self {
|
pub fn new(
|
||||||
|
module: &ModuleInfo,
|
||||||
|
handler_data: HandlerData,
|
||||||
|
trampolines: Arc<Trampolines>,
|
||||||
|
) -> Self {
|
||||||
let mut func_export_set = HashSet::new();
|
let mut func_export_set = HashSet::new();
|
||||||
for export_index in module.exports.values() {
|
for export_index in module.exports.values() {
|
||||||
if let ExportIndex::Func(func_index) = export_index {
|
if let ExportIndex::Func(func_index) = export_index {
|
||||||
@ -187,15 +191,16 @@ fn get_func_from_index<'a>(
|
|||||||
unsafe impl Send for HandlerData {}
|
unsafe impl Send for HandlerData {}
|
||||||
unsafe impl Sync for HandlerData {}
|
unsafe impl Sync for HandlerData {}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct HandlerData {
|
pub struct HandlerData {
|
||||||
pub trap_data: TrapSink,
|
pub trap_data: Arc<TrapSink>,
|
||||||
exec_buffer_ptr: *const c_void,
|
exec_buffer_ptr: *const c_void,
|
||||||
exec_buffer_size: usize,
|
exec_buffer_size: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HandlerData {
|
impl HandlerData {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
trap_data: TrapSink,
|
trap_data: Arc<TrapSink>,
|
||||||
exec_buffer_ptr: *const c_void,
|
exec_buffer_ptr: *const c_void,
|
||||||
exec_buffer_size: usize,
|
exec_buffer_size: usize,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
#[cfg(feature = "cache")]
|
|
||||||
use crate::cache::TrampolineCache;
|
use crate::cache::TrampolineCache;
|
||||||
use cranelift_codegen::{
|
use cranelift_codegen::{
|
||||||
binemit::{NullTrapSink, Reloc, RelocSink},
|
binemit::{NullTrapSink, Reloc, RelocSink},
|
||||||
@ -33,7 +32,6 @@ pub struct Trampolines {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Trampolines {
|
impl Trampolines {
|
||||||
#[cfg(feature = "cache")]
|
|
||||||
pub fn from_trampoline_cache(cache: TrampolineCache) -> Self {
|
pub fn from_trampoline_cache(cache: TrampolineCache) -> Self {
|
||||||
// pub struct TrampolineCache {
|
// pub struct TrampolineCache {
|
||||||
// #[serde(with = "serde_bytes")]
|
// #[serde(with = "serde_bytes")]
|
||||||
@ -57,8 +55,7 @@ impl Trampolines {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "cache")]
|
pub fn to_trampoline_cache(&self) -> TrampolineCache {
|
||||||
pub fn to_trampoline_cache(self) -> TrampolineCache {
|
|
||||||
let mut code = vec![0; self.memory.size()];
|
let mut code = vec![0; self.memory.size()];
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
@ -67,7 +64,7 @@ impl Trampolines {
|
|||||||
|
|
||||||
TrampolineCache {
|
TrampolineCache {
|
||||||
code,
|
code,
|
||||||
offsets: self.offsets,
|
offsets: self.offsets.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,10 +10,14 @@ build = "build/mod.rs"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
wasmer-runtime-core = { path = "../runtime-core", version = "0.1.0" }
|
wasmer-runtime-core = { path = "../runtime-core", version = "0.1.0" }
|
||||||
|
lazy_static = "1.2.0"
|
||||||
libc = { git = "https://github.com/rust-lang/libc" }
|
libc = { git = "https://github.com/rust-lang/libc" }
|
||||||
byteorder = "1"
|
byteorder = "1"
|
||||||
time = "0.1.41"
|
time = "0.1.41"
|
||||||
|
|
||||||
|
[target.'cfg(windows)'.dependencies]
|
||||||
|
rand = "0.6"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
wasmer-clif-backend = { path = "../clif-backend", version = "0.1.0" }
|
wasmer-clif-backend = { path = "../clif-backend", version = "0.1.0" }
|
||||||
wabt = "0.7.2"
|
wabt = "0.7.2"
|
||||||
|
BIN
lib/emscripten/emtests/FS_exports.wasm
vendored
BIN
lib/emscripten/emtests/FS_exports.wasm
vendored
Binary file not shown.
BIN
lib/emscripten/emtests/clock_gettime.wasm
vendored
BIN
lib/emscripten/emtests/clock_gettime.wasm
vendored
Binary file not shown.
BIN
lib/emscripten/emtests/closebitcasts.wasm
vendored
BIN
lib/emscripten/emtests/closebitcasts.wasm
vendored
Binary file not shown.
BIN
lib/emscripten/emtests/dyncall.wasm
vendored
BIN
lib/emscripten/emtests/dyncall.wasm
vendored
Binary file not shown.
BIN
lib/emscripten/emtests/dyncall_specific.wasm
vendored
BIN
lib/emscripten/emtests/dyncall_specific.wasm
vendored
Binary file not shown.
Binary file not shown.
BIN
lib/emscripten/emtests/env.wasm
vendored
BIN
lib/emscripten/emtests/env.wasm
vendored
Binary file not shown.
BIN
lib/emscripten/emtests/getValue_setValue.wasm
vendored
BIN
lib/emscripten/emtests/getValue_setValue.wasm
vendored
Binary file not shown.
Binary file not shown.
BIN
lib/emscripten/emtests/localtime.wasm
vendored
BIN
lib/emscripten/emtests/localtime.wasm
vendored
Binary file not shown.
BIN
lib/emscripten/emtests/modularize_closure_pre.wasm
vendored
BIN
lib/emscripten/emtests/modularize_closure_pre.wasm
vendored
Binary file not shown.
BIN
lib/emscripten/emtests/printf.wasm
vendored
BIN
lib/emscripten/emtests/printf.wasm
vendored
Binary file not shown.
BIN
lib/emscripten/emtests/puts.wasm
vendored
BIN
lib/emscripten/emtests/puts.wasm
vendored
Binary file not shown.
BIN
lib/emscripten/emtests/stackAlloc.wasm
vendored
BIN
lib/emscripten/emtests/stackAlloc.wasm
vendored
Binary file not shown.
BIN
lib/emscripten/emtests/stack_overflow.wasm
vendored
BIN
lib/emscripten/emtests/stack_overflow.wasm
vendored
Binary file not shown.
BIN
lib/emscripten/emtests/test_addr_of_stacked.wasm
vendored
BIN
lib/emscripten/emtests/test_addr_of_stacked.wasm
vendored
Binary file not shown.
BIN
lib/emscripten/emtests/test_alloca.wasm
vendored
BIN
lib/emscripten/emtests/test_alloca.wasm
vendored
Binary file not shown.
BIN
lib/emscripten/emtests/test_alloca_stack.wasm
vendored
BIN
lib/emscripten/emtests/test_alloca_stack.wasm
vendored
Binary file not shown.
BIN
lib/emscripten/emtests/test_array2.wasm
vendored
BIN
lib/emscripten/emtests/test_array2.wasm
vendored
Binary file not shown.
BIN
lib/emscripten/emtests/test_array2b.wasm
vendored
BIN
lib/emscripten/emtests/test_array2b.wasm
vendored
Binary file not shown.
BIN
lib/emscripten/emtests/test_atoX.wasm
vendored
BIN
lib/emscripten/emtests/test_atoX.wasm
vendored
Binary file not shown.
BIN
lib/emscripten/emtests/test_atomic.wasm
vendored
BIN
lib/emscripten/emtests/test_atomic.wasm
vendored
Binary file not shown.
BIN
lib/emscripten/emtests/test_atomic_cxx.wasm
vendored
BIN
lib/emscripten/emtests/test_atomic_cxx.wasm
vendored
Binary file not shown.
BIN
lib/emscripten/emtests/test_bsearch.wasm
vendored
BIN
lib/emscripten/emtests/test_bsearch.wasm
vendored
Binary file not shown.
BIN
lib/emscripten/emtests/test_ccall.wasm
vendored
BIN
lib/emscripten/emtests/test_ccall.wasm
vendored
Binary file not shown.
BIN
lib/emscripten/emtests/test_complex.wasm
vendored
BIN
lib/emscripten/emtests/test_complex.wasm
vendored
Binary file not shown.
BIN
lib/emscripten/emtests/test_demangle_stacks.wasm
vendored
BIN
lib/emscripten/emtests/test_demangle_stacks.wasm
vendored
Binary file not shown.
Binary file not shown.
BIN
lib/emscripten/emtests/test_dlmalloc_partial_2.wasm
vendored
BIN
lib/emscripten/emtests/test_dlmalloc_partial_2.wasm
vendored
Binary file not shown.
BIN
lib/emscripten/emtests/test_double_varargs.wasm
vendored
BIN
lib/emscripten/emtests/test_double_varargs.wasm
vendored
Binary file not shown.
BIN
lib/emscripten/emtests/test_em_asm.wasm
vendored
BIN
lib/emscripten/emtests/test_em_asm.wasm
vendored
Binary file not shown.
BIN
lib/emscripten/emtests/test_em_asm_2.wasm
vendored
BIN
lib/emscripten/emtests/test_em_asm_2.wasm
vendored
Binary file not shown.
Binary file not shown.
BIN
lib/emscripten/emtests/test_em_asm_signatures.wasm
vendored
BIN
lib/emscripten/emtests/test_em_asm_signatures.wasm
vendored
Binary file not shown.
BIN
lib/emscripten/emtests/test_em_asm_unicode.wasm
vendored
BIN
lib/emscripten/emtests/test_em_asm_unicode.wasm
vendored
Binary file not shown.
Binary file not shown.
BIN
lib/emscripten/emtests/test_em_js.wasm
vendored
BIN
lib/emscripten/emtests/test_em_js.wasm
vendored
Binary file not shown.
BIN
lib/emscripten/emtests/test_emscripten_api.wasm
vendored
BIN
lib/emscripten/emtests/test_emscripten_api.wasm
vendored
Binary file not shown.
Binary file not shown.
BIN
lib/emscripten/emtests/test_erf.wasm
vendored
BIN
lib/emscripten/emtests/test_erf.wasm
vendored
Binary file not shown.
BIN
lib/emscripten/emtests/test_errar.wasm
vendored
BIN
lib/emscripten/emtests/test_errar.wasm
vendored
Binary file not shown.
BIN
lib/emscripten/emtests/test_exceptions_2.wasm
vendored
BIN
lib/emscripten/emtests/test_exceptions_2.wasm
vendored
Binary file not shown.
BIN
lib/emscripten/emtests/test_exceptions_convert.wasm
vendored
BIN
lib/emscripten/emtests/test_exceptions_convert.wasm
vendored
Binary file not shown.
Binary file not shown.
BIN
lib/emscripten/emtests/test_exceptions_libcxx.wasm
vendored
BIN
lib/emscripten/emtests/test_exceptions_libcxx.wasm
vendored
Binary file not shown.
BIN
lib/emscripten/emtests/test_exceptions_multi.wasm
vendored
BIN
lib/emscripten/emtests/test_exceptions_multi.wasm
vendored
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
lib/emscripten/emtests/test_exceptions_primary.wasm
vendored
BIN
lib/emscripten/emtests/test_exceptions_primary.wasm
vendored
Binary file not shown.
BIN
lib/emscripten/emtests/test_exceptions_refcount.wasm
vendored
BIN
lib/emscripten/emtests/test_exceptions_refcount.wasm
vendored
Binary file not shown.
BIN
lib/emscripten/emtests/test_exceptions_resume.wasm
vendored
BIN
lib/emscripten/emtests/test_exceptions_resume.wasm
vendored
Binary file not shown.
BIN
lib/emscripten/emtests/test_exceptions_rethrow.wasm
vendored
BIN
lib/emscripten/emtests/test_exceptions_rethrow.wasm
vendored
Binary file not shown.
Binary file not shown.
BIN
lib/emscripten/emtests/test_exceptions_std.wasm
vendored
BIN
lib/emscripten/emtests/test_exceptions_std.wasm
vendored
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
lib/emscripten/emtests/test_fast_math.wasm
vendored
BIN
lib/emscripten/emtests/test_fast_math.wasm
vendored
Binary file not shown.
BIN
lib/emscripten/emtests/test_flexarray_struct.wasm
vendored
BIN
lib/emscripten/emtests/test_flexarray_struct.wasm
vendored
Binary file not shown.
BIN
lib/emscripten/emtests/test_float32_precise.wasm
vendored
BIN
lib/emscripten/emtests/test_float32_precise.wasm
vendored
Binary file not shown.
BIN
lib/emscripten/emtests/test_float_builtins.wasm
vendored
BIN
lib/emscripten/emtests/test_float_builtins.wasm
vendored
Binary file not shown.
BIN
lib/emscripten/emtests/test_frexp.wasm
vendored
BIN
lib/emscripten/emtests/test_frexp.wasm
vendored
Binary file not shown.
BIN
lib/emscripten/emtests/test_funcptr.wasm
vendored
BIN
lib/emscripten/emtests/test_funcptr.wasm
vendored
Binary file not shown.
BIN
lib/emscripten/emtests/test_funcptr_namecollide.wasm
vendored
BIN
lib/emscripten/emtests/test_funcptr_namecollide.wasm
vendored
Binary file not shown.
BIN
lib/emscripten/emtests/test_funcptrfunc.wasm
vendored
BIN
lib/emscripten/emtests/test_funcptrfunc.wasm
vendored
Binary file not shown.
BIN
lib/emscripten/emtests/test_funcs.wasm
vendored
BIN
lib/emscripten/emtests/test_funcs.wasm
vendored
Binary file not shown.
Binary file not shown.
BIN
lib/emscripten/emtests/test_fwrite_0.wasm
vendored
BIN
lib/emscripten/emtests/test_fwrite_0.wasm
vendored
Binary file not shown.
BIN
lib/emscripten/emtests/test_getgep.wasm
vendored
BIN
lib/emscripten/emtests/test_getgep.wasm
vendored
Binary file not shown.
BIN
lib/emscripten/emtests/test_getloadavg.wasm
vendored
BIN
lib/emscripten/emtests/test_getloadavg.wasm
vendored
Binary file not shown.
BIN
lib/emscripten/emtests/test_getopt.wasm
vendored
BIN
lib/emscripten/emtests/test_getopt.wasm
vendored
Binary file not shown.
BIN
lib/emscripten/emtests/test_getopt_long.wasm
vendored
BIN
lib/emscripten/emtests/test_getopt_long.wasm
vendored
Binary file not shown.
BIN
lib/emscripten/emtests/test_globaldoubles.wasm
vendored
BIN
lib/emscripten/emtests/test_globaldoubles.wasm
vendored
Binary file not shown.
BIN
lib/emscripten/emtests/test_globals.wasm
vendored
BIN
lib/emscripten/emtests/test_globals.wasm
vendored
Binary file not shown.
BIN
lib/emscripten/emtests/test_gmtime.wasm
vendored
BIN
lib/emscripten/emtests/test_gmtime.wasm
vendored
Binary file not shown.
BIN
lib/emscripten/emtests/test_hello_world.wasm
vendored
BIN
lib/emscripten/emtests/test_hello_world.wasm
vendored
Binary file not shown.
BIN
lib/emscripten/emtests/test_i16_emcc_intrinsic.wasm
vendored
BIN
lib/emscripten/emtests/test_i16_emcc_intrinsic.wasm
vendored
Binary file not shown.
BIN
lib/emscripten/emtests/test_i32_mul_precise.wasm
vendored
BIN
lib/emscripten/emtests/test_i32_mul_precise.wasm
vendored
Binary file not shown.
BIN
lib/emscripten/emtests/test_i64.wasm
vendored
BIN
lib/emscripten/emtests/test_i64.wasm
vendored
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user