mirror of
https://github.com/fluencelabs/wasmer
synced 2025-06-15 09:51:21 +00:00
Merge branch 'master' into fix/emscripten-translate
This commit is contained in:
420
Cargo.lock
generated
420
Cargo.lock
generated
@ -11,11 +11,16 @@ name = "atty"
|
|||||||
version = "0.2.11"
|
version = "0.2.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"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 = "autocfg"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "1.0.4"
|
version = "1.0.4"
|
||||||
@ -23,7 +28,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "byteorder"
|
name = "byteorder"
|
||||||
version = "1.2.7"
|
version = "1.3.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -33,12 +38,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.0.25"
|
version = "1.0.28"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cfg-if"
|
||||||
version = "0.1.5"
|
version = "0.1.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -55,12 +60,20 @@ dependencies = [
|
|||||||
"vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cloudabi"
|
||||||
|
version = "0.0.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cmake"
|
name = "cmake"
|
||||||
version = "0.1.35"
|
version = "0.1.35"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -79,9 +92,9 @@ dependencies = [
|
|||||||
"cranelift-bforest 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cranelift-bforest 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"cranelift-codegen-meta 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cranelift-codegen-meta 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"cranelift-entity 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cranelift-entity 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -104,7 +117,7 @@ version = "0.26.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cranelift-codegen 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cranelift-codegen 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -127,9 +140,9 @@ dependencies = [
|
|||||||
"cranelift-codegen 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cranelift-codegen 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"cranelift-entity 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cranelift-entity 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"cranelift-frontend 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cranelift-frontend 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"wasmparser 0.22.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"wasmparser 0.22.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -139,7 +152,7 @@ version = "0.2.4"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"errno-dragonfly 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"errno-dragonfly 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"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)",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -149,25 +162,25 @@ version = "0.1.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)",
|
"gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "failure"
|
name = "failure"
|
||||||
version = "0.1.3"
|
version = "0.1.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "failure_derive"
|
name = "failure_derive"
|
||||||
version = "0.1.3"
|
version = "0.1.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
"proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"syn 0.15.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
"syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -176,6 +189,20 @@ name = "field-offset"
|
|||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fuchsia-zircon"
|
||||||
|
version = "0.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fuchsia-zircon-sys"
|
||||||
|
version = "0.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gcc"
|
name = "gcc"
|
||||||
version = "0.3.55"
|
version = "0.3.55"
|
||||||
@ -188,10 +215,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hashbrown"
|
name = "hashbrown"
|
||||||
version = "0.1.7"
|
version = "0.1.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -218,21 +245,35 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "lazy_static"
|
||||||
version = "0.2.44"
|
version = "1.2.0"
|
||||||
source = "git+https://github.com/rust-lang/libc#d4b45f51ea751d9685a956b9c011698359e4cc06"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.44"
|
version = "0.2.48"
|
||||||
|
source = "git+https://github.com/rust-lang/libc#42cd3ba27254c423e03f6f4324de57075047f6a0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.48"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lock_api"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "log"
|
||||||
version = "0.4.5"
|
version = "0.4.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -241,25 +282,54 @@ version = "0.12.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "owning_ref"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "page_size"
|
name = "page_size"
|
||||||
version = "0.4.1"
|
version = "0.4.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parking_lot"
|
||||||
|
version = "0.7.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parking_lot_core"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"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)",
|
||||||
|
"rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"smallvec 0.6.8 (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 = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "0.4.20"
|
version = "0.4.26"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -267,10 +337,106 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "0.6.8"
|
version = "0.6.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
"proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand"
|
||||||
|
version = "0.6.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"rand_jitter 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"rand_os 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_chacha"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_core"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_core"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_hc"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_isaac"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_jitter"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_os"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_pcg"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_xorshift"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -279,13 +445,21 @@ version = "6.1.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rdrand"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redox_syscall"
|
name = "redox_syscall"
|
||||||
version = "0.1.40"
|
version = "0.1.51"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -293,7 +467,7 @@ name = "redox_termios"
|
|||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
"redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -306,7 +480,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ryu"
|
name = "ryu"
|
||||||
version = "0.2.6"
|
version = "0.2.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -329,29 +503,42 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.79"
|
version = "1.0.85"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.79"
|
version = "1.0.85"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
"proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"syn 0.15.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
"syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_json"
|
name = "serde_json"
|
||||||
version = "1.0.32"
|
version = "1.0.37"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"ryu 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "smallvec"
|
||||||
|
version = "0.6.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "stable_deref_trait"
|
||||||
|
version = "1.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "strsim"
|
name = "strsim"
|
||||||
version = "0.7.0"
|
version = "0.7.0"
|
||||||
@ -372,18 +559,18 @@ version = "0.2.14"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
"proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"syn 0.15.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
"syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "0.15.9"
|
version = "0.15.26"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
"proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -392,9 +579,9 @@ name = "synstructure"
|
|||||||
version = "0.10.1"
|
version = "0.10.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
"proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"syn 0.15.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
"syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -403,9 +590,9 @@ name = "target-lexicon"
|
|||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_json 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -413,8 +600,8 @@ name = "termion"
|
|||||||
version = "1.5.1"
|
version = "1.5.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
"redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -428,11 +615,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "time"
|
name = "time"
|
||||||
version = "0.1.41"
|
version = "0.1.42"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
"redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"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)",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -451,6 +638,14 @@ name = "unicode-xid"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unreachable"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "vec_map"
|
name = "vec_map"
|
||||||
version = "0.8.1"
|
version = "0.8.1"
|
||||||
@ -463,21 +658,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wabt"
|
name = "wabt"
|
||||||
version = "0.7.2"
|
version = "0.7.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde 1.0.79 (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.79 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_derive 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_json 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"wabt-sys 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"wabt-sys 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wabt-sys"
|
name = "wabt-sys"
|
||||||
version = "0.5.2"
|
version = "0.5.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"cmake 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cmake 0.1.35 (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)",
|
||||||
]
|
]
|
||||||
@ -488,7 +683,7 @@ version = "0.1.4"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"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)",
|
||||||
"structopt 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
"structopt 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"wabt 0.7.2 (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",
|
||||||
"wasmer-emscripten 0.1.0",
|
"wasmer-emscripten 0.1.0",
|
||||||
"wasmer-runtime 0.1.4",
|
"wasmer-runtime 0.1.4",
|
||||||
@ -499,12 +694,12 @@ dependencies = [
|
|||||||
name = "wasmer-clif-backend"
|
name = "wasmer-clif-backend"
|
||||||
version = "0.1.2"
|
version = "0.1.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"cranelift-codegen 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cranelift-codegen 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"cranelift-entity 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cranelift-entity 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"cranelift-native 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cranelift-native 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"cranelift-wasm 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cranelift-wasm 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"hashbrown 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"hashbrown 0.1.8 (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)",
|
||||||
"target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"wasmer-runtime-core 0.1.2",
|
"wasmer-runtime-core 0.1.2",
|
||||||
@ -515,11 +710,11 @@ dependencies = [
|
|||||||
name = "wasmer-emscripten"
|
name = "wasmer-emscripten"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder 1.2.7 (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.44 (git+https://github.com/rust-lang/libc)",
|
"libc 0.2.48 (git+https://github.com/rust-lang/libc)",
|
||||||
"time 0.1.41 (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.2 (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",
|
||||||
"wasmer-runtime-core 0.1.2",
|
"wasmer-runtime-core 0.1.2",
|
||||||
]
|
]
|
||||||
@ -538,10 +733,12 @@ version = "0.1.2"
|
|||||||
dependencies = [
|
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.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"lazy_static 1.2.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)",
|
||||||
"wabt 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"parking_lot 0.7.1 (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",
|
||||||
"wasmparser 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"wasmparser 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"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)",
|
||||||
@ -589,12 +786,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
[metadata]
|
[metadata]
|
||||||
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
|
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
|
||||||
"checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652"
|
"checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652"
|
||||||
|
"checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799"
|
||||||
"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"
|
"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"
|
||||||
"checksum byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d"
|
"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.25 (registry+https://github.com/rust-lang/crates.io-index)" = "f159dfd43363c4d08055a07703eb7a3406b0dac4d0584d96965a3262db3c9d16"
|
"checksum cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4a8b715cb4597106ea87c7c84b2f1d452c7492033765df7f32651e66fcf749"
|
||||||
"checksum cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0c4e7bb64a8ebb0d856483e1e682ea3422f883c5f5615a90d51a2c82fe87fdd3"
|
"checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4"
|
||||||
"checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e"
|
"checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e"
|
||||||
|
"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
|
||||||
"checksum cmake 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "6ec65ee4f9c9d16f335091d23693457ed4928657ba4982289d7fafee03bc614a"
|
"checksum cmake 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "6ec65ee4f9c9d16f335091d23693457ed4928657ba4982289d7fafee03bc614a"
|
||||||
"checksum cranelift-bforest 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "40f8ff24e9a6c89b8a846b14df9a34d2cac17cea7bdb5c81ed6b4744ee0e38bf"
|
"checksum cranelift-bforest 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "40f8ff24e9a6c89b8a846b14df9a34d2cac17cea7bdb5c81ed6b4744ee0e38bf"
|
||||||
"checksum cranelift-codegen 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "42f5b809bd885c368e01aeec8fe04f21dcb07569834b907d75b4a7bed8d067eb"
|
"checksum cranelift-codegen 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "42f5b809bd885c368e01aeec8fe04f21dcb07569834b907d75b4a7bed8d067eb"
|
||||||
@ -605,49 +804,70 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
"checksum cranelift-wasm 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49723365dab9a48b354bdc24cb6d9d5719bc1d3b858ffd2ea179d0d7d885804a"
|
"checksum cranelift-wasm 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49723365dab9a48b354bdc24cb6d9d5719bc1d3b858ffd2ea179d0d7d885804a"
|
||||||
"checksum errno 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c2a071601ed01b988f896ab14b95e67335d1eeb50190932a1320f7fe3cadc84e"
|
"checksum errno 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c2a071601ed01b988f896ab14b95e67335d1eeb50190932a1320f7fe3cadc84e"
|
||||||
"checksum errno-dragonfly 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "14ca354e36190500e1e1fb267c647932382b54053c50b14970856c0b00a35067"
|
"checksum errno-dragonfly 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "14ca354e36190500e1e1fb267c647932382b54053c50b14970856c0b00a35067"
|
||||||
"checksum failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6dd377bcc1b1b7ce911967e3ec24fa19c3224394ec05b54aa7b083d498341ac7"
|
"checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2"
|
||||||
"checksum failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "64c2d913fe8ed3b6c6518eedf4538255b989945c14c2a7d5cbff62a5e2120596"
|
"checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1"
|
||||||
"checksum field-offset 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "64e9bc339e426139e02601fa69d101e96a92aee71b58bc01697ec2a63a5c9e68"
|
"checksum field-offset 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "64e9bc339e426139e02601fa69d101e96a92aee71b58bc01697ec2a63a5c9e68"
|
||||||
|
"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
|
||||||
|
"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
|
||||||
"checksum gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)" = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2"
|
"checksum gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)" = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2"
|
||||||
"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb"
|
"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb"
|
||||||
"checksum hashbrown 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "64b7d419d0622ae02fe5da6b9a5e1964b610a65bb37923b976aeebb6dbb8f86e"
|
"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 itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b"
|
"checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b"
|
||||||
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
|
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
|
||||||
"checksum libc 0.2.44 (git+https://github.com/rust-lang/libc)" = "<none>"
|
"checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1"
|
||||||
"checksum libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)" = "10923947f84a519a45c8fefb7dd1b3e8c08747993381adee176d7a82b4195311"
|
"checksum libc 0.2.48 (git+https://github.com/rust-lang/libc)" = "<none>"
|
||||||
"checksum log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fcce5fa49cc693c312001daf1d13411c4a5283796bac1084299ea3e567113f"
|
"checksum libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)" = "e962c7641008ac010fa60a7dfdc1712449f29c44ef2d4702394aea943ee75047"
|
||||||
|
"checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c"
|
||||||
|
"checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6"
|
||||||
"checksum nix 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "921f61dc817b379d0834e45d5ec45beaacfae97082090a49c2cf30dcbc30206f"
|
"checksum nix 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "921f61dc817b379d0834e45d5ec45beaacfae97082090a49c2cf30dcbc30206f"
|
||||||
|
"checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13"
|
||||||
"checksum page_size 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f89ef58b3d32420dbd1a43d2f38ae92f6239ef12bb556ab09ca55445f5a67242"
|
"checksum page_size 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f89ef58b3d32420dbd1a43d2f38ae92f6239ef12bb556ab09ca55445f5a67242"
|
||||||
"checksum proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)" = "3d7b7eaaa90b4a90a932a9ea6666c95a389e424eff347f0f793979289429feee"
|
"checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337"
|
||||||
"checksum quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "dd636425967c33af890042c483632d33fa7a18f19ad1d7ea72e8998c6ef8dea5"
|
"checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9"
|
||||||
|
"checksum proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)" = "38fddd23d98b2144d197c0eca5705632d4fe2667d14a6be5df8934f8d74f1978"
|
||||||
|
"checksum quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cdd8e04bd9c52e0342b406469d494fcb033be4bdbe5c606016defbb1681411e1"
|
||||||
|
"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
|
||||||
|
"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
|
||||||
|
"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
|
||||||
|
"checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0"
|
||||||
|
"checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4"
|
||||||
|
"checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08"
|
||||||
|
"checksum rand_jitter 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f47842851e13bd803b506bdd1345328e0a1394733ee58e627b5e39332b9afafe"
|
||||||
|
"checksum rand_os 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f46fbd5550acf75b0c2730f5dd1873751daf9beb8f11b44027778fae50d7feca"
|
||||||
|
"checksum rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "086bd09a33c7044e56bb44d5bdde5a60e7f119a9e95b0775f545de759a32fe05"
|
||||||
|
"checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c"
|
||||||
"checksum raw-cpuid 6.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "30a9d219c32c9132f7be513c18be77c9881c7107d2ab5569d205a6a0f0e6dc7d"
|
"checksum raw-cpuid 6.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "30a9d219c32c9132f7be513c18be77c9881c7107d2ab5569d205a6a0f0e6dc7d"
|
||||||
"checksum redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "c214e91d3ecf43e9a4e41e578973adeb14b474f2bee858742d127af75a0112b1"
|
"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
|
||||||
|
"checksum redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)" = "423e376fffca3dfa06c9e9790a9ccd282fafb3cc6e6397d01dbf64f9bacc6b85"
|
||||||
"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 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.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7153dd96dade874ab973e098cb62fcdbb89a03682e46b144fd09550998d4a4a7"
|
"checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7"
|
||||||
"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27"
|
"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27"
|
||||||
"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
|
"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
|
||||||
"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
||||||
"checksum serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)" = "84257ccd054dc351472528c8587b4de2dbf0dc0fe2e634030c1a90bfdacebaa9"
|
"checksum serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)" = "534b8b91a95e0f71bca3ed5824752d558da048d4248c91af873b63bd60519752"
|
||||||
"checksum serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)" = "31569d901045afbff7a9479f793177fe9259819aff10ab4f89ef69bbc5f567fe"
|
"checksum serde_derive 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)" = "a915306b0f1ac5607797697148c223bedeaa36bcc2e28a01441cd638cc6567b4"
|
||||||
"checksum serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)" = "43344e7ce05d0d8280c5940cabb4964bea626aa58b1ec0e8c73fa2a8512a38ce"
|
"checksum serde_json 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)" = "4b90a9fbe1211e57d3e1c15670f1cb00802988fb23a1a4aad7a2b63544f1920e"
|
||||||
|
"checksum smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "88aea073965ab29f6edb5493faf96ad662fb18aa9eeb186a3b7057951605ed15"
|
||||||
|
"checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8"
|
||||||
"checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550"
|
"checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550"
|
||||||
"checksum structopt 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "670ad348dc73012fcf78c71f06f9d942232cdd4c859d4b6975e27836c3efc0c3"
|
"checksum structopt 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "670ad348dc73012fcf78c71f06f9d942232cdd4c859d4b6975e27836c3efc0c3"
|
||||||
"checksum structopt-derive 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "ef98172b1a00b0bec738508d3726540edcbd186d50dfd326f2b1febbb3559f04"
|
"checksum structopt-derive 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "ef98172b1a00b0bec738508d3726540edcbd186d50dfd326f2b1febbb3559f04"
|
||||||
"checksum syn 0.15.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b10ee269228fb723234fce98e9aac0eaed2bd5f1ad2f6930e8d5b93f04445a1a"
|
"checksum syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)" = "f92e629aa1d9c827b2bb8297046c1ccffc57c99b947a680d3ccff1f136a3bee9"
|
||||||
"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 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 time 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "847da467bf0db05882a9e2375934a8a55cffdc9db0d128af1518200260ba1f6c"
|
"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f"
|
||||||
"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"
|
||||||
"checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526"
|
"checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526"
|
||||||
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
|
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
|
||||||
|
"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56"
|
||||||
"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
|
"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
|
||||||
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
|
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
|
||||||
"checksum wabt 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff1f0f87e467255240c1faf5cf13a04410723407840d7733e75967224e191a5"
|
"checksum wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "74e463a508e390cc7447e70f640fbf44ad52e1bd095314ace1fdf99516d32add"
|
||||||
"checksum wabt-sys 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0cc8982bfe0a923f152e96d991e50a6f97fe73ca4af6d9d84d76634f03051fa2"
|
"checksum wabt-sys 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a6265b25719e82598d104b3717375e37661d41753e2c84cde3f51050c7ed7e3c"
|
||||||
"checksum wasmparser 0.22.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f46e666ecb4a406483a59a49f9d0c17f327e70da53a128eccddae2eadb95865c"
|
"checksum wasmparser 0.22.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f46e666ecb4a406483a59a49f9d0c17f327e70da53a128eccddae2eadb95865c"
|
||||||
"checksum wasmparser 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b5e01c420bc7d36e778bd242e1167b079562ba8b34087122cc9057187026d060"
|
"checksum wasmparser 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b5e01c420bc7d36e778bd242e1167b079562ba8b34087122cc9057187026d060"
|
||||||
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
|
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
|
||||||
|
@ -3,6 +3,9 @@
|
|||||||
<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/"><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://github.com/wasmerio/wasmer/blob/master/LICENSE"><img src="https://img.shields.io/github/license/wasmerio/wasmer.svg" alt="License"></a>
|
||||||
|
<a href="https://spectrum.chat/wasmer">
|
||||||
|
<img alt="Join the Wasmer Community" src="https://withspectrum.github.io/badge/badge.svg" />
|
||||||
|
</a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
## Introduction
|
## Introduction
|
||||||
|
@ -6,6 +6,7 @@ pub use self::recovery::{call_protected, HandlerData};
|
|||||||
use crate::trampoline::Trampolines;
|
use crate::trampoline::Trampolines;
|
||||||
|
|
||||||
use hashbrown::HashSet;
|
use hashbrown::HashSet;
|
||||||
|
use std::sync::Arc;
|
||||||
use wasmer_runtime_core::{
|
use wasmer_runtime_core::{
|
||||||
backend::{ProtectedCaller, Token},
|
backend::{ProtectedCaller, Token},
|
||||||
error::RuntimeResult,
|
error::RuntimeResult,
|
||||||
@ -62,11 +63,14 @@ impl ProtectedCaller for Caller {
|
|||||||
assert!(self.func_export_set.contains(&func_index));
|
assert!(self.func_export_set.contains(&func_index));
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
signature.returns.len() <= 1,
|
signature.returns().len() <= 1,
|
||||||
"multi-value returns not yet supported"
|
"multi-value returns not yet supported"
|
||||||
);
|
);
|
||||||
|
|
||||||
assert!(signature.check_sig(params), "incorrect signature");
|
assert!(
|
||||||
|
signature.check_param_value_types(params),
|
||||||
|
"incorrect signature"
|
||||||
|
);
|
||||||
|
|
||||||
let param_vec: Vec<u64> = params
|
let param_vec: Vec<u64> = params
|
||||||
.iter()
|
.iter()
|
||||||
@ -78,7 +82,7 @@ impl ProtectedCaller for Caller {
|
|||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let mut return_vec = vec![0; signature.returns.len()];
|
let mut return_vec = vec![0; signature.returns().len()];
|
||||||
|
|
||||||
let trampoline = self
|
let trampoline = self
|
||||||
.trampolines
|
.trampolines
|
||||||
@ -97,7 +101,7 @@ impl ProtectedCaller for Caller {
|
|||||||
|
|
||||||
Ok(return_vec
|
Ok(return_vec
|
||||||
.iter()
|
.iter()
|
||||||
.zip(signature.returns.iter())
|
.zip(signature.returns().iter())
|
||||||
.map(|(&x, ty)| match ty {
|
.map(|(&x, ty)| match ty {
|
||||||
Type::I32 => Value::I32(x as i32),
|
Type::I32 => Value::I32(x as i32),
|
||||||
Type::I64 => Value::I64(x as i64),
|
Type::I64 => Value::I64(x as i64),
|
||||||
@ -108,11 +112,11 @@ impl ProtectedCaller for Caller {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_func_from_index<'a>(
|
fn get_func_from_index(
|
||||||
module: &'a ModuleInner,
|
module: &ModuleInner,
|
||||||
import_backing: &ImportBacking,
|
import_backing: &ImportBacking,
|
||||||
func_index: FuncIndex,
|
func_index: FuncIndex,
|
||||||
) -> (*const vm::Func, Context, &'a FuncSig, SigIndex) {
|
) -> (*const vm::Func, Context, Arc<FuncSig>, SigIndex) {
|
||||||
let sig_index = *module
|
let sig_index = *module
|
||||||
.func_assoc
|
.func_assoc
|
||||||
.get(func_index)
|
.get(func_index)
|
||||||
@ -137,7 +141,7 @@ fn get_func_from_index<'a>(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let signature = module.sig_registry.lookup_func_sig(sig_index);
|
let signature = module.sig_registry.lookup_signature(sig_index);
|
||||||
|
|
||||||
(func_ptr, ctx, signature, sig_index)
|
(func_ptr, ctx, signature, sig_index)
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,9 @@ thread_local! {
|
|||||||
pub static CURRENT_EXECUTABLE_BUFFER: Cell<*const c_void> = Cell::new(ptr::null());
|
pub static CURRENT_EXECUTABLE_BUFFER: Cell<*const c_void> = Cell::new(ptr::null());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe impl Send for HandlerData {}
|
||||||
|
unsafe impl Sync for HandlerData {}
|
||||||
|
|
||||||
pub struct HandlerData {
|
pub struct HandlerData {
|
||||||
trap_data: TrapSink,
|
trap_data: TrapSink,
|
||||||
buffer_ptr: *const c_void,
|
buffer_ptr: *const c_void,
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
use crate::{module::Converter, module_env::ModuleEnv};
|
use crate::{module::Converter, module_env::ModuleEnv, relocation::call_names};
|
||||||
use cranelift_codegen::{
|
use cranelift_codegen::{
|
||||||
cursor::FuncCursor,
|
cursor::FuncCursor,
|
||||||
ir::{self, InstBuilder},
|
ir::{self, InstBuilder},
|
||||||
isa,
|
isa,
|
||||||
};
|
};
|
||||||
use cranelift_wasm::{self, FuncEnvironment, ModuleEnvironment};
|
use cranelift_wasm::{self, FuncEnvironment, ModuleEnvironment};
|
||||||
|
use std::mem;
|
||||||
use wasmer_runtime_core::{
|
use wasmer_runtime_core::{
|
||||||
memory::LinearMemory,
|
memory::MemoryType,
|
||||||
structures::TypedIndex,
|
structures::TypedIndex,
|
||||||
types::{FuncIndex, GlobalIndex, LocalOrImport, MemoryIndex, TableIndex},
|
types::{FuncIndex, GlobalIndex, LocalOrImport, MemoryIndex, TableIndex},
|
||||||
vm,
|
vm,
|
||||||
@ -22,9 +23,12 @@ impl<'env, 'module, 'isa> FuncEnv<'env, 'module, 'isa> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a signature with VMContext as the last param
|
/// Creates a signature with VMContext as the last param
|
||||||
pub fn generate_signature(&self, sig_index: cranelift_wasm::SignatureIndex) -> ir::Signature {
|
pub fn generate_signature(
|
||||||
|
&self,
|
||||||
|
clif_sig_index: cranelift_wasm::SignatureIndex,
|
||||||
|
) -> ir::Signature {
|
||||||
// Get signature
|
// Get signature
|
||||||
let mut signature = self.env.signatures[Converter(sig_index).into()].clone();
|
let mut signature = self.env.signatures[Converter(clif_sig_index).into()].clone();
|
||||||
|
|
||||||
// Add the vmctx parameter type to it
|
// Add the vmctx parameter type to it
|
||||||
signature.params.push(ir::AbiParam::special(
|
signature.params.push(ir::AbiParam::special(
|
||||||
@ -70,59 +74,59 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
|||||||
let vmctx = func.create_global_value(ir::GlobalValueData::VMContext);
|
let vmctx = func.create_global_value(ir::GlobalValueData::VMContext);
|
||||||
let ptr_type = self.pointer_type();
|
let ptr_type = self.pointer_type();
|
||||||
|
|
||||||
match global_index.local_or_import(self.env.module) {
|
let local_global_addr = match global_index.local_or_import(self.env.module) {
|
||||||
LocalOrImport::Local(local_global_index) => {
|
LocalOrImport::Local(local_global_index) => {
|
||||||
let globals_base_addr = func.create_global_value(ir::GlobalValueData::Load {
|
let globals_base_addr = func.create_global_value(ir::GlobalValueData::Load {
|
||||||
base: vmctx,
|
base: vmctx,
|
||||||
offset: (vm::Ctx::offset_globals() as i32).into(),
|
offset: (vm::Ctx::offset_globals() as i32).into(),
|
||||||
global_type: self.pointer_type(),
|
global_type: ptr_type,
|
||||||
readonly: true,
|
readonly: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
let offset = local_global_index.index() * vm::LocalGlobal::size() as usize;
|
let offset = local_global_index.index() * mem::size_of::<*mut vm::LocalGlobal>();
|
||||||
|
|
||||||
let local_global_addr = func.create_global_value(ir::GlobalValueData::IAddImm {
|
let local_global_ptr_ptr = func.create_global_value(ir::GlobalValueData::IAddImm {
|
||||||
base: globals_base_addr,
|
base: globals_base_addr,
|
||||||
offset: (offset as i64).into(),
|
offset: (offset as i64).into(),
|
||||||
global_type: ptr_type,
|
global_type: ptr_type,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Create global variable based on the data above.
|
func.create_global_value(ir::GlobalValueData::Load {
|
||||||
cranelift_wasm::GlobalVariable::Memory {
|
base: local_global_ptr_ptr,
|
||||||
gv: local_global_addr,
|
offset: 0.into(),
|
||||||
offset: (vm::LocalGlobal::offset_data() as i32).into(),
|
|
||||||
ty: self.env.get_global(clif_global_index).ty,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LocalOrImport::Import(imported_global_index) => {
|
|
||||||
let imported_globals_base_addr =
|
|
||||||
func.create_global_value(ir::GlobalValueData::Load {
|
|
||||||
base: vmctx,
|
|
||||||
offset: (vm::Ctx::offset_imported_globals() as i32).into(),
|
|
||||||
global_type: ptr_type,
|
|
||||||
readonly: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
let offset = imported_global_index.index() * vm::ImportedGlobal::size() as usize;
|
|
||||||
let imported_global_addr = func.create_global_value(ir::GlobalValueData::IAddImm {
|
|
||||||
base: imported_globals_base_addr,
|
|
||||||
offset: (offset as i64).into(),
|
|
||||||
global_type: ptr_type,
|
global_type: ptr_type,
|
||||||
});
|
readonly: true,
|
||||||
|
})
|
||||||
let local_global_addr = func.create_global_value(ir::GlobalValueData::Load {
|
}
|
||||||
base: imported_global_addr,
|
LocalOrImport::Import(import_global_index) => {
|
||||||
offset: (vm::ImportedGlobal::offset_global() as i32).into(),
|
let globals_base_addr = func.create_global_value(ir::GlobalValueData::Load {
|
||||||
|
base: vmctx,
|
||||||
|
offset: (vm::Ctx::offset_imported_globals() as i32).into(),
|
||||||
global_type: ptr_type,
|
global_type: ptr_type,
|
||||||
readonly: true,
|
readonly: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
cranelift_wasm::GlobalVariable::Memory {
|
let offset = import_global_index.index() * mem::size_of::<*mut vm::LocalGlobal>();
|
||||||
gv: local_global_addr,
|
|
||||||
offset: (vm::LocalGlobal::offset_data() as i32).into(),
|
let local_global_ptr_ptr = func.create_global_value(ir::GlobalValueData::IAddImm {
|
||||||
ty: self.env.get_global(clif_global_index).ty,
|
base: globals_base_addr,
|
||||||
}
|
offset: (offset as i64).into(),
|
||||||
|
global_type: ptr_type,
|
||||||
|
});
|
||||||
|
|
||||||
|
func.create_global_value(ir::GlobalValueData::Load {
|
||||||
|
base: local_global_ptr_ptr,
|
||||||
|
offset: 0.into(),
|
||||||
|
global_type: ptr_type,
|
||||||
|
readonly: true,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
cranelift_wasm::GlobalVariable::Memory {
|
||||||
|
gv: local_global_addr,
|
||||||
|
offset: (vm::LocalGlobal::offset_data() as i32).into(),
|
||||||
|
ty: self.env.get_global(clif_global_index).ty,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,7 +144,7 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
|||||||
let vmctx = func.create_global_value(ir::GlobalValueData::VMContext);
|
let vmctx = func.create_global_value(ir::GlobalValueData::VMContext);
|
||||||
let ptr_type = self.pointer_type();
|
let ptr_type = self.pointer_type();
|
||||||
|
|
||||||
match mem_index.local_or_import(self.env.module) {
|
let (local_memory_ptr_ptr, description) = match mem_index.local_or_import(self.env.module) {
|
||||||
LocalOrImport::Local(local_mem_index) => {
|
LocalOrImport::Local(local_mem_index) => {
|
||||||
let memories_base_addr = func.create_global_value(ir::GlobalValueData::Load {
|
let memories_base_addr = func.create_global_value(ir::GlobalValueData::Load {
|
||||||
base: vmctx,
|
base: vmctx,
|
||||||
@ -149,75 +153,88 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
|||||||
readonly: true,
|
readonly: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
let memory_offset = local_mem_index.index() * vm::LocalMemory::size() as usize;
|
let local_memory_ptr_offset =
|
||||||
|
local_mem_index.index() * mem::size_of::<*mut vm::LocalMemory>();
|
||||||
|
|
||||||
let memory_struct_addr = func.create_global_value(ir::GlobalValueData::IAddImm {
|
(
|
||||||
base: memories_base_addr,
|
func.create_global_value(ir::GlobalValueData::IAddImm {
|
||||||
offset: (memory_offset as i64).into(),
|
base: memories_base_addr,
|
||||||
global_type: ptr_type,
|
offset: (local_memory_ptr_offset as i64).into(),
|
||||||
});
|
global_type: ptr_type,
|
||||||
|
}),
|
||||||
let memory_base_addr = func.create_global_value(ir::GlobalValueData::Load {
|
self.env.module.memories[local_mem_index],
|
||||||
base: memory_struct_addr,
|
)
|
||||||
offset: (vm::LocalMemory::offset_base() as i32).into(),
|
|
||||||
global_type: ptr_type,
|
|
||||||
readonly: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
func.create_heap(ir::HeapData {
|
|
||||||
base: memory_base_addr,
|
|
||||||
min_size: (self.env.module.memories[local_mem_index].min as u64).into(),
|
|
||||||
offset_guard_size: (LinearMemory::DEFAULT_GUARD_SIZE as u64).into(),
|
|
||||||
style: ir::HeapStyle::Static {
|
|
||||||
bound: (LinearMemory::DEFAULT_HEAP_SIZE as u64).into(),
|
|
||||||
},
|
|
||||||
index_type: ir::types::I32,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
LocalOrImport::Import(imported_mem_index) => {
|
LocalOrImport::Import(import_mem_index) => {
|
||||||
let imported_memories_base = func.create_global_value(ir::GlobalValueData::Load {
|
let memories_base_addr = func.create_global_value(ir::GlobalValueData::Load {
|
||||||
base: vmctx,
|
base: vmctx,
|
||||||
offset: (vm::Ctx::offset_imported_memories() as i32).into(),
|
offset: (vm::Ctx::offset_imported_memories() as i32).into(),
|
||||||
global_type: ptr_type,
|
global_type: ptr_type,
|
||||||
readonly: true,
|
readonly: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
let imported_memory_offset =
|
let local_memory_ptr_offset =
|
||||||
imported_mem_index.index() * vm::ImportedMemory::size() as usize;
|
import_mem_index.index() * mem::size_of::<*mut vm::LocalMemory>();
|
||||||
|
|
||||||
let imported_memory_struct_addr =
|
(
|
||||||
func.create_global_value(ir::GlobalValueData::IAddImm {
|
func.create_global_value(ir::GlobalValueData::IAddImm {
|
||||||
base: imported_memories_base,
|
base: memories_base_addr,
|
||||||
offset: (imported_memory_offset as i64).into(),
|
offset: (local_memory_ptr_offset as i64).into(),
|
||||||
global_type: ptr_type,
|
global_type: ptr_type,
|
||||||
});
|
}),
|
||||||
|
self.env.module.imported_memories[import_mem_index].1,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let local_memory_struct_addr =
|
let (local_memory_ptr, local_memory_base) = {
|
||||||
func.create_global_value(ir::GlobalValueData::Load {
|
let local_memory_ptr = func.create_global_value(ir::GlobalValueData::Load {
|
||||||
base: imported_memory_struct_addr,
|
base: local_memory_ptr_ptr,
|
||||||
offset: (vm::ImportedMemory::offset_memory() as i32).into(),
|
offset: 0.into(),
|
||||||
global_type: ptr_type,
|
global_type: ptr_type,
|
||||||
readonly: true,
|
readonly: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
let local_memory_base = func.create_global_value(ir::GlobalValueData::Load {
|
(
|
||||||
base: local_memory_struct_addr,
|
local_memory_ptr,
|
||||||
|
func.create_global_value(ir::GlobalValueData::Load {
|
||||||
|
base: local_memory_ptr,
|
||||||
offset: (vm::LocalMemory::offset_base() as i32).into(),
|
offset: (vm::LocalMemory::offset_base() as i32).into(),
|
||||||
global_type: ptr_type,
|
global_type: ptr_type,
|
||||||
readonly: true,
|
readonly: false,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
match description.memory_type() {
|
||||||
|
mem_type @ MemoryType::Dynamic => {
|
||||||
|
let local_memory_bound = func.create_global_value(ir::GlobalValueData::Load {
|
||||||
|
base: local_memory_ptr,
|
||||||
|
offset: (vm::LocalMemory::offset_bound() as i32).into(),
|
||||||
|
global_type: ptr_type,
|
||||||
|
readonly: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
func.create_heap(ir::HeapData {
|
func.create_heap(ir::HeapData {
|
||||||
base: local_memory_base,
|
base: local_memory_base,
|
||||||
min_size: (self.env.module.imported_memories[imported_mem_index].1.min as u64)
|
min_size: (description.minimum.bytes().0 as u64).into(),
|
||||||
.into(),
|
offset_guard_size: mem_type.guard_size().into(),
|
||||||
offset_guard_size: (LinearMemory::DEFAULT_GUARD_SIZE as u64).into(),
|
style: ir::HeapStyle::Dynamic {
|
||||||
style: ir::HeapStyle::Static {
|
bound_gv: local_memory_bound,
|
||||||
bound: (LinearMemory::DEFAULT_HEAP_SIZE as u64).into(),
|
|
||||||
},
|
},
|
||||||
index_type: ir::types::I32,
|
index_type: ir::types::I32,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
mem_type @ MemoryType::Static | mem_type @ MemoryType::SharedStatic => func
|
||||||
|
.create_heap(ir::HeapData {
|
||||||
|
base: local_memory_base,
|
||||||
|
min_size: (description.minimum.bytes().0 as u64).into(),
|
||||||
|
offset_guard_size: mem_type.guard_size().into(),
|
||||||
|
style: ir::HeapStyle::Static {
|
||||||
|
bound: mem_type.bounds().unwrap().into(),
|
||||||
|
},
|
||||||
|
index_type: ir::types::I32,
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -235,7 +252,8 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
|||||||
let vmctx = func.create_global_value(ir::GlobalValueData::VMContext);
|
let vmctx = func.create_global_value(ir::GlobalValueData::VMContext);
|
||||||
let ptr_type = self.pointer_type();
|
let ptr_type = self.pointer_type();
|
||||||
|
|
||||||
match table_index.local_or_import(self.env.module) {
|
let (table_struct_ptr_ptr, description) = match table_index.local_or_import(self.env.module)
|
||||||
|
{
|
||||||
LocalOrImport::Local(local_table_index) => {
|
LocalOrImport::Local(local_table_index) => {
|
||||||
let tables_base = func.create_global_value(ir::GlobalValueData::Load {
|
let tables_base = func.create_global_value(ir::GlobalValueData::Load {
|
||||||
base: vmctx,
|
base: vmctx,
|
||||||
@ -244,88 +262,74 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
|||||||
readonly: true,
|
readonly: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
let table_struct_offset =
|
let table_struct_ptr_offset =
|
||||||
local_table_index.index() * vm::LocalTable::size() as usize;
|
local_table_index.index() * vm::LocalTable::size() as usize;
|
||||||
|
|
||||||
let table_struct_addr = func.create_global_value(ir::GlobalValueData::IAddImm {
|
let table_struct_ptr_ptr = func.create_global_value(ir::GlobalValueData::IAddImm {
|
||||||
base: tables_base,
|
base: tables_base,
|
||||||
offset: (table_struct_offset as i64).into(),
|
offset: (table_struct_ptr_offset as i64).into(),
|
||||||
global_type: ptr_type,
|
global_type: ptr_type,
|
||||||
});
|
});
|
||||||
|
|
||||||
let table_base = func.create_global_value(ir::GlobalValueData::Load {
|
(
|
||||||
base: table_struct_addr,
|
table_struct_ptr_ptr,
|
||||||
offset: (vm::LocalTable::offset_base() as i32).into(),
|
self.env.module.tables[local_table_index],
|
||||||
global_type: ptr_type,
|
)
|
||||||
// we will support growing tables, so this cannot be readonly.
|
|
||||||
readonly: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
let table_bound = func.create_global_value(ir::GlobalValueData::Load {
|
|
||||||
base: table_struct_addr,
|
|
||||||
offset: (vm::LocalTable::offset_current_elements() as i32).into(),
|
|
||||||
// the number of elements in a table will always fit in an `i32`.
|
|
||||||
global_type: ir::types::I32,
|
|
||||||
readonly: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
func.create_table(ir::TableData {
|
|
||||||
base_gv: table_base,
|
|
||||||
min_size: (self.env.module.tables[local_table_index].min as u64).into(),
|
|
||||||
bound_gv: table_bound,
|
|
||||||
element_size: (vm::Anyfunc::size() as u64).into(),
|
|
||||||
index_type: ir::types::I32,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
LocalOrImport::Import(imported_table_index) => {
|
LocalOrImport::Import(import_table_index) => {
|
||||||
let imported_tables_base = func.create_global_value(ir::GlobalValueData::Load {
|
let tables_base = func.create_global_value(ir::GlobalValueData::Load {
|
||||||
base: vmctx,
|
base: vmctx,
|
||||||
offset: (vm::Ctx::offset_imported_tables() as i32).into(),
|
offset: (vm::Ctx::offset_imported_tables() as i32).into(),
|
||||||
global_type: ptr_type,
|
global_type: ptr_type,
|
||||||
readonly: true,
|
readonly: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
let imported_table_struct_offset =
|
let table_struct_ptr_offset =
|
||||||
imported_table_index.index() * vm::ImportedTable::size() as usize;
|
import_table_index.index() * vm::LocalTable::size() as usize;
|
||||||
|
|
||||||
let imported_table_struct_addr =
|
let table_struct_ptr_ptr = func.create_global_value(ir::GlobalValueData::IAddImm {
|
||||||
func.create_global_value(ir::GlobalValueData::IAddImm {
|
base: tables_base,
|
||||||
base: imported_tables_base,
|
offset: (table_struct_ptr_offset as i64).into(),
|
||||||
offset: (imported_table_struct_offset as i64).into(),
|
|
||||||
global_type: ptr_type,
|
|
||||||
});
|
|
||||||
|
|
||||||
let local_table_struct_addr = func.create_global_value(ir::GlobalValueData::Load {
|
|
||||||
base: imported_table_struct_addr,
|
|
||||||
offset: (vm::ImportedTable::offset_table() as i32).into(),
|
|
||||||
global_type: ptr_type,
|
global_type: ptr_type,
|
||||||
readonly: true,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
let local_table_base = func.create_global_value(ir::GlobalValueData::Load {
|
(
|
||||||
base: local_table_struct_addr,
|
table_struct_ptr_ptr,
|
||||||
offset: (vm::LocalTable::offset_base() as i32).into(),
|
self.env.module.imported_tables[import_table_index].1,
|
||||||
global_type: ptr_type,
|
)
|
||||||
readonly: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
let local_table_bound = func.create_global_value(ir::GlobalValueData::Load {
|
|
||||||
base: local_table_struct_addr,
|
|
||||||
offset: (vm::LocalTable::offset_current_elements() as i32).into(),
|
|
||||||
global_type: ir::types::I32,
|
|
||||||
readonly: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
func.create_table(ir::TableData {
|
|
||||||
base_gv: local_table_base,
|
|
||||||
min_size: (self.env.module.imported_tables[imported_table_index].1.min as u64)
|
|
||||||
.into(),
|
|
||||||
bound_gv: local_table_bound,
|
|
||||||
element_size: (vm::Anyfunc::size() as u64).into(),
|
|
||||||
index_type: ir::types::I32,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
|
let table_struct_ptr = func.create_global_value(ir::GlobalValueData::Load {
|
||||||
|
base: table_struct_ptr_ptr,
|
||||||
|
offset: 0.into(),
|
||||||
|
global_type: ptr_type,
|
||||||
|
readonly: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
let table_base = func.create_global_value(ir::GlobalValueData::Load {
|
||||||
|
base: table_struct_ptr,
|
||||||
|
offset: (vm::LocalTable::offset_base() as i32).into(),
|
||||||
|
global_type: ptr_type,
|
||||||
|
// The table can reallocate, so the ptr can't be readonly.
|
||||||
|
readonly: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
let table_count = func.create_global_value(ir::GlobalValueData::Load {
|
||||||
|
base: table_struct_ptr,
|
||||||
|
offset: (vm::LocalTable::offset_count() as i32).into(),
|
||||||
|
global_type: ptr_type,
|
||||||
|
// The table length can change, so it can't be readonly.
|
||||||
|
readonly: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
func.create_table(ir::TableData {
|
||||||
|
base_gv: table_base,
|
||||||
|
min_size: (description.minimum as u64).into(),
|
||||||
|
bound_gv: table_count,
|
||||||
|
element_size: (vm::Anyfunc::size() as u64).into(),
|
||||||
|
index_type: ir::types::I32,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets up a signature definition in `func`'s preamble.
|
/// Sets up a signature definition in `func`'s preamble.
|
||||||
@ -335,10 +339,10 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
|||||||
fn make_indirect_sig(
|
fn make_indirect_sig(
|
||||||
&mut self,
|
&mut self,
|
||||||
func: &mut ir::Function,
|
func: &mut ir::Function,
|
||||||
index: cranelift_wasm::SignatureIndex,
|
clif_sig_index: cranelift_wasm::SignatureIndex,
|
||||||
) -> ir::SigRef {
|
) -> ir::SigRef {
|
||||||
// Create a signature reference out of specified signature (with VMContext param added).
|
// Create a signature reference out of specified signature (with VMContext param added).
|
||||||
func.import_signature(self.generate_signature(index))
|
func.import_signature(self.generate_signature(clif_sig_index))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets up an external function definition in the preamble of `func` that can be used to
|
/// Sets up an external function definition in the preamble of `func` that can be used to
|
||||||
@ -377,7 +381,7 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
|||||||
mut pos: FuncCursor,
|
mut pos: FuncCursor,
|
||||||
_table_index: cranelift_wasm::TableIndex,
|
_table_index: cranelift_wasm::TableIndex,
|
||||||
table: ir::Table,
|
table: ir::Table,
|
||||||
sig_index: cranelift_wasm::SignatureIndex,
|
clif_sig_index: cranelift_wasm::SignatureIndex,
|
||||||
sig_ref: ir::SigRef,
|
sig_ref: ir::SigRef,
|
||||||
callee: ir::Value,
|
callee: ir::Value,
|
||||||
call_args: &[ir::Value],
|
call_args: &[ir::Value],
|
||||||
@ -396,12 +400,25 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
|||||||
entry_addr,
|
entry_addr,
|
||||||
vm::Anyfunc::offset_func() as i32,
|
vm::Anyfunc::offset_func() as i32,
|
||||||
);
|
);
|
||||||
let vmctx_ptr = pos.ins().load(
|
|
||||||
ptr_type,
|
let vmctx_ptr = {
|
||||||
mflags,
|
let loaded_vmctx_ptr = pos.ins().load(
|
||||||
entry_addr,
|
ptr_type,
|
||||||
vm::Anyfunc::offset_vmctx() as i32,
|
mflags,
|
||||||
);
|
entry_addr,
|
||||||
|
vm::Anyfunc::offset_vmctx() as i32,
|
||||||
|
);
|
||||||
|
|
||||||
|
let argument_vmctx_ptr = pos
|
||||||
|
.func
|
||||||
|
.special_param(ir::ArgumentPurpose::VMContext)
|
||||||
|
.expect("missing vmctx parameter");
|
||||||
|
|
||||||
|
// If the loaded vmctx ptr is zero, use the caller vmctx, else use the callee (loaded) vmctx.
|
||||||
|
pos.ins()
|
||||||
|
.select(loaded_vmctx_ptr, loaded_vmctx_ptr, argument_vmctx_ptr)
|
||||||
|
};
|
||||||
|
|
||||||
let found_sig = pos.ins().load(
|
let found_sig = pos.ins().load(
|
||||||
ir::types::I32,
|
ir::types::I32,
|
||||||
mflags,
|
mflags,
|
||||||
@ -411,14 +428,9 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
|||||||
|
|
||||||
pos.ins().trapz(func_ptr, ir::TrapCode::IndirectCallToNull);
|
pos.ins().trapz(func_ptr, ir::TrapCode::IndirectCallToNull);
|
||||||
|
|
||||||
let deduplicated_sig_index = self
|
let sig_index = self.env.deduplicated[clif_sig_index];
|
||||||
.env
|
|
||||||
.module
|
let expected_sig = pos.ins().iconst(ir::types::I32, sig_index.index() as i64);
|
||||||
.sig_registry
|
|
||||||
.lookup_deduplicated_sigindex(Converter(sig_index).into());
|
|
||||||
let expected_sig = pos
|
|
||||||
.ins()
|
|
||||||
.iconst(ir::types::I32, deduplicated_sig_index.index() as i64);
|
|
||||||
let not_equal_flags = pos.ins().ifcmp(found_sig, expected_sig);
|
let not_equal_flags = pos.ins().ifcmp(found_sig, expected_sig);
|
||||||
|
|
||||||
pos.ins().trapif(
|
pos.ins().trapif(
|
||||||
@ -539,23 +551,27 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
|||||||
|
|
||||||
let mem_index: MemoryIndex = Converter(clif_mem_index).into();
|
let mem_index: MemoryIndex = Converter(clif_mem_index).into();
|
||||||
|
|
||||||
let (name, mem_index) = match mem_index.local_or_import(self.env.module) {
|
let (namespace, mem_index, description) = match mem_index.local_or_import(self.env.module) {
|
||||||
LocalOrImport::Local(local_mem_index) => {
|
LocalOrImport::Local(local_mem_index) => (
|
||||||
(
|
call_names::LOCAL_NAMESPACE,
|
||||||
// local_static_memory_grow
|
local_mem_index.index(),
|
||||||
ir::ExternalName::user(1, 0),
|
self.env.module.memories[local_mem_index],
|
||||||
local_mem_index.index(),
|
),
|
||||||
)
|
LocalOrImport::Import(import_mem_index) => (
|
||||||
}
|
call_names::IMPORT_NAMESPACE,
|
||||||
LocalOrImport::Import(imported_mem_index) => {
|
import_mem_index.index(),
|
||||||
(
|
self.env.module.imported_memories[import_mem_index].1,
|
||||||
// imported_static_memory_grow
|
),
|
||||||
ir::ExternalName::user(1, 2),
|
|
||||||
imported_mem_index.index(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let name_index = match description.memory_type() {
|
||||||
|
MemoryType::Dynamic => call_names::DYNAMIC_MEM_GROW,
|
||||||
|
MemoryType::Static => call_names::STATIC_MEM_GROW,
|
||||||
|
MemoryType::SharedStatic => call_names::SHARED_STATIC_MEM_GROW,
|
||||||
|
};
|
||||||
|
|
||||||
|
let name = ir::ExternalName::user(namespace, name_index);
|
||||||
|
|
||||||
let mem_grow_func = pos.func.import_function(ir::ExtFuncData {
|
let mem_grow_func = pos.func.import_function(ir::ExtFuncData {
|
||||||
name,
|
name,
|
||||||
signature,
|
signature,
|
||||||
@ -587,37 +603,6 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
|||||||
clif_mem_index: cranelift_wasm::MemoryIndex,
|
clif_mem_index: cranelift_wasm::MemoryIndex,
|
||||||
_heap: ir::Heap,
|
_heap: ir::Heap,
|
||||||
) -> cranelift_wasm::WasmResult<ir::Value> {
|
) -> cranelift_wasm::WasmResult<ir::Value> {
|
||||||
// let signature = pos.func.import_signature(ir::Signature {
|
|
||||||
// call_conv: self.target_config().default_call_conv,
|
|
||||||
// params: vec![
|
|
||||||
// ir::AbiParam::new(ir::types::I32),
|
|
||||||
// ir::AbiParam::special(self.pointer_type(), ir::ArgumentPurpose::VMContext),
|
|
||||||
// ],
|
|
||||||
// returns: vec![ir::AbiParam::new(ir::types::I32)],
|
|
||||||
// });
|
|
||||||
|
|
||||||
// let size_mem_func = pos.func.import_function(ir::ExtFuncData {
|
|
||||||
// // `ir::ExternalName` for static_grow_memory`
|
|
||||||
// name: ir::ExternalName::user(1, 1),
|
|
||||||
// signature,
|
|
||||||
// colocated: false,
|
|
||||||
// });
|
|
||||||
|
|
||||||
// // Create a memory index value.
|
|
||||||
// let memory_index = pos.ins().iconst(ir::types::I32, index.index() as i64);
|
|
||||||
|
|
||||||
// // Create a VMContext value.
|
|
||||||
// let vmctx = pos
|
|
||||||
// .func
|
|
||||||
// .special_param(ir::ArgumentPurpose::VMContext)
|
|
||||||
// .expect("missing vmctx parameter");
|
|
||||||
|
|
||||||
// // Insert call instructions for `grow_memory`.
|
|
||||||
// let call_inst = pos.ins().call(size_mem_func, &[memory_index, vmctx]);
|
|
||||||
|
|
||||||
// // Return value.
|
|
||||||
// Ok(*pos.func.dfg.inst_results(call_inst).first().unwrap())
|
|
||||||
|
|
||||||
let signature = pos.func.import_signature(ir::Signature {
|
let signature = pos.func.import_signature(ir::Signature {
|
||||||
call_conv: self.target_config().default_call_conv,
|
call_conv: self.target_config().default_call_conv,
|
||||||
params: vec![
|
params: vec![
|
||||||
@ -629,23 +614,27 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
|||||||
|
|
||||||
let mem_index: MemoryIndex = Converter(clif_mem_index).into();
|
let mem_index: MemoryIndex = Converter(clif_mem_index).into();
|
||||||
|
|
||||||
let (name, mem_index) = match mem_index.local_or_import(self.env.module) {
|
let (namespace, mem_index, description) = match mem_index.local_or_import(self.env.module) {
|
||||||
LocalOrImport::Local(local_mem_index) => {
|
LocalOrImport::Local(local_mem_index) => (
|
||||||
(
|
call_names::LOCAL_NAMESPACE,
|
||||||
// local_static_memory_size
|
local_mem_index.index(),
|
||||||
ir::ExternalName::user(1, 1),
|
self.env.module.memories[local_mem_index],
|
||||||
local_mem_index.index(),
|
),
|
||||||
)
|
LocalOrImport::Import(import_mem_index) => (
|
||||||
}
|
call_names::IMPORT_NAMESPACE,
|
||||||
LocalOrImport::Import(imported_mem_index) => {
|
import_mem_index.index(),
|
||||||
(
|
self.env.module.imported_memories[import_mem_index].1,
|
||||||
// imported_static_memory_size
|
),
|
||||||
ir::ExternalName::user(1, 3),
|
|
||||||
imported_mem_index.index(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let name_index = match description.memory_type() {
|
||||||
|
MemoryType::Dynamic => call_names::DYNAMIC_MEM_SIZE,
|
||||||
|
MemoryType::Static => call_names::STATIC_MEM_SIZE,
|
||||||
|
MemoryType::SharedStatic => call_names::SHARED_STATIC_MEM_SIZE,
|
||||||
|
};
|
||||||
|
|
||||||
|
let name = ir::ExternalName::user(namespace, name_index);
|
||||||
|
|
||||||
let mem_grow_func = pos.func.import_function(ir::ExtFuncData {
|
let mem_grow_func = pos.func.import_function(ir::ExtFuncData {
|
||||||
name,
|
name,
|
||||||
signature,
|
signature,
|
||||||
|
@ -76,7 +76,7 @@ impl Module {
|
|||||||
start_func: None,
|
start_func: None,
|
||||||
|
|
||||||
func_assoc: Map::new(),
|
func_assoc: Map::new(),
|
||||||
sig_registry: SigRegistry::new(),
|
sig_registry: SigRegistry,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -86,15 +86,10 @@ impl Module {
|
|||||||
isa: &isa::TargetIsa,
|
isa: &isa::TargetIsa,
|
||||||
functions: Map<LocalFuncIndex, ir::Function>,
|
functions: Map<LocalFuncIndex, ir::Function>,
|
||||||
) -> CompileResult<ModuleInner> {
|
) -> CompileResult<ModuleInner> {
|
||||||
// we have to deduplicate `module.func_assoc`
|
|
||||||
let func_assoc = &mut self.module.func_assoc;
|
|
||||||
let sig_registry = &self.module.sig_registry;
|
|
||||||
func_assoc.iter_mut().for_each(|(_, sig_index)| {
|
|
||||||
*sig_index = sig_registry.lookup_deduplicated_sigindex(*sig_index);
|
|
||||||
});
|
|
||||||
let imported_functions_len = self.module.imported_functions.len();
|
let imported_functions_len = self.module.imported_functions.len();
|
||||||
let (func_resolver_builder, handler_data) =
|
let (func_resolver_builder, handler_data) =
|
||||||
FuncResolverBuilder::new(isa, functions, imported_functions_len)?;
|
FuncResolverBuilder::new(isa, functions, imported_functions_len)?;
|
||||||
|
|
||||||
self.module.func_resolver = Box::new(func_resolver_builder.finalize()?);
|
self.module.func_resolver = Box::new(func_resolver_builder.finalize()?);
|
||||||
|
|
||||||
let trampolines = Trampolines::new(isa, &self.module);
|
let trampolines = Trampolines::new(isa, &self.module);
|
||||||
@ -153,20 +148,20 @@ convert_clif_to_runtime_index![
|
|||||||
|
|
||||||
impl<'a> From<Converter<&'a ir::Signature>> for FuncSig {
|
impl<'a> From<Converter<&'a ir::Signature>> for FuncSig {
|
||||||
fn from(signature: Converter<&'a ir::Signature>) -> Self {
|
fn from(signature: Converter<&'a ir::Signature>) -> Self {
|
||||||
FuncSig {
|
FuncSig::new(
|
||||||
params: signature
|
signature
|
||||||
.0
|
.0
|
||||||
.params
|
.params
|
||||||
.iter()
|
.iter()
|
||||||
.map(|param| Converter(param.value_type).into())
|
.map(|param| Converter(param.value_type).into())
|
||||||
.collect(),
|
.collect::<Vec<_>>(),
|
||||||
returns: signature
|
signature
|
||||||
.0
|
.0
|
||||||
.returns
|
.returns
|
||||||
.iter()
|
.iter()
|
||||||
.map(|ret| Converter(ret.value_type).into())
|
.map(|ret| Converter(ret.value_type).into())
|
||||||
.collect(),
|
.collect::<Vec<_>>(),
|
||||||
}
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,15 +3,18 @@ use crate::{
|
|||||||
module::{Converter, Module},
|
module::{Converter, Module},
|
||||||
};
|
};
|
||||||
use cranelift_codegen::{ir, isa};
|
use cranelift_codegen::{ir, isa};
|
||||||
|
use cranelift_entity::PrimaryMap;
|
||||||
use cranelift_wasm::{self, translate_module, FuncTranslator, ModuleEnvironment};
|
use cranelift_wasm::{self, translate_module, FuncTranslator, ModuleEnvironment};
|
||||||
|
use hashbrown::HashMap;
|
||||||
use wasmer_runtime_core::{
|
use wasmer_runtime_core::{
|
||||||
error::{CompileError, CompileResult},
|
error::{CompileError, CompileResult},
|
||||||
module::{DataInitializer, ExportIndex, ImportName, TableInitializer},
|
module::{DataInitializer, ExportIndex, ImportName, TableInitializer},
|
||||||
structures::{Map, TypedIndex},
|
structures::{Map, TypedIndex},
|
||||||
types::{
|
types::{
|
||||||
ElementType, Global, GlobalDesc, GlobalIndex, Initializer, LocalFuncIndex, LocalOrImport,
|
ElementType, FuncSig, GlobalDescriptor, GlobalIndex, GlobalInit, Initializer,
|
||||||
Memory, SigIndex, Table, Value,
|
LocalFuncIndex, LocalOrImport, MemoryDescriptor, SigIndex, TableDescriptor, Value,
|
||||||
},
|
},
|
||||||
|
units::Pages,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct ModuleEnv<'module, 'isa> {
|
pub struct ModuleEnv<'module, 'isa> {
|
||||||
@ -20,6 +23,8 @@ pub struct ModuleEnv<'module, 'isa> {
|
|||||||
pub signatures: Map<SigIndex, ir::Signature>,
|
pub signatures: Map<SigIndex, ir::Signature>,
|
||||||
globals: Map<GlobalIndex, cranelift_wasm::Global>,
|
globals: Map<GlobalIndex, cranelift_wasm::Global>,
|
||||||
func_bodies: Map<LocalFuncIndex, ir::Function>,
|
func_bodies: Map<LocalFuncIndex, ir::Function>,
|
||||||
|
pub deduplicated: PrimaryMap<cranelift_wasm::SignatureIndex, SigIndex>,
|
||||||
|
duplicated: HashMap<SigIndex, cranelift_wasm::SignatureIndex>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'module, 'isa> ModuleEnv<'module, 'isa> {
|
impl<'module, 'isa> ModuleEnv<'module, 'isa> {
|
||||||
@ -30,6 +35,8 @@ impl<'module, 'isa> ModuleEnv<'module, 'isa> {
|
|||||||
signatures: Map::new(),
|
signatures: Map::new(),
|
||||||
globals: Map::new(),
|
globals: Map::new(),
|
||||||
func_bodies: Map::new(),
|
func_bodies: Map::new(),
|
||||||
|
deduplicated: PrimaryMap::new(),
|
||||||
|
duplicated: HashMap::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,23 +55,28 @@ impl<'module, 'isa, 'data> ModuleEnvironment<'data> for ModuleEnv<'module, 'isa>
|
|||||||
|
|
||||||
/// Declares a function signature to the environment.
|
/// Declares a function signature to the environment.
|
||||||
fn declare_signature(&mut self, sig: &ir::Signature) {
|
fn declare_signature(&mut self, sig: &ir::Signature) {
|
||||||
self.signatures.push(sig.clone());
|
let clif_sig_index = self.signatures.push(sig.clone());
|
||||||
self.module.sig_registry.register(Converter(sig).into());
|
let func_sig: FuncSig = Converter(sig).into();
|
||||||
|
let sig_index = self.module.sig_registry.lookup_sig_index(func_sig);
|
||||||
|
self.deduplicated.push(sig_index);
|
||||||
|
self.duplicated
|
||||||
|
.insert(sig_index, Converter(clif_sig_index).into());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the signature with the given index.
|
/// Return the signature with the given index.
|
||||||
fn get_signature(&self, sig_index: cranelift_wasm::SignatureIndex) -> &ir::Signature {
|
fn get_signature(&self, clif_sig_index: cranelift_wasm::SignatureIndex) -> &ir::Signature {
|
||||||
&self.signatures[Converter(sig_index).into()]
|
&self.signatures[Converter(clif_sig_index).into()]
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Declares a function import to the environment.
|
/// Declares a function import to the environment.
|
||||||
fn declare_func_import(
|
fn declare_func_import(
|
||||||
&mut self,
|
&mut self,
|
||||||
sig_index: cranelift_wasm::SignatureIndex,
|
clif_sig_index: cranelift_wasm::SignatureIndex,
|
||||||
namespace: &'data str,
|
namespace: &'data str,
|
||||||
name: &'data str,
|
name: &'data str,
|
||||||
) {
|
) {
|
||||||
self.module.func_assoc.push(Converter(sig_index).into());
|
let sig_index = self.deduplicated[clif_sig_index];
|
||||||
|
self.module.func_assoc.push(sig_index);
|
||||||
|
|
||||||
// Add import names to list of imported functions
|
// Add import names to list of imported functions
|
||||||
self.module.imported_functions.push(ImportName {
|
self.module.imported_functions.push(ImportName {
|
||||||
@ -79,8 +91,9 @@ impl<'module, 'isa, 'data> ModuleEnvironment<'data> for ModuleEnv<'module, 'isa>
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Declares the type (signature) of a local function in the module.
|
/// Declares the type (signature) of a local function in the module.
|
||||||
fn declare_func_type(&mut self, sig_index: cranelift_wasm::SignatureIndex) {
|
fn declare_func_type(&mut self, clif_sig_index: cranelift_wasm::SignatureIndex) {
|
||||||
self.module.func_assoc.push(Converter(sig_index).into());
|
let sig_index = self.deduplicated[clif_sig_index];
|
||||||
|
self.module.func_assoc.push(sig_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the signature index for the given function index.
|
/// Return the signature index for the given function index.
|
||||||
@ -88,25 +101,28 @@ impl<'module, 'isa, 'data> ModuleEnvironment<'data> for ModuleEnv<'module, 'isa>
|
|||||||
&self,
|
&self,
|
||||||
func_index: cranelift_wasm::FuncIndex,
|
func_index: cranelift_wasm::FuncIndex,
|
||||||
) -> cranelift_wasm::SignatureIndex {
|
) -> cranelift_wasm::SignatureIndex {
|
||||||
Converter(self.module.func_assoc[Converter(func_index).into()]).into()
|
let sig_index: SigIndex = self.module.func_assoc[Converter(func_index).into()];
|
||||||
|
self.duplicated[&sig_index]
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Declares a global to the environment.
|
/// Declares a global to the environment.
|
||||||
fn declare_global(&mut self, global: cranelift_wasm::Global) {
|
fn declare_global(&mut self, global: cranelift_wasm::Global) {
|
||||||
use cranelift_wasm::GlobalInit;
|
let desc = GlobalDescriptor {
|
||||||
|
|
||||||
let desc = GlobalDesc {
|
|
||||||
mutable: global.mutability,
|
mutable: global.mutability,
|
||||||
ty: Converter(global.ty).into(),
|
ty: Converter(global.ty).into(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let init = match global.initializer {
|
let init = match global.initializer {
|
||||||
GlobalInit::I32Const(x) => Initializer::Const(Value::I32(x)),
|
cranelift_wasm::GlobalInit::I32Const(x) => Initializer::Const(Value::I32(x)),
|
||||||
GlobalInit::I64Const(x) => Initializer::Const(Value::I64(x)),
|
cranelift_wasm::GlobalInit::I64Const(x) => Initializer::Const(Value::I64(x)),
|
||||||
GlobalInit::F32Const(x) => Initializer::Const(Value::F32(f32::from_bits(x))),
|
cranelift_wasm::GlobalInit::F32Const(x) => {
|
||||||
GlobalInit::F64Const(x) => Initializer::Const(Value::F64(f64::from_bits(x))),
|
Initializer::Const(Value::F32(f32::from_bits(x)))
|
||||||
GlobalInit::GetGlobal(global_index) => {
|
}
|
||||||
// assert!(!desc.mutable); // Can be mutable
|
cranelift_wasm::GlobalInit::F64Const(x) => {
|
||||||
|
Initializer::Const(Value::F64(f64::from_bits(x)))
|
||||||
|
}
|
||||||
|
cranelift_wasm::GlobalInit::GetGlobal(global_index) => {
|
||||||
|
assert!(!desc.mutable);
|
||||||
let global_index: GlobalIndex = Converter(global_index).into();
|
let global_index: GlobalIndex = Converter(global_index).into();
|
||||||
let imported_global_index = global_index
|
let imported_global_index = global_index
|
||||||
.local_or_import(self.module)
|
.local_or_import(self.module)
|
||||||
@ -118,7 +134,7 @@ impl<'module, 'isa, 'data> ModuleEnvironment<'data> for ModuleEnv<'module, 'isa>
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Add global ir to the list of globals
|
// Add global ir to the list of globals
|
||||||
self.module.globals.push(Global { desc, init });
|
self.module.globals.push(GlobalInit { desc, init });
|
||||||
|
|
||||||
self.globals.push(global);
|
self.globals.push(global);
|
||||||
}
|
}
|
||||||
@ -140,7 +156,7 @@ impl<'module, 'isa, 'data> ModuleEnvironment<'data> for ModuleEnv<'module, 'isa>
|
|||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let desc = GlobalDesc {
|
let desc = GlobalDescriptor {
|
||||||
mutable: global.mutability,
|
mutable: global.mutability,
|
||||||
ty: Converter(global.ty).into(),
|
ty: Converter(global.ty).into(),
|
||||||
};
|
};
|
||||||
@ -160,13 +176,13 @@ impl<'module, 'isa, 'data> ModuleEnvironment<'data> for ModuleEnv<'module, 'isa>
|
|||||||
fn declare_table(&mut self, table: cranelift_wasm::Table) {
|
fn declare_table(&mut self, table: cranelift_wasm::Table) {
|
||||||
use cranelift_wasm::TableElementType;
|
use cranelift_wasm::TableElementType;
|
||||||
// Add table ir to the list of tables
|
// Add table ir to the list of tables
|
||||||
self.module.tables.push(Table {
|
self.module.tables.push(TableDescriptor {
|
||||||
ty: match table.ty {
|
element: match table.ty {
|
||||||
TableElementType::Func => ElementType::Anyfunc,
|
TableElementType::Func => ElementType::Anyfunc,
|
||||||
_ => unimplemented!(),
|
_ => unimplemented!(),
|
||||||
},
|
},
|
||||||
min: table.minimum,
|
minimum: table.minimum,
|
||||||
max: table.maximum,
|
maximum: table.maximum,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -184,13 +200,13 @@ impl<'module, 'isa, 'data> ModuleEnvironment<'data> for ModuleEnv<'module, 'isa>
|
|||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let imported_table = Table {
|
let imported_table = TableDescriptor {
|
||||||
ty: match table.ty {
|
element: match table.ty {
|
||||||
TableElementType::Func => ElementType::Anyfunc,
|
TableElementType::Func => ElementType::Anyfunc,
|
||||||
_ => unimplemented!(),
|
_ => unimplemented!(),
|
||||||
},
|
},
|
||||||
min: table.minimum,
|
minimum: table.minimum,
|
||||||
max: table.maximum,
|
maximum: table.maximum,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Add import names to list of imported tables
|
// Add import names to list of imported tables
|
||||||
@ -235,9 +251,9 @@ impl<'module, 'isa, 'data> ModuleEnvironment<'data> for ModuleEnv<'module, 'isa>
|
|||||||
|
|
||||||
/// Declares a memory to the environment
|
/// Declares a memory to the environment
|
||||||
fn declare_memory(&mut self, memory: cranelift_wasm::Memory) {
|
fn declare_memory(&mut self, memory: cranelift_wasm::Memory) {
|
||||||
self.module.memories.push(Memory {
|
self.module.memories.push(MemoryDescriptor {
|
||||||
min: memory.minimum,
|
minimum: Pages(memory.minimum),
|
||||||
max: memory.maximum,
|
maximum: memory.maximum.map(|max| Pages(max)),
|
||||||
shared: memory.shared,
|
shared: memory.shared,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -254,9 +270,9 @@ impl<'module, 'isa, 'data> ModuleEnvironment<'data> for ModuleEnv<'module, 'isa>
|
|||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let memory = Memory {
|
let memory = MemoryDescriptor {
|
||||||
min: memory.minimum,
|
minimum: Pages(memory.minimum),
|
||||||
max: memory.maximum,
|
maximum: memory.maximum.map(|max| Pages(max)),
|
||||||
shared: memory.shared,
|
shared: memory.shared,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -8,6 +8,18 @@ use cranelift_codegen::ir::{self, ExternalName, LibCall, SourceLoc, TrapCode};
|
|||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
use wasmer_runtime_core::{structures::TypedIndex, types::LocalFuncIndex};
|
use wasmer_runtime_core::{structures::TypedIndex, types::LocalFuncIndex};
|
||||||
|
|
||||||
|
pub mod call_names {
|
||||||
|
pub const LOCAL_NAMESPACE: u32 = 1;
|
||||||
|
pub const IMPORT_NAMESPACE: u32 = 2;
|
||||||
|
|
||||||
|
pub const STATIC_MEM_GROW: u32 = 0;
|
||||||
|
pub const STATIC_MEM_SIZE: u32 = 1;
|
||||||
|
pub const SHARED_STATIC_MEM_GROW: u32 = 2;
|
||||||
|
pub const SHARED_STATIC_MEM_SIZE: u32 = 3;
|
||||||
|
pub const DYNAMIC_MEM_GROW: u32 = 4;
|
||||||
|
pub const DYNAMIC_MEM_SIZE: u32 = 5;
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Relocation {
|
pub struct Relocation {
|
||||||
/// The relocation code.
|
/// The relocation code.
|
||||||
@ -20,12 +32,22 @@ pub struct Relocation {
|
|||||||
pub target: RelocationType,
|
pub target: RelocationType,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub enum VmCallKind {
|
||||||
|
StaticMemoryGrow,
|
||||||
|
StaticMemorySize,
|
||||||
|
|
||||||
|
SharedStaticMemoryGrow,
|
||||||
|
SharedStaticMemorySize,
|
||||||
|
|
||||||
|
DynamicMemoryGrow,
|
||||||
|
DynamicMemorySize,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub enum VmCall {
|
pub enum VmCall {
|
||||||
LocalStaticMemoryGrow,
|
Local(VmCallKind),
|
||||||
LocalStaticMemorySize,
|
Import(VmCallKind),
|
||||||
ImportedStaticMemoryGrow,
|
|
||||||
ImportedStaticMemorySize,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Specify the type of relocation
|
/// Specify the type of relocation
|
||||||
@ -72,15 +94,31 @@ impl binemit::RelocSink for RelocSink {
|
|||||||
target: RelocationType::Normal(LocalFuncIndex::new(index as usize)),
|
target: RelocationType::Normal(LocalFuncIndex::new(index as usize)),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
ExternalName::User {
|
ExternalName::User { namespace, index } => {
|
||||||
namespace: 1,
|
use self::call_names::*;
|
||||||
index,
|
let target = RelocationType::VmCall(match namespace {
|
||||||
} => {
|
LOCAL_NAMESPACE => VmCall::Local(match index {
|
||||||
let target = RelocationType::VmCall(match index {
|
STATIC_MEM_GROW => VmCallKind::StaticMemoryGrow,
|
||||||
0 => VmCall::LocalStaticMemoryGrow,
|
STATIC_MEM_SIZE => VmCallKind::StaticMemorySize,
|
||||||
1 => VmCall::LocalStaticMemorySize,
|
|
||||||
2 => VmCall::ImportedStaticMemoryGrow,
|
SHARED_STATIC_MEM_GROW => VmCallKind::SharedStaticMemoryGrow,
|
||||||
3 => VmCall::ImportedStaticMemorySize,
|
SHARED_STATIC_MEM_SIZE => VmCallKind::SharedStaticMemorySize,
|
||||||
|
|
||||||
|
DYNAMIC_MEM_GROW => VmCallKind::DynamicMemoryGrow,
|
||||||
|
DYNAMIC_MEM_SIZE => VmCallKind::DynamicMemorySize,
|
||||||
|
_ => unimplemented!(),
|
||||||
|
}),
|
||||||
|
IMPORT_NAMESPACE => VmCall::Import(match index {
|
||||||
|
STATIC_MEM_GROW => VmCallKind::StaticMemoryGrow,
|
||||||
|
STATIC_MEM_SIZE => VmCallKind::StaticMemorySize,
|
||||||
|
|
||||||
|
SHARED_STATIC_MEM_GROW => VmCallKind::SharedStaticMemoryGrow,
|
||||||
|
SHARED_STATIC_MEM_SIZE => VmCallKind::SharedStaticMemorySize,
|
||||||
|
|
||||||
|
DYNAMIC_MEM_GROW => VmCallKind::DynamicMemoryGrow,
|
||||||
|
DYNAMIC_MEM_SIZE => VmCallKind::DynamicMemorySize,
|
||||||
|
_ => unimplemented!(),
|
||||||
|
}),
|
||||||
_ => unimplemented!(),
|
_ => unimplemented!(),
|
||||||
});
|
});
|
||||||
self.func_relocs.push(Relocation {
|
self.func_relocs.push(Relocation {
|
||||||
@ -109,9 +147,6 @@ impl binemit::RelocSink for RelocSink {
|
|||||||
target: relocation_type,
|
target: relocation_type,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
_ => {
|
|
||||||
unimplemented!();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn reloc_jt(
|
fn reloc_jt(
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::call::HandlerData;
|
use crate::call::HandlerData;
|
||||||
use crate::libcalls;
|
use crate::libcalls;
|
||||||
use crate::relocation::{
|
use crate::relocation::{
|
||||||
LocalTrapSink, Reloc, RelocSink, Relocation, RelocationType, TrapSink, VmCall,
|
LocalTrapSink, Reloc, RelocSink, Relocation, RelocationType, TrapSink, VmCall, VmCallKind,
|
||||||
};
|
};
|
||||||
use byteorder::{ByteOrder, LittleEndian};
|
use byteorder::{ByteOrder, LittleEndian};
|
||||||
use cranelift_codegen::{ir, isa, Context};
|
use cranelift_codegen::{ir, isa, Context};
|
||||||
@ -140,14 +140,38 @@ impl FuncResolverBuilder {
|
|||||||
msg: format!("unexpected intrinsic: {}", name),
|
msg: format!("unexpected intrinsic: {}", name),
|
||||||
})?,
|
})?,
|
||||||
RelocationType::VmCall(vmcall) => match vmcall {
|
RelocationType::VmCall(vmcall) => match vmcall {
|
||||||
VmCall::LocalStaticMemoryGrow => vmcalls::local_static_memory_grow as _,
|
VmCall::Local(kind) => match kind {
|
||||||
VmCall::LocalStaticMemorySize => vmcalls::local_static_memory_size as _,
|
VmCallKind::StaticMemoryGrow => vmcalls::local_static_memory_grow as _,
|
||||||
VmCall::ImportedStaticMemoryGrow => {
|
VmCallKind::StaticMemorySize => vmcalls::local_static_memory_size as _,
|
||||||
vmcalls::imported_static_memory_grow as _
|
|
||||||
}
|
VmCallKind::SharedStaticMemoryGrow => unimplemented!(),
|
||||||
VmCall::ImportedStaticMemorySize => {
|
VmCallKind::SharedStaticMemorySize => unimplemented!(),
|
||||||
vmcalls::imported_static_memory_size as _
|
|
||||||
}
|
VmCallKind::DynamicMemoryGrow => {
|
||||||
|
vmcalls::local_dynamic_memory_grow as _
|
||||||
|
}
|
||||||
|
VmCallKind::DynamicMemorySize => {
|
||||||
|
vmcalls::local_dynamic_memory_size as _
|
||||||
|
}
|
||||||
|
},
|
||||||
|
VmCall::Import(kind) => match kind {
|
||||||
|
VmCallKind::StaticMemoryGrow => {
|
||||||
|
vmcalls::imported_static_memory_grow as _
|
||||||
|
}
|
||||||
|
VmCallKind::StaticMemorySize => {
|
||||||
|
vmcalls::imported_static_memory_size as _
|
||||||
|
}
|
||||||
|
|
||||||
|
VmCallKind::SharedStaticMemoryGrow => unimplemented!(),
|
||||||
|
VmCallKind::SharedStaticMemorySize => unimplemented!(),
|
||||||
|
|
||||||
|
VmCallKind::DynamicMemoryGrow => {
|
||||||
|
vmcalls::imported_dynamic_memory_grow as _
|
||||||
|
}
|
||||||
|
VmCallKind::DynamicMemorySize => {
|
||||||
|
vmcalls::imported_dynamic_memory_size as _
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -43,9 +43,9 @@ impl Trampolines {
|
|||||||
|
|
||||||
for exported_func_index in func_index_iter {
|
for exported_func_index in func_index_iter {
|
||||||
let sig_index = module.func_assoc[*exported_func_index];
|
let sig_index = module.func_assoc[*exported_func_index];
|
||||||
let func_sig = module.sig_registry.lookup_func_sig(sig_index);
|
let func_sig = module.sig_registry.lookup_signature(sig_index);
|
||||||
|
|
||||||
let trampoline_func = generate_func(func_sig);
|
let trampoline_func = generate_func(&func_sig);
|
||||||
|
|
||||||
ctx.func = trampoline_func;
|
ctx.func = trampoline_func;
|
||||||
|
|
||||||
@ -128,8 +128,8 @@ fn generate_func(func_sig: &FuncSig) -> ir::Function {
|
|||||||
|
|
||||||
let mut pos = FuncCursor::new(&mut func).at_first_insertion_point(entry_ebb);
|
let mut pos = FuncCursor::new(&mut func).at_first_insertion_point(entry_ebb);
|
||||||
|
|
||||||
let mut args_vec = Vec::with_capacity(func_sig.params.len() + 1);
|
let mut args_vec = Vec::with_capacity(func_sig.params().len() + 1);
|
||||||
for (index, wasm_ty) in func_sig.params.iter().enumerate() {
|
for (index, wasm_ty) in func_sig.params().iter().enumerate() {
|
||||||
let mem_flags = ir::MemFlags::trusted();
|
let mem_flags = ir::MemFlags::trusted();
|
||||||
|
|
||||||
let val = pos.ins().load(
|
let val = pos.ins().load(
|
||||||
@ -190,7 +190,7 @@ fn generate_export_signature(func_sig: &FuncSig) -> ir::Signature {
|
|||||||
let mut export_clif_sig = ir::Signature::new(isa::CallConv::SystemV);
|
let mut export_clif_sig = ir::Signature::new(isa::CallConv::SystemV);
|
||||||
|
|
||||||
export_clif_sig.params = func_sig
|
export_clif_sig.params = func_sig
|
||||||
.params
|
.params()
|
||||||
.iter()
|
.iter()
|
||||||
.map(|wasm_ty| ir::AbiParam {
|
.map(|wasm_ty| ir::AbiParam {
|
||||||
value_type: wasm_ty_to_clif(*wasm_ty),
|
value_type: wasm_ty_to_clif(*wasm_ty),
|
||||||
@ -207,7 +207,7 @@ fn generate_export_signature(func_sig: &FuncSig) -> ir::Signature {
|
|||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
export_clif_sig.returns = func_sig
|
export_clif_sig.returns = func_sig
|
||||||
.returns
|
.returns()
|
||||||
.iter()
|
.iter()
|
||||||
.map(|wasm_ty| ir::AbiParam {
|
.map(|wasm_ty| ir::AbiParam {
|
||||||
value_type: wasm_ty_to_clif(*wasm_ty),
|
value_type: wasm_ty_to_clif(*wasm_ty),
|
||||||
|
@ -5,16 +5,17 @@ use libc::c_int;
|
|||||||
use std::cell::UnsafeCell;
|
use std::cell::UnsafeCell;
|
||||||
use std::{ffi::c_void, fmt, mem, ptr};
|
use std::{ffi::c_void, fmt, mem, ptr};
|
||||||
use wasmer_runtime_core::{
|
use wasmer_runtime_core::{
|
||||||
error::CallResult,
|
export::{Context, Export, FuncPointer},
|
||||||
export::{Context, Export, FuncPointer, GlobalPointer, MemoryPointer, TablePointer},
|
func,
|
||||||
|
global::Global,
|
||||||
import::{ImportObject, Namespace},
|
import::{ImportObject, Namespace},
|
||||||
instance::Instance,
|
imports,
|
||||||
memory::LinearMemory,
|
memory::Memory,
|
||||||
module::Module,
|
table::Table,
|
||||||
structures::TypedIndex,
|
types::{
|
||||||
table::TableBacking,
|
FuncSig, GlobalDescriptor,
|
||||||
types::{ElementType, FuncSig, GlobalDesc, LocalMemoryIndex, Memory, Table, Type::*, Value},
|
Type::{self, *},
|
||||||
vm::Ctx,
|
},
|
||||||
vm::LocalGlobal,
|
vm::LocalGlobal,
|
||||||
vm::LocalMemory,
|
vm::LocalMemory,
|
||||||
vm::LocalTable,
|
vm::LocalTable,
|
||||||
@ -196,23 +197,24 @@ fn store_module_arguments(path: &str, args: Vec<&str>, ctx: &mut Ctx) -> (u32, u
|
|||||||
(argc as u32, argv_offset)
|
(argc as u32, argv_offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn emscripten_set_up_memory(memory: &mut LinearMemory) {
|
pub fn emscripten_set_up_memory(memory: &mut Memory) {
|
||||||
let dynamictop_ptr = dynamictop_ptr(STATIC_BUMP) as usize;
|
let dynamictop_ptr = dynamictop_ptr(STATIC_BUMP) as usize;
|
||||||
let dynamictop_ptr_offset = dynamictop_ptr + mem::size_of::<u32>();
|
let dynamictop_ptr_offset = dynamictop_ptr + mem::size_of::<u32>();
|
||||||
|
|
||||||
// println!("value = {:?}");
|
// println!("value = {:?}");
|
||||||
|
|
||||||
// We avoid failures of setting the u32 in our memory if it's out of bounds
|
// We avoid failures of setting the u32 in our memory if it's out of bounds
|
||||||
if dynamictop_ptr_offset > memory.len() {
|
unimplemented!()
|
||||||
return; // TODO: We should panic instead?
|
// if dynamictop_ptr_offset > memory.len() {
|
||||||
}
|
// return; // TODO: We should panic instead?
|
||||||
|
// }
|
||||||
// debug!("###### dynamic_base = {:?}", dynamic_base(STATIC_BUMP));
|
//
|
||||||
// debug!("###### dynamictop_ptr = {:?}", dynamictop_ptr);
|
// // debug!("###### dynamic_base = {:?}", dynamic_base(STATIC_BUMP));
|
||||||
// debug!("###### dynamictop_ptr_offset = {:?}", dynamictop_ptr_offset);
|
// // debug!("###### dynamictop_ptr = {:?}", dynamictop_ptr);
|
||||||
|
// // debug!("###### dynamictop_ptr_offset = {:?}", dynamictop_ptr_offset);
|
||||||
let mem = &mut memory[dynamictop_ptr..dynamictop_ptr_offset];
|
//
|
||||||
LittleEndian::write_u32(mem, dynamic_base(STATIC_BUMP));
|
// let mem = &mut memory[dynamictop_ptr..dynamictop_ptr_offset];
|
||||||
|
// LittleEndian::write_u32(mem, dynamic_base(STATIC_BUMP));
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! mock_external {
|
macro_rules! mock_external {
|
||||||
|
@ -1,7 +1,3 @@
|
|||||||
macro_rules! debug {
|
|
||||||
($fmt:expr) => (if cfg!(any(debug_assertions, feature="debug")) { println!(concat!("wasmer-runtime(:{})::", $fmt), line!()) });
|
|
||||||
($fmt:expr, $($arg:tt)*) => (if cfg!(any(debug_assertions, feature="debug")) { println!(concat!("wasmer-runtime(:{})::", $fmt, "\n"), line!(), $($arg)*) });
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! emscripten_memory_pointer {
|
macro_rules! emscripten_memory_pointer {
|
||||||
($memory:expr, $pointer:expr) => {
|
($memory:expr, $pointer:expr) => {
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
// use crate::webassembly::LinearMemory;
|
// use crate::webassembly::Memory;
|
||||||
|
|
||||||
pub fn align_memory(ptr: u32) -> u32 {
|
pub fn align_memory(ptr: u32) -> u32 {
|
||||||
(ptr + 15) & !15
|
(ptr + 15) & !15
|
||||||
}
|
}
|
||||||
|
|
||||||
// pub fn static_alloc(size: u32, static_top: &mut u32, memory: &LinearMemory) -> u32 {
|
// pub fn static_alloc(size: u32, static_top: &mut u32, memory: &Memory) -> u32 {
|
||||||
// let old_static_top = *static_top;
|
// let old_static_top = *static_top;
|
||||||
// let total_memory = memory.maximum_size() * LinearMemory::PAGE_SIZE;
|
// let total_memory = memory.maximum_size() * Memory::PAGE_SIZE;
|
||||||
// // NOTE: The `4294967280` is a u32 conversion of -16 as gotten from emscripten.
|
// // NOTE: The `4294967280` is a u32 conversion of -16 as gotten from emscripten.
|
||||||
// *static_top = (*static_top + size + 15) & 4294967280;
|
// *static_top = (*static_top + size + 15) & 4294967280;
|
||||||
// assert!(
|
// assert!(
|
||||||
|
@ -13,6 +13,8 @@ hashbrown = "0.1"
|
|||||||
nix = "0.12.0"
|
nix = "0.12.0"
|
||||||
page_size = "0.4.1"
|
page_size = "0.4.1"
|
||||||
wasmparser = "0.23.0"
|
wasmparser = "0.23.0"
|
||||||
|
parking_lot = "0.7.1"
|
||||||
|
lazy_static = "1.2.0"
|
||||||
|
|
||||||
[target.'cfg(windows)'.dependencies]
|
[target.'cfg(windows)'.dependencies]
|
||||||
winapi = { version = "0.3", features = ["memoryapi"] }
|
winapi = { version = "0.3", features = ["memoryapi"] }
|
||||||
|
@ -1,6 +1,14 @@
|
|||||||
use wabt::wat2wasm;
|
use wabt::wat2wasm;
|
||||||
use wasmer_clif_backend::CraneliftCompiler;
|
use wasmer_clif_backend::CraneliftCompiler;
|
||||||
use wasmer_runtime_core::{error::Result, prelude::*};
|
use wasmer_runtime_core::{
|
||||||
|
error::Result,
|
||||||
|
global::Global,
|
||||||
|
memory::Memory,
|
||||||
|
prelude::*,
|
||||||
|
table::Table,
|
||||||
|
types::{ElementType, MemoryDescriptor, TableDescriptor, Value},
|
||||||
|
units::Pages,
|
||||||
|
};
|
||||||
|
|
||||||
static EXAMPLE_WASM: &'static [u8] = include_bytes!("simple.wasm");
|
static EXAMPLE_WASM: &'static [u8] = include_bytes!("simple.wasm");
|
||||||
|
|
||||||
@ -8,9 +16,32 @@ fn main() -> Result<()> {
|
|||||||
let wasm_binary = wat2wasm(IMPORT_MODULE.as_bytes()).expect("WAST not valid or malformed");
|
let wasm_binary = wat2wasm(IMPORT_MODULE.as_bytes()).expect("WAST not valid or malformed");
|
||||||
let inner_module = wasmer_runtime_core::compile_with(&wasm_binary, &CraneliftCompiler::new())?;
|
let inner_module = wasmer_runtime_core::compile_with(&wasm_binary, &CraneliftCompiler::new())?;
|
||||||
|
|
||||||
|
let memory = Memory::new(MemoryDescriptor {
|
||||||
|
minimum: Pages(1),
|
||||||
|
maximum: Some(Pages(1)),
|
||||||
|
shared: false,
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let global = Global::new(Value::I32(42));
|
||||||
|
|
||||||
|
let table = Table::new(TableDescriptor {
|
||||||
|
element: ElementType::Anyfunc,
|
||||||
|
minimum: 10,
|
||||||
|
maximum: None,
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
memory.direct_access_mut(|slice: &mut [u32]| {
|
||||||
|
slice[0] = 42;
|
||||||
|
});
|
||||||
|
|
||||||
let import_object = imports! {
|
let import_object = imports! {
|
||||||
"env" => {
|
"env" => {
|
||||||
"print_i32" => print_num<[i32] -> [i32]>,
|
"print_i32" => func!(print_num, [i32] -> [i32]),
|
||||||
|
"memory" => memory,
|
||||||
|
"global" => global,
|
||||||
|
"table" => table,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -21,23 +52,31 @@ fn main() -> Result<()> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let outer_module = wasmer_runtime_core::compile_with(EXAMPLE_WASM, &CraneliftCompiler::new())?;
|
let outer_module = wasmer_runtime_core::compile_with(EXAMPLE_WASM, &CraneliftCompiler::new())?;
|
||||||
let mut outer_instance = outer_module.instantiate(outer_imports)?;
|
let outer_instance = outer_module.instantiate(outer_imports)?;
|
||||||
let ret = outer_instance.call("main", &[Value::I32(42)])?;
|
let ret = outer_instance.call("main", &[Value::I32(42)])?;
|
||||||
println!("ret: {:?}", ret);
|
println!("ret: {:?}", ret);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" fn print_num(n: i32, _vmctx: &mut vm::Ctx) -> i32 {
|
extern "C" fn print_num(n: i32, ctx: &mut vm::Ctx) -> i32 {
|
||||||
println!("print_num({})", n);
|
println!("print_num({})", n);
|
||||||
n + 1
|
|
||||||
|
let memory = ctx.memory(0);
|
||||||
|
|
||||||
|
let a: i32 = memory.read(0).unwrap();
|
||||||
|
|
||||||
|
a + n + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
static IMPORT_MODULE: &str = r#"
|
static IMPORT_MODULE: &str = r#"
|
||||||
(module
|
(module
|
||||||
(type $t0 (func (param i32) (result i32)))
|
(type $t0 (func (param i32) (result i32)))
|
||||||
|
(import "env" "memory" (memory 1 1))
|
||||||
|
(import "env" "table" (table 10 anyfunc))
|
||||||
|
(import "env" "global" (global i32))
|
||||||
(import "env" "print_i32" (func $print_i32 (type $t0)))
|
(import "env" "print_i32" (func $print_i32 (type $t0)))
|
||||||
(func $print_num (export "print_num") (type $t0) (param $p0 i32) (result i32)
|
(func $print_num (export "print_num") (type $t0) (param $p0 i32) (result i32)
|
||||||
get_local $p0
|
get_global 0
|
||||||
call $print_i32))
|
call $print_i32))
|
||||||
"#;
|
"#;
|
||||||
|
@ -3,7 +3,7 @@ use wasmer_clif_backend::CraneliftCompiler;
|
|||||||
use wasmer_runtime_core::{import::ImportObject, Instance};
|
use wasmer_runtime_core::{import::ImportObject, Instance};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut instance = create_module_1();
|
let instance = create_module_1();
|
||||||
let result = instance.call("call-overwritten-element", &[]);
|
let result = instance.call("call-overwritten-element", &[]);
|
||||||
println!("result: {:?}", result);
|
println!("result: {:?}", result);
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ pub trait Compiler {
|
|||||||
/// The functionality exposed by this trait is expected to be used
|
/// The functionality exposed by this trait is expected to be used
|
||||||
/// for calling functions exported by a webassembly module from
|
/// for calling functions exported by a webassembly module from
|
||||||
/// host code only.
|
/// host code only.
|
||||||
pub trait ProtectedCaller {
|
pub trait ProtectedCaller: Send + Sync {
|
||||||
/// This calls the exported function designated by `local_func_index`.
|
/// This calls the exported function designated by `local_func_index`.
|
||||||
/// Important to note, this supports calling imported functions that are
|
/// Important to note, this supports calling imported functions that are
|
||||||
/// then exported.
|
/// then exported.
|
||||||
@ -62,7 +62,7 @@ pub trait ProtectedCaller {
|
|||||||
) -> RuntimeResult<Vec<Value>>;
|
) -> RuntimeResult<Vec<Value>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait FuncResolver {
|
pub trait FuncResolver: Send + Sync {
|
||||||
/// This returns a pointer to the function designated by the `local_func_index`
|
/// This returns a pointer to the function designated by the `local_func_index`
|
||||||
/// parameter.
|
/// parameter.
|
||||||
fn get(
|
fn get(
|
||||||
|
@ -1,53 +1,55 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
error::{LinkError, LinkResult},
|
error::{LinkError, LinkResult},
|
||||||
export::{Context, Export},
|
export::{Context, Export},
|
||||||
|
global::Global,
|
||||||
import::ImportObject,
|
import::ImportObject,
|
||||||
memory::LinearMemory,
|
memory::Memory,
|
||||||
module::{ImportName, ModuleInner},
|
module::{ImportName, ModuleInner},
|
||||||
structures::{BoxedMap, Map, SliceMap, TypedIndex},
|
structures::{BoxedMap, Map, SliceMap, TypedIndex},
|
||||||
table::{TableBacking, TableElements},
|
table::Table,
|
||||||
types::{
|
types::{
|
||||||
ElementType, ImportedFuncIndex, ImportedGlobalIndex, ImportedMemoryIndex,
|
ImportedFuncIndex, ImportedGlobalIndex, ImportedMemoryIndex, ImportedTableIndex,
|
||||||
ImportedTableIndex, Initializer, LocalGlobalIndex, LocalMemoryIndex, LocalOrImport,
|
Initializer, LocalGlobalIndex, LocalMemoryIndex, LocalOrImport, LocalTableIndex, Value,
|
||||||
LocalTableIndex, Type, Value,
|
|
||||||
},
|
},
|
||||||
vm,
|
vm,
|
||||||
};
|
};
|
||||||
use std::{mem, slice};
|
use std::slice;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct LocalBacking {
|
pub struct LocalBacking {
|
||||||
pub(crate) memories: BoxedMap<LocalMemoryIndex, LinearMemory>,
|
pub(crate) memories: BoxedMap<LocalMemoryIndex, Memory>,
|
||||||
pub(crate) tables: BoxedMap<LocalTableIndex, TableBacking>,
|
pub(crate) tables: BoxedMap<LocalTableIndex, Table>,
|
||||||
|
pub(crate) globals: BoxedMap<LocalGlobalIndex, Global>,
|
||||||
|
|
||||||
pub(crate) vm_memories: BoxedMap<LocalMemoryIndex, vm::LocalMemory>,
|
pub(crate) vm_memories: BoxedMap<LocalMemoryIndex, *mut vm::LocalMemory>,
|
||||||
pub(crate) vm_tables: BoxedMap<LocalTableIndex, vm::LocalTable>,
|
pub(crate) vm_tables: BoxedMap<LocalTableIndex, *mut vm::LocalTable>,
|
||||||
pub(crate) vm_globals: BoxedMap<LocalGlobalIndex, vm::LocalGlobal>,
|
pub(crate) vm_globals: BoxedMap<LocalGlobalIndex, *mut vm::LocalGlobal>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LocalBacking {
|
// impl LocalBacking {
|
||||||
pub fn memory(&mut self, local_memory_index: LocalMemoryIndex) -> &mut LinearMemory {
|
// pub fn memory(&mut self, local_memory_index: LocalMemoryIndex) -> &mut Memory {
|
||||||
&mut self.memories[local_memory_index]
|
// &mut self.memories[local_memory_index]
|
||||||
}
|
// }
|
||||||
|
|
||||||
pub fn table(&mut self, local_table_index: LocalTableIndex) -> &mut TableBacking {
|
// pub fn table(&mut self, local_table_index: LocalTableIndex) -> &mut TableBacking {
|
||||||
&mut self.tables[local_table_index]
|
// &mut self.tables[local_table_index]
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
impl LocalBacking {
|
impl LocalBacking {
|
||||||
pub(crate) fn new(module: &ModuleInner, imports: &ImportBacking, vmctx: *mut vm::Ctx) -> Self {
|
pub(crate) fn new(module: &ModuleInner, imports: &ImportBacking, vmctx: *mut vm::Ctx) -> Self {
|
||||||
let mut memories = Self::generate_memories(module);
|
let mut memories = Self::generate_memories(module);
|
||||||
let mut tables = Self::generate_tables(module);
|
let mut tables = Self::generate_tables(module);
|
||||||
let globals = Self::generate_globals(module);
|
let mut globals = Self::generate_globals(module, imports);
|
||||||
|
|
||||||
let vm_memories = Self::finalize_memories(module, imports, &mut memories);
|
let vm_memories = Self::finalize_memories(module, imports, &mut memories);
|
||||||
let vm_tables = Self::finalize_tables(module, imports, &mut tables, vmctx);
|
let vm_tables = Self::finalize_tables(module, imports, &mut tables, vmctx);
|
||||||
let vm_globals = Self::finalize_globals(module, imports, globals);
|
let vm_globals = Self::finalize_globals(&mut globals);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
memories,
|
memories,
|
||||||
tables,
|
tables,
|
||||||
|
globals,
|
||||||
|
|
||||||
vm_memories,
|
vm_memories,
|
||||||
vm_tables,
|
vm_tables,
|
||||||
@ -55,20 +57,20 @@ impl LocalBacking {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_memories(module: &ModuleInner) -> BoxedMap<LocalMemoryIndex, LinearMemory> {
|
fn generate_memories(module: &ModuleInner) -> BoxedMap<LocalMemoryIndex, Memory> {
|
||||||
let mut memories = Map::with_capacity(module.memories.len());
|
let mut memories = Map::with_capacity(module.memories.len());
|
||||||
|
|
||||||
for (_, mem) in &module.memories {
|
for (_, &desc) in &module.memories {
|
||||||
// If we use emscripten, we set a fixed initial and maximum
|
// If we use emscripten, we set a fixed initial and maximum
|
||||||
// let memory = if options.abi == InstanceABI::Emscripten {
|
// let memory = if options.abi == InstanceABI::Emscripten {
|
||||||
// // We use MAX_PAGES, so at the end the result is:
|
// // We use MAX_PAGES, so at the end the result is:
|
||||||
// // (initial * LinearMemory::PAGE_SIZE) == LinearMemory::DEFAULT_HEAP_SIZE
|
// // (initial * Memory::PAGE_SIZE) == Memory::DEFAULT_HEAP_SIZE
|
||||||
// // However, it should be: (initial * LinearMemory::PAGE_SIZE) == 16777216
|
// // However, it should be: (initial * Memory::PAGE_SIZE) == 16777216
|
||||||
// LinearMemory::new(LinearMemory::MAX_PAGES, None)
|
// Memory::new(Memory::MAX_PAGES, None)
|
||||||
// } else {
|
// } else {
|
||||||
// LinearMemory::new(memory.minimum, memory.maximum.map(|m| m as u32))
|
// Memory::new(memory.minimum, memory.maximum.map(|m| m as u32))
|
||||||
// };
|
// };
|
||||||
let memory = LinearMemory::new(mem);
|
let memory = Memory::new(desc).expect("unable to create memory");
|
||||||
memories.push(memory);
|
memories.push(memory);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,8 +80,8 @@ impl LocalBacking {
|
|||||||
fn finalize_memories(
|
fn finalize_memories(
|
||||||
module: &ModuleInner,
|
module: &ModuleInner,
|
||||||
imports: &ImportBacking,
|
imports: &ImportBacking,
|
||||||
memories: &mut SliceMap<LocalMemoryIndex, LinearMemory>,
|
memories: &mut SliceMap<LocalMemoryIndex, Memory>,
|
||||||
) -> BoxedMap<LocalMemoryIndex, vm::LocalMemory> {
|
) -> BoxedMap<LocalMemoryIndex, *mut vm::LocalMemory> {
|
||||||
// For each init that has some data...
|
// For each init that has some data...
|
||||||
for init in module
|
for init in module
|
||||||
.data_initializers
|
.data_initializers
|
||||||
@ -89,9 +91,9 @@ impl LocalBacking {
|
|||||||
let init_base = match init.base {
|
let init_base = match init.base {
|
||||||
Initializer::Const(Value::I32(offset)) => offset as u32,
|
Initializer::Const(Value::I32(offset)) => offset as u32,
|
||||||
Initializer::Const(_) => panic!("a const initializer must be the i32 type"),
|
Initializer::Const(_) => panic!("a const initializer must be the i32 type"),
|
||||||
Initializer::GetGlobal(imported_global_index) => {
|
Initializer::GetGlobal(import_global_index) => {
|
||||||
if module.imported_globals[imported_global_index].1.ty == Type::I32 {
|
if let Value::I32(x) = imports.globals[import_global_index].get() {
|
||||||
unsafe { (*imports.globals[imported_global_index].global).data as u32 }
|
x as u32
|
||||||
} else {
|
} else {
|
||||||
panic!("unsupported global type for initialzer")
|
panic!("unsupported global type for initialzer")
|
||||||
}
|
}
|
||||||
@ -100,20 +102,20 @@ impl LocalBacking {
|
|||||||
|
|
||||||
match init.memory_index.local_or_import(module) {
|
match init.memory_index.local_or_import(module) {
|
||||||
LocalOrImport::Local(local_memory_index) => {
|
LocalOrImport::Local(local_memory_index) => {
|
||||||
let memory_desc = &module.memories[local_memory_index];
|
let memory_desc = module.memories[local_memory_index];
|
||||||
let data_top = init_base + init.data.len();
|
let data_top = init_base + init.data.len();
|
||||||
assert!((memory_desc.min * LinearMemory::PAGE_SIZE) as usize >= data_top);
|
assert!(memory_desc.minimum.bytes().0 >= data_top);
|
||||||
let mem: &mut LinearMemory = &mut memories[local_memory_index];
|
|
||||||
|
|
||||||
let mem_init_view = &mut mem[init_base..init_base + init.data.len()];
|
let mem = &memories[local_memory_index];
|
||||||
mem_init_view.copy_from_slice(&init.data);
|
mem.write_many(init_base as u32, &init.data).unwrap();
|
||||||
}
|
}
|
||||||
LocalOrImport::Import(imported_memory_index) => {
|
LocalOrImport::Import(imported_memory_index) => {
|
||||||
let vm_imported_memory = imports.imported_memory(imported_memory_index);
|
// Write the initialization data to the memory that
|
||||||
|
// we think the imported memory is.
|
||||||
unsafe {
|
unsafe {
|
||||||
let local_memory = &(*vm_imported_memory.memory);
|
let local_memory = &*imports.vm_memories[imported_memory_index];
|
||||||
let memory_slice =
|
let memory_slice =
|
||||||
slice::from_raw_parts_mut(local_memory.base, local_memory.size);
|
slice::from_raw_parts_mut(local_memory.base, local_memory.bound);
|
||||||
|
|
||||||
let mem_init_view =
|
let mem_init_view =
|
||||||
&mut memory_slice[init_base..init_base + init.data.len()];
|
&mut memory_slice[init_base..init_base + init.data.len()];
|
||||||
@ -125,17 +127,17 @@ impl LocalBacking {
|
|||||||
|
|
||||||
memories
|
memories
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
.map(|(index, mem)| mem.into_vm_memory(index))
|
.map(|(_, mem)| mem.vm_local_memory())
|
||||||
.collect::<Map<_, _>>()
|
.collect::<Map<_, _>>()
|
||||||
.into_boxed_map()
|
.into_boxed_map()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_tables(module: &ModuleInner) -> BoxedMap<LocalTableIndex, TableBacking> {
|
fn generate_tables(module: &ModuleInner) -> BoxedMap<LocalTableIndex, Table> {
|
||||||
let mut tables = Map::with_capacity(module.tables.len());
|
let mut tables = Map::with_capacity(module.tables.len());
|
||||||
|
|
||||||
for (_, table) in &module.tables {
|
for (_, &table_desc) in module.tables.iter() {
|
||||||
let table_backing = TableBacking::new(table);
|
let table = Table::new(table_desc).unwrap();
|
||||||
tables.push(table_backing);
|
tables.push(table);
|
||||||
}
|
}
|
||||||
|
|
||||||
tables.into_boxed_map()
|
tables.into_boxed_map()
|
||||||
@ -145,16 +147,16 @@ impl LocalBacking {
|
|||||||
fn finalize_tables(
|
fn finalize_tables(
|
||||||
module: &ModuleInner,
|
module: &ModuleInner,
|
||||||
imports: &ImportBacking,
|
imports: &ImportBacking,
|
||||||
tables: &mut SliceMap<LocalTableIndex, TableBacking>,
|
tables: &mut SliceMap<LocalTableIndex, Table>,
|
||||||
vmctx: *mut vm::Ctx,
|
vmctx: *mut vm::Ctx,
|
||||||
) -> BoxedMap<LocalTableIndex, vm::LocalTable> {
|
) -> BoxedMap<LocalTableIndex, *mut vm::LocalTable> {
|
||||||
for init in &module.elem_initializers {
|
for init in &module.elem_initializers {
|
||||||
let init_base = match init.base {
|
let init_base = match init.base {
|
||||||
Initializer::Const(Value::I32(offset)) => offset as u32,
|
Initializer::Const(Value::I32(offset)) => offset as u32,
|
||||||
Initializer::Const(_) => panic!("a const initializer must be the i32 type"),
|
Initializer::Const(_) => panic!("a const initializer must be the i32 type"),
|
||||||
Initializer::GetGlobal(imported_global_index) => {
|
Initializer::GetGlobal(import_global_index) => {
|
||||||
if module.imported_globals[imported_global_index].1.ty == Type::I32 {
|
if let Value::I32(x) = imports.globals[import_global_index].get() {
|
||||||
unsafe { (*imports.globals[imported_global_index].global).data as u32 }
|
x as u32
|
||||||
} else {
|
} else {
|
||||||
panic!("unsupported global type for initialzer")
|
panic!("unsupported global type for initialzer")
|
||||||
}
|
}
|
||||||
@ -163,141 +165,132 @@ impl LocalBacking {
|
|||||||
|
|
||||||
match init.table_index.local_or_import(module) {
|
match init.table_index.local_or_import(module) {
|
||||||
LocalOrImport::Local(local_table_index) => {
|
LocalOrImport::Local(local_table_index) => {
|
||||||
let table = &mut tables[local_table_index];
|
let table = &tables[local_table_index];
|
||||||
match table.elements {
|
|
||||||
TableElements::Anyfunc(ref mut elements) => {
|
|
||||||
if elements.len() < init_base + init.elements.len() {
|
|
||||||
// Grow the table if it's too small.
|
|
||||||
elements
|
|
||||||
.resize(init_base + init.elements.len(), vm::Anyfunc::null());
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i, &func_index) in init.elements.iter().enumerate() {
|
if (table.size() as usize) < init_base + init.elements.len() {
|
||||||
let sig_index = module.func_assoc[func_index];
|
let delta = (init_base + init.elements.len()) - table.size() as usize;
|
||||||
let sig_id = vm::SigId(sig_index.index() as u32);
|
// Grow the table if it's too small.
|
||||||
|
table.grow(delta as u32).expect("couldn't grow table");
|
||||||
let func_data = match func_index.local_or_import(module) {
|
|
||||||
LocalOrImport::Local(local_func_index) => vm::ImportedFunc {
|
|
||||||
func: module
|
|
||||||
.func_resolver
|
|
||||||
.get(module, local_func_index)
|
|
||||||
.unwrap()
|
|
||||||
.as_ptr(),
|
|
||||||
vmctx,
|
|
||||||
},
|
|
||||||
LocalOrImport::Import(imported_func_index) => {
|
|
||||||
imports.functions[imported_func_index].clone()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
elements[init_base + i] = vm::Anyfunc { func_data, sig_id };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
LocalOrImport::Import(imported_table_index) => {
|
|
||||||
let (_, table_description) = module.imported_tables[imported_table_index];
|
|
||||||
match table_description.ty {
|
|
||||||
ElementType::Anyfunc => {
|
|
||||||
let imported_table = &imports.tables[imported_table_index];
|
|
||||||
let imported_local_table = (*imported_table).table;
|
|
||||||
|
|
||||||
let mut elements = unsafe {
|
table.anyfunc_direct_access_mut(|elements| {
|
||||||
Vec::from_raw_parts(
|
for (i, &func_index) in init.elements.iter().enumerate() {
|
||||||
(*imported_local_table).base as *mut vm::Anyfunc,
|
let sig_index = module.func_assoc[func_index];
|
||||||
(*imported_local_table).current_elements,
|
let sig_id = vm::SigId(sig_index.index() as u32);
|
||||||
(*imported_local_table).capacity,
|
|
||||||
)
|
let (func, ctx) = match func_index.local_or_import(module) {
|
||||||
|
LocalOrImport::Local(local_func_index) => (
|
||||||
|
module
|
||||||
|
.func_resolver
|
||||||
|
.get(module, local_func_index)
|
||||||
|
.unwrap()
|
||||||
|
.as_ptr()
|
||||||
|
as *const vm::Func,
|
||||||
|
vmctx,
|
||||||
|
),
|
||||||
|
LocalOrImport::Import(imported_func_index) => {
|
||||||
|
let vm::ImportedFunc { func, vmctx } =
|
||||||
|
imports.vm_functions[imported_func_index];
|
||||||
|
(func, vmctx)
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if elements.len() < init_base + init.elements.len() {
|
elements[init_base + i] = vm::Anyfunc { func, ctx, sig_id };
|
||||||
// Grow the table if it's too small.
|
|
||||||
elements
|
|
||||||
.resize(init_base + init.elements.len(), vm::Anyfunc::null());
|
|
||||||
// Since the vector may have changed location after reallocating,
|
|
||||||
// we must fix the base, current_elements, and capacity fields.
|
|
||||||
unsafe {
|
|
||||||
(*imported_local_table).base = elements.as_mut_ptr() as *mut u8;
|
|
||||||
(*imported_local_table).current_elements = elements.len();
|
|
||||||
(*imported_local_table).capacity = elements.capacity();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i, &func_index) in init.elements.iter().enumerate() {
|
|
||||||
let sig_index = module.func_assoc[func_index];
|
|
||||||
let sig_id = vm::SigId(sig_index.index() as u32);
|
|
||||||
|
|
||||||
let func_data = match func_index.local_or_import(module) {
|
|
||||||
LocalOrImport::Local(local_func_index) => vm::ImportedFunc {
|
|
||||||
func: module
|
|
||||||
.func_resolver
|
|
||||||
.get(module, local_func_index)
|
|
||||||
.unwrap()
|
|
||||||
.as_ptr(),
|
|
||||||
vmctx,
|
|
||||||
},
|
|
||||||
LocalOrImport::Import(imported_func_index) => {
|
|
||||||
imports.functions[imported_func_index].clone()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
elements[init_base + i] = vm::Anyfunc { func_data, sig_id };
|
|
||||||
}
|
|
||||||
|
|
||||||
// println!("imported elements: {:#?}", elements);
|
|
||||||
|
|
||||||
// THIS IS EXTREMELY IMPORTANT.
|
|
||||||
mem::forget(elements);
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
LocalOrImport::Import(import_table_index) => {
|
||||||
|
let table = &imports.tables[import_table_index];
|
||||||
|
|
||||||
|
if (table.size() as usize) < init_base + init.elements.len() {
|
||||||
|
let delta = (init_base + init.elements.len()) - table.size() as usize;
|
||||||
|
// Grow the table if it's too small.
|
||||||
|
table.grow(delta as u32).expect("couldn't grow table");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
table.anyfunc_direct_access_mut(|elements| {
|
||||||
|
for (i, &func_index) in init.elements.iter().enumerate() {
|
||||||
|
let sig_index = module.func_assoc[func_index];
|
||||||
|
let sig_id = vm::SigId(sig_index.index() as u32);
|
||||||
|
|
||||||
|
let (func, ctx) = match func_index.local_or_import(module) {
|
||||||
|
LocalOrImport::Local(local_func_index) => (
|
||||||
|
module
|
||||||
|
.func_resolver
|
||||||
|
.get(module, local_func_index)
|
||||||
|
.unwrap()
|
||||||
|
.as_ptr()
|
||||||
|
as *const vm::Func,
|
||||||
|
vmctx,
|
||||||
|
),
|
||||||
|
LocalOrImport::Import(imported_func_index) => {
|
||||||
|
let vm::ImportedFunc { func, vmctx } =
|
||||||
|
imports.vm_functions[imported_func_index];
|
||||||
|
(func, vmctx)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
elements[init_base + i] = vm::Anyfunc { func, ctx, sig_id };
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tables
|
tables
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
.map(|(_, table)| table.into_vm_table())
|
.map(|(_, table)| table.vm_local_table())
|
||||||
.collect::<Map<_, _>>()
|
.collect::<Map<_, _>>()
|
||||||
.into_boxed_map()
|
.into_boxed_map()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_globals(module: &ModuleInner) -> BoxedMap<LocalGlobalIndex, vm::LocalGlobal> {
|
fn generate_globals(
|
||||||
|
module: &ModuleInner,
|
||||||
|
imports: &ImportBacking,
|
||||||
|
) -> BoxedMap<LocalGlobalIndex, Global> {
|
||||||
let mut globals = Map::with_capacity(module.globals.len());
|
let mut globals = Map::with_capacity(module.globals.len());
|
||||||
|
|
||||||
globals.resize(module.globals.len(), vm::LocalGlobal::null());
|
for (_, global_init) in module.globals.iter() {
|
||||||
|
let value = match &global_init.init {
|
||||||
|
Initializer::Const(value) => value.clone(),
|
||||||
|
Initializer::GetGlobal(import_global_index) => {
|
||||||
|
imports.globals[*import_global_index].get()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let global = if global_init.desc.mutable {
|
||||||
|
Global::new_mutable(value)
|
||||||
|
} else {
|
||||||
|
Global::new(value)
|
||||||
|
};
|
||||||
|
|
||||||
|
globals.push(global);
|
||||||
|
}
|
||||||
|
|
||||||
globals.into_boxed_map()
|
globals.into_boxed_map()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn finalize_globals(
|
fn finalize_globals(
|
||||||
module: &ModuleInner,
|
globals: &mut SliceMap<LocalGlobalIndex, Global>,
|
||||||
imports: &ImportBacking,
|
) -> BoxedMap<LocalGlobalIndex, *mut vm::LocalGlobal> {
|
||||||
mut globals: BoxedMap<LocalGlobalIndex, vm::LocalGlobal>,
|
|
||||||
) -> BoxedMap<LocalGlobalIndex, vm::LocalGlobal> {
|
|
||||||
for ((_, to), (_, from)) in globals.iter_mut().zip(module.globals.iter()) {
|
|
||||||
to.data = match from.init {
|
|
||||||
Initializer::Const(ref value) => match value {
|
|
||||||
Value::I32(x) => *x as u64,
|
|
||||||
Value::I64(x) => *x as u64,
|
|
||||||
Value::F32(x) => x.to_bits() as u64,
|
|
||||||
Value::F64(x) => x.to_bits(),
|
|
||||||
},
|
|
||||||
Initializer::GetGlobal(imported_global_index) => unsafe {
|
|
||||||
(*imports.globals[imported_global_index].global).data
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
globals
|
globals
|
||||||
|
.iter_mut()
|
||||||
|
.map(|(_, global)| global.vm_local_global())
|
||||||
|
.collect::<Map<_, _>>()
|
||||||
|
.into_boxed_map()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ImportBacking {
|
pub struct ImportBacking {
|
||||||
pub(crate) functions: BoxedMap<ImportedFuncIndex, vm::ImportedFunc>,
|
pub(crate) memories: BoxedMap<ImportedMemoryIndex, Memory>,
|
||||||
pub(crate) memories: BoxedMap<ImportedMemoryIndex, vm::ImportedMemory>,
|
pub(crate) tables: BoxedMap<ImportedTableIndex, Table>,
|
||||||
pub(crate) tables: BoxedMap<ImportedTableIndex, vm::ImportedTable>,
|
pub(crate) globals: BoxedMap<ImportedGlobalIndex, Global>,
|
||||||
pub(crate) globals: BoxedMap<ImportedGlobalIndex, vm::ImportedGlobal>,
|
|
||||||
|
pub(crate) vm_functions: BoxedMap<ImportedFuncIndex, vm::ImportedFunc>,
|
||||||
|
pub(crate) vm_memories: BoxedMap<ImportedMemoryIndex, *mut vm::LocalMemory>,
|
||||||
|
pub(crate) vm_tables: BoxedMap<ImportedTableIndex, *mut vm::LocalTable>,
|
||||||
|
pub(crate) vm_globals: BoxedMap<ImportedGlobalIndex, *mut vm::LocalGlobal>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ImportBacking {
|
impl ImportBacking {
|
||||||
@ -309,48 +302,48 @@ impl ImportBacking {
|
|||||||
let mut failed = false;
|
let mut failed = false;
|
||||||
let mut link_errors = vec![];
|
let mut link_errors = vec![];
|
||||||
|
|
||||||
let functions = import_functions(module, imports, vmctx).unwrap_or_else(|le| {
|
let vm_functions = import_functions(module, imports, vmctx).unwrap_or_else(|le| {
|
||||||
failed = true;
|
failed = true;
|
||||||
link_errors.extend(le);
|
link_errors.extend(le);
|
||||||
Map::new().into_boxed_map()
|
Map::new().into_boxed_map()
|
||||||
});
|
});
|
||||||
|
|
||||||
let memories = import_memories(module, imports, vmctx).unwrap_or_else(|le| {
|
let (memories, vm_memories) = import_memories(module, imports).unwrap_or_else(|le| {
|
||||||
failed = true;
|
failed = true;
|
||||||
link_errors.extend(le);
|
link_errors.extend(le);
|
||||||
Map::new().into_boxed_map()
|
(Map::new().into_boxed_map(), Map::new().into_boxed_map())
|
||||||
});
|
});
|
||||||
|
|
||||||
let tables = import_tables(module, imports, vmctx).unwrap_or_else(|le| {
|
let (tables, vm_tables) = import_tables(module, imports).unwrap_or_else(|le| {
|
||||||
failed = true;
|
failed = true;
|
||||||
link_errors.extend(le);
|
link_errors.extend(le);
|
||||||
Map::new().into_boxed_map()
|
(Map::new().into_boxed_map(), Map::new().into_boxed_map())
|
||||||
});
|
});
|
||||||
|
|
||||||
let globals = import_globals(module, imports).unwrap_or_else(|le| {
|
let (globals, vm_globals) = import_globals(module, imports).unwrap_or_else(|le| {
|
||||||
failed = true;
|
failed = true;
|
||||||
link_errors.extend(le);
|
link_errors.extend(le);
|
||||||
Map::new().into_boxed_map()
|
(Map::new().into_boxed_map(), Map::new().into_boxed_map())
|
||||||
});
|
});
|
||||||
|
|
||||||
if failed {
|
if failed {
|
||||||
Err(link_errors)
|
Err(link_errors)
|
||||||
} else {
|
} else {
|
||||||
Ok(ImportBacking {
|
Ok(ImportBacking {
|
||||||
functions,
|
|
||||||
memories,
|
memories,
|
||||||
tables,
|
tables,
|
||||||
globals,
|
globals,
|
||||||
|
|
||||||
|
vm_functions,
|
||||||
|
vm_memories,
|
||||||
|
vm_tables,
|
||||||
|
vm_globals,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn imported_func(&self, func_index: ImportedFuncIndex) -> vm::ImportedFunc {
|
pub fn imported_func(&self, index: ImportedFuncIndex) -> vm::ImportedFunc {
|
||||||
self.functions[func_index].clone()
|
self.vm_functions[index].clone()
|
||||||
}
|
|
||||||
|
|
||||||
pub fn imported_memory(&self, memory_index: ImportedMemoryIndex) -> vm::ImportedMemory {
|
|
||||||
self.memories[memory_index].clone()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -363,7 +356,7 @@ fn import_functions(
|
|||||||
let mut functions = Map::with_capacity(module.imported_functions.len());
|
let mut functions = Map::with_capacity(module.imported_functions.len());
|
||||||
for (index, ImportName { namespace, name }) in &module.imported_functions {
|
for (index, ImportName { namespace, name }) in &module.imported_functions {
|
||||||
let sig_index = module.func_assoc[index.convert_up(module)];
|
let sig_index = module.func_assoc[index.convert_up(module)];
|
||||||
let expected_sig = module.sig_registry.lookup_func_sig(sig_index);
|
let expected_sig = module.sig_registry.lookup_signature(sig_index);
|
||||||
let import = imports
|
let import = imports
|
||||||
.get_namespace(namespace)
|
.get_namespace(namespace)
|
||||||
.and_then(|namespace| namespace.get_export(name));
|
.and_then(|namespace| namespace.get_export(name));
|
||||||
@ -373,7 +366,7 @@ fn import_functions(
|
|||||||
ctx,
|
ctx,
|
||||||
signature,
|
signature,
|
||||||
}) => {
|
}) => {
|
||||||
if expected_sig == &signature {
|
if expected_sig == signature {
|
||||||
functions.push(vm::ImportedFunc {
|
functions.push(vm::ImportedFunc {
|
||||||
func: func.inner(),
|
func: func.inner(),
|
||||||
vmctx: match ctx {
|
vmctx: match ctx {
|
||||||
@ -424,36 +417,30 @@ fn import_functions(
|
|||||||
fn import_memories(
|
fn import_memories(
|
||||||
module: &ModuleInner,
|
module: &ModuleInner,
|
||||||
imports: &mut ImportObject,
|
imports: &mut ImportObject,
|
||||||
vmctx: *mut vm::Ctx,
|
) -> LinkResult<(
|
||||||
) -> LinkResult<BoxedMap<ImportedMemoryIndex, vm::ImportedMemory>> {
|
BoxedMap<ImportedMemoryIndex, Memory>,
|
||||||
|
BoxedMap<ImportedMemoryIndex, *mut vm::LocalMemory>,
|
||||||
|
)> {
|
||||||
let mut link_errors = vec![];
|
let mut link_errors = vec![];
|
||||||
let mut memories = Map::with_capacity(module.imported_memories.len());
|
let mut memories = Map::with_capacity(module.imported_memories.len());
|
||||||
|
let mut vm_memories = Map::with_capacity(module.imported_memories.len());
|
||||||
for (_index, (ImportName { namespace, name }, expected_memory_desc)) in
|
for (_index, (ImportName { namespace, name }, expected_memory_desc)) in
|
||||||
&module.imported_memories
|
&module.imported_memories
|
||||||
{
|
{
|
||||||
let memory_import = imports
|
let memory_import = imports
|
||||||
.get_namespace(namespace)
|
.get_namespace(&namespace)
|
||||||
.and_then(|namespace| namespace.get_export(name));
|
.and_then(|namespace| namespace.get_export(&name));
|
||||||
match memory_import {
|
match memory_import {
|
||||||
Some(Export::Memory {
|
Some(Export::Memory(mut memory)) => {
|
||||||
local,
|
if expected_memory_desc.fits_in_imported(memory.descriptor()) {
|
||||||
ctx,
|
memories.push(memory.clone());
|
||||||
memory: memory_desc,
|
vm_memories.push(memory.vm_local_memory());
|
||||||
}) => {
|
|
||||||
if expected_memory_desc.fits_in_imported(&memory_desc) {
|
|
||||||
memories.push(vm::ImportedMemory {
|
|
||||||
memory: local.inner(),
|
|
||||||
vmctx: match ctx {
|
|
||||||
Context::External(ctx) => ctx,
|
|
||||||
Context::Internal => vmctx,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
link_errors.push(LinkError::IncorrectMemoryDescription {
|
link_errors.push(LinkError::IncorrectMemoryDescriptor {
|
||||||
namespace: namespace.clone(),
|
namespace: namespace.clone(),
|
||||||
name: name.clone(),
|
name: name.clone(),
|
||||||
expected: expected_memory_desc.clone(),
|
expected: *expected_memory_desc,
|
||||||
found: memory_desc.clone(),
|
found: memory.descriptor(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -484,41 +471,35 @@ fn import_memories(
|
|||||||
if link_errors.len() > 0 {
|
if link_errors.len() > 0 {
|
||||||
Err(link_errors)
|
Err(link_errors)
|
||||||
} else {
|
} else {
|
||||||
Ok(memories.into_boxed_map())
|
Ok((memories.into_boxed_map(), vm_memories.into_boxed_map()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn import_tables(
|
fn import_tables(
|
||||||
module: &ModuleInner,
|
module: &ModuleInner,
|
||||||
imports: &mut ImportObject,
|
imports: &mut ImportObject,
|
||||||
vmctx: *mut vm::Ctx,
|
) -> LinkResult<(
|
||||||
) -> LinkResult<BoxedMap<ImportedTableIndex, vm::ImportedTable>> {
|
BoxedMap<ImportedTableIndex, Table>,
|
||||||
|
BoxedMap<ImportedTableIndex, *mut vm::LocalTable>,
|
||||||
|
)> {
|
||||||
let mut link_errors = vec![];
|
let mut link_errors = vec![];
|
||||||
let mut tables = Map::with_capacity(module.imported_tables.len());
|
let mut tables = Map::with_capacity(module.imported_tables.len());
|
||||||
|
let mut vm_tables = Map::with_capacity(module.imported_tables.len());
|
||||||
for (_index, (ImportName { namespace, name }, expected_table_desc)) in &module.imported_tables {
|
for (_index, (ImportName { namespace, name }, expected_table_desc)) in &module.imported_tables {
|
||||||
let table_import = imports
|
let table_import = imports
|
||||||
.get_namespace(namespace)
|
.get_namespace(&namespace)
|
||||||
.and_then(|namespace| namespace.get_export(name));
|
.and_then(|namespace| namespace.get_export(&name));
|
||||||
match table_import {
|
match table_import {
|
||||||
Some(Export::Table {
|
Some(Export::Table(mut table)) => {
|
||||||
local,
|
if expected_table_desc.fits_in_imported(table.descriptor()) {
|
||||||
ctx,
|
vm_tables.push(table.vm_local_table());
|
||||||
table: table_desc,
|
tables.push(table);
|
||||||
}) => {
|
|
||||||
if expected_table_desc.fits_in_imported(&table_desc) {
|
|
||||||
tables.push(vm::ImportedTable {
|
|
||||||
table: local.inner(),
|
|
||||||
vmctx: match ctx {
|
|
||||||
Context::External(ctx) => ctx,
|
|
||||||
Context::Internal => vmctx,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
link_errors.push(LinkError::IncorrectTableDescription {
|
link_errors.push(LinkError::IncorrectTableDescriptor {
|
||||||
namespace: namespace.clone(),
|
namespace: namespace.clone(),
|
||||||
name: name.clone(),
|
name: name.clone(),
|
||||||
expected: expected_table_desc.clone(),
|
expected: *expected_table_desc,
|
||||||
found: table_desc.clone(),
|
found: table.descriptor(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -549,32 +530,35 @@ fn import_tables(
|
|||||||
if link_errors.len() > 0 {
|
if link_errors.len() > 0 {
|
||||||
Err(link_errors)
|
Err(link_errors)
|
||||||
} else {
|
} else {
|
||||||
Ok(tables.into_boxed_map())
|
Ok((tables.into_boxed_map(), vm_tables.into_boxed_map()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn import_globals(
|
fn import_globals(
|
||||||
module: &ModuleInner,
|
module: &ModuleInner,
|
||||||
imports: &mut ImportObject,
|
imports: &mut ImportObject,
|
||||||
) -> LinkResult<BoxedMap<ImportedGlobalIndex, vm::ImportedGlobal>> {
|
) -> LinkResult<(
|
||||||
|
BoxedMap<ImportedGlobalIndex, Global>,
|
||||||
|
BoxedMap<ImportedGlobalIndex, *mut vm::LocalGlobal>,
|
||||||
|
)> {
|
||||||
let mut link_errors = vec![];
|
let mut link_errors = vec![];
|
||||||
let mut globals = Map::with_capacity(module.imported_globals.len());
|
let mut globals = Map::with_capacity(module.imported_globals.len());
|
||||||
|
let mut vm_globals = Map::with_capacity(module.imported_globals.len());
|
||||||
for (_, (ImportName { namespace, name }, imported_global_desc)) in &module.imported_globals {
|
for (_, (ImportName { namespace, name }, imported_global_desc)) in &module.imported_globals {
|
||||||
let import = imports
|
let import = imports
|
||||||
.get_namespace(namespace)
|
.get_namespace(namespace)
|
||||||
.and_then(|namespace| namespace.get_export(name));
|
.and_then(|namespace| namespace.get_export(name));
|
||||||
match import {
|
match import {
|
||||||
Some(Export::Global { local, global }) => {
|
Some(Export::Global(mut global)) => {
|
||||||
if global == *imported_global_desc {
|
if global.descriptor() == *imported_global_desc {
|
||||||
globals.push(vm::ImportedGlobal {
|
vm_globals.push(global.vm_local_global());
|
||||||
global: local.inner(),
|
globals.push(global);
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
link_errors.push(LinkError::IncorrectGlobalDescription {
|
link_errors.push(LinkError::IncorrectGlobalDescriptor {
|
||||||
namespace: namespace.clone(),
|
namespace: namespace.clone(),
|
||||||
name: name.clone(),
|
name: name.clone(),
|
||||||
expected: imported_global_desc.clone(),
|
expected: *imported_global_desc,
|
||||||
found: global.clone(),
|
found: global.descriptor(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -605,6 +589,6 @@ fn import_globals(
|
|||||||
if link_errors.len() > 0 {
|
if link_errors.len() > 0 {
|
||||||
Err(link_errors)
|
Err(link_errors)
|
||||||
} else {
|
} else {
|
||||||
Ok(globals.into_boxed_map())
|
Ok((globals.into_boxed_map(), vm_globals.into_boxed_map()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
use crate::types::{FuncSig, GlobalDesc, Memory, MemoryIndex, Table, TableIndex, Type};
|
use crate::types::{
|
||||||
|
FuncSig, GlobalDescriptor, MemoryDescriptor, MemoryIndex, TableDescriptor, TableIndex, Type,
|
||||||
|
};
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
pub type Result<T> = std::result::Result<T, Box<Error>>;
|
pub type Result<T> = std::result::Result<T, Box<Error>>;
|
||||||
pub type CompileResult<T> = std::result::Result<T, Box<CompileError>>;
|
pub type CompileResult<T> = std::result::Result<T, Box<CompileError>>;
|
||||||
@ -39,30 +42,30 @@ pub enum LinkError {
|
|||||||
IncorrectImportSignature {
|
IncorrectImportSignature {
|
||||||
namespace: String,
|
namespace: String,
|
||||||
name: String,
|
name: String,
|
||||||
expected: FuncSig,
|
expected: Arc<FuncSig>,
|
||||||
found: FuncSig,
|
found: Arc<FuncSig>,
|
||||||
},
|
},
|
||||||
ImportNotFound {
|
ImportNotFound {
|
||||||
namespace: String,
|
namespace: String,
|
||||||
name: String,
|
name: String,
|
||||||
},
|
},
|
||||||
IncorrectMemoryDescription {
|
IncorrectMemoryDescriptor {
|
||||||
namespace: String,
|
namespace: String,
|
||||||
name: String,
|
name: String,
|
||||||
expected: Memory,
|
expected: MemoryDescriptor,
|
||||||
found: Memory,
|
found: MemoryDescriptor,
|
||||||
},
|
},
|
||||||
IncorrectTableDescription {
|
IncorrectTableDescriptor {
|
||||||
namespace: String,
|
namespace: String,
|
||||||
name: String,
|
name: String,
|
||||||
expected: Table,
|
expected: TableDescriptor,
|
||||||
found: Table,
|
found: TableDescriptor,
|
||||||
},
|
},
|
||||||
IncorrectGlobalDescription {
|
IncorrectGlobalDescriptor {
|
||||||
namespace: String,
|
namespace: String,
|
||||||
name: String,
|
name: String,
|
||||||
expected: GlobalDesc,
|
expected: GlobalDescriptor,
|
||||||
found: GlobalDesc,
|
found: GlobalDescriptor,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,9 +103,16 @@ impl PartialEq for RuntimeError {
|
|||||||
/// Comparing two `ResolveError`s always evaluates to false.
|
/// Comparing two `ResolveError`s always evaluates to false.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum ResolveError {
|
pub enum ResolveError {
|
||||||
Signature { expected: FuncSig, found: Vec<Type> },
|
Signature {
|
||||||
ExportNotFound { name: String },
|
expected: Arc<FuncSig>,
|
||||||
ExportWrongType { name: String },
|
found: Vec<Type>,
|
||||||
|
},
|
||||||
|
ExportNotFound {
|
||||||
|
name: String,
|
||||||
|
},
|
||||||
|
ExportWrongType {
|
||||||
|
name: String,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq for ResolveError {
|
impl PartialEq for ResolveError {
|
||||||
@ -130,6 +140,20 @@ impl PartialEq for CallError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This error type is produced when creating something,
|
||||||
|
/// like a `Memory` or a `Table`.
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum CreationError {
|
||||||
|
UnableToCreateMemory,
|
||||||
|
UnableToCreateTable,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq for CreationError {
|
||||||
|
fn eq(&self, _other: &CreationError) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// The amalgamation of all errors that can occur
|
/// The amalgamation of all errors that can occur
|
||||||
/// during the compilation, instantiation, or execution
|
/// during the compilation, instantiation, or execution
|
||||||
/// of a webassembly module.
|
/// of a webassembly module.
|
||||||
@ -142,6 +166,7 @@ pub enum Error {
|
|||||||
RuntimeError(RuntimeError),
|
RuntimeError(RuntimeError),
|
||||||
ResolveError(ResolveError),
|
ResolveError(ResolveError),
|
||||||
CallError(CallError),
|
CallError(CallError),
|
||||||
|
CreationError(CreationError),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq for Error {
|
impl PartialEq for Error {
|
||||||
@ -210,6 +235,12 @@ impl From<CallError> for Box<Error> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<CreationError> for Box<Error> {
|
||||||
|
fn from(creation_err: CreationError) -> Self {
|
||||||
|
Box::new(Error::CreationError(creation_err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<RuntimeError> for Box<CallError> {
|
impl From<RuntimeError> for Box<CallError> {
|
||||||
fn from(runtime_err: RuntimeError) -> Self {
|
fn from(runtime_err: RuntimeError) -> Self {
|
||||||
Box::new(CallError::Runtime(runtime_err))
|
Box::new(CallError::Runtime(runtime_err))
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
instance::InstanceInner,
|
global::Global, instance::InstanceInner, memory::Memory, module::ExportIndex,
|
||||||
module::ExportIndex,
|
module::ModuleInner, table::Table, types::FuncSig, vm,
|
||||||
module::ModuleInner,
|
|
||||||
types::{FuncSig, GlobalDesc, Memory, Table},
|
|
||||||
vm,
|
|
||||||
};
|
};
|
||||||
use hashbrown::hash_map;
|
use hashbrown::hash_map;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub enum Context {
|
pub enum Context {
|
||||||
@ -18,22 +16,11 @@ pub enum Export {
|
|||||||
Function {
|
Function {
|
||||||
func: FuncPointer,
|
func: FuncPointer,
|
||||||
ctx: Context,
|
ctx: Context,
|
||||||
signature: FuncSig,
|
signature: Arc<FuncSig>,
|
||||||
},
|
|
||||||
Memory {
|
|
||||||
local: MemoryPointer,
|
|
||||||
ctx: Context,
|
|
||||||
memory: Memory,
|
|
||||||
},
|
|
||||||
Table {
|
|
||||||
local: TablePointer,
|
|
||||||
ctx: Context,
|
|
||||||
table: Table,
|
|
||||||
},
|
|
||||||
Global {
|
|
||||||
local: GlobalPointer,
|
|
||||||
global: GlobalDesc,
|
|
||||||
},
|
},
|
||||||
|
Memory(Memory),
|
||||||
|
Table(Table),
|
||||||
|
Global(Global),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@ -52,54 +39,6 @@ impl FuncPointer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct MemoryPointer(*mut vm::LocalMemory);
|
|
||||||
|
|
||||||
impl MemoryPointer {
|
|
||||||
/// This needs to be unsafe because there is
|
|
||||||
/// no way to check whether the passed function
|
|
||||||
/// is valid and has the right signature.
|
|
||||||
pub unsafe fn new(f: *mut vm::LocalMemory) -> Self {
|
|
||||||
MemoryPointer(f)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn inner(&self) -> *mut vm::LocalMemory {
|
|
||||||
self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct TablePointer(*mut vm::LocalTable);
|
|
||||||
|
|
||||||
impl TablePointer {
|
|
||||||
/// This needs to be unsafe because there is
|
|
||||||
/// no way to check whether the passed function
|
|
||||||
/// is valid and has the right signature.
|
|
||||||
pub unsafe fn new(f: *mut vm::LocalTable) -> Self {
|
|
||||||
TablePointer(f)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn inner(&self) -> *mut vm::LocalTable {
|
|
||||||
self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct GlobalPointer(*mut vm::LocalGlobal);
|
|
||||||
|
|
||||||
impl GlobalPointer {
|
|
||||||
/// This needs to be unsafe because there is
|
|
||||||
/// no way to check whether the passed function
|
|
||||||
/// is valid and has the right signature.
|
|
||||||
pub unsafe fn new(f: *mut vm::LocalGlobal) -> Self {
|
|
||||||
GlobalPointer(f)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn inner(&self) -> *mut vm::LocalGlobal {
|
|
||||||
self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct ExportIter<'a> {
|
pub struct ExportIter<'a> {
|
||||||
inner: &'a mut InstanceInner,
|
inner: &'a mut InstanceInner,
|
||||||
iter: hash_map::Iter<'a, String, ExportIndex>,
|
iter: hash_map::Iter<'a, String, ExportIndex>,
|
||||||
|
132
lib/runtime-core/src/global.rs
Normal file
132
lib/runtime-core/src/global.rs
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
use crate::{
|
||||||
|
export::Export,
|
||||||
|
import::IsExport,
|
||||||
|
types::{GlobalDescriptor, Type, Value},
|
||||||
|
vm,
|
||||||
|
};
|
||||||
|
use std::{cell::RefCell, fmt, rc::Rc};
|
||||||
|
|
||||||
|
pub struct Global {
|
||||||
|
desc: GlobalDescriptor,
|
||||||
|
storage: Rc<RefCell<vm::LocalGlobal>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Global {
|
||||||
|
/// Create a new `Global` value.
|
||||||
|
///
|
||||||
|
/// Usage:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use wasmer_runtime_core::global::Global;
|
||||||
|
/// # use wasmer_runtime_core::types::Value;
|
||||||
|
/// let global = Global::new(Value::I32(42));
|
||||||
|
/// ```
|
||||||
|
pub fn new(value: Value) -> Self {
|
||||||
|
Self::new_internal(value, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a new, mutable `Global` value.
|
||||||
|
///
|
||||||
|
/// Usage:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use wasmer_runtime_core::global::Global;
|
||||||
|
/// # use wasmer_runtime_core::types::Value;
|
||||||
|
/// let global = Global::new_mutable(Value::I32(42));
|
||||||
|
/// ```
|
||||||
|
pub fn new_mutable(value: Value) -> Self {
|
||||||
|
Self::new_internal(value, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_internal(value: Value, mutable: bool) -> Self {
|
||||||
|
let desc = GlobalDescriptor {
|
||||||
|
mutable,
|
||||||
|
ty: value.ty(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let local_global = vm::LocalGlobal {
|
||||||
|
data: match value {
|
||||||
|
Value::I32(x) => x as u64,
|
||||||
|
Value::I64(x) => x as u64,
|
||||||
|
Value::F32(x) => x.to_bits() as u64,
|
||||||
|
Value::F64(x) => x.to_bits(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
Self {
|
||||||
|
desc,
|
||||||
|
storage: Rc::new(RefCell::new(local_global)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the [`GlobalDescriptor`] generated for this global.
|
||||||
|
///
|
||||||
|
/// [`GlobalDescriptor`]: struct.GlobalDescriptor.html
|
||||||
|
pub fn descriptor(&self) -> GlobalDescriptor {
|
||||||
|
self.desc
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the value help by this global.
|
||||||
|
///
|
||||||
|
/// This method will panic if the value is
|
||||||
|
/// the wrong type.
|
||||||
|
pub fn set(&self, value: Value) {
|
||||||
|
if self.desc.mutable {
|
||||||
|
if self.desc.ty == value.ty() {
|
||||||
|
let local_global = vm::LocalGlobal {
|
||||||
|
data: match value {
|
||||||
|
Value::I32(x) => x as u64,
|
||||||
|
Value::I64(x) => x as u64,
|
||||||
|
Value::F32(x) => x.to_bits() as u64,
|
||||||
|
Value::F64(x) => x.to_bits(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
*self.storage.borrow_mut() = local_global;
|
||||||
|
} else {
|
||||||
|
panic!("Wrong type for setting this global")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
panic!("Cannot modify global immutable by default")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the value held by this global.
|
||||||
|
pub fn get(&self) -> Value {
|
||||||
|
let data = self.storage.borrow().data;
|
||||||
|
|
||||||
|
match self.desc.ty {
|
||||||
|
Type::I32 => Value::I32(data as i32),
|
||||||
|
Type::I64 => Value::I64(data as i64),
|
||||||
|
Type::F32 => Value::F32(f32::from_bits(data as u32)),
|
||||||
|
Type::F64 => Value::F64(f64::from_bits(data)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn vm_local_global(&mut self) -> *mut vm::LocalGlobal {
|
||||||
|
&mut *self.storage.borrow_mut()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IsExport for Global {
|
||||||
|
fn to_export(&mut self) -> Export {
|
||||||
|
Export::Global(self.clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Clone for Global {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
Self {
|
||||||
|
desc: self.desc,
|
||||||
|
storage: Rc::clone(&self.storage),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for Global {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
f.debug_struct("Global")
|
||||||
|
.field("desc", &self.desc)
|
||||||
|
.field("value", &self.get())
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
@ -5,6 +5,16 @@ pub trait LikeNamespace {
|
|||||||
fn get_export(&mut self, name: &str) -> Option<Export>;
|
fn get_export(&mut self, name: &str) -> Option<Export>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait IsExport {
|
||||||
|
fn to_export(&mut self) -> Export;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IsExport for Export {
|
||||||
|
fn to_export(&mut self) -> Export {
|
||||||
|
self.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// All of the import data used when instantiating.
|
/// All of the import data used when instantiating.
|
||||||
///
|
///
|
||||||
/// It's suggested that you use the [`imports!`] macro
|
/// It's suggested that you use the [`imports!`] macro
|
||||||
@ -14,11 +24,11 @@ pub trait LikeNamespace {
|
|||||||
///
|
///
|
||||||
/// # Usage:
|
/// # Usage:
|
||||||
/// ```
|
/// ```
|
||||||
/// # use wasmer_runtime_core::imports;
|
/// # use wasmer_runtime_core::{imports, func};
|
||||||
/// # use wasmer_runtime_core::vm::Ctx;
|
/// # use wasmer_runtime_core::vm::Ctx;
|
||||||
/// let import_object = imports! {
|
/// let import_object = imports! {
|
||||||
/// "env" => {
|
/// "env" => {
|
||||||
/// "foo" => foo<[i32] -> [i32]>,
|
/// "foo" => func!(foo, [i32] -> [i32]),
|
||||||
/// },
|
/// },
|
||||||
/// };
|
/// };
|
||||||
///
|
///
|
||||||
@ -74,7 +84,7 @@ impl ImportObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct Namespace {
|
pub struct Namespace {
|
||||||
map: HashMap<String, Export>,
|
map: HashMap<String, Box<dyn IsExport>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Namespace {
|
impl Namespace {
|
||||||
@ -84,13 +94,19 @@ impl Namespace {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert(&mut self, name: impl Into<String>, export: Export) -> Option<Export> {
|
pub fn insert<S, E>(&mut self, name: S, export: E) -> Option<Box<dyn IsExport>>
|
||||||
self.map.insert(name.into(), export)
|
where
|
||||||
|
S: Into<String>,
|
||||||
|
E: IsExport + 'static,
|
||||||
|
{
|
||||||
|
self.map.insert(name.into(), Box::new(export))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LikeNamespace for Namespace {
|
impl LikeNamespace for Namespace {
|
||||||
fn get_export(&mut self, name: &str) -> Option<Export> {
|
fn get_export(&mut self, name: &str) -> Option<Export> {
|
||||||
self.map.get(name).cloned()
|
self.map
|
||||||
|
.get_mut(name)
|
||||||
|
.map(|is_export| is_export.to_export())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,24 +2,29 @@ use crate::{
|
|||||||
backend::Token,
|
backend::Token,
|
||||||
backing::{ImportBacking, LocalBacking},
|
backing::{ImportBacking, LocalBacking},
|
||||||
error::{CallError, CallResult, ResolveError, ResolveResult, Result},
|
error::{CallError, CallResult, ResolveError, ResolveResult, Result},
|
||||||
export::{
|
export::{Context, Export, ExportIter, FuncPointer},
|
||||||
Context, Export, ExportIter, FuncPointer, GlobalPointer, MemoryPointer, TablePointer,
|
global::Global,
|
||||||
},
|
|
||||||
import::{ImportObject, LikeNamespace},
|
import::{ImportObject, LikeNamespace},
|
||||||
|
memory::Memory,
|
||||||
module::{ExportIndex, Module, ModuleInner},
|
module::{ExportIndex, Module, ModuleInner},
|
||||||
types::{
|
table::Table,
|
||||||
FuncIndex, FuncSig, GlobalDesc, GlobalIndex, LocalOrImport, Memory, MemoryIndex, Table,
|
types::{FuncIndex, FuncSig, GlobalIndex, LocalOrImport, MemoryIndex, TableIndex, Value},
|
||||||
TableIndex, Value,
|
|
||||||
},
|
|
||||||
vm,
|
vm,
|
||||||
};
|
};
|
||||||
use std::{mem, rc::Rc};
|
use std::{mem, sync::Arc};
|
||||||
|
|
||||||
pub(crate) struct InstanceInner {
|
pub(crate) struct InstanceInner {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub(crate) backing: LocalBacking,
|
pub(crate) backing: LocalBacking,
|
||||||
import_backing: ImportBacking,
|
import_backing: ImportBacking,
|
||||||
vmctx: Box<vm::Ctx>,
|
pub(crate) vmctx: *mut vm::Ctx,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for InstanceInner {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
// Drop the vmctx.
|
||||||
|
unsafe { Box::from_raw(self.vmctx) };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An instantiated WebAssembly module.
|
/// An instantiated WebAssembly module.
|
||||||
@ -30,14 +35,17 @@ pub(crate) struct InstanceInner {
|
|||||||
///
|
///
|
||||||
/// [`ImportObject`]: struct.ImportObject.html
|
/// [`ImportObject`]: struct.ImportObject.html
|
||||||
pub struct Instance {
|
pub struct Instance {
|
||||||
module: Rc<ModuleInner>,
|
module: Arc<ModuleInner>,
|
||||||
inner: Box<InstanceInner>,
|
inner: Box<InstanceInner>,
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
imports: Box<ImportObject>,
|
imports: Box<ImportObject>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Instance {
|
impl Instance {
|
||||||
pub(crate) fn new(module: Rc<ModuleInner>, mut imports: Box<ImportObject>) -> Result<Instance> {
|
pub(crate) fn new(
|
||||||
|
module: Arc<ModuleInner>,
|
||||||
|
mut imports: Box<ImportObject>,
|
||||||
|
) -> Result<Instance> {
|
||||||
// We need the backing and import_backing to create a vm::Ctx, but we need
|
// We need the backing and import_backing to create a vm::Ctx, but we need
|
||||||
// a vm::Ctx to create a backing and an import_backing. The solution is to create an
|
// a vm::Ctx to create a backing and an import_backing. The solution is to create an
|
||||||
// uninitialized vm::Ctx and then initialize it in-place.
|
// uninitialized vm::Ctx and then initialize it in-place.
|
||||||
@ -50,15 +58,16 @@ impl Instance {
|
|||||||
let mut inner = Box::new(InstanceInner {
|
let mut inner = Box::new(InstanceInner {
|
||||||
backing,
|
backing,
|
||||||
import_backing,
|
import_backing,
|
||||||
vmctx,
|
vmctx: Box::leak(vmctx),
|
||||||
});
|
});
|
||||||
|
|
||||||
// Initialize the vm::Ctx in-place after the backing
|
// Initialize the vm::Ctx in-place after the backing
|
||||||
// has been boxed.
|
// has been boxed.
|
||||||
*inner.vmctx =
|
unsafe {
|
||||||
unsafe { vm::Ctx::new(&mut inner.backing, &mut inner.import_backing, &module) };
|
*inner.vmctx = vm::Ctx::new(&mut inner.backing, &mut inner.import_backing, &module)
|
||||||
|
};
|
||||||
|
|
||||||
let mut instance = Instance {
|
let instance = Instance {
|
||||||
module,
|
module,
|
||||||
inner,
|
inner,
|
||||||
imports,
|
imports,
|
||||||
@ -85,7 +94,7 @@ impl Instance {
|
|||||||
/// # Ok(())
|
/// # Ok(())
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn func(&mut self, name: &str) -> ResolveResult<Function> {
|
pub fn func(&self, name: &str) -> ResolveResult<Function> {
|
||||||
let export_index =
|
let export_index =
|
||||||
self.module
|
self.module
|
||||||
.exports
|
.exports
|
||||||
@ -100,12 +109,12 @@ impl Instance {
|
|||||||
.func_assoc
|
.func_assoc
|
||||||
.get(*func_index)
|
.get(*func_index)
|
||||||
.expect("broken invariant, incorrect func index");
|
.expect("broken invariant, incorrect func index");
|
||||||
let signature = self.module.sig_registry.lookup_func_sig(sig_index);
|
let signature = self.module.sig_registry.lookup_signature(sig_index);
|
||||||
|
|
||||||
Ok(Function {
|
Ok(Function {
|
||||||
signature,
|
signature,
|
||||||
module: &self.module,
|
module: &self.module,
|
||||||
instance_inner: &mut self.inner,
|
instance_inner: &self.inner,
|
||||||
func_index: *func_index,
|
func_index: *func_index,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
@ -138,7 +147,7 @@ impl Instance {
|
|||||||
/// # Ok(())
|
/// # Ok(())
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn call(&mut self, name: &str, args: &[Value]) -> CallResult<Vec<Value>> {
|
pub fn call(&self, name: &str, args: &[Value]) -> CallResult<Vec<Value>> {
|
||||||
let export_index =
|
let export_index =
|
||||||
self.module
|
self.module
|
||||||
.exports
|
.exports
|
||||||
@ -164,7 +173,7 @@ impl Instance {
|
|||||||
///
|
///
|
||||||
/// [`Ctx`]: struct.Ctx.html
|
/// [`Ctx`]: struct.Ctx.html
|
||||||
pub fn context(&self) -> &vm::Ctx {
|
pub fn context(&self) -> &vm::Ctx {
|
||||||
&self.inner.vmctx
|
unsafe { &*self.inner.vmctx }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a mutable reference to the
|
/// Returns a mutable reference to the
|
||||||
@ -172,7 +181,7 @@ impl Instance {
|
|||||||
///
|
///
|
||||||
/// [`Ctx`]: struct.Ctx.html
|
/// [`Ctx`]: struct.Ctx.html
|
||||||
pub fn context_mut(&mut self) -> &mut vm::Ctx {
|
pub fn context_mut(&mut self) -> &mut vm::Ctx {
|
||||||
&mut self.inner.vmctx
|
unsafe { &mut *self.inner.vmctx }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a iterator over all of the items
|
/// Returns a iterator over all of the items
|
||||||
@ -183,7 +192,7 @@ impl Instance {
|
|||||||
|
|
||||||
/// The module used to instantiate this Instance.
|
/// The module used to instantiate this Instance.
|
||||||
pub fn module(&self) -> Module {
|
pub fn module(&self) -> Module {
|
||||||
Module::new(Rc::clone(&self.module))
|
Module::new(Arc::clone(&self.module))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ctx(&mut self) -> &mut vm::Ctx {
|
pub fn ctx(&mut self) -> &mut vm::Ctx {
|
||||||
@ -192,15 +201,15 @@ impl Instance {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Instance {
|
impl Instance {
|
||||||
fn call_with_index(&mut self, func_index: FuncIndex, args: &[Value]) -> CallResult<Vec<Value>> {
|
fn call_with_index(&self, func_index: FuncIndex, args: &[Value]) -> CallResult<Vec<Value>> {
|
||||||
let sig_index = *self
|
let sig_index = *self
|
||||||
.module
|
.module
|
||||||
.func_assoc
|
.func_assoc
|
||||||
.get(func_index)
|
.get(func_index)
|
||||||
.expect("broken invariant, incorrect func index");
|
.expect("broken invariant, incorrect func index");
|
||||||
let signature = self.module.sig_registry.lookup_func_sig(sig_index);
|
let signature = self.module.sig_registry.lookup_signature(sig_index);
|
||||||
|
|
||||||
if !signature.check_sig(args) {
|
if !signature.check_param_value_types(args) {
|
||||||
Err(ResolveError::Signature {
|
Err(ResolveError::Signature {
|
||||||
expected: signature.clone(),
|
expected: signature.clone(),
|
||||||
found: args.iter().map(|val| val.ty()).collect(),
|
found: args.iter().map(|val| val.ty()).collect(),
|
||||||
@ -208,9 +217,9 @@ impl Instance {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let vmctx = match func_index.local_or_import(&self.module) {
|
let vmctx = match func_index.local_or_import(&self.module) {
|
||||||
LocalOrImport::Local(_) => &mut *self.inner.vmctx,
|
LocalOrImport::Local(_) => self.inner.vmctx,
|
||||||
LocalOrImport::Import(imported_func_index) => {
|
LocalOrImport::Import(imported_func_index) => {
|
||||||
self.inner.import_backing.functions[imported_func_index].vmctx
|
self.inner.import_backing.vm_functions[imported_func_index].vmctx
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -231,7 +240,7 @@ impl Instance {
|
|||||||
|
|
||||||
impl InstanceInner {
|
impl InstanceInner {
|
||||||
pub(crate) fn get_export_from_index(
|
pub(crate) fn get_export_from_index(
|
||||||
&mut self,
|
&self,
|
||||||
module: &ModuleInner,
|
module: &ModuleInner,
|
||||||
export_index: &ExportIndex,
|
export_index: &ExportIndex,
|
||||||
) -> Export {
|
) -> Export {
|
||||||
@ -242,46 +251,32 @@ impl InstanceInner {
|
|||||||
Export::Function {
|
Export::Function {
|
||||||
func,
|
func,
|
||||||
ctx: match ctx {
|
ctx: match ctx {
|
||||||
Context::Internal => Context::External(&mut *self.vmctx),
|
Context::Internal => Context::External(self.vmctx),
|
||||||
ctx @ Context::External(_) => ctx,
|
ctx @ Context::External(_) => ctx,
|
||||||
},
|
},
|
||||||
signature,
|
signature,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ExportIndex::Memory(memory_index) => {
|
ExportIndex::Memory(memory_index) => {
|
||||||
let (local, ctx, memory) = self.get_memory_from_index(module, *memory_index);
|
let memory = self.get_memory_from_index(module, *memory_index);
|
||||||
Export::Memory {
|
Export::Memory(memory)
|
||||||
local,
|
|
||||||
ctx: match ctx {
|
|
||||||
Context::Internal => Context::External(&mut *self.vmctx),
|
|
||||||
ctx @ Context::External(_) => ctx,
|
|
||||||
},
|
|
||||||
memory,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ExportIndex::Global(global_index) => {
|
ExportIndex::Global(global_index) => {
|
||||||
let (local, global) = self.get_global_from_index(module, *global_index);
|
let global = self.get_global_from_index(module, *global_index);
|
||||||
Export::Global { local, global }
|
Export::Global(global)
|
||||||
}
|
}
|
||||||
ExportIndex::Table(table_index) => {
|
ExportIndex::Table(table_index) => {
|
||||||
let (local, ctx, table) = self.get_table_from_index(module, *table_index);
|
let table = self.get_table_from_index(module, *table_index);
|
||||||
Export::Table {
|
Export::Table(table)
|
||||||
local,
|
|
||||||
ctx: match ctx {
|
|
||||||
Context::Internal => Context::External(&mut *self.vmctx),
|
|
||||||
ctx @ Context::External(_) => ctx,
|
|
||||||
},
|
|
||||||
table,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_func_from_index(
|
fn get_func_from_index(
|
||||||
&mut self,
|
&self,
|
||||||
module: &ModuleInner,
|
module: &ModuleInner,
|
||||||
func_index: FuncIndex,
|
func_index: FuncIndex,
|
||||||
) -> (FuncPointer, Context, FuncSig) {
|
) -> (FuncPointer, Context, Arc<FuncSig>) {
|
||||||
let sig_index = *module
|
let sig_index = *module
|
||||||
.func_assoc
|
.func_assoc
|
||||||
.get(func_index)
|
.get(func_index)
|
||||||
@ -298,7 +293,7 @@ impl InstanceInner {
|
|||||||
Context::Internal,
|
Context::Internal,
|
||||||
),
|
),
|
||||||
LocalOrImport::Import(imported_func_index) => {
|
LocalOrImport::Import(imported_func_index) => {
|
||||||
let imported_func = &self.import_backing.functions[imported_func_index];
|
let imported_func = &self.import_backing.vm_functions[imported_func_index];
|
||||||
(
|
(
|
||||||
imported_func.func as *const _,
|
imported_func.func as *const _,
|
||||||
Context::External(imported_func.vmctx),
|
Context::External(imported_func.vmctx),
|
||||||
@ -306,105 +301,38 @@ impl InstanceInner {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let signature = module.sig_registry.lookup_func_sig(sig_index).clone();
|
let signature = module.sig_registry.lookup_signature(sig_index);
|
||||||
|
|
||||||
(unsafe { FuncPointer::new(func_ptr) }, ctx, signature)
|
(unsafe { FuncPointer::new(func_ptr) }, ctx, signature)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_memory_from_index(
|
fn get_memory_from_index(&self, module: &ModuleInner, mem_index: MemoryIndex) -> Memory {
|
||||||
&mut self,
|
|
||||||
module: &ModuleInner,
|
|
||||||
mem_index: MemoryIndex,
|
|
||||||
) -> (MemoryPointer, Context, Memory) {
|
|
||||||
match mem_index.local_or_import(module) {
|
match mem_index.local_or_import(module) {
|
||||||
LocalOrImport::Local(local_mem_index) => {
|
LocalOrImport::Local(local_mem_index) => self.backing.memories[local_mem_index].clone(),
|
||||||
let vm_mem = &mut self.backing.vm_memories[local_mem_index];
|
|
||||||
(
|
|
||||||
unsafe { MemoryPointer::new(vm_mem) },
|
|
||||||
Context::Internal,
|
|
||||||
*module
|
|
||||||
.memories
|
|
||||||
.get(local_mem_index)
|
|
||||||
.expect("broken invariant, memories"),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
LocalOrImport::Import(imported_mem_index) => {
|
LocalOrImport::Import(imported_mem_index) => {
|
||||||
let &(_, mem) = &module
|
self.import_backing.memories[imported_mem_index].clone()
|
||||||
.imported_memories
|
|
||||||
.get(imported_mem_index)
|
|
||||||
.expect("missing imported memory index");
|
|
||||||
let vm::ImportedMemory { memory, vmctx } =
|
|
||||||
&self.import_backing.memories[imported_mem_index];
|
|
||||||
(
|
|
||||||
unsafe { MemoryPointer::new(*memory) },
|
|
||||||
Context::External(*vmctx),
|
|
||||||
*mem,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_global_from_index(
|
fn get_global_from_index(&self, module: &ModuleInner, global_index: GlobalIndex) -> Global {
|
||||||
&mut self,
|
|
||||||
module: &ModuleInner,
|
|
||||||
global_index: GlobalIndex,
|
|
||||||
) -> (GlobalPointer, GlobalDesc) {
|
|
||||||
match global_index.local_or_import(module) {
|
match global_index.local_or_import(module) {
|
||||||
LocalOrImport::Local(local_global_index) => {
|
LocalOrImport::Local(local_global_index) => {
|
||||||
let vm_global = &mut self.backing.vm_globals[local_global_index];
|
self.backing.globals[local_global_index].clone()
|
||||||
(
|
|
||||||
unsafe { GlobalPointer::new(vm_global) },
|
|
||||||
module
|
|
||||||
.globals
|
|
||||||
.get(local_global_index)
|
|
||||||
.expect("broken invariant, globals")
|
|
||||||
.desc,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
LocalOrImport::Import(imported_global_index) => {
|
LocalOrImport::Import(import_global_index) => {
|
||||||
let &(_, imported_global_desc) = &module
|
self.import_backing.globals[import_global_index].clone()
|
||||||
.imported_globals
|
|
||||||
.get(imported_global_index)
|
|
||||||
.expect("missing imported global index");
|
|
||||||
let vm::ImportedGlobal { global } =
|
|
||||||
&self.import_backing.globals[imported_global_index];
|
|
||||||
(
|
|
||||||
unsafe { GlobalPointer::new(*global) },
|
|
||||||
*imported_global_desc,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_table_from_index(
|
fn get_table_from_index(&self, module: &ModuleInner, table_index: TableIndex) -> Table {
|
||||||
&mut self,
|
|
||||||
module: &ModuleInner,
|
|
||||||
table_index: TableIndex,
|
|
||||||
) -> (TablePointer, Context, Table) {
|
|
||||||
match table_index.local_or_import(module) {
|
match table_index.local_or_import(module) {
|
||||||
LocalOrImport::Local(local_table_index) => {
|
LocalOrImport::Local(local_table_index) => {
|
||||||
let vm_table = &mut self.backing.vm_tables[local_table_index];
|
self.backing.tables[local_table_index].clone()
|
||||||
(
|
|
||||||
unsafe { TablePointer::new(vm_table) },
|
|
||||||
Context::Internal,
|
|
||||||
*module
|
|
||||||
.tables
|
|
||||||
.get(local_table_index)
|
|
||||||
.expect("broken invariant, tables"),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
LocalOrImport::Import(imported_table_index) => {
|
LocalOrImport::Import(imported_table_index) => {
|
||||||
let &(_, tab) = &module
|
self.import_backing.tables[imported_table_index].clone()
|
||||||
.imported_tables
|
|
||||||
.get(imported_table_index)
|
|
||||||
.expect("missing imported table index");
|
|
||||||
let vm::ImportedTable { table, vmctx } =
|
|
||||||
&self.import_backing.tables[imported_table_index];
|
|
||||||
(
|
|
||||||
unsafe { TablePointer::new(*table) },
|
|
||||||
Context::External(*vmctx),
|
|
||||||
*tab,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -420,9 +348,9 @@ impl LikeNamespace for Instance {
|
|||||||
|
|
||||||
/// A representation of an exported WebAssembly function.
|
/// A representation of an exported WebAssembly function.
|
||||||
pub struct Function<'a> {
|
pub struct Function<'a> {
|
||||||
signature: &'a FuncSig,
|
pub(crate) signature: Arc<FuncSig>,
|
||||||
module: &'a ModuleInner,
|
module: &'a ModuleInner,
|
||||||
instance_inner: &'a mut InstanceInner,
|
pub(crate) instance_inner: &'a InstanceInner,
|
||||||
func_index: FuncIndex,
|
func_index: FuncIndex,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -450,7 +378,7 @@ impl<'a> Function<'a> {
|
|||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn call(&mut self, params: &[Value]) -> CallResult<Vec<Value>> {
|
pub fn call(&mut self, params: &[Value]) -> CallResult<Vec<Value>> {
|
||||||
if !self.signature.check_sig(params) {
|
if !self.signature.check_param_value_types(params) {
|
||||||
Err(ResolveError::Signature {
|
Err(ResolveError::Signature {
|
||||||
expected: self.signature.clone(),
|
expected: self.signature.clone(),
|
||||||
found: params.iter().map(|val| val.ty()).collect(),
|
found: params.iter().map(|val| val.ty()).collect(),
|
||||||
@ -458,9 +386,9 @@ impl<'a> Function<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let vmctx = match self.func_index.local_or_import(self.module) {
|
let vmctx = match self.func_index.local_or_import(self.module) {
|
||||||
LocalOrImport::Local(_) => &mut *self.instance_inner.vmctx,
|
LocalOrImport::Local(_) => self.instance_inner.vmctx,
|
||||||
LocalOrImport::Import(imported_func_index) => {
|
LocalOrImport::Import(imported_func_index) => {
|
||||||
self.instance_inner.import_backing.functions[imported_func_index].vmctx
|
self.instance_inner.import_backing.vm_functions[imported_func_index].vmctx
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -479,7 +407,7 @@ impl<'a> Function<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn signature(&self) -> &FuncSig {
|
pub fn signature(&self) -> &FuncSig {
|
||||||
self.signature
|
&*self.signature
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn raw(&self) -> *const vm::Func {
|
pub fn raw(&self) -> *const vm::Func {
|
||||||
@ -491,7 +419,7 @@ impl<'a> Function<'a> {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.as_ptr(),
|
.as_ptr(),
|
||||||
LocalOrImport::Import(import_func_index) => {
|
LocalOrImport::Import(import_func_index) => {
|
||||||
self.instance_inner.import_backing.functions[import_func_index].func
|
self.instance_inner.import_backing.vm_functions[import_func_index].func
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ pub mod backend;
|
|||||||
mod backing;
|
mod backing;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
pub mod export;
|
pub mod export;
|
||||||
|
pub mod global;
|
||||||
pub mod import;
|
pub mod import;
|
||||||
pub mod instance;
|
pub mod instance;
|
||||||
pub mod memory;
|
pub mod memory;
|
||||||
@ -18,6 +19,7 @@ pub mod structures;
|
|||||||
mod sys;
|
mod sys;
|
||||||
pub mod table;
|
pub mod table;
|
||||||
pub mod types;
|
pub mod types;
|
||||||
|
pub mod units;
|
||||||
pub mod vm;
|
pub mod vm;
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub mod vmcalls;
|
pub mod vmcalls;
|
||||||
@ -29,7 +31,7 @@ pub use self::error::Result;
|
|||||||
pub use self::instance::Instance;
|
pub use self::instance::Instance;
|
||||||
#[doc(inline)]
|
#[doc(inline)]
|
||||||
pub use self::module::Module;
|
pub use self::module::Module;
|
||||||
use std::rc::Rc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
pub mod prelude {
|
pub mod prelude {
|
||||||
pub use crate::import::{ImportObject, Namespace};
|
pub use crate::import::{ImportObject, Namespace};
|
||||||
@ -39,7 +41,7 @@ pub mod prelude {
|
|||||||
MemoryIndex, TableIndex, Type, Value,
|
MemoryIndex, TableIndex, Type, Value,
|
||||||
};
|
};
|
||||||
pub use crate::vm;
|
pub use crate::vm;
|
||||||
pub use crate::{export_func, imports};
|
pub use crate::{func, imports};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Compile a [`Module`] using the provided compiler from
|
/// Compile a [`Module`] using the provided compiler from
|
||||||
@ -55,7 +57,7 @@ pub fn compile_with(
|
|||||||
let token = backend::Token::generate();
|
let token = backend::Token::generate();
|
||||||
compiler
|
compiler
|
||||||
.compile(wasm, token)
|
.compile(wasm, token)
|
||||||
.map(|inner| module::Module::new(Rc::new(inner)))
|
.map(|inner| module::Module::new(Arc::new(inner)))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Perform validation as defined by the
|
/// Perform validation as defined by the
|
||||||
|
@ -1,11 +1,20 @@
|
|||||||
|
#[macro_export]
|
||||||
|
#[cfg(feature = "debug")]
|
||||||
macro_rules! debug {
|
macro_rules! debug {
|
||||||
($fmt:expr) => (if cfg!(any(debug_assertions, feature="debug")) { println!(concat!("wasmer-runtime(:{})::", $fmt), line!()) });
|
($fmt:expr) => (println!(concat!("wasmer-runtime(:{})::", $fmt), line!()));
|
||||||
($fmt:expr, $($arg:tt)*) => (if cfg!(any(debug_assertions, feature="debug")) { println!(concat!("wasmer-runtime(:{})::", $fmt, "\n"), line!(), $($arg)*) });
|
($fmt:expr, $($arg:tt)*) => (println!(concat!("wasmer-runtime(:{})::", $fmt, "\n"), line!(), $($arg)*));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! export_func {
|
#[cfg(not(feature = "debug"))]
|
||||||
($func:ident, [ $( $params:ident ),* ] -> [ $( $returns:ident ),* ]) => {{
|
macro_rules! debug {
|
||||||
|
($fmt:expr) => {};
|
||||||
|
($fmt:expr, $($arg:tt)*) => {};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! func {
|
||||||
|
($func:ident, [ $( $params:ident ),* ] -> [ $( $returns:ident ),* ] ) => {{
|
||||||
use $crate::{
|
use $crate::{
|
||||||
export::{Context, Export, FuncPointer},
|
export::{Context, Export, FuncPointer},
|
||||||
types::{FuncSig, Type},
|
types::{FuncSig, Type},
|
||||||
@ -17,10 +26,10 @@ macro_rules! export_func {
|
|||||||
Export::Function {
|
Export::Function {
|
||||||
func: unsafe { FuncPointer::new(func as _) },
|
func: unsafe { FuncPointer::new(func as _) },
|
||||||
ctx: Context::Internal,
|
ctx: Context::Internal,
|
||||||
signature: FuncSig {
|
signature: FuncSig::new(
|
||||||
params: vec![$($crate::__export_func_convert_type!($params),)*],
|
&[$($crate::__export_func_convert_type!($params),)*] as &[Type],
|
||||||
returns: vec![$($crate::__export_func_convert_type!($returns),)*],
|
&[$($crate::__export_func_convert_type!($returns),)*] as &[Type],
|
||||||
},
|
).into(),
|
||||||
}
|
}
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
@ -62,11 +71,11 @@ macro_rules! __export_func_convert_type {
|
|||||||
///
|
///
|
||||||
/// # Usage:
|
/// # Usage:
|
||||||
/// ```
|
/// ```
|
||||||
/// # use wasmer_runtime_core::imports;
|
/// # use wasmer_runtime_core::{imports, func};
|
||||||
/// # use wasmer_runtime_core::vm::Ctx;
|
/// # use wasmer_runtime_core::vm::Ctx;
|
||||||
/// let import_object = imports! {
|
/// let import_object = imports! {
|
||||||
/// "env" => {
|
/// "env" => {
|
||||||
/// "foo" => foo<[i32] -> [i32]>,
|
/// "foo" => func!(foo, [i32] -> [i32]),
|
||||||
/// },
|
/// },
|
||||||
/// };
|
/// };
|
||||||
///
|
///
|
||||||
@ -96,13 +105,10 @@ macro_rules! imports {
|
|||||||
#[macro_export]
|
#[macro_export]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
macro_rules! __imports_internal {
|
macro_rules! __imports_internal {
|
||||||
( { $( $imp_name:expr => $func:ident < [ $( $params:ident ),* ] -> [ $( $returns:ident ),* ] >, )* } ) => {{
|
( { $( $imp_name:expr => $import_item:expr, )* } ) => {{
|
||||||
let mut ns = Namespace::new();
|
let mut ns = Namespace::new();
|
||||||
$(
|
$(
|
||||||
ns.insert($imp_name, $crate::export_func!(
|
ns.insert($imp_name, $import_item);
|
||||||
$func,
|
|
||||||
[ $( $params ),* ] -> [ $( $returns )* ]
|
|
||||||
));
|
|
||||||
)*
|
)*
|
||||||
ns
|
ns
|
||||||
}};
|
}};
|
||||||
|
@ -1,224 +0,0 @@
|
|||||||
use std::ops::{Deref, DerefMut};
|
|
||||||
|
|
||||||
use crate::{
|
|
||||||
sys,
|
|
||||||
types::{LocalMemoryIndex, Memory},
|
|
||||||
vm,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// A linear memory instance.
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct LinearMemory {
|
|
||||||
/// The actual memory allocation.
|
|
||||||
memory: sys::Memory,
|
|
||||||
|
|
||||||
/// The current number of wasm pages.
|
|
||||||
current: u32,
|
|
||||||
|
|
||||||
// The maximum size the WebAssembly Memory is allowed to grow
|
|
||||||
// to, in units of WebAssembly pages. When present, the maximum
|
|
||||||
// parameter acts as a hint to the engine to reserve memory up
|
|
||||||
// front. However, the engine may ignore or clamp this reservation
|
|
||||||
// request. In general, most WebAssembly modules shouldn't need
|
|
||||||
// to set a maximum.
|
|
||||||
max: Option<u32>,
|
|
||||||
|
|
||||||
// The size of the extra guard pages after the end.
|
|
||||||
// Is used to optimize loads and stores with constant offsets.
|
|
||||||
offset_guard_size: usize,
|
|
||||||
|
|
||||||
/// Requires exception catching to handle out-of-bounds accesses.
|
|
||||||
requires_signal_catch: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// It holds the raw bytes of memory accessed by a WebAssembly Instance
|
|
||||||
impl LinearMemory {
|
|
||||||
pub(crate) const PAGE_SIZE: u32 = 65_536;
|
|
||||||
pub(crate) const MAX_PAGES: u32 = 65_536;
|
|
||||||
#[doc(hidden)]
|
|
||||||
pub const DEFAULT_HEAP_SIZE: usize = 1 << 32; // 4 GiB
|
|
||||||
#[doc(hidden)]
|
|
||||||
pub const DEFAULT_GUARD_SIZE: usize = 1 << 31; // 2 GiB
|
|
||||||
pub(crate) const DEFAULT_SIZE: usize = Self::DEFAULT_HEAP_SIZE + Self::DEFAULT_GUARD_SIZE; // 6 GiB
|
|
||||||
|
|
||||||
/// Create a new linear memory instance with specified initial and maximum number of pages.
|
|
||||||
///
|
|
||||||
/// `maximum` cannot be set to more than `65536` pages.
|
|
||||||
pub fn new(mem: &Memory) -> Self {
|
|
||||||
assert!(mem.min <= Self::MAX_PAGES);
|
|
||||||
assert!(mem.max.is_none() || mem.max.unwrap() <= Self::MAX_PAGES);
|
|
||||||
|
|
||||||
let (mmap_size, initial_pages, offset_guard_size, requires_signal_catch) = if
|
|
||||||
/*mem.is_static_heap()*/
|
|
||||||
true {
|
|
||||||
(Self::DEFAULT_SIZE, mem.min, Self::DEFAULT_GUARD_SIZE, true)
|
|
||||||
// This is a static heap
|
|
||||||
} else {
|
|
||||||
// this is a dynamic heap
|
|
||||||
assert!(!mem.shared, "shared memories must have a maximum size.");
|
|
||||||
|
|
||||||
(
|
|
||||||
mem.min as usize * Self::PAGE_SIZE as usize,
|
|
||||||
mem.min,
|
|
||||||
0,
|
|
||||||
false,
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut memory = sys::Memory::with_size(mmap_size).unwrap();
|
|
||||||
|
|
||||||
// map initial pages as readwrite since the inital mmap is mapped as not accessible.
|
|
||||||
if initial_pages != 0 {
|
|
||||||
unsafe {
|
|
||||||
memory
|
|
||||||
.protect(
|
|
||||||
0..(initial_pages as usize * Self::PAGE_SIZE as usize),
|
|
||||||
sys::Protect::ReadWrite,
|
|
||||||
)
|
|
||||||
.expect("unable to make memory accessible");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Self {
|
|
||||||
memory,
|
|
||||||
current: initial_pages,
|
|
||||||
max: mem.max,
|
|
||||||
offset_guard_size,
|
|
||||||
requires_signal_catch,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns an base address of this linear memory.
|
|
||||||
fn base(&mut self) -> *mut u8 {
|
|
||||||
self.memory.as_ptr()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the size in bytes
|
|
||||||
pub(crate) fn size(&self) -> usize {
|
|
||||||
self.current as usize * Self::PAGE_SIZE as usize
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn pages(&self) -> u32 {
|
|
||||||
self.current
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the maximum number of wasm pages allowed.
|
|
||||||
pub fn max(&self) -> u32 {
|
|
||||||
self.max.unwrap_or(Self::MAX_PAGES)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn into_vm_memory(&mut self, index: LocalMemoryIndex) -> vm::LocalMemory {
|
|
||||||
vm::LocalMemory {
|
|
||||||
base: self.base(),
|
|
||||||
size: self.size(),
|
|
||||||
index,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Grow memory by the specified amount of pages.
|
|
||||||
///
|
|
||||||
/// Returns `None` if memory can't be grown by the specified amount
|
|
||||||
/// of pages.
|
|
||||||
pub(crate) fn grow_dynamic(&mut self, add_pages: u32) -> Option<i32> {
|
|
||||||
debug!("grow_memory_dynamic called!");
|
|
||||||
assert!(self.max.is_none());
|
|
||||||
if add_pages == 0 {
|
|
||||||
return Some(self.current as _);
|
|
||||||
}
|
|
||||||
|
|
||||||
let prev_pages = self.current;
|
|
||||||
|
|
||||||
let new_pages = match self.current.checked_add(add_pages) {
|
|
||||||
Some(new_pages) => new_pages,
|
|
||||||
None => return None,
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(val) = self.max {
|
|
||||||
if new_pages > val {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
// Wasm linear memories are never allowed to grow beyond what is
|
|
||||||
// indexable. If the memory has no maximum, enforce the greatest
|
|
||||||
// limit here.
|
|
||||||
} else if new_pages >= Self::MAX_PAGES {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
let new_bytes = (new_pages * Self::PAGE_SIZE) as usize;
|
|
||||||
|
|
||||||
if new_bytes > self.memory.size() - self.offset_guard_size {
|
|
||||||
let memory_size = new_bytes.checked_add(self.offset_guard_size)?;
|
|
||||||
let mut new_memory = sys::Memory::with_size(memory_size).ok()?;
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
new_memory
|
|
||||||
.protect(0..new_bytes, sys::Protect::ReadWrite)
|
|
||||||
.ok()?;
|
|
||||||
}
|
|
||||||
|
|
||||||
let copy_size = self.memory.size() - self.offset_guard_size;
|
|
||||||
unsafe {
|
|
||||||
new_memory.as_slice_mut()[..copy_size]
|
|
||||||
.copy_from_slice(&self.memory.as_slice()[..copy_size]);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.memory = new_memory;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.current = new_pages;
|
|
||||||
|
|
||||||
Some(prev_pages as i32)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn grow_static(&mut self, add_pages: u32) -> Option<i32> {
|
|
||||||
// debug!("grow_memory_static called!");
|
|
||||||
// assert!(self.max.is_some());
|
|
||||||
if add_pages == 0 {
|
|
||||||
return Some(self.current as _);
|
|
||||||
}
|
|
||||||
|
|
||||||
let prev_pages = self.current;
|
|
||||||
|
|
||||||
let new_pages = match self.current.checked_add(add_pages) {
|
|
||||||
Some(new_pages) => new_pages,
|
|
||||||
None => return None,
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(val) = self.max {
|
|
||||||
if new_pages > val {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
// Wasm linear memories are never allowed to grow beyond what is
|
|
||||||
// indexable. If the memory has no maximum, enforce the greatest
|
|
||||||
// limit here.
|
|
||||||
} else if new_pages >= Self::MAX_PAGES {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
let prev_bytes = (prev_pages * Self::PAGE_SIZE) as usize;
|
|
||||||
let new_bytes = (new_pages * Self::PAGE_SIZE) as usize;
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
self.memory
|
|
||||||
.protect(prev_bytes..new_bytes, sys::Protect::ReadWrite)
|
|
||||||
.ok()?;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.current = new_pages;
|
|
||||||
|
|
||||||
Some(prev_pages as i32)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Deref for LinearMemory {
|
|
||||||
type Target = [u8];
|
|
||||||
fn deref(&self) -> &[u8] {
|
|
||||||
unsafe { self.memory.as_slice() }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DerefMut for LinearMemory {
|
|
||||||
fn deref_mut(&mut self) -> &mut [u8] {
|
|
||||||
unsafe { self.memory.as_slice_mut() }
|
|
||||||
}
|
|
||||||
}
|
|
110
lib/runtime-core/src/memory/dynamic.rs
Normal file
110
lib/runtime-core/src/memory/dynamic.rs
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
use crate::{
|
||||||
|
error::CreationError,
|
||||||
|
sys,
|
||||||
|
types::MemoryDescriptor,
|
||||||
|
units::{Bytes, Pages},
|
||||||
|
vm,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const DYNAMIC_GUARD_SIZE: usize = 4096;
|
||||||
|
|
||||||
|
/// This is an internal-only api.
|
||||||
|
///
|
||||||
|
/// A Dynamic memory allocates only the minimum amount of memory
|
||||||
|
/// when first created. Over time, as it grows, it may reallocate to
|
||||||
|
/// a different location and size.
|
||||||
|
///
|
||||||
|
/// Dynamic memories are signifigantly faster to create than static
|
||||||
|
/// memories and use much less virtual memory, however, they require
|
||||||
|
/// the webassembly module to bounds-check memory accesses.
|
||||||
|
///
|
||||||
|
/// While, a dynamic memory could use a vector of some sort as its
|
||||||
|
/// backing memory, we use mmap (or the platform-equivalent) to allow
|
||||||
|
/// us to add a guard-page at the end to help elide some bounds-checks.
|
||||||
|
pub struct DynamicMemory {
|
||||||
|
memory: sys::Memory,
|
||||||
|
current: Pages,
|
||||||
|
max: Option<Pages>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DynamicMemory {
|
||||||
|
pub(super) fn new(
|
||||||
|
desc: MemoryDescriptor,
|
||||||
|
local: &mut vm::LocalMemory,
|
||||||
|
) -> Result<Box<Self>, CreationError> {
|
||||||
|
let min_bytes: Bytes = desc.minimum.into();
|
||||||
|
let memory = {
|
||||||
|
let mut memory = sys::Memory::with_size(min_bytes.0 + DYNAMIC_GUARD_SIZE)
|
||||||
|
.map_err(|_| CreationError::UnableToCreateMemory)?;
|
||||||
|
if desc.minimum != Pages(0) {
|
||||||
|
unsafe {
|
||||||
|
memory
|
||||||
|
.protect(0..min_bytes.0, sys::Protect::ReadWrite)
|
||||||
|
.map_err(|_| CreationError::UnableToCreateMemory)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
memory
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut storage = Box::new(DynamicMemory {
|
||||||
|
memory,
|
||||||
|
current: desc.minimum,
|
||||||
|
max: desc.maximum,
|
||||||
|
});
|
||||||
|
let storage_ptr: *mut DynamicMemory = &mut *storage;
|
||||||
|
|
||||||
|
local.base = storage.memory.as_ptr();
|
||||||
|
local.bound = min_bytes.0;
|
||||||
|
local.memory = storage_ptr as *mut ();
|
||||||
|
|
||||||
|
Ok(storage)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn size(&self) -> Pages {
|
||||||
|
self.current
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn grow(&mut self, delta: Pages, local: &mut vm::LocalMemory) -> Option<Pages> {
|
||||||
|
if delta == Pages(0) {
|
||||||
|
return Some(self.current);
|
||||||
|
}
|
||||||
|
|
||||||
|
let new_pages = self.current.checked_add(delta)?;
|
||||||
|
|
||||||
|
if let Some(max) = self.max {
|
||||||
|
if new_pages > max {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut new_memory =
|
||||||
|
sys::Memory::with_size(new_pages.bytes().0 + DYNAMIC_GUARD_SIZE).ok()?;
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
new_memory
|
||||||
|
.protect(0..new_pages.bytes().0, sys::Protect::ReadWrite)
|
||||||
|
.ok()?;
|
||||||
|
|
||||||
|
new_memory.as_slice_mut()[..self.current.bytes().0]
|
||||||
|
.copy_from_slice(&self.memory.as_slice()[..self.current.bytes().0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.memory = new_memory; //The old memory gets dropped.
|
||||||
|
|
||||||
|
local.base = self.memory.as_ptr();
|
||||||
|
local.bound = new_pages.bytes().0;
|
||||||
|
|
||||||
|
let old_pages = self.current;
|
||||||
|
self.current = new_pages;
|
||||||
|
Some(old_pages)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_slice(&self) -> &[u8] {
|
||||||
|
unsafe { &self.memory.as_slice()[0..self.current.bytes().0] }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_slice_mut(&mut self) -> &mut [u8] {
|
||||||
|
unsafe { &mut self.memory.as_slice_mut()[0..self.current.bytes().0] }
|
||||||
|
}
|
||||||
|
}
|
303
lib/runtime-core/src/memory/mod.rs
Normal file
303
lib/runtime-core/src/memory/mod.rs
Normal file
@ -0,0 +1,303 @@
|
|||||||
|
use crate::{
|
||||||
|
error::CreationError,
|
||||||
|
export::Export,
|
||||||
|
import::IsExport,
|
||||||
|
memory::dynamic::DYNAMIC_GUARD_SIZE,
|
||||||
|
memory::static_::{SAFE_STATIC_GUARD_SIZE, SAFE_STATIC_HEAP_SIZE},
|
||||||
|
types::{MemoryDescriptor, ValueType},
|
||||||
|
units::Pages,
|
||||||
|
vm,
|
||||||
|
};
|
||||||
|
use std::{cell::RefCell, fmt, mem, ptr, rc::Rc, slice};
|
||||||
|
|
||||||
|
pub use self::dynamic::DynamicMemory;
|
||||||
|
pub use self::static_::{SharedStaticMemory, StaticMemory};
|
||||||
|
|
||||||
|
mod dynamic;
|
||||||
|
mod static_;
|
||||||
|
|
||||||
|
pub struct Memory {
|
||||||
|
desc: MemoryDescriptor,
|
||||||
|
storage: Rc<RefCell<(MemoryStorage, Box<vm::LocalMemory>)>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Memory {
|
||||||
|
/// Create a new `Memory` from a [`MemoryDescriptor`]
|
||||||
|
///
|
||||||
|
/// [`MemoryDescriptor`]: struct.MemoryDescriptor.html
|
||||||
|
///
|
||||||
|
/// Usage:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use wasmer_runtime_core::types::MemoryDescriptor;
|
||||||
|
/// # use wasmer_runtime_core::memory::Memory;
|
||||||
|
/// # use wasmer_runtime_core::error::Result;
|
||||||
|
/// # use wasmer_runtime_core::units::Pages;
|
||||||
|
/// # fn create_memory() -> Result<()> {
|
||||||
|
/// let descriptor = MemoryDescriptor {
|
||||||
|
/// minimum: Pages(10),
|
||||||
|
/// maximum: None,
|
||||||
|
/// shared: false,
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// let memory = Memory::new(descriptor)?;
|
||||||
|
/// # Ok(())
|
||||||
|
/// # }
|
||||||
|
/// ```
|
||||||
|
pub fn new(desc: MemoryDescriptor) -> Result<Self, CreationError> {
|
||||||
|
let mut vm_local_memory = Box::new(vm::LocalMemory {
|
||||||
|
base: ptr::null_mut(),
|
||||||
|
bound: 0,
|
||||||
|
memory: ptr::null_mut(),
|
||||||
|
});
|
||||||
|
|
||||||
|
let memory_storage = match desc.memory_type() {
|
||||||
|
MemoryType::Dynamic => {
|
||||||
|
MemoryStorage::Dynamic(DynamicMemory::new(desc, &mut vm_local_memory)?)
|
||||||
|
}
|
||||||
|
MemoryType::Static => {
|
||||||
|
MemoryStorage::Static(StaticMemory::new(desc, &mut vm_local_memory)?)
|
||||||
|
}
|
||||||
|
MemoryType::SharedStatic => unimplemented!("shared memories are not yet implemented"),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(Memory {
|
||||||
|
desc,
|
||||||
|
storage: Rc::new(RefCell::new((memory_storage, vm_local_memory))),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the [`MemoryDescriptor`] that this memory
|
||||||
|
/// was created with.
|
||||||
|
///
|
||||||
|
/// [`MemoryDescriptor`]: struct.MemoryDescriptor.html
|
||||||
|
pub fn descriptor(&self) -> MemoryDescriptor {
|
||||||
|
self.desc
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Grow this memory by the specfied number of pages.
|
||||||
|
pub fn grow(&mut self, delta: Pages) -> Option<Pages> {
|
||||||
|
match &mut *self.storage.borrow_mut() {
|
||||||
|
(MemoryStorage::Dynamic(ref mut dynamic_memory), ref mut local) => {
|
||||||
|
dynamic_memory.grow(delta, local)
|
||||||
|
}
|
||||||
|
(MemoryStorage::Static(ref mut static_memory), ref mut local) => {
|
||||||
|
static_memory.grow(delta, local)
|
||||||
|
}
|
||||||
|
(MemoryStorage::SharedStatic(_), _) => unimplemented!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The size, in wasm pages, of this memory.
|
||||||
|
pub fn size(&self) -> Pages {
|
||||||
|
match &*self.storage.borrow() {
|
||||||
|
(MemoryStorage::Dynamic(ref dynamic_memory), _) => dynamic_memory.size(),
|
||||||
|
(MemoryStorage::Static(ref static_memory), _) => static_memory.size(),
|
||||||
|
(MemoryStorage::SharedStatic(_), _) => unimplemented!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read<T: ValueType>(&self, offset: u32) -> Result<T, ()> {
|
||||||
|
let offset = offset as usize;
|
||||||
|
let borrow_ref = self.storage.borrow();
|
||||||
|
let memory_storage = &borrow_ref.0;
|
||||||
|
|
||||||
|
let mem_slice = match memory_storage {
|
||||||
|
MemoryStorage::Dynamic(ref dynamic_memory) => dynamic_memory.as_slice(),
|
||||||
|
MemoryStorage::Static(ref static_memory) => static_memory.as_slice(),
|
||||||
|
MemoryStorage::SharedStatic(_) => panic!("cannot slice a shared memory"),
|
||||||
|
};
|
||||||
|
|
||||||
|
if offset + mem::size_of::<T>() <= mem_slice.len() {
|
||||||
|
T::from_le(&mem_slice[offset..]).map_err(|_| ())
|
||||||
|
} else {
|
||||||
|
Err(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write<T: ValueType>(&self, offset: u32, value: T) -> Result<(), ()> {
|
||||||
|
let offset = offset as usize;
|
||||||
|
let mut borrow_ref = self.storage.borrow_mut();
|
||||||
|
let memory_storage = &mut borrow_ref.0;
|
||||||
|
|
||||||
|
let mem_slice = match memory_storage {
|
||||||
|
MemoryStorage::Dynamic(ref mut dynamic_memory) => dynamic_memory.as_slice_mut(),
|
||||||
|
MemoryStorage::Static(ref mut static_memory) => static_memory.as_slice_mut(),
|
||||||
|
MemoryStorage::SharedStatic(_) => panic!("cannot slice a shared memory"),
|
||||||
|
};
|
||||||
|
|
||||||
|
if offset + mem::size_of::<T>() <= mem_slice.len() {
|
||||||
|
value.into_le(&mut mem_slice[offset..]);
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_many<T: ValueType>(&self, offset: u32, count: usize) -> Result<Vec<T>, ()> {
|
||||||
|
let offset = offset as usize;
|
||||||
|
let borrow_ref = self.storage.borrow();
|
||||||
|
let memory_storage = &borrow_ref.0;
|
||||||
|
|
||||||
|
let mem_slice = match memory_storage {
|
||||||
|
MemoryStorage::Dynamic(ref dynamic_memory) => dynamic_memory.as_slice(),
|
||||||
|
MemoryStorage::Static(ref static_memory) => static_memory.as_slice(),
|
||||||
|
MemoryStorage::SharedStatic(_) => panic!("cannot slice a shared memory"),
|
||||||
|
};
|
||||||
|
|
||||||
|
let bytes_size = count * mem::size_of::<T>();
|
||||||
|
|
||||||
|
if offset + bytes_size <= mem_slice.len() {
|
||||||
|
let buffer = &mem_slice[offset..offset + bytes_size];
|
||||||
|
let value_type_buffer = unsafe {
|
||||||
|
slice::from_raw_parts(
|
||||||
|
buffer.as_ptr() as *const T,
|
||||||
|
buffer.len() / mem::size_of::<T>(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
Ok(value_type_buffer.to_vec())
|
||||||
|
} else {
|
||||||
|
Err(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_many<T: ValueType>(&self, offset: u32, values: &[T]) -> Result<(), ()> {
|
||||||
|
let offset = offset as usize;
|
||||||
|
let mut borrow_ref = self.storage.borrow_mut();
|
||||||
|
let memory_storage = &mut borrow_ref.0;
|
||||||
|
|
||||||
|
let mem_slice = match memory_storage {
|
||||||
|
MemoryStorage::Dynamic(ref mut dynamic_memory) => dynamic_memory.as_slice_mut(),
|
||||||
|
MemoryStorage::Static(ref mut static_memory) => static_memory.as_slice_mut(),
|
||||||
|
MemoryStorage::SharedStatic(_) => panic!("cannot slice a shared memory"),
|
||||||
|
};
|
||||||
|
|
||||||
|
let bytes_size = values.len() * mem::size_of::<T>();
|
||||||
|
|
||||||
|
if offset + bytes_size <= mem_slice.len() {
|
||||||
|
let u8_buffer =
|
||||||
|
unsafe { slice::from_raw_parts(values.as_ptr() as *const u8, bytes_size) };
|
||||||
|
mem_slice[offset..offset + bytes_size].copy_from_slice(u8_buffer);
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn direct_access<T: ValueType, F, R>(&self, f: F) -> R
|
||||||
|
where
|
||||||
|
F: FnOnce(&[T]) -> R,
|
||||||
|
{
|
||||||
|
let borrow_ref = self.storage.borrow();
|
||||||
|
let memory_storage = &borrow_ref.0;
|
||||||
|
|
||||||
|
let mem_slice = match memory_storage {
|
||||||
|
MemoryStorage::Dynamic(ref dynamic_memory) => dynamic_memory.as_slice(),
|
||||||
|
MemoryStorage::Static(ref static_memory) => static_memory.as_slice(),
|
||||||
|
MemoryStorage::SharedStatic(_) => panic!("cannot slice a shared memory"),
|
||||||
|
};
|
||||||
|
|
||||||
|
let t_buffer = unsafe {
|
||||||
|
slice::from_raw_parts(
|
||||||
|
mem_slice.as_ptr() as *const T,
|
||||||
|
mem_slice.len() / mem::size_of::<T>(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
f(t_buffer)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn direct_access_mut<T: ValueType, F, R>(&self, f: F) -> R
|
||||||
|
where
|
||||||
|
F: FnOnce(&mut [T]) -> R,
|
||||||
|
{
|
||||||
|
let mut borrow_ref = self.storage.borrow_mut();
|
||||||
|
let memory_storage = &mut borrow_ref.0;
|
||||||
|
|
||||||
|
let mem_slice = match memory_storage {
|
||||||
|
MemoryStorage::Dynamic(ref mut dynamic_memory) => dynamic_memory.as_slice_mut(),
|
||||||
|
MemoryStorage::Static(ref mut static_memory) => static_memory.as_slice_mut(),
|
||||||
|
MemoryStorage::SharedStatic(_) => panic!("cannot slice a shared memory"),
|
||||||
|
};
|
||||||
|
|
||||||
|
let t_buffer = unsafe {
|
||||||
|
slice::from_raw_parts_mut(
|
||||||
|
mem_slice.as_mut_ptr() as *mut T,
|
||||||
|
mem_slice.len() / mem::size_of::<T>(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
f(t_buffer)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn vm_local_memory(&mut self) -> *mut vm::LocalMemory {
|
||||||
|
&mut *self.storage.borrow_mut().1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IsExport for Memory {
|
||||||
|
fn to_export(&mut self) -> Export {
|
||||||
|
Export::Memory(self.clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Clone for Memory {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
Self {
|
||||||
|
desc: self.desc,
|
||||||
|
storage: Rc::clone(&self.storage),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum MemoryStorage {
|
||||||
|
Dynamic(Box<DynamicMemory>),
|
||||||
|
Static(Box<StaticMemory>),
|
||||||
|
SharedStatic(Box<SharedStaticMemory>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MemoryStorage {
|
||||||
|
pub fn to_type(&self) -> MemoryType {
|
||||||
|
match self {
|
||||||
|
MemoryStorage::Dynamic(_) => MemoryType::Dynamic,
|
||||||
|
MemoryStorage::Static(_) => MemoryType::Static,
|
||||||
|
MemoryStorage::SharedStatic(_) => MemoryType::SharedStatic,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub enum MemoryType {
|
||||||
|
Dynamic,
|
||||||
|
Static,
|
||||||
|
SharedStatic,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MemoryType {
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub fn guard_size(self) -> u64 {
|
||||||
|
match self {
|
||||||
|
MemoryType::Dynamic => DYNAMIC_GUARD_SIZE as u64,
|
||||||
|
MemoryType::Static => SAFE_STATIC_GUARD_SIZE as u64,
|
||||||
|
MemoryType::SharedStatic => SAFE_STATIC_GUARD_SIZE as u64,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub fn bounds(self) -> Option<u64> {
|
||||||
|
match self {
|
||||||
|
MemoryType::Dynamic => None,
|
||||||
|
MemoryType::Static => Some(SAFE_STATIC_HEAP_SIZE as u64),
|
||||||
|
MemoryType::SharedStatic => Some(SAFE_STATIC_HEAP_SIZE as u64),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for Memory {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
f.debug_struct("Memory")
|
||||||
|
.field("desc", &self.desc)
|
||||||
|
.field("size", &self.size())
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
10
lib/runtime-core/src/memory/static_/mod.rs
Normal file
10
lib/runtime-core/src/memory/static_/mod.rs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#[doc(hidden)]
|
||||||
|
pub const SAFE_STATIC_HEAP_SIZE: usize = 1 << 32; // 4 GiB
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub const SAFE_STATIC_GUARD_SIZE: usize = 1 << 31; // 2 GiB
|
||||||
|
|
||||||
|
mod shared;
|
||||||
|
mod unshared;
|
||||||
|
|
||||||
|
pub use self::shared::SharedStaticMemory;
|
||||||
|
pub use self::unshared::StaticMemory;
|
11
lib/runtime-core/src/memory/static_/shared.rs
Normal file
11
lib/runtime-core/src/memory/static_/shared.rs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
use crate::sys;
|
||||||
|
use parking_lot::Mutex;
|
||||||
|
use std::sync::atomic::AtomicUsize;
|
||||||
|
|
||||||
|
// Remove this attribute once this is used.
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub struct SharedStaticMemory {
|
||||||
|
memory: sys::Memory,
|
||||||
|
current: AtomicUsize,
|
||||||
|
lock: Mutex<()>,
|
||||||
|
}
|
102
lib/runtime-core/src/memory/static_/unshared.rs
Normal file
102
lib/runtime-core/src/memory/static_/unshared.rs
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
use crate::{
|
||||||
|
error::CreationError,
|
||||||
|
memory::static_::{SAFE_STATIC_GUARD_SIZE, SAFE_STATIC_HEAP_SIZE},
|
||||||
|
sys,
|
||||||
|
types::MemoryDescriptor,
|
||||||
|
units::Pages,
|
||||||
|
vm,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// This is an internal-only api.
|
||||||
|
///
|
||||||
|
/// A static memory allocates 6GB of *virtual* memory when created
|
||||||
|
/// in order to allow the webassembly module to contain no bounds-checks.
|
||||||
|
///
|
||||||
|
/// Additionally, static memories stay at a single virtual address, so there is no need
|
||||||
|
/// to reload its address on each use.
|
||||||
|
///
|
||||||
|
/// Static memories take a relatively long time to create, so if memories are short-lived,
|
||||||
|
/// it's recommended that a dynamic memory is used. There is currently no user-facing api that
|
||||||
|
/// allows them to select the type of memory used however.
|
||||||
|
pub struct StaticMemory {
|
||||||
|
memory: sys::Memory,
|
||||||
|
current: Pages,
|
||||||
|
max: Option<Pages>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StaticMemory {
|
||||||
|
pub(in crate::memory) fn new(
|
||||||
|
desc: MemoryDescriptor,
|
||||||
|
local: &mut vm::LocalMemory,
|
||||||
|
) -> Result<Box<Self>, CreationError> {
|
||||||
|
let memory = {
|
||||||
|
let mut memory = sys::Memory::with_size(SAFE_STATIC_HEAP_SIZE + SAFE_STATIC_GUARD_SIZE)
|
||||||
|
.map_err(|_| CreationError::UnableToCreateMemory)?;
|
||||||
|
if desc.minimum != Pages(0) {
|
||||||
|
unsafe {
|
||||||
|
memory
|
||||||
|
.protect(0..desc.minimum.bytes().0, sys::Protect::ReadWrite)
|
||||||
|
.map_err(|_| CreationError::UnableToCreateMemory)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
memory
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut storage = Box::new(StaticMemory {
|
||||||
|
memory,
|
||||||
|
current: desc.minimum,
|
||||||
|
max: desc.maximum,
|
||||||
|
});
|
||||||
|
let storage_ptr: *mut StaticMemory = &mut *storage;
|
||||||
|
|
||||||
|
local.base = storage.memory.as_ptr();
|
||||||
|
local.bound = desc.minimum.bytes().0;
|
||||||
|
local.memory = storage_ptr as *mut ();
|
||||||
|
|
||||||
|
Ok(storage)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn size(&self) -> Pages {
|
||||||
|
self.current
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn grow(&mut self, delta: Pages, local: &mut vm::LocalMemory) -> Option<Pages> {
|
||||||
|
if delta == Pages(0) {
|
||||||
|
return Some(self.current);
|
||||||
|
}
|
||||||
|
|
||||||
|
let new_pages = self.current.checked_add(delta)?;
|
||||||
|
|
||||||
|
if let Some(max) = self.max {
|
||||||
|
if new_pages > max {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
self.memory
|
||||||
|
.protect(
|
||||||
|
self.current.bytes().0..new_pages.bytes().0,
|
||||||
|
sys::Protect::ReadWrite,
|
||||||
|
)
|
||||||
|
.ok()?;
|
||||||
|
}
|
||||||
|
|
||||||
|
local.bound = new_pages.bytes().0;
|
||||||
|
|
||||||
|
let old_pages = self.current;
|
||||||
|
|
||||||
|
self.current = new_pages;
|
||||||
|
|
||||||
|
Some(old_pages)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_slice(&self) -> &[u8] {
|
||||||
|
unsafe { &self.memory.as_slice()[0..self.current.bytes().0] }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_slice_mut(&mut self) -> &mut [u8] {
|
||||||
|
unsafe { &mut self.memory.as_slice_mut()[0..self.current.bytes().0] }
|
||||||
|
}
|
||||||
|
}
|
@ -5,14 +5,15 @@ use crate::{
|
|||||||
sig_registry::SigRegistry,
|
sig_registry::SigRegistry,
|
||||||
structures::Map,
|
structures::Map,
|
||||||
types::{
|
types::{
|
||||||
FuncIndex, Global, GlobalDesc, GlobalIndex, ImportedFuncIndex, ImportedGlobalIndex,
|
FuncIndex, GlobalDescriptor, GlobalIndex, GlobalInit, ImportedFuncIndex,
|
||||||
ImportedMemoryIndex, ImportedTableIndex, Initializer, LocalGlobalIndex, LocalMemoryIndex,
|
ImportedGlobalIndex, ImportedMemoryIndex, ImportedTableIndex, Initializer,
|
||||||
LocalTableIndex, Memory, MemoryIndex, SigIndex, Table, TableIndex,
|
LocalGlobalIndex, LocalMemoryIndex, LocalTableIndex, MemoryDescriptor, MemoryIndex,
|
||||||
|
SigIndex, TableDescriptor, TableIndex,
|
||||||
},
|
},
|
||||||
Instance,
|
Instance,
|
||||||
};
|
};
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
use std::rc::Rc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
/// This is used to instantiate a new WebAssembly module.
|
/// This is used to instantiate a new WebAssembly module.
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
@ -21,15 +22,15 @@ pub struct ModuleInner {
|
|||||||
pub protected_caller: Box<dyn ProtectedCaller>,
|
pub protected_caller: Box<dyn ProtectedCaller>,
|
||||||
|
|
||||||
// This are strictly local and the typsystem ensures that.
|
// This are strictly local and the typsystem ensures that.
|
||||||
pub memories: Map<LocalMemoryIndex, Memory>,
|
pub memories: Map<LocalMemoryIndex, MemoryDescriptor>,
|
||||||
pub globals: Map<LocalGlobalIndex, Global>,
|
pub globals: Map<LocalGlobalIndex, GlobalInit>,
|
||||||
pub tables: Map<LocalTableIndex, Table>,
|
pub tables: Map<LocalTableIndex, TableDescriptor>,
|
||||||
|
|
||||||
// These are strictly imported and the typesystem ensures that.
|
// These are strictly imported and the typesystem ensures that.
|
||||||
pub imported_functions: Map<ImportedFuncIndex, ImportName>,
|
pub imported_functions: Map<ImportedFuncIndex, ImportName>,
|
||||||
pub imported_memories: Map<ImportedMemoryIndex, (ImportName, Memory)>,
|
pub imported_memories: Map<ImportedMemoryIndex, (ImportName, MemoryDescriptor)>,
|
||||||
pub imported_tables: Map<ImportedTableIndex, (ImportName, Table)>,
|
pub imported_tables: Map<ImportedTableIndex, (ImportName, TableDescriptor)>,
|
||||||
pub imported_globals: Map<ImportedGlobalIndex, (ImportName, GlobalDesc)>,
|
pub imported_globals: Map<ImportedGlobalIndex, (ImportName, GlobalDescriptor)>,
|
||||||
|
|
||||||
pub exports: HashMap<String, ExportIndex>,
|
pub exports: HashMap<String, ExportIndex>,
|
||||||
|
|
||||||
@ -49,10 +50,10 @@ pub struct ModuleInner {
|
|||||||
///
|
///
|
||||||
/// [`compile`]: fn.compile.html
|
/// [`compile`]: fn.compile.html
|
||||||
/// [`compile_with`]: fn.compile_with.html
|
/// [`compile_with`]: fn.compile_with.html
|
||||||
pub struct Module(#[doc(hidden)] pub Rc<ModuleInner>);
|
pub struct Module(#[doc(hidden)] pub Arc<ModuleInner>);
|
||||||
|
|
||||||
impl Module {
|
impl Module {
|
||||||
pub(crate) fn new(inner: Rc<ModuleInner>) -> Self {
|
pub(crate) fn new(inner: Arc<ModuleInner>) -> Self {
|
||||||
Module(inner)
|
Module(inner)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,7 +80,7 @@ impl Module {
|
|||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn instantiate(&self, import_object: ImportObject) -> Result<Instance> {
|
pub fn instantiate(&self, import_object: ImportObject) -> Result<Instance> {
|
||||||
Instance::new(Rc::clone(&self.0), Box::new(import_object))
|
Instance::new(Arc::clone(&self.0), Box::new(import_object))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,39 +3,50 @@ use crate::{
|
|||||||
types::{FuncSig, SigIndex},
|
types::{FuncSig, SigIndex},
|
||||||
};
|
};
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
|
use lazy_static::lazy_static;
|
||||||
|
use parking_lot::RwLock;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
#[derive(Debug)]
|
lazy_static! {
|
||||||
pub struct SigRegistry {
|
static ref GLOBAL_SIG_REGISTRY: RwLock<GlobalSigRegistry> = {
|
||||||
func_table: HashMap<FuncSig, SigIndex>,
|
let registry = GlobalSigRegistry {
|
||||||
sig_assoc: Map<SigIndex, FuncSig>,
|
|
||||||
duplicated_sig_assoc: Map<SigIndex, SigIndex>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SigRegistry {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
func_table: HashMap::new(),
|
func_table: HashMap::new(),
|
||||||
sig_assoc: Map::new(),
|
sig_assoc: Map::new(),
|
||||||
duplicated_sig_assoc: Map::new(),
|
};
|
||||||
}
|
|
||||||
}
|
RwLock::new(registry)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
struct GlobalSigRegistry {
|
||||||
|
func_table: HashMap<Arc<FuncSig>, SigIndex>,
|
||||||
|
sig_assoc: Map<SigIndex, Arc<FuncSig>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct SigRegistry;
|
||||||
|
|
||||||
|
impl SigRegistry {
|
||||||
|
pub fn lookup_sig_index<Sig>(&self, func_sig: Sig) -> SigIndex
|
||||||
|
where
|
||||||
|
Sig: Into<Arc<FuncSig>>,
|
||||||
|
{
|
||||||
|
let func_sig = func_sig.into();
|
||||||
|
let mut global = (*GLOBAL_SIG_REGISTRY).write();
|
||||||
|
let global = &mut *global;
|
||||||
|
|
||||||
|
let func_table = &mut global.func_table;
|
||||||
|
let sig_assoc = &mut global.sig_assoc;
|
||||||
|
|
||||||
pub fn register(&mut self, func_sig: FuncSig) -> SigIndex {
|
|
||||||
// self.sig_assoc.push(func_sig)
|
|
||||||
let func_table = &mut self.func_table;
|
|
||||||
let sig_assoc = &mut self.sig_assoc;
|
|
||||||
let sig_index = *func_table
|
let sig_index = *func_table
|
||||||
.entry(func_sig.clone())
|
.entry(Arc::clone(&func_sig))
|
||||||
.or_insert_with(|| sig_assoc.push(func_sig));
|
.or_insert_with(|| sig_assoc.push(func_sig));
|
||||||
self.duplicated_sig_assoc.push(sig_index);
|
|
||||||
sig_index
|
sig_index
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn lookup_deduplicated_sigindex(&self, sig_index: SigIndex) -> SigIndex {
|
pub fn lookup_signature(&self, sig_index: SigIndex) -> Arc<FuncSig> {
|
||||||
self.duplicated_sig_assoc[sig_index]
|
let global = (*GLOBAL_SIG_REGISTRY).read();
|
||||||
}
|
Arc::clone(&global.sig_assoc[sig_index])
|
||||||
|
|
||||||
pub fn lookup_func_sig(&self, sig_index: SigIndex) -> &FuncSig {
|
|
||||||
&self.sig_assoc[sig_index]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,9 @@ use page_size;
|
|||||||
use std::ops::{Bound, RangeBounds};
|
use std::ops::{Bound, RangeBounds};
|
||||||
use std::{ptr, slice};
|
use std::{ptr, slice};
|
||||||
|
|
||||||
|
unsafe impl Send for Memory {}
|
||||||
|
unsafe impl Sync for Memory {}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Memory {
|
pub struct Memory {
|
||||||
ptr: *mut u8,
|
ptr: *mut u8,
|
||||||
|
@ -7,6 +7,9 @@ use page_size;
|
|||||||
use std::ops::{Bound, RangeBounds};
|
use std::ops::{Bound, RangeBounds};
|
||||||
use std::{ptr, slice};
|
use std::{ptr, slice};
|
||||||
|
|
||||||
|
unsafe impl Send for Memory {}
|
||||||
|
unsafe impl Sync for Memory {}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Memory {
|
pub struct Memory {
|
||||||
ptr: *mut u8,
|
ptr: *mut u8,
|
||||||
|
@ -1,45 +0,0 @@
|
|||||||
use super::vm;
|
|
||||||
use crate::types::{ElementType, Table};
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub enum TableElements {
|
|
||||||
/// This is intended to be a caller-checked Anyfunc.
|
|
||||||
Anyfunc(Vec<vm::Anyfunc>),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct TableBacking {
|
|
||||||
pub elements: TableElements,
|
|
||||||
pub max: Option<u32>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TableBacking {
|
|
||||||
pub fn new(table: &Table) -> Self {
|
|
||||||
match table.ty {
|
|
||||||
ElementType::Anyfunc => {
|
|
||||||
let initial_table_backing_len = match table.max {
|
|
||||||
Some(max) => max,
|
|
||||||
None => table.min,
|
|
||||||
} as usize;
|
|
||||||
|
|
||||||
Self {
|
|
||||||
elements: TableElements::Anyfunc(vec![
|
|
||||||
vm::Anyfunc::null();
|
|
||||||
initial_table_backing_len
|
|
||||||
]),
|
|
||||||
max: table.max,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn into_vm_table(&mut self) -> vm::LocalTable {
|
|
||||||
match self.elements {
|
|
||||||
TableElements::Anyfunc(ref mut funcs) => vm::LocalTable {
|
|
||||||
base: funcs.as_mut_ptr() as *mut u8,
|
|
||||||
current_elements: funcs.len(),
|
|
||||||
capacity: funcs.capacity(),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
134
lib/runtime-core/src/table/anyfunc.rs
Normal file
134
lib/runtime-core/src/table/anyfunc.rs
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
use crate::{
|
||||||
|
error::CreationError,
|
||||||
|
instance::Function,
|
||||||
|
sig_registry::SigRegistry,
|
||||||
|
structures::TypedIndex,
|
||||||
|
types::{FuncSig, TableDescriptor},
|
||||||
|
vm,
|
||||||
|
};
|
||||||
|
|
||||||
|
use std::{ptr, sync::Arc};
|
||||||
|
|
||||||
|
enum AnyfuncInner<'a> {
|
||||||
|
Host {
|
||||||
|
ptr: *const vm::Func,
|
||||||
|
signature: Arc<FuncSig>,
|
||||||
|
},
|
||||||
|
Managed(Function<'a>),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Anyfunc<'a> {
|
||||||
|
inner: AnyfuncInner<'a>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Anyfunc<'a> {
|
||||||
|
pub unsafe fn new<Sig>(func: *const vm::Func, signature: Sig) -> Self
|
||||||
|
where
|
||||||
|
Sig: Into<Arc<FuncSig>>,
|
||||||
|
{
|
||||||
|
Self {
|
||||||
|
inner: AnyfuncInner::Host {
|
||||||
|
ptr: func as _,
|
||||||
|
signature: signature.into(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> From<Function<'a>> for Anyfunc<'a> {
|
||||||
|
fn from(function: Function<'a>) -> Self {
|
||||||
|
Anyfunc {
|
||||||
|
inner: AnyfuncInner::Managed(function),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct AnyfuncTable {
|
||||||
|
backing: Vec<vm::Anyfunc>,
|
||||||
|
max: Option<u32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AnyfuncTable {
|
||||||
|
pub fn new(
|
||||||
|
desc: TableDescriptor,
|
||||||
|
local: &mut vm::LocalTable,
|
||||||
|
) -> Result<Box<Self>, CreationError> {
|
||||||
|
let initial_table_backing_len = match desc.maximum {
|
||||||
|
Some(max) => max,
|
||||||
|
None => desc.minimum,
|
||||||
|
} as usize;
|
||||||
|
|
||||||
|
let mut storage = Box::new(AnyfuncTable {
|
||||||
|
backing: vec![vm::Anyfunc::null(); initial_table_backing_len],
|
||||||
|
max: desc.maximum,
|
||||||
|
});
|
||||||
|
|
||||||
|
let storage_ptr: *mut AnyfuncTable = &mut *storage;
|
||||||
|
|
||||||
|
local.base = storage.backing.as_mut_ptr() as *mut u8;
|
||||||
|
local.count = storage.backing.len();
|
||||||
|
local.table = storage_ptr as *mut ();
|
||||||
|
|
||||||
|
Ok(storage)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn current_size(&self) -> u32 {
|
||||||
|
self.backing.len() as u32
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn internal_buffer(&mut self) -> &mut [vm::Anyfunc] {
|
||||||
|
&mut self.backing
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn grow(&mut self, delta: u32, local: &mut vm::LocalTable) -> Option<u32> {
|
||||||
|
let starting_len = self.backing.len() as u32;
|
||||||
|
|
||||||
|
let new_len = starting_len.checked_add(delta)?;
|
||||||
|
|
||||||
|
if let Some(max) = self.max {
|
||||||
|
if new_len > max {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.backing.resize(new_len as usize, vm::Anyfunc::null());
|
||||||
|
|
||||||
|
local.base = self.backing.as_mut_ptr() as *mut u8;
|
||||||
|
local.count = self.backing.len();
|
||||||
|
|
||||||
|
Some(starting_len)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set(&mut self, index: u32, element: Anyfunc) -> Result<(), ()> {
|
||||||
|
if let Some(slot) = self.backing.get_mut(index as usize) {
|
||||||
|
let anyfunc = match element.inner {
|
||||||
|
AnyfuncInner::Host { ptr, signature } => {
|
||||||
|
let sig_index = SigRegistry.lookup_sig_index(signature);
|
||||||
|
let sig_id = vm::SigId(sig_index.index() as u32);
|
||||||
|
|
||||||
|
vm::Anyfunc {
|
||||||
|
func: ptr,
|
||||||
|
ctx: ptr::null_mut(),
|
||||||
|
sig_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AnyfuncInner::Managed(ref func) => {
|
||||||
|
let sig_index = SigRegistry.lookup_sig_index(Arc::clone(&func.signature));
|
||||||
|
let sig_id = vm::SigId(sig_index.index() as u32);
|
||||||
|
|
||||||
|
vm::Anyfunc {
|
||||||
|
func: func.raw(),
|
||||||
|
ctx: func.instance_inner.vmctx,
|
||||||
|
sig_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
*slot = anyfunc;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
142
lib/runtime-core/src/table/mod.rs
Normal file
142
lib/runtime-core/src/table/mod.rs
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
use crate::{
|
||||||
|
error::CreationError,
|
||||||
|
export::Export,
|
||||||
|
import::IsExport,
|
||||||
|
types::{ElementType, TableDescriptor},
|
||||||
|
vm,
|
||||||
|
};
|
||||||
|
use std::{cell::RefCell, fmt, ptr, rc::Rc};
|
||||||
|
|
||||||
|
mod anyfunc;
|
||||||
|
|
||||||
|
pub use self::anyfunc::Anyfunc;
|
||||||
|
use self::anyfunc::AnyfuncTable;
|
||||||
|
|
||||||
|
pub enum Element<'a> {
|
||||||
|
Anyfunc(Anyfunc<'a>),
|
||||||
|
}
|
||||||
|
|
||||||
|
// #[derive(Debug)]
|
||||||
|
pub enum TableStorage {
|
||||||
|
/// This is intended to be a caller-checked Anyfunc.
|
||||||
|
Anyfunc(Box<AnyfuncTable>),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Table {
|
||||||
|
desc: TableDescriptor,
|
||||||
|
storage: Rc<RefCell<(TableStorage, vm::LocalTable)>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Table {
|
||||||
|
/// Create a new `Table` from a [`TableDescriptor`]
|
||||||
|
///
|
||||||
|
/// [`TableDescriptor`]: struct.TableDescriptor.html
|
||||||
|
///
|
||||||
|
/// Usage:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use wasmer_runtime_core::types::{TableDescriptor, ElementType};
|
||||||
|
/// # use wasmer_runtime_core::table::Table;
|
||||||
|
/// # use wasmer_runtime_core::error::Result;
|
||||||
|
/// # fn create_table() -> Result<()> {
|
||||||
|
/// let descriptor = TableDescriptor {
|
||||||
|
/// element: ElementType::Anyfunc,
|
||||||
|
/// minimum: 10,
|
||||||
|
/// maximum: None,
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// let table = Table::new(descriptor)?;
|
||||||
|
/// # Ok(())
|
||||||
|
/// # }
|
||||||
|
/// ```
|
||||||
|
pub fn new(desc: TableDescriptor) -> Result<Self, CreationError> {
|
||||||
|
let mut local = vm::LocalTable {
|
||||||
|
base: ptr::null_mut(),
|
||||||
|
count: 0,
|
||||||
|
table: ptr::null_mut(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let storage = match desc.element {
|
||||||
|
ElementType::Anyfunc => TableStorage::Anyfunc(AnyfuncTable::new(desc, &mut local)?),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
desc,
|
||||||
|
storage: Rc::new(RefCell::new((storage, local))),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the `TableDescriptor` used to create this `Table`.
|
||||||
|
pub fn descriptor(&self) -> TableDescriptor {
|
||||||
|
self.desc
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the element at index.
|
||||||
|
pub fn set(&self, index: u32, element: Element) -> Result<(), ()> {
|
||||||
|
match &mut *self.storage.borrow_mut() {
|
||||||
|
(TableStorage::Anyfunc(ref mut anyfunc_table), _) => {
|
||||||
|
match element {
|
||||||
|
Element::Anyfunc(anyfunc) => anyfunc_table.set(index, anyfunc),
|
||||||
|
// _ => panic!("wrong element type for anyfunc table"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn anyfunc_direct_access_mut<F, R>(&self, f: F) -> R
|
||||||
|
where
|
||||||
|
F: FnOnce(&mut [vm::Anyfunc]) -> R,
|
||||||
|
{
|
||||||
|
match &mut *self.storage.borrow_mut() {
|
||||||
|
(TableStorage::Anyfunc(ref mut anyfunc_table), _) => f(anyfunc_table.internal_buffer()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The current size of this table.
|
||||||
|
pub fn size(&self) -> u32 {
|
||||||
|
match &*self.storage.borrow() {
|
||||||
|
(TableStorage::Anyfunc(ref anyfunc_table), _) => anyfunc_table.current_size(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Grow this table by `delta`.
|
||||||
|
pub fn grow(&self, delta: u32) -> Option<u32> {
|
||||||
|
if delta == 0 {
|
||||||
|
return Some(self.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
match &mut *self.storage.borrow_mut() {
|
||||||
|
(TableStorage::Anyfunc(ref mut anyfunc_table), ref mut local) => {
|
||||||
|
anyfunc_table.grow(delta, local)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn vm_local_table(&mut self) -> *mut vm::LocalTable {
|
||||||
|
&mut self.storage.borrow_mut().1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IsExport for Table {
|
||||||
|
fn to_export(&mut self) -> Export {
|
||||||
|
Export::Table(self.clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Clone for Table {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
Self {
|
||||||
|
desc: self.desc,
|
||||||
|
storage: Rc::clone(&self.storage),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for Table {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
f.debug_struct("Table")
|
||||||
|
.field("desc", &self.desc)
|
||||||
|
.field("size", &self.size())
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
use crate::{module::ModuleInner, structures::TypedIndex};
|
use crate::{memory::MemoryType, module::ModuleInner, structures::TypedIndex, units::Pages};
|
||||||
|
use std::{borrow::Cow, mem};
|
||||||
|
|
||||||
/// Represents a WebAssembly type.
|
/// Represents a WebAssembly type.
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
@ -64,6 +65,62 @@ impl From<f64> for Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum ValueError {
|
||||||
|
BufferTooSmall,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait ValueType: Copy + Clone
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
{
|
||||||
|
fn into_le(self, buffer: &mut [u8]);
|
||||||
|
fn from_le(buffer: &[u8]) -> Result<Self, ValueError>;
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! convert_value_impl {
|
||||||
|
($t:ty) => {
|
||||||
|
impl ValueType for $t {
|
||||||
|
fn into_le(self, buffer: &mut [u8]) {
|
||||||
|
buffer[..mem::size_of::<Self>()].copy_from_slice(&self.to_le_bytes());
|
||||||
|
}
|
||||||
|
fn from_le(buffer: &[u8]) -> Result<Self, ValueError> {
|
||||||
|
if buffer.len() >= mem::size_of::<Self>() {
|
||||||
|
let mut array = [0u8; mem::size_of::<Self>()];
|
||||||
|
array.copy_from_slice(&buffer[..mem::size_of::<Self>()]);
|
||||||
|
Ok(Self::from_le_bytes(array))
|
||||||
|
} else {
|
||||||
|
Err(ValueError::BufferTooSmall)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
( $($t:ty),* ) => {
|
||||||
|
$(
|
||||||
|
convert_value_impl!($t);
|
||||||
|
)*
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
convert_value_impl!(u8, i8, u16, i16, u32, i32, u64, i64);
|
||||||
|
|
||||||
|
impl ValueType for f32 {
|
||||||
|
fn into_le(self, buffer: &mut [u8]) {
|
||||||
|
self.to_bits().into_le(buffer);
|
||||||
|
}
|
||||||
|
fn from_le(buffer: &[u8]) -> Result<Self, ValueError> {
|
||||||
|
Ok(f32::from_bits(<u32 as ValueType>::from_le(buffer)?))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ValueType for f64 {
|
||||||
|
fn into_le(self, buffer: &mut [u8]) {
|
||||||
|
self.to_bits().into_le(buffer);
|
||||||
|
}
|
||||||
|
fn from_le(buffer: &[u8]) -> Result<Self, ValueError> {
|
||||||
|
Ok(f64::from_bits(<u64 as ValueType>::from_le(buffer)?))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub enum ElementType {
|
pub enum ElementType {
|
||||||
/// Any wasm function.
|
/// Any wasm function.
|
||||||
@ -71,21 +128,23 @@ pub enum ElementType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct Table {
|
pub struct TableDescriptor {
|
||||||
/// Type of data stored in this table.
|
/// Type of data stored in this table.
|
||||||
pub ty: ElementType,
|
pub element: ElementType,
|
||||||
/// The minimum number of elements that must be stored in this table.
|
/// The minimum number of elements that must be stored in this table.
|
||||||
pub min: u32,
|
pub minimum: u32,
|
||||||
/// The maximum number of elements in this table.
|
/// The maximum number of elements in this table.
|
||||||
pub max: Option<u32>,
|
pub maximum: Option<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Table {
|
impl TableDescriptor {
|
||||||
pub(crate) fn fits_in_imported(&self, imported: &Table) -> bool {
|
pub(crate) fn fits_in_imported(&self, imported: TableDescriptor) -> bool {
|
||||||
// TODO: We should define implementation limits.
|
// TODO: We should define implementation limits.
|
||||||
let imported_max = imported.max.unwrap_or(u32::max_value());
|
let imported_max = imported.maximum.unwrap_or(u32::max_value());
|
||||||
let self_max = self.max.unwrap_or(u32::max_value());
|
let self_max = self.maximum.unwrap_or(u32::max_value());
|
||||||
self.ty == imported.ty && imported_max <= self_max && self.min <= imported.min
|
self.element == imported.element
|
||||||
|
&& imported_max <= self_max
|
||||||
|
&& self.minimum <= imported.minimum
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,39 +160,46 @@ pub enum Initializer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub struct GlobalDesc {
|
pub struct GlobalDescriptor {
|
||||||
pub mutable: bool,
|
pub mutable: bool,
|
||||||
pub ty: Type,
|
pub ty: Type,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A wasm global.
|
/// A wasm global.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Global {
|
pub struct GlobalInit {
|
||||||
pub desc: GlobalDesc,
|
pub desc: GlobalDescriptor,
|
||||||
pub init: Initializer,
|
pub init: Initializer,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A wasm memory.
|
/// A wasm memory.
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub struct Memory {
|
pub struct MemoryDescriptor {
|
||||||
/// The minimum number of allowed pages.
|
/// The minimum number of allowed pages.
|
||||||
pub min: u32,
|
pub minimum: Pages,
|
||||||
/// The maximum number of allowed pages.
|
/// The maximum number of allowed pages.
|
||||||
pub max: Option<u32>,
|
pub maximum: Option<Pages>,
|
||||||
/// This memory can be shared between wasm threads.
|
/// This memory can be shared between wasm threads.
|
||||||
pub shared: bool,
|
pub shared: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Memory {
|
impl MemoryDescriptor {
|
||||||
pub fn is_static_heap(&self) -> bool {
|
pub fn memory_type(self) -> MemoryType {
|
||||||
self.max.is_some()
|
match (self.maximum.is_some(), self.shared) {
|
||||||
|
(true, true) => MemoryType::SharedStatic,
|
||||||
|
(true, false) => MemoryType::Static,
|
||||||
|
(false, false) => MemoryType::Dynamic,
|
||||||
|
(false, true) => panic!("shared memory without a max is not allowed"),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn fits_in_imported(&self, imported: &Memory) -> bool {
|
pub(crate) fn fits_in_imported(&self, imported: MemoryDescriptor) -> bool {
|
||||||
let imported_max = imported.max.unwrap_or(65_536);
|
let imported_max = imported.maximum.unwrap_or(Pages(65_536));
|
||||||
let self_max = self.max.unwrap_or(65_536);
|
let self_max = self.maximum.unwrap_or(Pages(65_536));
|
||||||
|
|
||||||
self.shared == imported.shared && imported_max <= self_max && self.min <= imported.min
|
self.shared == imported.shared
|
||||||
|
&& imported_max <= self_max
|
||||||
|
&& self.minimum <= imported.minimum
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,12 +207,31 @@ impl Memory {
|
|||||||
/// in a wasm module or exposed to wasm by the host.
|
/// in a wasm module or exposed to wasm by the host.
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub struct FuncSig {
|
pub struct FuncSig {
|
||||||
pub params: Vec<Type>,
|
params: Cow<'static, [Type]>,
|
||||||
pub returns: Vec<Type>,
|
returns: Cow<'static, [Type]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FuncSig {
|
impl FuncSig {
|
||||||
pub fn check_sig(&self, params: &[Value]) -> bool {
|
pub fn new<Params, Returns>(params: Params, returns: Returns) -> Self
|
||||||
|
where
|
||||||
|
Params: Into<Cow<'static, [Type]>>,
|
||||||
|
Returns: Into<Cow<'static, [Type]>>,
|
||||||
|
{
|
||||||
|
Self {
|
||||||
|
params: params.into(),
|
||||||
|
returns: returns.into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn params(&self) -> &[Type] {
|
||||||
|
&self.params
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn returns(&self) -> &[Type] {
|
||||||
|
&self.returns
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn check_param_value_types(&self, params: &[Value]) -> bool {
|
||||||
self.params.len() == params.len()
|
self.params.len() == params.len()
|
||||||
&& self
|
&& self
|
||||||
.params
|
.params
|
||||||
|
94
lib/runtime-core/src/units.rs
Normal file
94
lib/runtime-core/src/units.rs
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
use std::{
|
||||||
|
fmt,
|
||||||
|
ops::{Add, Sub},
|
||||||
|
};
|
||||||
|
|
||||||
|
const WASM_PAGE_SIZE: usize = 65_536;
|
||||||
|
const WASM_MAX_PAGES: usize = 65_536;
|
||||||
|
|
||||||
|
/// Units of WebAssembly pages (as specified to be 65,536 bytes).
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
|
pub struct Pages(pub u32);
|
||||||
|
|
||||||
|
impl Pages {
|
||||||
|
pub fn checked_add(self, rhs: Pages) -> Option<Pages> {
|
||||||
|
let added = (self.0 as usize) + (rhs.0 as usize);
|
||||||
|
if added <= WASM_MAX_PAGES {
|
||||||
|
Some(Pages(added as u32))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn bytes(self) -> Bytes {
|
||||||
|
self.into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for Pages {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "{} pages", self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Units of WebAssembly memory in terms of 8-bit bytes.
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
|
pub struct Bytes(pub usize);
|
||||||
|
|
||||||
|
impl fmt::Debug for Bytes {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "{} bytes", self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Pages> for Bytes {
|
||||||
|
fn from(pages: Pages) -> Bytes {
|
||||||
|
Bytes((pages.0 as usize) * WASM_PAGE_SIZE)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Sub<T> for Pages
|
||||||
|
where
|
||||||
|
T: Into<Pages>,
|
||||||
|
{
|
||||||
|
type Output = Pages;
|
||||||
|
fn sub(self, rhs: T) -> Pages {
|
||||||
|
Pages(self.0 - rhs.into().0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Add<T> for Pages
|
||||||
|
where
|
||||||
|
T: Into<Pages>,
|
||||||
|
{
|
||||||
|
type Output = Pages;
|
||||||
|
fn add(self, rhs: T) -> Pages {
|
||||||
|
Pages(self.0 + rhs.into().0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Bytes> for Pages {
|
||||||
|
fn from(bytes: Bytes) -> Pages {
|
||||||
|
Pages((bytes.0 / WASM_PAGE_SIZE) as u32)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Sub<T> for Bytes
|
||||||
|
where
|
||||||
|
T: Into<Bytes>,
|
||||||
|
{
|
||||||
|
type Output = Bytes;
|
||||||
|
fn sub(self, rhs: T) -> Bytes {
|
||||||
|
Bytes(self.0 - rhs.into().0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Add<T> for Bytes
|
||||||
|
where
|
||||||
|
T: Into<Bytes>,
|
||||||
|
{
|
||||||
|
type Output = Bytes;
|
||||||
|
fn add(self, rhs: T) -> Bytes {
|
||||||
|
Bytes(self.0 + rhs.into().0)
|
||||||
|
}
|
||||||
|
}
|
@ -1,10 +1,11 @@
|
|||||||
pub use crate::backing::{ImportBacking, LocalBacking};
|
pub use crate::backing::{ImportBacking, LocalBacking};
|
||||||
use crate::{
|
use crate::{
|
||||||
|
memory::Memory,
|
||||||
module::ModuleInner,
|
module::ModuleInner,
|
||||||
structures::TypedIndex,
|
structures::TypedIndex,
|
||||||
types::{LocalMemoryIndex, LocalOrImport, MemoryIndex},
|
types::{LocalOrImport, MemoryIndex},
|
||||||
};
|
};
|
||||||
use std::{ffi::c_void, mem, ptr, slice};
|
use std::{ffi::c_void, mem, ptr};
|
||||||
|
|
||||||
/// The context of the currently running WebAssembly instance.
|
/// The context of the currently running WebAssembly instance.
|
||||||
///
|
///
|
||||||
@ -13,28 +14,28 @@ use std::{ffi::c_void, mem, ptr, slice};
|
|||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct Ctx {
|
pub struct Ctx {
|
||||||
/// A pointer to an array of locally-defined memories, indexed by `MemoryIndex`.
|
/// A pointer to an array of locally-defined memories, indexed by `MemoryIndex`.
|
||||||
pub(crate) memories: *mut LocalMemory,
|
pub(crate) memories: *mut *mut LocalMemory,
|
||||||
|
|
||||||
/// A pointer to an array of locally-defined tables, indexed by `TableIndex`.
|
/// A pointer to an array of locally-defined tables, indexed by `TableIndex`.
|
||||||
pub(crate) tables: *mut LocalTable,
|
pub(crate) tables: *mut *mut LocalTable,
|
||||||
|
|
||||||
/// A pointer to an array of locally-defined globals, indexed by `GlobalIndex`.
|
/// A pointer to an array of locally-defined globals, indexed by `GlobalIndex`.
|
||||||
pub(crate) globals: *mut LocalGlobal,
|
pub(crate) globals: *mut *mut LocalGlobal,
|
||||||
|
|
||||||
/// A pointer to an array of imported memories, indexed by `MemoryIndex,
|
/// A pointer to an array of imported memories, indexed by `MemoryIndex,
|
||||||
pub(crate) imported_memories: *mut ImportedMemory,
|
pub(crate) imported_memories: *mut *mut LocalMemory,
|
||||||
|
|
||||||
/// A pointer to an array of imported tables, indexed by `TableIndex`.
|
/// A pointer to an array of imported tables, indexed by `TableIndex`.
|
||||||
pub(crate) imported_tables: *mut ImportedTable,
|
pub(crate) imported_tables: *mut *mut LocalTable,
|
||||||
|
|
||||||
/// A pointer to an array of imported globals, indexed by `GlobalIndex`.
|
/// A pointer to an array of imported globals, indexed by `GlobalIndex`.
|
||||||
pub(crate) imported_globals: *mut ImportedGlobal,
|
pub(crate) imported_globals: *mut *mut LocalGlobal,
|
||||||
|
|
||||||
/// A pointer to an array of imported functions, indexed by `FuncIndex`.
|
/// A pointer to an array of imported functions, indexed by `FuncIndex`.
|
||||||
pub(crate) imported_funcs: *mut ImportedFunc,
|
pub(crate) imported_funcs: *mut ImportedFunc,
|
||||||
|
|
||||||
pub(crate) local_backing: *mut LocalBacking,
|
local_backing: *mut LocalBacking,
|
||||||
pub(crate) import_backing: *mut ImportBacking,
|
import_backing: *mut ImportBacking,
|
||||||
module: *const ModuleInner,
|
module: *const ModuleInner,
|
||||||
|
|
||||||
pub data: *mut c_void,
|
pub data: *mut c_void,
|
||||||
@ -53,10 +54,10 @@ impl Ctx {
|
|||||||
tables: local_backing.vm_tables.as_mut_ptr(),
|
tables: local_backing.vm_tables.as_mut_ptr(),
|
||||||
globals: local_backing.vm_globals.as_mut_ptr(),
|
globals: local_backing.vm_globals.as_mut_ptr(),
|
||||||
|
|
||||||
imported_memories: import_backing.memories.as_mut_ptr(),
|
imported_memories: import_backing.vm_memories.as_mut_ptr(),
|
||||||
imported_tables: import_backing.tables.as_mut_ptr(),
|
imported_tables: import_backing.vm_tables.as_mut_ptr(),
|
||||||
imported_globals: import_backing.globals.as_mut_ptr(),
|
imported_globals: import_backing.vm_globals.as_mut_ptr(),
|
||||||
imported_funcs: import_backing.functions.as_mut_ptr(),
|
imported_funcs: import_backing.vm_functions.as_mut_ptr(),
|
||||||
|
|
||||||
local_backing,
|
local_backing,
|
||||||
import_backing,
|
import_backing,
|
||||||
@ -80,10 +81,10 @@ impl Ctx {
|
|||||||
tables: local_backing.vm_tables.as_mut_ptr(),
|
tables: local_backing.vm_tables.as_mut_ptr(),
|
||||||
globals: local_backing.vm_globals.as_mut_ptr(),
|
globals: local_backing.vm_globals.as_mut_ptr(),
|
||||||
|
|
||||||
imported_memories: import_backing.memories.as_mut_ptr(),
|
imported_memories: import_backing.vm_memories.as_mut_ptr(),
|
||||||
imported_tables: import_backing.tables.as_mut_ptr(),
|
imported_tables: import_backing.vm_tables.as_mut_ptr(),
|
||||||
imported_globals: import_backing.globals.as_mut_ptr(),
|
imported_globals: import_backing.vm_globals.as_mut_ptr(),
|
||||||
imported_funcs: import_backing.functions.as_mut_ptr(),
|
imported_funcs: import_backing.vm_functions.as_mut_ptr(),
|
||||||
|
|
||||||
local_backing,
|
local_backing,
|
||||||
import_backing,
|
import_backing,
|
||||||
@ -109,65 +110,21 @@ impl Ctx {
|
|||||||
/// fn read_memory(ctx: &Ctx) -> u8 {
|
/// fn read_memory(ctx: &Ctx) -> u8 {
|
||||||
/// let first_memory = ctx.memory(0);
|
/// let first_memory = ctx.memory(0);
|
||||||
/// // Read the first byte of that linear memory.
|
/// // Read the first byte of that linear memory.
|
||||||
/// first_memory[0]
|
/// first_memory.read(0).unwrap()
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn memory<'a>(&'a self, mem_index: u32) -> &'a [u8] {
|
pub fn memory<'a>(&'a self, mem_index: u32) -> &'a Memory {
|
||||||
let module = unsafe { &*self.module };
|
let module = unsafe { &*self.module };
|
||||||
let mem_index = MemoryIndex::new(mem_index as usize);
|
let mem_index = MemoryIndex::new(mem_index as usize);
|
||||||
match mem_index.local_or_import(module) {
|
match mem_index.local_or_import(module) {
|
||||||
LocalOrImport::Local(local_mem_index) => {
|
LocalOrImport::Local(local_mem_index) => unsafe {
|
||||||
let local_backing = unsafe { &*self.local_backing };
|
let local_backing = &*self.local_backing;
|
||||||
&local_backing.memories[local_mem_index][..]
|
&local_backing.memories[local_mem_index]
|
||||||
}
|
},
|
||||||
LocalOrImport::Import(import_mem_index) => {
|
LocalOrImport::Import(import_mem_index) => unsafe {
|
||||||
let import_backing = unsafe { &mut *self.import_backing };
|
let import_backing = &*self.import_backing;
|
||||||
let vm_memory_import = import_backing.memories[import_mem_index].clone();
|
&import_backing.memories[import_mem_index]
|
||||||
unsafe {
|
},
|
||||||
let memory = &*vm_memory_import.memory;
|
|
||||||
|
|
||||||
slice::from_raw_parts(memory.base, memory.size)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This exposes the specified memory of the WebAssembly instance
|
|
||||||
/// as a mutable slice.
|
|
||||||
///
|
|
||||||
/// WebAssembly will soon support multiple linear memories, so this
|
|
||||||
/// forces the user to specify.
|
|
||||||
///
|
|
||||||
/// # Usage:
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// # use wasmer_runtime_core::{
|
|
||||||
/// # vm::Ctx,
|
|
||||||
/// # error::Result,
|
|
||||||
/// # };
|
|
||||||
/// extern fn host_func(ctx: &mut Ctx) {
|
|
||||||
/// let first_memory = ctx.memory_mut(0);
|
|
||||||
/// // Set the first byte of that linear memory.
|
|
||||||
/// first_memory[0] = 42;
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
pub fn memory_mut<'a>(&'a mut self, mem_index: u32) -> &'a mut [u8] {
|
|
||||||
let module = unsafe { &*self.module };
|
|
||||||
let mem_index = MemoryIndex::new(mem_index as usize);
|
|
||||||
match mem_index.local_or_import(module) {
|
|
||||||
LocalOrImport::Local(local_mem_index) => {
|
|
||||||
let local_backing = unsafe { &mut *self.local_backing };
|
|
||||||
&mut local_backing.memories[local_mem_index][..]
|
|
||||||
}
|
|
||||||
LocalOrImport::Import(import_mem_index) => {
|
|
||||||
let import_backing = unsafe { &mut *self.import_backing };
|
|
||||||
let vm_memory_import = import_backing.memories[import_mem_index].clone();
|
|
||||||
unsafe {
|
|
||||||
let memory = &*vm_memory_import.memory;
|
|
||||||
|
|
||||||
slice::from_raw_parts_mut(memory.base, memory.size)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -244,9 +201,9 @@ pub struct LocalTable {
|
|||||||
/// pointer to the elements in the table.
|
/// pointer to the elements in the table.
|
||||||
pub base: *mut u8,
|
pub base: *mut u8,
|
||||||
/// Number of elements in the table (NOT necessarily the size of the table in bytes!).
|
/// Number of elements in the table (NOT necessarily the size of the table in bytes!).
|
||||||
pub current_elements: usize,
|
pub count: usize,
|
||||||
/// The number of elements that can fit into the memory allocated for this table.
|
/// The table that this represents. At the moment, this can only be `*mut AnyfuncTable`.
|
||||||
pub capacity: usize,
|
pub table: *mut (),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LocalTable {
|
impl LocalTable {
|
||||||
@ -255,31 +212,7 @@ impl LocalTable {
|
|||||||
0 * (mem::size_of::<usize>() as u8)
|
0 * (mem::size_of::<usize>() as u8)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn offset_current_elements() -> u8 {
|
pub fn offset_count() -> u8 {
|
||||||
1 * (mem::size_of::<usize>() as u8)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn size() -> u8 {
|
|
||||||
mem::size_of::<Self>() as u8
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
#[repr(C)]
|
|
||||||
pub struct ImportedTable {
|
|
||||||
/// A pointer to the table definition.
|
|
||||||
pub table: *mut LocalTable,
|
|
||||||
/// A pointer to the vmcontext that owns this table definition.
|
|
||||||
pub vmctx: *mut Ctx,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ImportedTable {
|
|
||||||
#[allow(clippy::erasing_op)] // TODO
|
|
||||||
pub fn offset_table() -> u8 {
|
|
||||||
0 * (mem::size_of::<usize>() as u8)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn offset_vmctx() -> u8 {
|
|
||||||
1 * (mem::size_of::<usize>() as u8)
|
1 * (mem::size_of::<usize>() as u8)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -295,9 +228,11 @@ pub struct LocalMemory {
|
|||||||
/// Pointer to the bottom of this linear memory.
|
/// Pointer to the bottom of this linear memory.
|
||||||
pub base: *mut u8,
|
pub base: *mut u8,
|
||||||
/// Current size of this linear memory in bytes.
|
/// Current size of this linear memory in bytes.
|
||||||
pub size: usize,
|
pub bound: usize,
|
||||||
/// The local memory index.
|
/// The actual memory that this represents.
|
||||||
pub index: LocalMemoryIndex,
|
/// This is either `*mut DynamicMemory`, `*mut StaticMemory`,
|
||||||
|
/// or `*mut SharedStaticMemory`.
|
||||||
|
pub memory: *mut (),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LocalMemory {
|
impl LocalMemory {
|
||||||
@ -306,30 +241,7 @@ impl LocalMemory {
|
|||||||
0 * (mem::size_of::<usize>() as u8)
|
0 * (mem::size_of::<usize>() as u8)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn offset_size() -> u8 {
|
pub fn offset_bound() -> u8 {
|
||||||
1 * (mem::size_of::<usize>() as u8)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn size() -> u8 {
|
|
||||||
mem::size_of::<Self>() as u8
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
#[repr(C)]
|
|
||||||
pub struct ImportedMemory {
|
|
||||||
/// A pointer to the memory definition.
|
|
||||||
pub memory: *mut LocalMemory,
|
|
||||||
pub vmctx: *mut Ctx,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ImportedMemory {
|
|
||||||
#[allow(clippy::erasing_op)] // TODO
|
|
||||||
pub fn offset_memory() -> u8 {
|
|
||||||
0 * (mem::size_of::<usize>() as u8)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn offset_vmctx() -> u8 {
|
|
||||||
1 * (mem::size_of::<usize>() as u8)
|
1 * (mem::size_of::<usize>() as u8)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -360,23 +272,6 @@ impl LocalGlobal {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
#[repr(C)]
|
|
||||||
pub struct ImportedGlobal {
|
|
||||||
pub global: *mut LocalGlobal,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ImportedGlobal {
|
|
||||||
#[allow(clippy::erasing_op)] // TODO
|
|
||||||
pub fn offset_global() -> u8 {
|
|
||||||
0 * (mem::size_of::<usize>() as u8)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn size() -> u8 {
|
|
||||||
mem::size_of::<Self>() as u8
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
pub struct SigId(pub u32);
|
pub struct SigId(pub u32);
|
||||||
@ -385,17 +280,16 @@ pub struct SigId(pub u32);
|
|||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct Anyfunc {
|
pub struct Anyfunc {
|
||||||
pub func_data: ImportedFunc,
|
pub func: *const Func,
|
||||||
|
pub ctx: *mut Ctx,
|
||||||
pub sig_id: SigId,
|
pub sig_id: SigId,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Anyfunc {
|
impl Anyfunc {
|
||||||
pub fn null() -> Self {
|
pub fn null() -> Self {
|
||||||
Self {
|
Self {
|
||||||
func_data: ImportedFunc {
|
func: ptr::null(),
|
||||||
func: ptr::null(),
|
ctx: ptr::null_mut(),
|
||||||
vmctx: ptr::null_mut(),
|
|
||||||
},
|
|
||||||
sig_id: SigId(u32::max_value()),
|
sig_id: SigId(u32::max_value()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -420,10 +314,7 @@ impl Anyfunc {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod vm_offset_tests {
|
mod vm_offset_tests {
|
||||||
use super::{
|
use super::{Anyfunc, Ctx, ImportedFunc, LocalGlobal, LocalMemory, LocalTable};
|
||||||
Anyfunc, Ctx, ImportedFunc, ImportedGlobal, ImportedMemory, ImportedTable, LocalGlobal,
|
|
||||||
LocalMemory, LocalTable,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn vmctx() {
|
fn vmctx() {
|
||||||
@ -484,21 +375,8 @@ mod vm_offset_tests {
|
|||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
LocalTable::offset_current_elements() as usize,
|
LocalTable::offset_count() as usize,
|
||||||
offset_of!(LocalTable => current_elements).get_byte_offset(),
|
offset_of!(LocalTable => count).get_byte_offset(),
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn imported_table() {
|
|
||||||
assert_eq!(
|
|
||||||
ImportedTable::offset_table() as usize,
|
|
||||||
offset_of!(ImportedTable => table).get_byte_offset(),
|
|
||||||
);
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
ImportedTable::offset_vmctx() as usize,
|
|
||||||
offset_of!(ImportedTable => vmctx).get_byte_offset(),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -510,21 +388,8 @@ mod vm_offset_tests {
|
|||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
LocalMemory::offset_size() as usize,
|
LocalMemory::offset_bound() as usize,
|
||||||
offset_of!(LocalMemory => size).get_byte_offset(),
|
offset_of!(LocalMemory => bound).get_byte_offset(),
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn imported_memory() {
|
|
||||||
assert_eq!(
|
|
||||||
ImportedMemory::offset_memory() as usize,
|
|
||||||
offset_of!(ImportedMemory => memory).get_byte_offset(),
|
|
||||||
);
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
ImportedMemory::offset_vmctx() as usize,
|
|
||||||
offset_of!(ImportedMemory => vmctx).get_byte_offset(),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -536,24 +401,16 @@ mod vm_offset_tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn imported_global() {
|
|
||||||
assert_eq!(
|
|
||||||
ImportedGlobal::offset_global() as usize,
|
|
||||||
offset_of!(ImportedGlobal => global).get_byte_offset(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn cc_anyfunc() {
|
fn cc_anyfunc() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Anyfunc::offset_func() as usize,
|
Anyfunc::offset_func() as usize,
|
||||||
offset_of!(Anyfunc => func_data: ImportedFunc => func).get_byte_offset(),
|
offset_of!(Anyfunc => func).get_byte_offset(),
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Anyfunc::offset_vmctx() as usize,
|
Anyfunc::offset_vmctx() as usize,
|
||||||
offset_of!(Anyfunc => func_data: ImportedFunc => vmctx).get_byte_offset(),
|
offset_of!(Anyfunc => ctx).get_byte_offset(),
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -595,15 +452,21 @@ mod vm_ctx_tests {
|
|||||||
let mut local_backing = LocalBacking {
|
let mut local_backing = LocalBacking {
|
||||||
memories: Map::new().into_boxed_map(),
|
memories: Map::new().into_boxed_map(),
|
||||||
tables: Map::new().into_boxed_map(),
|
tables: Map::new().into_boxed_map(),
|
||||||
|
globals: Map::new().into_boxed_map(),
|
||||||
|
|
||||||
vm_memories: Map::new().into_boxed_map(),
|
vm_memories: Map::new().into_boxed_map(),
|
||||||
vm_tables: Map::new().into_boxed_map(),
|
vm_tables: Map::new().into_boxed_map(),
|
||||||
vm_globals: Map::new().into_boxed_map(),
|
vm_globals: Map::new().into_boxed_map(),
|
||||||
};
|
};
|
||||||
let mut import_backing = ImportBacking {
|
let mut import_backing = ImportBacking {
|
||||||
functions: Map::new().into_boxed_map(),
|
|
||||||
memories: Map::new().into_boxed_map(),
|
memories: Map::new().into_boxed_map(),
|
||||||
tables: Map::new().into_boxed_map(),
|
tables: Map::new().into_boxed_map(),
|
||||||
globals: Map::new().into_boxed_map(),
|
globals: Map::new().into_boxed_map(),
|
||||||
|
|
||||||
|
vm_functions: Map::new().into_boxed_map(),
|
||||||
|
vm_memories: Map::new().into_boxed_map(),
|
||||||
|
vm_tables: Map::new().into_boxed_map(),
|
||||||
|
vm_globals: Map::new().into_boxed_map(),
|
||||||
};
|
};
|
||||||
let module = generate_module();
|
let module = generate_module();
|
||||||
let data = &mut data as *mut _ as *mut c_void;
|
let data = &mut data as *mut _ as *mut c_void;
|
||||||
@ -680,7 +543,7 @@ mod vm_ctx_tests {
|
|||||||
start_func: None,
|
start_func: None,
|
||||||
|
|
||||||
func_assoc: Map::new(),
|
func_assoc: Map::new(),
|
||||||
sig_registry: SigRegistry::new(),
|
sig_registry: SigRegistry,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
|
#![allow(clippy::cast_ptr_alignment)]
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
memory::LinearMemory,
|
memory::{DynamicMemory, StaticMemory},
|
||||||
structures::TypedIndex,
|
structures::TypedIndex,
|
||||||
types::{ImportedMemoryIndex, LocalMemoryIndex, LocalTableIndex},
|
types::{ImportedMemoryIndex, LocalMemoryIndex, LocalTableIndex},
|
||||||
|
units::Pages,
|
||||||
vm,
|
vm,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -11,17 +14,14 @@ use crate::{
|
|||||||
|
|
||||||
pub unsafe extern "C" fn local_static_memory_grow(
|
pub unsafe extern "C" fn local_static_memory_grow(
|
||||||
memory_index: LocalMemoryIndex,
|
memory_index: LocalMemoryIndex,
|
||||||
by_pages: u32,
|
delta: Pages,
|
||||||
ctx: *mut vm::Ctx,
|
ctx: &mut vm::Ctx,
|
||||||
) -> i32 {
|
) -> i32 {
|
||||||
if let Some(old) = (*(*ctx).local_backing)
|
let local_memory = *ctx.memories.add(memory_index.index());
|
||||||
.memory(memory_index)
|
let memory = (*local_memory).memory as *mut StaticMemory;
|
||||||
.grow_static(by_pages)
|
|
||||||
{
|
if let Some(old) = (*memory).grow(delta, &mut *local_memory) {
|
||||||
// Store the new size back into the vmctx.
|
old.0 as i32
|
||||||
(*(*ctx).memories.add(memory_index.index())).size =
|
|
||||||
(old as usize + by_pages as usize) * LinearMemory::PAGE_SIZE as usize;
|
|
||||||
old
|
|
||||||
} else {
|
} else {
|
||||||
-1
|
-1
|
||||||
}
|
}
|
||||||
@ -29,71 +29,91 @@ pub unsafe extern "C" fn local_static_memory_grow(
|
|||||||
|
|
||||||
pub unsafe extern "C" fn local_static_memory_size(
|
pub unsafe extern "C" fn local_static_memory_size(
|
||||||
memory_index: LocalMemoryIndex,
|
memory_index: LocalMemoryIndex,
|
||||||
ctx: *mut vm::Ctx,
|
ctx: &vm::Ctx,
|
||||||
) -> u32 {
|
) -> Pages {
|
||||||
(*(*ctx).local_backing).memory(memory_index).pages()
|
let local_memory = *ctx.memories.add(memory_index.index());
|
||||||
|
let memory = (*local_memory).memory as *mut StaticMemory;
|
||||||
|
|
||||||
|
(*memory).size()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe extern "C" fn local_dynamic_memory_grow(
|
pub unsafe extern "C" fn local_dynamic_memory_grow(
|
||||||
memory_index: LocalMemoryIndex,
|
memory_index: LocalMemoryIndex,
|
||||||
by_pages: u32,
|
delta: Pages,
|
||||||
ctx: *mut vm::Ctx,
|
ctx: &mut vm::Ctx,
|
||||||
) -> i32 {
|
) -> i32 {
|
||||||
if let Some(old) = (*(*ctx).local_backing)
|
let local_memory = *ctx.memories.add(memory_index.index());
|
||||||
.memory(memory_index)
|
let memory = (*local_memory).memory as *mut DynamicMemory;
|
||||||
.grow_dynamic(by_pages)
|
|
||||||
{
|
if let Some(old) = (*memory).grow(delta, &mut *local_memory) {
|
||||||
// Store the new size back into the vmctx.
|
old.0 as i32
|
||||||
(*(*ctx).memories.add(memory_index.index())).size =
|
|
||||||
(old as usize + by_pages as usize) * LinearMemory::PAGE_SIZE as usize;
|
|
||||||
old
|
|
||||||
} else {
|
} else {
|
||||||
-1
|
-1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub unsafe extern "C" fn local_dynamic_memory_size(
|
||||||
|
memory_index: LocalMemoryIndex,
|
||||||
|
ctx: &vm::Ctx,
|
||||||
|
) -> Pages {
|
||||||
|
let local_memory = *ctx.memories.add(memory_index.index());
|
||||||
|
let memory = (*local_memory).memory as *mut DynamicMemory;
|
||||||
|
|
||||||
|
(*memory).size()
|
||||||
|
}
|
||||||
|
|
||||||
// +*****************************+
|
// +*****************************+
|
||||||
// | IMPORTED MEMORIES |
|
// | IMPORTED MEMORIES |
|
||||||
// +****************************+
|
// +****************************+
|
||||||
|
|
||||||
pub unsafe extern "C" fn imported_static_memory_grow(
|
pub unsafe extern "C" fn imported_static_memory_grow(
|
||||||
imported_mem_index: ImportedMemoryIndex,
|
import_memory_index: ImportedMemoryIndex,
|
||||||
by_pages: u32,
|
delta: Pages,
|
||||||
caller_ctx: *mut vm::Ctx,
|
ctx: &mut vm::Ctx,
|
||||||
) -> i32 {
|
) -> i32 {
|
||||||
let import_backing = &*(*caller_ctx).import_backing;
|
let local_memory = *ctx.imported_memories.add(import_memory_index.index());
|
||||||
let vm_imported_mem = import_backing.imported_memory(imported_mem_index);
|
let memory = (*local_memory).memory as *mut StaticMemory;
|
||||||
|
|
||||||
// We can assume that the memory here is local to the callee ctx.
|
if let Some(old) = (*memory).grow(delta, &mut *local_memory) {
|
||||||
let local_mem_index = (*vm_imported_mem.memory).index;
|
old.0 as i32
|
||||||
|
|
||||||
if let Some(old) = (*(*vm_imported_mem.vmctx).local_backing)
|
|
||||||
.memory(local_mem_index)
|
|
||||||
.grow_dynamic(by_pages)
|
|
||||||
{
|
|
||||||
// Store the new size back into the vmctx.
|
|
||||||
(*(*vm_imported_mem.vmctx)
|
|
||||||
.memories
|
|
||||||
.add(local_mem_index.index()))
|
|
||||||
.size = (old as usize + by_pages as usize) * LinearMemory::PAGE_SIZE as usize;
|
|
||||||
old
|
|
||||||
} else {
|
} else {
|
||||||
-1
|
-1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe extern "C" fn imported_static_memory_size(
|
pub unsafe extern "C" fn imported_static_memory_size(
|
||||||
imported_memory_index: ImportedMemoryIndex,
|
import_memory_index: ImportedMemoryIndex,
|
||||||
caller_ctx: *mut vm::Ctx,
|
ctx: &vm::Ctx,
|
||||||
) -> u32 {
|
) -> Pages {
|
||||||
let import_backing = &*(*caller_ctx).import_backing;
|
let local_memory = *ctx.imported_memories.add(import_memory_index.index());
|
||||||
let vm_imported_mem = import_backing.imported_memory(imported_memory_index);
|
let memory = (*local_memory).memory as *mut StaticMemory;
|
||||||
|
|
||||||
// We can assume that the memory here is local to the callee ctx.
|
(*memory).size()
|
||||||
let local_mem_index = (*vm_imported_mem.memory).index;
|
}
|
||||||
(*(*vm_imported_mem.vmctx).local_backing)
|
|
||||||
.memory(local_mem_index)
|
pub unsafe extern "C" fn imported_dynamic_memory_grow(
|
||||||
.pages()
|
memory_index: ImportedMemoryIndex,
|
||||||
|
delta: Pages,
|
||||||
|
ctx: &mut vm::Ctx,
|
||||||
|
) -> i32 {
|
||||||
|
let local_memory = *ctx.imported_memories.add(memory_index.index());
|
||||||
|
let memory = (*local_memory).memory as *mut DynamicMemory;
|
||||||
|
|
||||||
|
if let Some(old) = (*memory).grow(delta, &mut *local_memory) {
|
||||||
|
old.0 as i32
|
||||||
|
} else {
|
||||||
|
-1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe extern "C" fn imported_dynamic_memory_size(
|
||||||
|
memory_index: ImportedMemoryIndex,
|
||||||
|
ctx: &vm::Ctx,
|
||||||
|
) -> Pages {
|
||||||
|
let local_memory = *ctx.imported_memories.add(memory_index.index());
|
||||||
|
let memory = (*local_memory).memory as *mut DynamicMemory;
|
||||||
|
|
||||||
|
(*memory).size()
|
||||||
}
|
}
|
||||||
|
|
||||||
// +*****************************+
|
// +*****************************+
|
||||||
@ -102,16 +122,16 @@ pub unsafe extern "C" fn imported_static_memory_size(
|
|||||||
|
|
||||||
pub unsafe extern "C" fn local_table_grow(
|
pub unsafe extern "C" fn local_table_grow(
|
||||||
table_index: LocalTableIndex,
|
table_index: LocalTableIndex,
|
||||||
by_elems: u32,
|
delta: u32,
|
||||||
ctx: *mut vm::Ctx,
|
ctx: &mut vm::Ctx,
|
||||||
) -> i32 {
|
) -> i32 {
|
||||||
let _ = table_index;
|
let _ = table_index;
|
||||||
let _ = by_elems;
|
let _ = delta;
|
||||||
let _ = ctx;
|
let _ = ctx;
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe extern "C" fn local_table_size(table_index: LocalTableIndex, ctx: *mut vm::Ctx) -> u32 {
|
pub unsafe extern "C" fn local_table_size(table_index: LocalTableIndex, ctx: &vm::Ctx) -> u32 {
|
||||||
let _ = table_index;
|
let _ = table_index;
|
||||||
let _ = ctx;
|
let _ = ctx;
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
|
@ -24,7 +24,7 @@ mod tests {
|
|||||||
let wasm_binary = wat2wasm(module_str.as_bytes()).expect("WAST not valid or malformed");
|
let wasm_binary = wat2wasm(module_str.as_bytes()).expect("WAST not valid or malformed");
|
||||||
let module = wasmer_runtime_core::compile_with(&wasm_binary[..], &CraneliftCompiler::new())
|
let module = wasmer_runtime_core::compile_with(&wasm_binary[..], &CraneliftCompiler::new())
|
||||||
.expect("WASM can't be compiled");
|
.expect("WASM can't be compiled");
|
||||||
let mut instance = module
|
let instance = module
|
||||||
.instantiate(ImportObject::new())
|
.instantiate(ImportObject::new())
|
||||||
.expect("WASM can't be instantiated");
|
.expect("WASM can't be instantiated");
|
||||||
let result = instance.call("stack-overflow", &[]);
|
let result = instance.call("stack-overflow", &[]);
|
||||||
|
@ -73,20 +73,33 @@
|
|||||||
//! [`wasmer-clif-backend`]: https://crates.io/crates/wasmer-clif-backend
|
//! [`wasmer-clif-backend`]: https://crates.io/crates/wasmer-clif-backend
|
||||||
//! [`compile_with`]: fn.compile_with.html
|
//! [`compile_with`]: fn.compile_with.html
|
||||||
|
|
||||||
|
pub use wasmer_runtime_core::global::Global;
|
||||||
pub use wasmer_runtime_core::import::ImportObject;
|
pub use wasmer_runtime_core::import::ImportObject;
|
||||||
pub use wasmer_runtime_core::instance::{Function, Instance};
|
pub use wasmer_runtime_core::instance::{Function, Instance};
|
||||||
|
pub use wasmer_runtime_core::memory::Memory;
|
||||||
pub use wasmer_runtime_core::module::Module;
|
pub use wasmer_runtime_core::module::Module;
|
||||||
|
pub use wasmer_runtime_core::table::Table;
|
||||||
pub use wasmer_runtime_core::types::Value;
|
pub use wasmer_runtime_core::types::Value;
|
||||||
pub use wasmer_runtime_core::vm::Ctx;
|
pub use wasmer_runtime_core::vm::Ctx;
|
||||||
|
|
||||||
pub use wasmer_runtime_core::{compile_with, validate};
|
pub use wasmer_runtime_core::{compile_with, validate};
|
||||||
|
|
||||||
pub use wasmer_runtime_core::error;
|
pub use wasmer_runtime_core::error;
|
||||||
pub use wasmer_runtime_core::imports;
|
pub use wasmer_runtime_core::{func, imports};
|
||||||
|
|
||||||
pub mod wasm {
|
pub mod wasm {
|
||||||
|
//! Various types exposed by the Wasmer Runtime.
|
||||||
|
pub use wasmer_runtime_core::global::Global;
|
||||||
pub use wasmer_runtime_core::instance::Function;
|
pub use wasmer_runtime_core::instance::Function;
|
||||||
pub use wasmer_runtime_core::types::{FuncSig, Type, Value};
|
pub use wasmer_runtime_core::memory::Memory;
|
||||||
|
pub use wasmer_runtime_core::table::Table;
|
||||||
|
pub use wasmer_runtime_core::types::{FuncSig, MemoryDescriptor, TableDescriptor, Type, Value};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub mod units {
|
||||||
|
//! Various unit types.
|
||||||
|
|
||||||
|
pub use wasmer_runtime_core::units::{Bytes, Pages};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Compile WebAssembly binary code into a [`Module`].
|
/// Compile WebAssembly binary code into a [`Module`].
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
|
#[macro_use]
|
||||||
extern crate wasmer_runtime_core;
|
extern crate wasmer_runtime_core;
|
||||||
// extern crate wasmer_emscripten;
|
// extern crate wasmer_emscripten;
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
mod macros;
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
pub mod update;
|
pub mod update;
|
||||||
pub mod utils;
|
pub mod utils;
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
#[macro_export]
|
|
||||||
macro_rules! debug {
|
|
||||||
($fmt:expr) => (if cfg!(any(debug_assertions, feature="debug")) { println!(concat!("Wasmer::", $fmt)) });
|
|
||||||
($fmt:expr, $($arg:tt)*) => (if cfg!(any(debug_assertions, feature="debug")) { println!(concat!("Wasmer::", $fmt, "\n"), $($arg)*) });
|
|
||||||
}
|
|
Reference in New Issue
Block a user