Merge remote-tracking branch 'upstream/master' into poll
This commit is contained in:
2
.gitmodules
vendored
2
.gitmodules
vendored
@@ -5,5 +5,5 @@
|
|||||||
path = crates/api/c-examples/wasm-c-api
|
path = crates/api/c-examples/wasm-c-api
|
||||||
url = https://github.com/WebAssembly/wasm-c-api
|
url = https://github.com/WebAssembly/wasm-c-api
|
||||||
[submodule "crates/wasi-common/WASI"]
|
[submodule "crates/wasi-common/WASI"]
|
||||||
path = crates/wasi-common/WASI
|
path = crates/wasi-common/wig/WASI
|
||||||
url = https://github.com/WebAssembly/WASI
|
url = https://github.com/WebAssembly/WASI
|
||||||
|
|||||||
383
Cargo.lock
generated
383
Cargo.lock
generated
@@ -20,9 +20,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anyhow"
|
name = "anyhow"
|
||||||
version = "1.0.25"
|
version = "1.0.26"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9267dff192e68f3399525901e709a48c1d3982c9c072fa32f2127a0cb0babf14"
|
checksum = "7825f6833612eb2414095684fcf6c635becf3ce97fe48cf6421321e93bfbd53c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "arbitrary"
|
name = "arbitrary"
|
||||||
@@ -53,10 +53,11 @@ checksum = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "atty"
|
name = "atty"
|
||||||
version = "0.2.13"
|
version = "0.2.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90"
|
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"hermit-abi",
|
||||||
"libc",
|
"libc",
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
@@ -67,6 +68,12 @@ version = "0.1.7"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2"
|
checksum = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "autocfg"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "backtrace"
|
name = "backtrace"
|
||||||
version = "0.3.40"
|
version = "0.3.40"
|
||||||
@@ -119,7 +126,7 @@ version = "0.8.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "440d600bca1c3b3982dd2533518e15ba73d051b532768804aa3c06ae52f4ce44"
|
checksum = "440d600bca1c3b3982dd2533518e15ba73d051b532768804aa3c06ae52f4ce44"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bindgen 0.52.0",
|
"bindgen",
|
||||||
"cc",
|
"cc",
|
||||||
"cmake",
|
"cmake",
|
||||||
"heck",
|
"heck",
|
||||||
@@ -136,29 +143,6 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "bindgen"
|
|
||||||
version = "0.51.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ebd71393f1ec0509b553aa012b9b58e81dadbdff7130bd3b8cba576e69b32f75"
|
|
||||||
dependencies = [
|
|
||||||
"bitflags",
|
|
||||||
"cexpr",
|
|
||||||
"cfg-if",
|
|
||||||
"clang-sys",
|
|
||||||
"clap",
|
|
||||||
"env_logger 0.6.2",
|
|
||||||
"lazy_static",
|
|
||||||
"log",
|
|
||||||
"peeking_take_while",
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"regex",
|
|
||||||
"rustc-hash",
|
|
||||||
"shlex",
|
|
||||||
"which",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bindgen"
|
name = "bindgen"
|
||||||
version = "0.52.0"
|
version = "0.52.0"
|
||||||
@@ -191,9 +175,9 @@ checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "blake2b_simd"
|
name = "blake2b_simd"
|
||||||
version = "0.5.9"
|
version = "0.5.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b83b7baab1e671718d78204225800d6b170e648188ac7dc992e9d6bddf87d0c0"
|
checksum = "d8fb2d74254a3a0b5cac33ac9f8ed0e44aa50378d9dbb2e5d83bd21ed1dc2c8a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrayref",
|
"arrayref",
|
||||||
"arrayvec 0.5.1",
|
"arrayvec 0.5.1",
|
||||||
@@ -262,12 +246,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.0.48"
|
version = "1.0.50"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f52a465a666ca3d838ebbf08b241383421412fe7ebb463527bba275526d89f76"
|
checksum = "95e28fa049fda1c330bcf9d723be7663a899c4679724b34c81e9f5a326aab8cd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"jobserver",
|
"jobserver",
|
||||||
"num_cpus",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -358,18 +341,18 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cranelift-bforest"
|
name = "cranelift-bforest"
|
||||||
version = "0.52.0"
|
version = "0.54.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "56aa72ef104c5d634f2f9e84ef2c47e116c1d185fae13f196b97ca84b0a514f1"
|
checksum = "bd3225fff1be118941c5fb66f1fb1f7f3e86468fac0e7364713c4fb99b72632b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cranelift-entity",
|
"cranelift-entity",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cranelift-codegen"
|
name = "cranelift-codegen"
|
||||||
version = "0.52.0"
|
version = "0.54.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "460b9d20793543599308d22f5a1172c196e63a780c4e9aacb0b3f4f63d63ffe1"
|
checksum = "f3e3e6679892029f76a99b9059d2b74e77ac03637d573bb014bc21579ec1b7da"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"cranelift-bforest",
|
"cranelift-bforest",
|
||||||
@@ -385,9 +368,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cranelift-codegen-meta"
|
name = "cranelift-codegen-meta"
|
||||||
version = "0.52.0"
|
version = "0.54.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cc70e4e8ccebd53a4f925147def857c9e9f7fe0fdbef4bb645a420473e012f50"
|
checksum = "3cabe691548e28ca82ebd218f2fe76eec4c5629b64ef3db8b58443b7d9047275"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cranelift-codegen-shared",
|
"cranelift-codegen-shared",
|
||||||
"cranelift-entity",
|
"cranelift-entity",
|
||||||
@@ -395,24 +378,24 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cranelift-codegen-shared"
|
name = "cranelift-codegen-shared"
|
||||||
version = "0.52.0"
|
version = "0.54.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3992000be4d18df0fe332b7c42c120de896e8ec54cd7b6cfa050910a8c9f6e2f"
|
checksum = "d173252ffade4aa6e929090977b9a4cd5ac28e15a42626f878be3844b3000ad9"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cranelift-entity"
|
name = "cranelift-entity"
|
||||||
version = "0.52.0"
|
version = "0.54.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "722957e05064d97a3157bf0976deed0f3e8ee4f8a4ce167a7c724ca63a4e8bd9"
|
checksum = "3498ad9ba021715716a1c52e2b31d7829a149913fb0d88493e4b07d3b772b656"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cranelift-frontend"
|
name = "cranelift-frontend"
|
||||||
version = "0.52.0"
|
version = "0.54.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "13051964302dc7948e8869735de42591559ea55e319b9b92da5b38f8e6a75cb7"
|
checksum = "521a30773b8de74345c807a38853f055aca8fecaa39a0fc7698bfebc5a3da515"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cranelift-codegen",
|
"cranelift-codegen",
|
||||||
"log",
|
"log",
|
||||||
@@ -422,9 +405,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cranelift-native"
|
name = "cranelift-native"
|
||||||
version = "0.52.0"
|
version = "0.54.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "21398a0bc6ba389ea86964ac4a495426dd61080f2ddd306184777a8560fe9976"
|
checksum = "624e755cbe984e437308968239736e7f9aa3193e99928fb76eec7a1946627b34"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cranelift-codegen",
|
"cranelift-codegen",
|
||||||
"raw-cpuid",
|
"raw-cpuid",
|
||||||
@@ -433,9 +416,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cranelift-wasm"
|
name = "cranelift-wasm"
|
||||||
version = "0.52.0"
|
version = "0.54.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b72b7b10c09f70a604122fab76e6c4411255cf35403b68c3285566cc9d21c486"
|
checksum = "0320733e518ab9e0e2d1a22034d40e2851fb403ed14db5220cf9b86576b9cfd4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cranelift-codegen",
|
"cranelift-codegen",
|
||||||
"cranelift-entity",
|
"cranelift-entity",
|
||||||
@@ -443,7 +426,7 @@ dependencies = [
|
|||||||
"log",
|
"log",
|
||||||
"serde",
|
"serde",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"wasmparser 0.45.1",
|
"wasmparser 0.45.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -462,7 +445,7 @@ version = "0.8.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5064ebdbf05ce3cb95e45c8b086f72263f4166b29b97f6baff7ef7fe047b55ac"
|
checksum = "5064ebdbf05ce3cb95e45c8b086f72263f4166b29b97f6baff7ef7fe047b55ac"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"autocfg 0.1.7",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"crossbeam-utils 0.7.0",
|
"crossbeam-utils 0.7.0",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
@@ -472,10 +455,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-queue"
|
name = "crossbeam-queue"
|
||||||
version = "0.2.0"
|
version = "0.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dfd6515864a82d2f877b42813d4553292c6659498c9a2aa31bab5a15243c2700"
|
checksum = "c695eeca1e7173472a32221542ae469b3e9aac3a4fc81f7696bcad82029493db"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
"crossbeam-utils 0.7.0",
|
"crossbeam-utils 0.7.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -495,7 +479,7 @@ version = "0.7.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ce446db02cdc3165b94ae73111e570793400d0794e46125cc4056c81cbb039f4"
|
checksum = "ce446db02cdc3165b94ae73111e570793400d0794e46125cc4056c81cbb039f4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"autocfg 0.1.7",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
]
|
]
|
||||||
@@ -630,9 +614,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "faerie"
|
name = "faerie"
|
||||||
version = "0.13.0"
|
version = "0.14.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f902f2af041f6c7177a2a04f805687cdc71e69c7cbef059a2755d8923f4cd7a8"
|
checksum = "74b9ed6159e4a6212c61d9c6a86bee01876b192a64accecf58d5b5ae3b667b52"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"goblin",
|
"goblin",
|
||||||
@@ -723,9 +707,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "getrandom"
|
name = "getrandom"
|
||||||
version = "0.1.13"
|
version = "0.1.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e7db7ca94ed4cd01190ceee0d8a8052f08a247aa1b469a7f68c6a3b71afcf407"
|
checksum = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -764,9 +748,9 @@ checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "goblin"
|
name = "goblin"
|
||||||
version = "0.1.2"
|
version = "0.1.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "88a79ef1f0dad46fd78075b6f80f92d97710eddf87b3e18a15a66761e8942672"
|
checksum = "3081214398d39e4bd7f2c1975f0488ed04614ffdd976c6fc7a0708278552c0da"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"plain",
|
"plain",
|
||||||
@@ -784,9 +768,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hermit-abi"
|
name = "hermit-abi"
|
||||||
version = "0.1.3"
|
version = "0.1.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "307c3c9f937f38e3534b1d6447ecf090cafcc9744e4a6360e8b037b2cf5af120"
|
checksum = "eff2656d88f158ce120947499e971d743c05dbcbed62e5bd2f38f1698bbc3772"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
@@ -812,7 +796,7 @@ version = "1.3.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "712d7b3ea5827fcb9d4fda14bf4da5f136f0db2ae9c8f4bd4e2d1c6fde4e6db2"
|
checksum = "712d7b3ea5827fcb9d4fda14bf4da5f136f0db2ae9c8f4bd4e2d1c6fde4e6db2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"autocfg 0.1.7",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -840,9 +824,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "inventory"
|
name = "inventory"
|
||||||
version = "0.1.4"
|
version = "0.1.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f4cece20baea71d9f3435e7bbe9adf4765f091c5fe404975f844006964a71299"
|
checksum = "2bf98296081bd2cb540acc09ef9c97f22b7e487841520350293605db1b2c7a27"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ctor",
|
"ctor",
|
||||||
"ghost",
|
"ghost",
|
||||||
@@ -851,9 +835,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "inventory-impl"
|
name = "inventory-impl"
|
||||||
version = "0.1.4"
|
version = "0.1.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c2869bf972e998977b1cb87e60df70341d48e48dca0823f534feb91ea44adaf9"
|
checksum = "0a8e30575afe28eea36a9a39136b70b2fb6b0dd0a212a5bd1f30a498395c0274"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -877,13 +861,11 @@ checksum = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jobserver"
|
name = "jobserver"
|
||||||
version = "0.1.17"
|
version = "0.1.18"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f2b1d42ef453b30b7387e113da1c83ab1605d90c5b4e0eb8e96d016ed3b8c160"
|
checksum = "230ae9adf468173aecd4176c7233bddc84a15871a586c5971ace9a55f881c075"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"getrandom",
|
|
||||||
"libc",
|
"libc",
|
||||||
"log",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -931,7 +913,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lightbeam"
|
name = "lightbeam"
|
||||||
version = "0.7.0"
|
version = "0.9.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"capstone",
|
"capstone",
|
||||||
@@ -948,7 +930,7 @@ dependencies = [
|
|||||||
"smallvec",
|
"smallvec",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"typemap",
|
"typemap",
|
||||||
"wasmparser 0.45.1",
|
"wasmparser 0.47.0",
|
||||||
"wat",
|
"wat",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -1025,9 +1007,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num"
|
name = "num"
|
||||||
version = "0.2.0"
|
version = "0.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cf4825417e1e1406b3782a8ce92f4d53f26ec055e3622e1881ca8e9f5f9e08db"
|
checksum = "b8536030f9fea7127f841b45bb6243b27255787fb4eb83958aa1ef9d2fdc0c36"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"num-complex",
|
"num-complex",
|
||||||
"num-integer",
|
"num-integer",
|
||||||
@@ -1038,53 +1020,53 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-complex"
|
name = "num-complex"
|
||||||
version = "0.2.3"
|
version = "0.2.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fcb0cf31fb3ff77e6d2a6ebd6800df7fdcd106f2ad89113c9130bcd07f93dffc"
|
checksum = "b6b19411a9719e753aff12e5187b74d60d3dc449ec3f4dc21e3989c3f554bc95"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"autocfg 1.0.0",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-integer"
|
name = "num-integer"
|
||||||
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"
|
||||||
checksum = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09"
|
checksum = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"autocfg 1.0.0",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-iter"
|
name = "num-iter"
|
||||||
version = "0.1.39"
|
version = "0.1.40"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "76bd5272412d173d6bf9afdf98db8612bbabc9a7a830b7bfc9c188911716132e"
|
checksum = "dfb0800a0291891dd9f4fe7bd9c19384f98f7fbe0cd0f39a2c6b88b9868bbc00"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"autocfg 1.0.0",
|
||||||
"num-integer",
|
"num-integer",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-rational"
|
name = "num-rational"
|
||||||
version = "0.2.2"
|
version = "0.2.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f2885278d5fe2adc2f75ced642d52d879bffaceb5a2e0b1d4309ffdfb239b454"
|
checksum = "da4dc79f9e6c81bef96148c8f6b8e72ad4541caa4a24373e900a36da07de03a3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"autocfg 1.0.0",
|
||||||
"num-integer",
|
"num-integer",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-traits"
|
name = "num-traits"
|
||||||
version = "0.2.10"
|
version = "0.2.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d4c81ffc11c212fa327657cb19dd85eb7419e163b5b076bede2bdb5c974c07e4"
|
checksum = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"autocfg 1.0.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1175,13 +1157,28 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro-error"
|
name = "proc-macro-error"
|
||||||
version = "0.2.6"
|
version = "0.4.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "aeccfe4d5d8ea175d5f0e4a2ad0637e0f4121d63bd99d356fb1f39ab2e7c6097"
|
checksum = "53c98547ceaea14eeb26fcadf51dc70d01a2479a7839170eae133721105e4428"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro-error-attr",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"rustversion",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro-error-attr"
|
||||||
|
version = "0.4.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c2bf5d493cf5d3e296beccfd61794e445e830dfc8070a9c248ad3ee071392c6c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
"rustversion",
|
||||||
"syn",
|
"syn",
|
||||||
|
"syn-mid",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1197,18 +1194,18 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.6"
|
version = "1.0.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27"
|
checksum = "0319972dcae462681daf4da1adeeaa066e3ebd29c69be96c6abb1259d2ee2bcc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-xid",
|
"unicode-xid",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pyo3"
|
name = "pyo3"
|
||||||
version = "0.8.3"
|
version = "0.8.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8b338139584e698b341996e4f453c71fa937daa408aaf301e042383724e0caca"
|
checksum = "e1bfe257586436fbe1296d917f14a167d4253d0873bf43e2c9b9bdd58a3f9f35"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"indoc",
|
"indoc",
|
||||||
"inventory",
|
"inventory",
|
||||||
@@ -1227,9 +1224,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pyo3-derive-backend"
|
name = "pyo3-derive-backend"
|
||||||
version = "0.8.3"
|
version = "0.8.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3b8c805249a82c04a00d96f562e66537e8ddfe5d895bc2a414a8e6b6ae3d53be"
|
checksum = "4882d8237fd8c7373cc25cb802fe0dab9ff70830fd56f47ef6c7f3f287fcc057"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -1238,9 +1235,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pyo3cls"
|
name = "pyo3cls"
|
||||||
version = "0.8.3"
|
version = "0.8.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3575ad614aa547044119f3ff78aff7bdcba6bcde53fcd67065611546d2b8a122"
|
checksum = "fdf321cfab555f7411298733c86d21e5136f5ded13f5872fabf9de3337beecda"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"pyo3-derive-backend",
|
"pyo3-derive-backend",
|
||||||
@@ -1250,9 +1247,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quick-error"
|
name = "quick-error"
|
||||||
version = "1.2.2"
|
version = "1.2.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0"
|
checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quickcheck"
|
name = "quickcheck"
|
||||||
@@ -1368,9 +1365,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rayon"
|
name = "rayon"
|
||||||
version = "1.2.1"
|
version = "1.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "43739f8831493b276363637423d3622d4bd6394ab6f0a9c4a552e208aeb7fddd"
|
checksum = "db6ce3297f9c85e16621bb8cca38a06779ffc31bb8184e1be4bed2be4678a098"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crossbeam-deque",
|
"crossbeam-deque",
|
||||||
"either",
|
"either",
|
||||||
@@ -1379,9 +1376,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rayon-core"
|
name = "rayon-core"
|
||||||
version = "1.6.1"
|
version = "1.7.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f8bf17de6f23b05473c437eb958b9c850bfc8af0961fe17b4cc92d5a627b4791"
|
checksum = "08a89b46efaf957e52b18062fb2f4660f8b8a4dde1807ca002690868ef2c85a9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crossbeam-deque",
|
"crossbeam-deque",
|
||||||
"crossbeam-queue",
|
"crossbeam-queue",
|
||||||
@@ -1419,9 +1416,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex"
|
name = "regex"
|
||||||
version = "1.3.1"
|
version = "1.3.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dc220bd33bdce8f093101afe22a037b8eb0e5af33592e6a9caafff0d4cb81cbd"
|
checksum = "b5508c1941e4e7cb19965abef075d35a9a8b5cdf0846f30b4050e9b55dc55e87"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aho-corasick",
|
"aho-corasick",
|
||||||
"memchr",
|
"memchr",
|
||||||
@@ -1431,9 +1428,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex-syntax"
|
name = "regex-syntax"
|
||||||
version = "0.6.12"
|
version = "0.6.13"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716"
|
checksum = "e734e891f5b408a29efbf8309e656876276f49ab6a6ac208600b4419bd893d90"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "region"
|
name = "region"
|
||||||
@@ -1491,6 +1488,17 @@ dependencies = [
|
|||||||
"semver",
|
"semver",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustversion"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3a0538bd897e17257b0128d2fd95c2ed6df939374073a36166051a79e2eb7986"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ryu"
|
name = "ryu"
|
||||||
version = "1.0.2"
|
version = "1.0.2"
|
||||||
@@ -1540,18 +1548,18 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.103"
|
version = "1.0.104"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1217f97ab8e8904b57dd22eb61cde455fa7446a9c1cf43966066da047c1f3702"
|
checksum = "414115f25f818d7dfccec8ee535d76949ae78584fc4f79a6f45a904bf8ab4449"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.103"
|
version = "1.0.104"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a8c6faef9a2e64b0064f48570289b4bf8823b7581f1d6157c1b52152306651d0"
|
checksum = "128f9e303a5a29922045a830221b8f78ec74a5f544944f3d5984f8ec3895ef64"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -1571,9 +1579,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sha2"
|
name = "sha2"
|
||||||
version = "0.8.0"
|
version = "0.8.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d"
|
checksum = "27044adfd2e1f077f649f59deb9490d3941d674002f7d062870a60ebe9bd47a0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"block-buffer",
|
"block-buffer",
|
||||||
"digest",
|
"digest",
|
||||||
@@ -1589,9 +1597,9 @@ checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "smallvec"
|
name = "smallvec"
|
||||||
version = "1.0.0"
|
version = "1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4ecf3b85f68e8abaa7555aa5abdb1153079387e60b718283d732f03897fcfc86"
|
checksum = "44e59e0c9fa00817912ae6e4e6e3c4fe04455e75699d06eedc7d85917ed8e8f4"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "spin"
|
name = "spin"
|
||||||
@@ -1622,9 +1630,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "structopt"
|
name = "structopt"
|
||||||
version = "0.3.5"
|
version = "0.3.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "30b3a3e93f5ad553c38b3301c8a0a0cec829a36783f6a0c467fc4bf553a5f5bf"
|
checksum = "884ae79d6aad1e738f4a70dff314203fd498490a63ebc4d03ea83323c40b7b72"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
"structopt-derive",
|
"structopt-derive",
|
||||||
@@ -1632,9 +1640,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "structopt-derive"
|
name = "structopt-derive"
|
||||||
version = "0.3.5"
|
version = "0.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ea692d40005b3ceba90a9fe7a78fa8d4b82b0ce627eebbffc329aab850f3410e"
|
checksum = "0a97f829a34a0a9d5b353a881025a23b8c9fd09d46be6045df6b22920dbd7a93"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"heck",
|
"heck",
|
||||||
"proc-macro-error",
|
"proc-macro-error",
|
||||||
@@ -1645,15 +1653,26 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.11"
|
version = "1.0.13"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dff0acdb207ae2fe6d5976617f887eb1e35a2ba52c13c7234c790960cdad9238"
|
checksum = "1e4ff033220a41d1a57d8125eab57bf5263783dfdcc18688b1dacc6ce9651ef8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"unicode-xid",
|
"unicode-xid",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn-mid"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9fd3937748a7eccff61ba5b90af1a20dbf610858923a9192ea0ecb0cb77db1d0"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "synstructure"
|
name = "synstructure"
|
||||||
version = "0.12.3"
|
version = "0.12.3"
|
||||||
@@ -1668,9 +1687,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "target-lexicon"
|
name = "target-lexicon"
|
||||||
version = "0.9.0"
|
version = "0.10.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6f4c118a7a38378f305a9e111fcb2f7f838c0be324bfb31a77ea04f7f6e684b4"
|
checksum = "ab0e7238dcc7b40a7be719a25365910f6807bd864f4cce6b2e6b873658e2b19d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tempfile"
|
name = "tempfile"
|
||||||
@@ -1697,7 +1716,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "test-programs"
|
name = "test-programs"
|
||||||
version = "0.7.0"
|
version = "0.9.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
@@ -1745,9 +1764,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thread_local"
|
name = "thread_local"
|
||||||
version = "0.3.6"
|
version = "1.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
|
checksum = "88ddf1ad580c7e3d1efff877d972bcc93f995556b9087a5a259630985c88ceab"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
]
|
]
|
||||||
@@ -1780,9 +1799,9 @@ checksum = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "trybuild"
|
name = "trybuild"
|
||||||
version = "1.0.18"
|
version = "1.0.19"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b75e31d624df08744532e935f1d4bfedd319a277d5a162c5b15f6ced59307575"
|
checksum = "987d6fdc45ddd7f3be5aa7386c8c8a844d1655c95b9ed948a9cd9cded8f2b79f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"glob",
|
"glob",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
@@ -1886,13 +1905,13 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasi"
|
name = "wasi"
|
||||||
version = "0.7.0"
|
version = "0.9.0+wasi-snapshot-preview1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d"
|
checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasi-common"
|
name = "wasi-common"
|
||||||
version = "0.7.0"
|
version = "0.9.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
@@ -1913,7 +1932,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasi-common-cbindgen"
|
name = "wasi-common-cbindgen"
|
||||||
version = "0.7.0"
|
version = "0.9.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -1947,9 +1966,15 @@ checksum = "1527c84a5bd585215f29c06b0e2a5274e478ad4dfc970d26ffad66fdc6cb311d"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasmparser"
|
name = "wasmparser"
|
||||||
version = "0.45.1"
|
version = "0.45.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4ee23c9b67aa5d7a2381ae56805ced08960d21b7cf6ca11f78b42d68e698d03b"
|
checksum = "8b4eab1d9971d0803729cba3617b56eb04fcb4bd25361cb63880ed41a42f20d5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasmparser"
|
||||||
|
version = "0.47.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1add8db5a53a2f64f13418b241982c4ab533d7a9e1e8a5dcadccce633d8d393b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasmprinter"
|
name = "wasmprinter"
|
||||||
@@ -1963,27 +1988,28 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasmtime"
|
name = "wasmtime"
|
||||||
version = "0.7.0"
|
version = "0.9.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
|
"cfg-if",
|
||||||
"file-per-thread-logger",
|
"file-per-thread-logger",
|
||||||
|
"libc",
|
||||||
"pretty_env_logger",
|
"pretty_env_logger",
|
||||||
"rayon",
|
"rayon",
|
||||||
"region",
|
"region",
|
||||||
"target-lexicon",
|
"target-lexicon",
|
||||||
"wasi-common",
|
"wasi-common",
|
||||||
"wasmparser 0.45.1",
|
"wasmparser 0.47.0",
|
||||||
"wasmtime-environ",
|
"wasmtime-environ",
|
||||||
"wasmtime-jit",
|
"wasmtime-jit",
|
||||||
"wasmtime-runtime",
|
"wasmtime-runtime",
|
||||||
"wasmtime-wasi",
|
|
||||||
"wasmtime-wast",
|
|
||||||
"wat",
|
"wat",
|
||||||
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasmtime-cli"
|
name = "wasmtime-cli"
|
||||||
version = "0.7.0"
|
version = "0.9.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"faerie",
|
"faerie",
|
||||||
@@ -2003,6 +2029,7 @@ dependencies = [
|
|||||||
"wasmtime-interface-types",
|
"wasmtime-interface-types",
|
||||||
"wasmtime-jit",
|
"wasmtime-jit",
|
||||||
"wasmtime-obj",
|
"wasmtime-obj",
|
||||||
|
"wasmtime-runtime",
|
||||||
"wasmtime-wasi",
|
"wasmtime-wasi",
|
||||||
"wasmtime-wasi-c",
|
"wasmtime-wasi-c",
|
||||||
"wasmtime-wast",
|
"wasmtime-wast",
|
||||||
@@ -2011,7 +2038,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasmtime-debug"
|
name = "wasmtime-debug"
|
||||||
version = "0.7.0"
|
version = "0.9.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"faerie",
|
"faerie",
|
||||||
@@ -2019,13 +2046,13 @@ dependencies = [
|
|||||||
"more-asserts",
|
"more-asserts",
|
||||||
"target-lexicon",
|
"target-lexicon",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"wasmparser 0.45.1",
|
"wasmparser 0.47.0",
|
||||||
"wasmtime-environ",
|
"wasmtime-environ",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasmtime-environ"
|
name = "wasmtime-environ"
|
||||||
version = "0.7.0"
|
version = "0.9.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"base64 0.11.0",
|
"base64 0.11.0",
|
||||||
@@ -2053,14 +2080,14 @@ dependencies = [
|
|||||||
"tempfile",
|
"tempfile",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"toml",
|
"toml",
|
||||||
"wasmparser 0.45.1",
|
"wasmparser 0.47.0",
|
||||||
"winapi",
|
"winapi",
|
||||||
"zstd",
|
"zstd",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasmtime-fuzz"
|
name = "wasmtime-fuzz"
|
||||||
version = "0.7.0"
|
version = "0.9.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arbitrary",
|
"arbitrary",
|
||||||
"env_logger 0.7.1",
|
"env_logger 0.7.1",
|
||||||
@@ -2073,14 +2100,14 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasmtime-fuzzing"
|
name = "wasmtime-fuzzing"
|
||||||
version = "0.1.0"
|
version = "0.9.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"arbitrary",
|
"arbitrary",
|
||||||
"binaryen",
|
"binaryen",
|
||||||
"env_logger 0.7.1",
|
"env_logger 0.7.1",
|
||||||
"log",
|
"log",
|
||||||
"wasmparser 0.45.1",
|
"wasmparser 0.47.0",
|
||||||
"wasmprinter",
|
"wasmprinter",
|
||||||
"wasmtime",
|
"wasmtime",
|
||||||
"wasmtime-environ",
|
"wasmtime-environ",
|
||||||
@@ -2090,12 +2117,12 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasmtime-interface-types"
|
name = "wasmtime-interface-types"
|
||||||
version = "0.7.0"
|
version = "0.9.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"walrus",
|
"walrus",
|
||||||
"wasm-webidl-bindings",
|
"wasm-webidl-bindings",
|
||||||
"wasmparser 0.45.1",
|
"wasmparser 0.47.0",
|
||||||
"wasmtime",
|
"wasmtime",
|
||||||
"wasmtime-environ",
|
"wasmtime-environ",
|
||||||
"wasmtime-jit",
|
"wasmtime-jit",
|
||||||
@@ -2105,7 +2132,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasmtime-jit"
|
name = "wasmtime-jit"
|
||||||
version = "0.7.0"
|
version = "0.9.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"cranelift-codegen",
|
"cranelift-codegen",
|
||||||
@@ -2117,7 +2144,7 @@ dependencies = [
|
|||||||
"region",
|
"region",
|
||||||
"target-lexicon",
|
"target-lexicon",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"wasmparser 0.45.1",
|
"wasmparser 0.47.0",
|
||||||
"wasmtime-debug",
|
"wasmtime-debug",
|
||||||
"wasmtime-environ",
|
"wasmtime-environ",
|
||||||
"wasmtime-runtime",
|
"wasmtime-runtime",
|
||||||
@@ -2126,7 +2153,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasmtime-obj"
|
name = "wasmtime-obj"
|
||||||
version = "0.7.0"
|
version = "0.9.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"faerie",
|
"faerie",
|
||||||
@@ -2136,13 +2163,13 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasmtime-py"
|
name = "wasmtime-py"
|
||||||
version = "0.7.0"
|
version = "0.9.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"pyo3",
|
"pyo3",
|
||||||
"region",
|
"region",
|
||||||
"target-lexicon",
|
"target-lexicon",
|
||||||
"wasmparser 0.45.1",
|
"wasmparser 0.47.0",
|
||||||
"wasmtime",
|
"wasmtime",
|
||||||
"wasmtime-environ",
|
"wasmtime-environ",
|
||||||
"wasmtime-interface-types",
|
"wasmtime-interface-types",
|
||||||
@@ -2152,9 +2179,10 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasmtime-runtime"
|
name = "wasmtime-runtime"
|
||||||
version = "0.7.0"
|
version = "0.9.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
|
"cfg-if",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -2168,7 +2196,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasmtime-rust"
|
name = "wasmtime-rust"
|
||||||
version = "0.7.0"
|
version = "0.9.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"wasmtime",
|
"wasmtime",
|
||||||
@@ -2179,7 +2207,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasmtime-rust-macro"
|
name = "wasmtime-rust-macro"
|
||||||
version = "0.7.0"
|
version = "0.9.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -2188,7 +2216,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasmtime-wasi"
|
name = "wasmtime-wasi"
|
||||||
version = "0.7.0"
|
version = "0.9.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cranelift-codegen",
|
"cranelift-codegen",
|
||||||
"cranelift-entity",
|
"cranelift-entity",
|
||||||
@@ -2205,9 +2233,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasmtime-wasi-c"
|
name = "wasmtime-wasi-c"
|
||||||
version = "0.7.0"
|
version = "0.9.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bindgen 0.51.1",
|
"bindgen",
|
||||||
"cmake",
|
"cmake",
|
||||||
"cranelift-codegen",
|
"cranelift-codegen",
|
||||||
"cranelift-entity",
|
"cranelift-entity",
|
||||||
@@ -2223,11 +2251,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasmtime-wast"
|
name = "wasmtime-wast"
|
||||||
version = "0.7.0"
|
version = "0.9.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"wasmtime",
|
"wasmtime",
|
||||||
"wast 5.0.1",
|
"wast 6.0.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2241,29 +2269,20 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wast"
|
name = "wast"
|
||||||
version = "4.0.0"
|
version = "6.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fdd03645007fe5c76cdacbcf51c145db79ab82756e977f7ed051b7cf896dc7df"
|
checksum = "3ed3db7029d1d31a15c10126e78b58e51781faefafbc8afb20fb01291b779984"
|
||||||
dependencies = [
|
|
||||||
"leb128",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wast"
|
|
||||||
version = "5.0.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8d1de68310854a9840d39487701a8c1acccb5c9f9f2650d5fce3cdfe6650c372"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"leb128",
|
"leb128",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wat"
|
name = "wat"
|
||||||
version = "1.0.5"
|
version = "1.0.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "78ba86afa8d9f69291394de512e10e5ca6788998f4c426a56113770048826dc9"
|
checksum = "9d59ba5b224f5507d55e4f89d0b18cc6452d84640ab11b4c9086d61a3ee62d03"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"wast 4.0.0",
|
"wast 6.0.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2277,7 +2296,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wig"
|
name = "wig"
|
||||||
version = "0.7.0"
|
version = "0.9.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"heck",
|
"heck",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
@@ -2328,7 +2347,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winx"
|
name = "winx"
|
||||||
version = "0.7.0"
|
version = "0.9.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"cvt",
|
"cvt",
|
||||||
@@ -2338,6 +2357,8 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "witx"
|
name = "witx"
|
||||||
version = "0.6.0"
|
version = "0.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "abc432537dbc9940e06816ebc3e1c4694fc835b90720615c32038769d7b2967d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
@@ -2346,7 +2367,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "yanix"
|
name = "yanix"
|
||||||
version = "0.1.0"
|
version = "0.9.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "wasmtime-cli"
|
name = "wasmtime-cli"
|
||||||
version = "0.7.0"
|
version = "0.9.0"
|
||||||
authors = ["The Wasmtime Project Developers"]
|
authors = ["The Wasmtime Project Developers"]
|
||||||
description = "Command-line interface for Wasmtime"
|
description = "Command-line interface for Wasmtime"
|
||||||
license = "Apache-2.0 WITH LLVM-exception"
|
license = "Apache-2.0 WITH LLVM-exception"
|
||||||
@@ -29,9 +29,9 @@ wasmtime-wasi = { path = "crates/wasi" }
|
|||||||
wasmtime-wasi-c = { path = "crates/wasi-c", optional = true }
|
wasmtime-wasi-c = { path = "crates/wasi-c", optional = true }
|
||||||
wasi-common = { path = "crates/wasi-common" }
|
wasi-common = { path = "crates/wasi-common" }
|
||||||
structopt = { version = "0.3.5", features = ["color", "suggestions"] }
|
structopt = { version = "0.3.5", features = ["color", "suggestions"] }
|
||||||
faerie = "0.13.0"
|
faerie = "0.14.0"
|
||||||
anyhow = "1.0.19"
|
anyhow = "1.0.19"
|
||||||
target-lexicon = { version = "0.9.0", default-features = false }
|
target-lexicon = { version = "0.10.0", default-features = false }
|
||||||
pretty_env_logger = "0.3.0"
|
pretty_env_logger = "0.3.0"
|
||||||
file-per-thread-logger = "0.1.1"
|
file-per-thread-logger = "0.1.1"
|
||||||
wat = "1.0.2"
|
wat = "1.0.2"
|
||||||
@@ -40,6 +40,7 @@ rayon = "1.2.1"
|
|||||||
wasm-webidl-bindings = "0.6"
|
wasm-webidl-bindings = "0.6"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
wasmtime-runtime = { path = "crates/runtime" }
|
||||||
more-asserts = "0.2.1"
|
more-asserts = "0.2.1"
|
||||||
# This feature requires the wasm32-wasi target be installed. It enables
|
# This feature requires the wasm32-wasi target be installed. It enables
|
||||||
# wasm32-wasi integration tests. To enable, run
|
# wasm32-wasi integration tests. To enable, run
|
||||||
|
|||||||
37
build.rs
37
build.rs
@@ -30,26 +30,8 @@ fn main() -> anyhow::Result<()> {
|
|||||||
// Skip running spec_testsuite tests if the submodule isn't checked
|
// Skip running spec_testsuite tests if the submodule isn't checked
|
||||||
// out.
|
// out.
|
||||||
if spec_tests > 0 {
|
if spec_tests > 0 {
|
||||||
start_test_module(&mut out, "simd")?;
|
test_directory(&mut out, "tests/spec_testsuite/proposals/simd", strategy)
|
||||||
write_testsuite_tests(
|
.expect("generating tests");
|
||||||
&mut out,
|
|
||||||
"tests/spec_testsuite/proposals/simd/simd_address.wast",
|
|
||||||
"simd",
|
|
||||||
strategy,
|
|
||||||
)?;
|
|
||||||
write_testsuite_tests(
|
|
||||||
&mut out,
|
|
||||||
"tests/spec_testsuite/proposals/simd/simd_align.wast",
|
|
||||||
"simd",
|
|
||||||
strategy,
|
|
||||||
)?;
|
|
||||||
write_testsuite_tests(
|
|
||||||
&mut out,
|
|
||||||
"tests/spec_testsuite/proposals/simd/simd_const.wast",
|
|
||||||
"simd",
|
|
||||||
strategy,
|
|
||||||
)?;
|
|
||||||
finish_test_module(&mut out)?;
|
|
||||||
|
|
||||||
test_directory(
|
test_directory(
|
||||||
&mut out,
|
&mut out,
|
||||||
@@ -139,7 +121,6 @@ fn write_testsuite_tests(
|
|||||||
strategy: &str,
|
strategy: &str,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
let path = path.as_ref();
|
let path = path.as_ref();
|
||||||
println!("cargo:rerun-if-changed={}", path.display());
|
|
||||||
let testname = extract_name(path);
|
let testname = extract_name(path);
|
||||||
|
|
||||||
writeln!(out, "#[test]")?;
|
writeln!(out, "#[test]")?;
|
||||||
@@ -165,9 +146,23 @@ fn ignore(testsuite: &str, testname: &str, strategy: &str) -> bool {
|
|||||||
"Lightbeam" => match (testsuite, testname) {
|
"Lightbeam" => match (testsuite, testname) {
|
||||||
(_, _) if testname.starts_with("simd") => return true,
|
(_, _) if testname.starts_with("simd") => return true,
|
||||||
(_, _) if testsuite.ends_with("multi_value") => return true,
|
(_, _) if testsuite.ends_with("multi_value") => return true,
|
||||||
|
// Lightbeam doesn't support float arguments on the stack.
|
||||||
|
("spec_testsuite", "call") => return true,
|
||||||
_ => (),
|
_ => (),
|
||||||
},
|
},
|
||||||
"Cranelift" => match (testsuite, testname) {
|
"Cranelift" => match (testsuite, testname) {
|
||||||
|
("simd", "simd_bit_shift") => return true, // FIXME Unsupported feature: proposed SIMD operator I8x16Shl
|
||||||
|
("simd", "simd_const") => return true, // FIXME Invalid input WebAssembly code at offset 474: Unexpected data at the end of the section
|
||||||
|
("simd", "simd_conversions") => return true, // FIXME Unsupported feature: proposed SIMD operator I16x8NarrowI32x4S
|
||||||
|
("simd", "simd_f32x4") => return true, // FIXME expected V128(F32x4([CanonicalNan, CanonicalNan, Value(Float32 { bits: 0 }), Value(Float32 { bits: 0 })])), got V128(18428729675200069632)
|
||||||
|
("simd", "simd_f64x2") => return true, // FIXME expected V128(F64x2([Value(Float64 { bits: 9221120237041090560 }), Value(Float64 { bits: 0 })])), got V128(0)
|
||||||
|
("simd", "simd_f64x2_arith") => return true, // FIXME expected V128(F64x2([Value(Float64 { bits: 9221120237041090560 }), Value(Float64 { bits: 13835058055282163712 })])), got V128(255211775190703847615975447847722024960)
|
||||||
|
("simd", "simd_i64x2_arith") => return true, // FIXME Unsupported feature: proposed SIMD operator I64x2Mul
|
||||||
|
("simd", "simd_lane") => return true, // FIXME invalid u8 number: constant out of range: (v8x16.shuffle -1 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14...
|
||||||
|
("simd", "simd_load") => return true, // FIXME Unsupported feature: proposed SIMD operator I8x16Shl
|
||||||
|
("simd", "simd_load_extend") => return true, // FIXME Unsupported feature: proposed SIMD operator I16x8Load8x8S { memarg: MemoryImmediate { flags: 0, offset: 0 } }
|
||||||
|
("simd", "simd_load_splat") => return true, // FIXME Unsupported feature: proposed SIMD operator V8x16LoadSplat { memarg: MemoryImmediate { flags: 0, offset: 0 } }
|
||||||
|
("simd", "simd_splat") => return true, // FIXME Unsupported feature: proposed SIMD operator I8x16ShrS
|
||||||
_ => {}
|
_ => {}
|
||||||
},
|
},
|
||||||
_ => panic!("unrecognized strategy"),
|
_ => panic!("unrecognized strategy"),
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "wasmtime"
|
name = "wasmtime"
|
||||||
version = "0.7.0"
|
version = "0.9.0"
|
||||||
authors = ["The Wasmtime Project Developers"]
|
authors = ["The Wasmtime Project Developers"]
|
||||||
description = "High-level API to expose the Wasmtime runtime"
|
description = "High-level API to expose the Wasmtime runtime"
|
||||||
license = "Apache-2.0 WITH LLVM-exception"
|
license = "Apache-2.0 WITH LLVM-exception"
|
||||||
@@ -13,11 +13,11 @@ name = "wasmtime"
|
|||||||
crate-type = ["lib", "staticlib", "cdylib"]
|
crate-type = ["lib", "staticlib", "cdylib"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
wasmtime-runtime = { path = "../runtime" }
|
wasmtime-runtime = { path = "../runtime", version = "0.9.0" }
|
||||||
wasmtime-environ = { path = "../environ" }
|
wasmtime-environ = { path = "../environ", version = "0.9.0" }
|
||||||
wasmtime-jit = { path = "../jit" }
|
wasmtime-jit = { path = "../jit", version = "0.9.0" }
|
||||||
wasmparser = { version = "0.45.1", default-features = false }
|
wasmparser = { version = "0.47.0", default-features = false }
|
||||||
target-lexicon = { version = "0.9.0", default-features = false }
|
target-lexicon = { version = "0.10.0", default-features = false }
|
||||||
anyhow = "1.0.19"
|
anyhow = "1.0.19"
|
||||||
region = "2.0.0"
|
region = "2.0.0"
|
||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
@@ -28,10 +28,8 @@ winapi = "0.3.7"
|
|||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
# for wasmtime.rs
|
# for wasmtime.rs
|
||||||
wasi-common = { path = "../wasi-common" }
|
wasi-common = { path = "../wasi-common", version = "0.9.0" }
|
||||||
pretty_env_logger = "0.3.0"
|
pretty_env_logger = "0.3.0"
|
||||||
wasmtime-wast = { path = "../wast" }
|
|
||||||
wasmtime-wasi = { path = "../wasi" }
|
|
||||||
rayon = "1.2.1"
|
rayon = "1.2.1"
|
||||||
file-per-thread-logger = "0.1.1"
|
file-per-thread-logger = "0.1.1"
|
||||||
wat = "1.0"
|
wat = "1.0"
|
||||||
|
|||||||
Submodule crates/api/c-examples/wasm-c-api updated: 8782d5b456...d9a80099d4
@@ -50,11 +50,11 @@ fn main() -> anyhow::Result<()> {
|
|||||||
.0;
|
.0;
|
||||||
|
|
||||||
// Instantiate the module.
|
// Instantiate the module.
|
||||||
let instance = Instance::new(&store, &module, &[])?;
|
let instance = Instance::new(&module, &[])?;
|
||||||
|
|
||||||
// Invoke `gcd` export
|
// Invoke `gcd` export
|
||||||
let gcd = instance.exports()[gcd_index].func().expect("gcd");
|
let gcd = instance.exports()[gcd_index].func().expect("gcd");
|
||||||
let result = gcd.borrow().call(&[Val::from(6i32), Val::from(27i32)])?;
|
let result = gcd.call(&[Val::from(6i32), Val::from(27i32)])?;
|
||||||
|
|
||||||
println!("{:?}", result);
|
println!("{:?}", result);
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -41,15 +41,14 @@ fn main() -> Result<()> {
|
|||||||
// `HelloCallback` type and its associated implementation of `Callback.
|
// `HelloCallback` type and its associated implementation of `Callback.
|
||||||
println!("Creating callback...");
|
println!("Creating callback...");
|
||||||
let hello_type = FuncType::new(Box::new([]), Box::new([]));
|
let hello_type = FuncType::new(Box::new([]), Box::new([]));
|
||||||
let hello_func = HostRef::new(Func::new(&store, hello_type, Rc::new(HelloCallback)));
|
let hello_func = Func::new(&store, hello_type, Rc::new(HelloCallback));
|
||||||
|
|
||||||
// Once we've got that all set up we can then move to the instantiation
|
// Once we've got that all set up we can then move to the instantiation
|
||||||
// phase, pairing together a compiled module as well as a set of imports.
|
// phase, pairing together a compiled module as well as a set of imports.
|
||||||
// Note that this is where the wasm `start` function, if any, would run.
|
// Note that this is where the wasm `start` function, if any, would run.
|
||||||
println!("Instantiating module...");
|
println!("Instantiating module...");
|
||||||
let imports = vec![hello_func.into()];
|
let imports = vec![hello_func.into()];
|
||||||
let instance = Instance::new(&store, &module, imports.as_slice())
|
let instance = Instance::new(&module, &imports).context("> Error instantiating module!")?;
|
||||||
.context("> Error instantiating module!")?;
|
|
||||||
|
|
||||||
// Next we poke around a bit to extract the `run` function from the module.
|
// Next we poke around a bit to extract the `run` function from the module.
|
||||||
println!("Extracting export...");
|
println!("Extracting export...");
|
||||||
@@ -59,7 +58,7 @@ fn main() -> Result<()> {
|
|||||||
|
|
||||||
// And last but not least we can call it!
|
// And last but not least we can call it!
|
||||||
println!("Calling export...");
|
println!("Calling export...");
|
||||||
run_func.borrow().call(&[])?;
|
run_func.call(&[])?;
|
||||||
|
|
||||||
println!("Done.");
|
println!("Done.");
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
use anyhow::{bail, ensure, Context as _, Error};
|
use anyhow::{bail, ensure, Context as _, Error};
|
||||||
use wasmtime::*;
|
use wasmtime::*;
|
||||||
|
|
||||||
fn get_export_memory(exports: &[Extern], i: usize) -> Result<HostRef<Memory>, Error> {
|
fn get_export_memory(exports: &[Extern], i: usize) -> Result<Memory, Error> {
|
||||||
if exports.len() <= i {
|
if exports.len() <= i {
|
||||||
bail!("> Error accessing memory export {}!", i);
|
bail!("> Error accessing memory export {}!", i);
|
||||||
}
|
}
|
||||||
@@ -13,7 +13,7 @@ fn get_export_memory(exports: &[Extern], i: usize) -> Result<HostRef<Memory>, Er
|
|||||||
.clone())
|
.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_export_func(exports: &[Extern], i: usize) -> Result<HostRef<Func>, Error> {
|
fn get_export_func(exports: &[Extern], i: usize) -> Result<Func, Error> {
|
||||||
if exports.len() <= i {
|
if exports.len() <= i {
|
||||||
bail!("> Error accessing function export {}!", i);
|
bail!("> Error accessing function export {}!", i);
|
||||||
}
|
}
|
||||||
@@ -33,7 +33,7 @@ macro_rules! check {
|
|||||||
|
|
||||||
macro_rules! check_ok {
|
macro_rules! check_ok {
|
||||||
($func:expr, $($p:expr),*) => {
|
($func:expr, $($p:expr),*) => {
|
||||||
if let Err(_) = $func.borrow().call(&[$($p.into()),*]) {
|
if let Err(_) = $func.call(&[$($p.into()),*]) {
|
||||||
bail!("> Error on result, expected return");
|
bail!("> Error on result, expected return");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -41,7 +41,7 @@ macro_rules! check_ok {
|
|||||||
|
|
||||||
macro_rules! check_trap {
|
macro_rules! check_trap {
|
||||||
($func:expr, $($p:expr),*) => {
|
($func:expr, $($p:expr),*) => {
|
||||||
if let Ok(_) = $func.borrow().call(&[$($p.into()),*]) {
|
if let Ok(_) = $func.call(&[$($p.into()),*]) {
|
||||||
bail!("> Error on result, expected trap");
|
bail!("> Error on result, expected trap");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -49,7 +49,7 @@ macro_rules! check_trap {
|
|||||||
|
|
||||||
macro_rules! call {
|
macro_rules! call {
|
||||||
($func:expr, $($p:expr),*) => {
|
($func:expr, $($p:expr),*) => {
|
||||||
match $func.borrow().call(&[$($p.into()),*]) {
|
match $func.call(&[$($p.into()),*]) {
|
||||||
Ok(result) => {
|
Ok(result) => {
|
||||||
let result: i32 = result[0].unwrap_i32();
|
let result: i32 = result[0].unwrap_i32();
|
||||||
result
|
result
|
||||||
@@ -90,7 +90,7 @@ fn main() -> Result<(), Error> {
|
|||||||
|
|
||||||
// Instantiate.
|
// Instantiate.
|
||||||
println!("Instantiating module...");
|
println!("Instantiating module...");
|
||||||
let instance = Instance::new(&store, &module, &[]).context("> Error instantiating module!")?;
|
let instance = Instance::new(&module, &[]).context("> Error instantiating module!")?;
|
||||||
|
|
||||||
// Extract export.
|
// Extract export.
|
||||||
println!("Extracting export...");
|
println!("Extracting export...");
|
||||||
@@ -101,16 +101,13 @@ fn main() -> Result<(), Error> {
|
|||||||
let load_func = get_export_func(&exports, 2)?;
|
let load_func = get_export_func(&exports, 2)?;
|
||||||
let store_func = get_export_func(&exports, 3)?;
|
let store_func = get_export_func(&exports, 3)?;
|
||||||
|
|
||||||
// Try cloning.
|
|
||||||
check!(memory.clone().ptr_eq(&memory), true);
|
|
||||||
|
|
||||||
// Check initial memory.
|
// Check initial memory.
|
||||||
println!("Checking memory...");
|
println!("Checking memory...");
|
||||||
check!(memory.borrow().size(), 2u32);
|
check!(memory.size(), 2u32);
|
||||||
check!(memory.borrow().data_size(), 0x20000usize);
|
check!(memory.data_size(), 0x20000usize);
|
||||||
check!(unsafe { memory.borrow().data()[0] }, 0);
|
check!(unsafe { memory.data()[0] }, 0);
|
||||||
check!(unsafe { memory.borrow().data()[0x1000] }, 1);
|
check!(unsafe { memory.data()[0x1000] }, 1);
|
||||||
check!(unsafe { memory.borrow().data()[0x1003] }, 4);
|
check!(unsafe { memory.data()[0x1003] }, 4);
|
||||||
|
|
||||||
check!(call!(size_func,), 2);
|
check!(call!(size_func,), 2);
|
||||||
check!(call!(load_func, 0), 0);
|
check!(call!(load_func, 0), 0);
|
||||||
@@ -122,36 +119,36 @@ fn main() -> Result<(), Error> {
|
|||||||
// Mutate memory.
|
// Mutate memory.
|
||||||
println!("Mutating memory...");
|
println!("Mutating memory...");
|
||||||
unsafe {
|
unsafe {
|
||||||
memory.borrow_mut().data()[0x1003] = 5;
|
memory.data()[0x1003] = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
check_ok!(store_func, 0x1002, 6);
|
check_ok!(store_func, 0x1002, 6);
|
||||||
check_trap!(store_func, 0x20000, 0);
|
check_trap!(store_func, 0x20000, 0);
|
||||||
|
|
||||||
check!(unsafe { memory.borrow().data()[0x1002] }, 6);
|
check!(unsafe { memory.data()[0x1002] }, 6);
|
||||||
check!(unsafe { memory.borrow().data()[0x1003] }, 5);
|
check!(unsafe { memory.data()[0x1003] }, 5);
|
||||||
check!(call!(load_func, 0x1002), 6);
|
check!(call!(load_func, 0x1002), 6);
|
||||||
check!(call!(load_func, 0x1003), 5);
|
check!(call!(load_func, 0x1003), 5);
|
||||||
|
|
||||||
// Grow memory.
|
// Grow memory.
|
||||||
println!("Growing memory...");
|
println!("Growing memory...");
|
||||||
check!(memory.borrow_mut().grow(1), true);
|
check!(memory.grow(1), true);
|
||||||
check!(memory.borrow().size(), 3u32);
|
check!(memory.size(), 3u32);
|
||||||
check!(memory.borrow().data_size(), 0x30000usize);
|
check!(memory.data_size(), 0x30000usize);
|
||||||
|
|
||||||
check!(call!(load_func, 0x20000), 0);
|
check!(call!(load_func, 0x20000), 0);
|
||||||
check_ok!(store_func, 0x20000, 0);
|
check_ok!(store_func, 0x20000, 0);
|
||||||
check_trap!(load_func, 0x30000);
|
check_trap!(load_func, 0x30000);
|
||||||
check_trap!(store_func, 0x30000, 0);
|
check_trap!(store_func, 0x30000, 0);
|
||||||
|
|
||||||
check!(memory.borrow_mut().grow(1), false);
|
check!(memory.grow(1), false);
|
||||||
check!(memory.borrow_mut().grow(0), true);
|
check!(memory.grow(0), true);
|
||||||
|
|
||||||
// Create stand-alone memory.
|
// Create stand-alone memory.
|
||||||
// TODO(wasm+): Once Wasm allows multiple memories, turn this into import.
|
// TODO(wasm+): Once Wasm allows multiple memories, turn this into import.
|
||||||
println!("Creating stand-alone memory...");
|
println!("Creating stand-alone memory...");
|
||||||
let memorytype = MemoryType::new(Limits::new(5, Some(5)));
|
let memorytype = MemoryType::new(Limits::new(5, Some(5)));
|
||||||
let mut memory2 = Memory::new(&store, memorytype);
|
let memory2 = Memory::new(&store, memorytype);
|
||||||
check!(memory2.size(), 5u32);
|
check!(memory2.size(), 5u32);
|
||||||
check!(memory2.grow(1), false);
|
check!(memory2.grow(1), false);
|
||||||
check!(memory2.grow(0), true);
|
check!(memory2.grow(0), true);
|
||||||
|
|||||||
@@ -62,13 +62,13 @@ fn main() -> Result<()> {
|
|||||||
Box::new([ValType::I32, ValType::I64]),
|
Box::new([ValType::I32, ValType::I64]),
|
||||||
Box::new([ValType::I64, ValType::I32]),
|
Box::new([ValType::I64, ValType::I32]),
|
||||||
);
|
);
|
||||||
let callback_func = HostRef::new(Func::new(&store, callback_type, Rc::new(Callback)));
|
let callback_func = Func::new(&store, callback_type, Rc::new(Callback));
|
||||||
|
|
||||||
// Instantiate.
|
// Instantiate.
|
||||||
println!("Instantiating module...");
|
println!("Instantiating module...");
|
||||||
let imports = vec![callback_func.into()];
|
let imports = vec![callback_func.into()];
|
||||||
let instance = Instance::new(&store, &module, imports.as_slice())
|
let instance =
|
||||||
.context("Error instantiating module!")?;
|
Instance::new(&module, imports.as_slice()).context("Error instantiating module!")?;
|
||||||
|
|
||||||
// Extract exports.
|
// Extract exports.
|
||||||
println!("Extracting export...");
|
println!("Extracting export...");
|
||||||
@@ -83,7 +83,6 @@ fn main() -> Result<()> {
|
|||||||
println!("Calling export \"g\"...");
|
println!("Calling export \"g\"...");
|
||||||
let args = vec![Val::I32(1), Val::I64(3)];
|
let args = vec![Val::I32(1), Val::I64(3)];
|
||||||
let results = g
|
let results = g
|
||||||
.borrow()
|
|
||||||
.call(&args)
|
.call(&args)
|
||||||
.map_err(|e| format_err!("> Error calling g! {:?}", e))?;
|
.map_err(|e| format_err!("> Error calling g! {:?}", e))?;
|
||||||
|
|
||||||
@@ -108,7 +107,6 @@ fn main() -> Result<()> {
|
|||||||
Val::I64(9),
|
Val::I64(9),
|
||||||
];
|
];
|
||||||
let results = round_trip_many
|
let results = round_trip_many
|
||||||
.borrow()
|
|
||||||
.call(&args)
|
.call(&args)
|
||||||
.map_err(|e| format_err!("> Error calling round_trip_many! {:?}", e))?;
|
.map_err(|e| format_err!("> Error calling round_trip_many! {:?}", e))?;
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ use wasmtime_runtime::Export;
|
|||||||
/// WebAssembly.
|
/// WebAssembly.
|
||||||
/// # Example
|
/// # Example
|
||||||
/// ```
|
/// ```
|
||||||
/// use wasmtime::{HostRef, Val};
|
/// use wasmtime::Val;
|
||||||
///
|
///
|
||||||
/// struct TimesTwo;
|
/// struct TimesTwo;
|
||||||
///
|
///
|
||||||
@@ -54,13 +54,11 @@ use wasmtime_runtime::Export;
|
|||||||
/// );
|
/// );
|
||||||
///
|
///
|
||||||
/// // Build a reference to the "times_two" function that can be used.
|
/// // Build a reference to the "times_two" function that can be used.
|
||||||
/// let times_two_function = HostRef::new(
|
/// let times_two_function =
|
||||||
/// wasmtime::Func::new(&store, times_two_type, std::rc::Rc::new(TimesTwo))
|
/// wasmtime::Func::new(&store, times_two_type, std::rc::Rc::new(TimesTwo));
|
||||||
/// );
|
|
||||||
///
|
///
|
||||||
/// // Create module instance that imports our function
|
/// // Create module instance that imports our function
|
||||||
/// let instance = wasmtime::Instance::new(
|
/// let instance = wasmtime::Instance::new(
|
||||||
/// &store,
|
|
||||||
/// &module,
|
/// &module,
|
||||||
/// &[times_two_function.into()]
|
/// &[times_two_function.into()]
|
||||||
/// )?;
|
/// )?;
|
||||||
@@ -71,7 +69,6 @@ use wasmtime_runtime::Export;
|
|||||||
/// // Borrow and call "run". Returning any error message from Wasm as a string.
|
/// // Borrow and call "run". Returning any error message from Wasm as a string.
|
||||||
/// let original = 5i32;
|
/// let original = 5i32;
|
||||||
/// let results = run_function
|
/// let results = run_function
|
||||||
/// .borrow()
|
|
||||||
/// .call(&[original.into()])
|
/// .call(&[original.into()])
|
||||||
/// .map_err(|trap| trap.to_string())?;
|
/// .map_err(|trap| trap.to_string())?;
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use crate::callable::{Callable, NativeCallable, WasmtimeFn, WrappedCallable};
|
use crate::callable::{Callable, NativeCallable, WasmtimeFn, WrappedCallable};
|
||||||
use crate::r#ref::{AnyRef, HostRef};
|
use crate::r#ref::AnyRef;
|
||||||
use crate::runtime::Store;
|
use crate::runtime::Store;
|
||||||
use crate::trampoline::{generate_global_export, generate_memory_export, generate_table_export};
|
use crate::trampoline::{generate_global_export, generate_memory_export, generate_table_export};
|
||||||
use crate::trap::Trap;
|
use crate::trap::Trap;
|
||||||
@@ -15,53 +15,53 @@ use wasmtime_runtime::InstanceHandle;
|
|||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub enum Extern {
|
pub enum Extern {
|
||||||
Func(HostRef<Func>),
|
Func(Func),
|
||||||
Global(HostRef<Global>),
|
Global(Global),
|
||||||
Table(HostRef<Table>),
|
Table(Table),
|
||||||
Memory(HostRef<Memory>),
|
Memory(Memory),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Extern {
|
impl Extern {
|
||||||
pub fn func(&self) -> Option<&HostRef<Func>> {
|
pub fn func(&self) -> Option<&Func> {
|
||||||
match self {
|
match self {
|
||||||
Extern::Func(func) => Some(func),
|
Extern::Func(func) => Some(func),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn global(&self) -> Option<&HostRef<Global>> {
|
pub fn global(&self) -> Option<&Global> {
|
||||||
match self {
|
match self {
|
||||||
Extern::Global(global) => Some(global),
|
Extern::Global(global) => Some(global),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn table(&self) -> Option<&HostRef<Table>> {
|
pub fn table(&self) -> Option<&Table> {
|
||||||
match self {
|
match self {
|
||||||
Extern::Table(table) => Some(table),
|
Extern::Table(table) => Some(table),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn memory(&self) -> Option<&HostRef<Memory>> {
|
pub fn memory(&self) -> Option<&Memory> {
|
||||||
match self {
|
match self {
|
||||||
Extern::Memory(memory) => Some(memory),
|
Extern::Memory(memory) => Some(memory),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn r#type(&self) -> ExternType {
|
pub fn ty(&self) -> ExternType {
|
||||||
match self {
|
match self {
|
||||||
Extern::Func(ft) => ExternType::Func(ft.borrow().r#type().clone()),
|
Extern::Func(ft) => ExternType::Func(ft.ty().clone()),
|
||||||
Extern::Memory(ft) => ExternType::Memory(ft.borrow().r#type().clone()),
|
Extern::Memory(ft) => ExternType::Memory(ft.ty().clone()),
|
||||||
Extern::Table(tt) => ExternType::Table(tt.borrow().r#type().clone()),
|
Extern::Table(tt) => ExternType::Table(tt.ty().clone()),
|
||||||
Extern::Global(gt) => ExternType::Global(gt.borrow().r#type().clone()),
|
Extern::Global(gt) => ExternType::Global(gt.ty().clone()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn get_wasmtime_export(&mut self) -> wasmtime_runtime::Export {
|
pub(crate) fn get_wasmtime_export(&self) -> wasmtime_runtime::Export {
|
||||||
match self {
|
match self {
|
||||||
Extern::Func(f) => f.borrow().wasmtime_export().clone(),
|
Extern::Func(f) => f.wasmtime_export().clone(),
|
||||||
Extern::Global(g) => g.borrow().wasmtime_export().clone(),
|
Extern::Global(g) => g.wasmtime_export().clone(),
|
||||||
Extern::Memory(m) => m.borrow().wasmtime_export().clone(),
|
Extern::Memory(m) => m.wasmtime_export().clone(),
|
||||||
Extern::Table(t) => t.borrow().wasmtime_export().clone(),
|
Extern::Table(t) => t.wasmtime_export().clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,50 +71,51 @@ impl Extern {
|
|||||||
export: wasmtime_runtime::Export,
|
export: wasmtime_runtime::Export,
|
||||||
) -> Extern {
|
) -> Extern {
|
||||||
match export {
|
match export {
|
||||||
wasmtime_runtime::Export::Function { .. } => Extern::Func(HostRef::new(
|
wasmtime_runtime::Export::Function { .. } => {
|
||||||
Func::from_wasmtime_function(export, store, instance_handle),
|
Extern::Func(Func::from_wasmtime_function(export, store, instance_handle))
|
||||||
)),
|
}
|
||||||
wasmtime_runtime::Export::Memory { .. } => Extern::Memory(HostRef::new(
|
wasmtime_runtime::Export::Memory { .. } => {
|
||||||
Memory::from_wasmtime_memory(export, store, instance_handle),
|
Extern::Memory(Memory::from_wasmtime_memory(export, store, instance_handle))
|
||||||
)),
|
}
|
||||||
wasmtime_runtime::Export::Global { .. } => {
|
wasmtime_runtime::Export::Global { .. } => {
|
||||||
Extern::Global(HostRef::new(Global::from_wasmtime_global(export, store)))
|
Extern::Global(Global::from_wasmtime_global(export, store))
|
||||||
|
}
|
||||||
|
wasmtime_runtime::Export::Table { .. } => {
|
||||||
|
Extern::Table(Table::from_wasmtime_table(export, store, instance_handle))
|
||||||
}
|
}
|
||||||
wasmtime_runtime::Export::Table { .. } => Extern::Table(HostRef::new(
|
|
||||||
Table::from_wasmtime_table(export, store, instance_handle),
|
|
||||||
)),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<HostRef<Func>> for Extern {
|
impl From<Func> for Extern {
|
||||||
fn from(r: HostRef<Func>) -> Self {
|
fn from(r: Func) -> Self {
|
||||||
Extern::Func(r)
|
Extern::Func(r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<HostRef<Global>> for Extern {
|
impl From<Global> for Extern {
|
||||||
fn from(r: HostRef<Global>) -> Self {
|
fn from(r: Global) -> Self {
|
||||||
Extern::Global(r)
|
Extern::Global(r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<HostRef<Memory>> for Extern {
|
impl From<Memory> for Extern {
|
||||||
fn from(r: HostRef<Memory>) -> Self {
|
fn from(r: Memory) -> Self {
|
||||||
Extern::Memory(r)
|
Extern::Memory(r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<HostRef<Table>> for Extern {
|
impl From<Table> for Extern {
|
||||||
fn from(r: HostRef<Table>) -> Self {
|
fn from(r: Table) -> Self {
|
||||||
Extern::Table(r)
|
Extern::Table(r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct Func {
|
pub struct Func {
|
||||||
_store: Store,
|
_store: Store,
|
||||||
callable: Rc<dyn WrappedCallable + 'static>,
|
callable: Rc<dyn WrappedCallable + 'static>,
|
||||||
r#type: FuncType,
|
ty: FuncType,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Func {
|
impl Func {
|
||||||
@@ -125,26 +126,26 @@ impl Func {
|
|||||||
|
|
||||||
fn from_wrapped(
|
fn from_wrapped(
|
||||||
store: &Store,
|
store: &Store,
|
||||||
r#type: FuncType,
|
ty: FuncType,
|
||||||
callable: Rc<dyn WrappedCallable + 'static>,
|
callable: Rc<dyn WrappedCallable + 'static>,
|
||||||
) -> Func {
|
) -> Func {
|
||||||
Func {
|
Func {
|
||||||
_store: store.clone(),
|
_store: store.clone(),
|
||||||
callable,
|
callable,
|
||||||
r#type,
|
ty,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn r#type(&self) -> &FuncType {
|
pub fn ty(&self) -> &FuncType {
|
||||||
&self.r#type
|
&self.ty
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn param_arity(&self) -> usize {
|
pub fn param_arity(&self) -> usize {
|
||||||
self.r#type.params().len()
|
self.ty.params().len()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn result_arity(&self) -> usize {
|
pub fn result_arity(&self) -> usize {
|
||||||
self.r#type.results().len()
|
self.ty.results().len()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn call(&self, params: &[Val]) -> Result<Box<[Val]>, Trap> {
|
pub fn call(&self, params: &[Val]) -> Result<Box<[Val]>, Trap> {
|
||||||
@@ -162,8 +163,12 @@ impl Func {
|
|||||||
store: &Store,
|
store: &Store,
|
||||||
instance_handle: InstanceHandle,
|
instance_handle: InstanceHandle,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
// This is only called with `Export::Function`, and since it's coming
|
||||||
|
// from wasmtime_runtime itself we should support all the types coming
|
||||||
|
// out of it, so assert such here.
|
||||||
let ty = if let wasmtime_runtime::Export::Function { signature, .. } = &export {
|
let ty = if let wasmtime_runtime::Export::Function { signature, .. } = &export {
|
||||||
FuncType::from_wasmtime_signature(signature.clone())
|
FuncType::from_wasmtime_signature(signature.clone())
|
||||||
|
.expect("core wasm signature should be supported")
|
||||||
} else {
|
} else {
|
||||||
panic!("expected function export")
|
panic!("expected function export")
|
||||||
};
|
};
|
||||||
@@ -178,32 +183,39 @@ impl fmt::Debug for Func {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct Global {
|
pub struct Global {
|
||||||
|
inner: Rc<GlobalInner>,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct GlobalInner {
|
||||||
_store: Store,
|
_store: Store,
|
||||||
r#type: GlobalType,
|
ty: GlobalType,
|
||||||
wasmtime_export: wasmtime_runtime::Export,
|
wasmtime_export: wasmtime_runtime::Export,
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
wasmtime_state: Option<crate::trampoline::GlobalState>,
|
wasmtime_state: Option<crate::trampoline::GlobalState>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Global {
|
impl Global {
|
||||||
pub fn new(store: &Store, r#type: GlobalType, val: Val) -> Global {
|
pub fn new(store: &Store, ty: GlobalType, val: Val) -> Global {
|
||||||
let (wasmtime_export, wasmtime_state) =
|
let (wasmtime_export, wasmtime_state) =
|
||||||
generate_global_export(&r#type, val).expect("generated global");
|
generate_global_export(&ty, val).expect("generated global");
|
||||||
Global {
|
Global {
|
||||||
_store: store.clone(),
|
inner: Rc::new(GlobalInner {
|
||||||
r#type,
|
_store: store.clone(),
|
||||||
wasmtime_export,
|
ty,
|
||||||
wasmtime_state: Some(wasmtime_state),
|
wasmtime_export,
|
||||||
|
wasmtime_state: Some(wasmtime_state),
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn r#type(&self) -> &GlobalType {
|
pub fn ty(&self) -> &GlobalType {
|
||||||
&self.r#type
|
&self.inner.ty
|
||||||
}
|
}
|
||||||
|
|
||||||
fn wasmtime_global_definition(&self) -> *mut wasmtime_runtime::VMGlobalDefinition {
|
fn wasmtime_global_definition(&self) -> *mut wasmtime_runtime::VMGlobalDefinition {
|
||||||
match self.wasmtime_export {
|
match self.inner.wasmtime_export {
|
||||||
wasmtime_runtime::Export::Global { definition, .. } => definition,
|
wasmtime_runtime::Export::Global { definition, .. } => definition,
|
||||||
_ => panic!("global definition not found"),
|
_ => panic!("global definition not found"),
|
||||||
}
|
}
|
||||||
@@ -212,22 +224,22 @@ impl Global {
|
|||||||
pub fn get(&self) -> Val {
|
pub fn get(&self) -> Val {
|
||||||
let definition = unsafe { &mut *self.wasmtime_global_definition() };
|
let definition = unsafe { &mut *self.wasmtime_global_definition() };
|
||||||
unsafe {
|
unsafe {
|
||||||
match self.r#type().content() {
|
match self.ty().content() {
|
||||||
ValType::I32 => Val::from(*definition.as_i32()),
|
ValType::I32 => Val::from(*definition.as_i32()),
|
||||||
ValType::I64 => Val::from(*definition.as_i64()),
|
ValType::I64 => Val::from(*definition.as_i64()),
|
||||||
ValType::F32 => Val::F32(*definition.as_u32()),
|
ValType::F32 => Val::F32(*definition.as_u32()),
|
||||||
ValType::F64 => Val::F64(*definition.as_u64()),
|
ValType::F64 => Val::F64(*definition.as_u64()),
|
||||||
_ => unimplemented!("Global::get for {:?}", self.r#type().content()),
|
_ => unimplemented!("Global::get for {:?}", self.ty().content()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set(&mut self, val: Val) {
|
pub fn set(&self, val: Val) {
|
||||||
if val.r#type() != *self.r#type().content() {
|
if val.ty() != *self.ty().content() {
|
||||||
panic!(
|
panic!(
|
||||||
"global of type {:?} cannot be set to {:?}",
|
"global of type {:?} cannot be set to {:?}",
|
||||||
self.r#type().content(),
|
self.ty().content(),
|
||||||
val.r#type()
|
val.ty()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
let definition = unsafe { &mut *self.wasmtime_global_definition() };
|
let definition = unsafe { &mut *self.wasmtime_global_definition() };
|
||||||
@@ -237,34 +249,40 @@ impl Global {
|
|||||||
Val::I64(i) => *definition.as_i64_mut() = i,
|
Val::I64(i) => *definition.as_i64_mut() = i,
|
||||||
Val::F32(f) => *definition.as_u32_mut() = f,
|
Val::F32(f) => *definition.as_u32_mut() = f,
|
||||||
Val::F64(f) => *definition.as_u64_mut() = f,
|
Val::F64(f) => *definition.as_u64_mut() = f,
|
||||||
_ => unimplemented!("Global::set for {:?}", val.r#type()),
|
_ => unimplemented!("Global::set for {:?}", val.ty()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn wasmtime_export(&self) -> &wasmtime_runtime::Export {
|
pub(crate) fn wasmtime_export(&self) -> &wasmtime_runtime::Export {
|
||||||
&self.wasmtime_export
|
&self.inner.wasmtime_export
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn from_wasmtime_global(export: wasmtime_runtime::Export, store: &Store) -> Global {
|
pub(crate) fn from_wasmtime_global(export: wasmtime_runtime::Export, store: &Store) -> Global {
|
||||||
let global = if let wasmtime_runtime::Export::Global { ref global, .. } = export {
|
let global = if let wasmtime_runtime::Export::Global { ref global, .. } = export {
|
||||||
global
|
global
|
||||||
} else {
|
} else {
|
||||||
panic!("wasmtime export is not memory")
|
panic!("wasmtime export is not global")
|
||||||
};
|
};
|
||||||
let ty = GlobalType::from_wasmtime_global(&global);
|
// The original export is coming from wasmtime_runtime itself we should
|
||||||
|
// support all the types coming out of it, so assert such here.
|
||||||
|
let ty = GlobalType::from_wasmtime_global(&global)
|
||||||
|
.expect("core wasm global type should be supported");
|
||||||
Global {
|
Global {
|
||||||
_store: store.clone(),
|
inner: Rc::new(GlobalInner {
|
||||||
r#type: ty,
|
_store: store.clone(),
|
||||||
wasmtime_export: export,
|
ty: ty,
|
||||||
wasmtime_state: None,
|
wasmtime_export: export,
|
||||||
|
wasmtime_state: None,
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct Table {
|
pub struct Table {
|
||||||
store: Store,
|
store: Store,
|
||||||
r#type: TableType,
|
ty: TableType,
|
||||||
wasmtime_handle: InstanceHandle,
|
wasmtime_handle: InstanceHandle,
|
||||||
wasmtime_export: wasmtime_runtime::Export,
|
wasmtime_export: wasmtime_runtime::Export,
|
||||||
}
|
}
|
||||||
@@ -299,13 +317,13 @@ fn set_table_item(
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Table {
|
impl Table {
|
||||||
pub fn new(store: &Store, r#type: TableType, init: Val) -> Table {
|
pub fn new(store: &Store, ty: TableType, init: Val) -> Table {
|
||||||
match r#type.element() {
|
match ty.element() {
|
||||||
ValType::FuncRef => (),
|
ValType::FuncRef => (),
|
||||||
_ => panic!("table is not for funcref"),
|
_ => panic!("table is not for funcref"),
|
||||||
}
|
}
|
||||||
let (mut wasmtime_handle, wasmtime_export) =
|
let (mut wasmtime_handle, wasmtime_export) =
|
||||||
generate_table_export(&r#type).expect("generated table");
|
generate_table_export(&ty).expect("generated table");
|
||||||
|
|
||||||
// Initialize entries with the init value.
|
// Initialize entries with the init value.
|
||||||
match wasmtime_export {
|
match wasmtime_export {
|
||||||
@@ -323,14 +341,14 @@ impl Table {
|
|||||||
|
|
||||||
Table {
|
Table {
|
||||||
store: store.clone(),
|
store: store.clone(),
|
||||||
r#type,
|
ty,
|
||||||
wasmtime_handle,
|
wasmtime_handle,
|
||||||
wasmtime_export,
|
wasmtime_export,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn r#type(&self) -> &TableType {
|
pub fn ty(&self) -> &TableType {
|
||||||
&self.r#type
|
&self.ty
|
||||||
}
|
}
|
||||||
|
|
||||||
fn wasmtime_table_index(&self) -> wasm::DefinedTableIndex {
|
fn wasmtime_table_index(&self) -> wasm::DefinedTableIndex {
|
||||||
@@ -362,9 +380,9 @@ impl Table {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn grow(&mut self, delta: u32, init: Val) -> bool {
|
pub fn grow(&self, delta: u32, init: Val) -> bool {
|
||||||
let index = self.wasmtime_table_index();
|
let index = self.wasmtime_table_index();
|
||||||
if let Some(len) = self.wasmtime_handle.table_grow(index, delta) {
|
if let Some(len) = self.wasmtime_handle.clone().table_grow(index, delta) {
|
||||||
let mut wasmtime_handle = self.wasmtime_handle.clone();
|
let mut wasmtime_handle = self.wasmtime_handle.clone();
|
||||||
for i in 0..delta {
|
for i in 0..delta {
|
||||||
let i = len - (delta - i);
|
let i = len - (delta - i);
|
||||||
@@ -395,34 +413,35 @@ impl Table {
|
|||||||
let ty = TableType::from_wasmtime_table(&table.table);
|
let ty = TableType::from_wasmtime_table(&table.table);
|
||||||
Table {
|
Table {
|
||||||
store: store.clone(),
|
store: store.clone(),
|
||||||
r#type: ty,
|
ty: ty,
|
||||||
wasmtime_handle: instance_handle,
|
wasmtime_handle: instance_handle,
|
||||||
wasmtime_export: export,
|
wasmtime_export: export,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct Memory {
|
pub struct Memory {
|
||||||
_store: Store,
|
_store: Store,
|
||||||
r#type: MemoryType,
|
ty: MemoryType,
|
||||||
wasmtime_handle: InstanceHandle,
|
wasmtime_handle: InstanceHandle,
|
||||||
wasmtime_export: wasmtime_runtime::Export,
|
wasmtime_export: wasmtime_runtime::Export,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Memory {
|
impl Memory {
|
||||||
pub fn new(store: &Store, r#type: MemoryType) -> Memory {
|
pub fn new(store: &Store, ty: MemoryType) -> Memory {
|
||||||
let (wasmtime_handle, wasmtime_export) =
|
let (wasmtime_handle, wasmtime_export) =
|
||||||
generate_memory_export(&r#type).expect("generated memory");
|
generate_memory_export(&ty).expect("generated memory");
|
||||||
Memory {
|
Memory {
|
||||||
_store: store.clone(),
|
_store: store.clone(),
|
||||||
r#type,
|
ty,
|
||||||
wasmtime_handle,
|
wasmtime_handle,
|
||||||
wasmtime_export,
|
wasmtime_export,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn r#type(&self) -> &MemoryType {
|
pub fn ty(&self) -> &MemoryType {
|
||||||
&self.r#type
|
&self.ty
|
||||||
}
|
}
|
||||||
|
|
||||||
fn wasmtime_memory_definition(&self) -> *mut wasmtime_runtime::VMMemoryDefinition {
|
fn wasmtime_memory_definition(&self) -> *mut wasmtime_runtime::VMMemoryDefinition {
|
||||||
@@ -453,12 +472,15 @@ impl Memory {
|
|||||||
(self.data_size() / wasmtime_environ::WASM_PAGE_SIZE as usize) as u32
|
(self.data_size() / wasmtime_environ::WASM_PAGE_SIZE as usize) as u32
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn grow(&mut self, delta: u32) -> bool {
|
pub fn grow(&self, delta: u32) -> bool {
|
||||||
match self.wasmtime_export {
|
match self.wasmtime_export {
|
||||||
wasmtime_runtime::Export::Memory { definition, .. } => {
|
wasmtime_runtime::Export::Memory { definition, .. } => {
|
||||||
let definition = unsafe { &(*definition) };
|
let definition = unsafe { &(*definition) };
|
||||||
let index = self.wasmtime_handle.memory_index(definition);
|
let index = self.wasmtime_handle.memory_index(definition);
|
||||||
self.wasmtime_handle.memory_grow(index, delta).is_some()
|
self.wasmtime_handle
|
||||||
|
.clone()
|
||||||
|
.memory_grow(index, delta)
|
||||||
|
.is_some()
|
||||||
}
|
}
|
||||||
_ => panic!("memory definition not found"),
|
_ => panic!("memory definition not found"),
|
||||||
}
|
}
|
||||||
@@ -481,7 +503,7 @@ impl Memory {
|
|||||||
let ty = MemoryType::from_wasmtime_memory(&memory.memory);
|
let ty = MemoryType::from_wasmtime_memory(&memory.memory);
|
||||||
Memory {
|
Memory {
|
||||||
_store: store.clone(),
|
_store: store.clone(),
|
||||||
r#type: ty,
|
ty: ty,
|
||||||
wasmtime_handle: instance_handle,
|
wasmtime_handle: instance_handle,
|
||||||
wasmtime_export: export,
|
wasmtime_export: export,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,45 +9,50 @@ use anyhow::{Error, Result};
|
|||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use wasmtime_jit::{instantiate, Resolver, SetupError};
|
use wasmtime_jit::{CompiledModule, Resolver};
|
||||||
use wasmtime_runtime::{Export, InstanceHandle, InstantiationError};
|
use wasmtime_runtime::{Export, InstanceHandle, InstantiationError};
|
||||||
|
|
||||||
struct SimpleResolver {
|
struct SimpleResolver<'a> {
|
||||||
imports: Vec<(String, String, Extern)>,
|
imports: &'a [Extern],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Resolver for SimpleResolver {
|
impl Resolver for SimpleResolver<'_> {
|
||||||
fn resolve(&mut self, name: &str, field: &str) -> Option<Export> {
|
fn resolve(&mut self, idx: u32, _name: &str, _field: &str) -> Option<Export> {
|
||||||
// TODO speedup lookup
|
|
||||||
self.imports
|
self.imports
|
||||||
.iter_mut()
|
.get(idx as usize)
|
||||||
.find(|(n, f, _)| name == n && field == f)
|
.map(|i| i.get_wasmtime_export())
|
||||||
.map(|(_, _, e)| e.get_wasmtime_export())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn instantiate_in_context(
|
fn instantiate_in_context(
|
||||||
|
store: &Store,
|
||||||
data: &[u8],
|
data: &[u8],
|
||||||
imports: Vec<(String, String, Extern)>,
|
imports: &[Extern],
|
||||||
module_name: Option<String>,
|
module_name: Option<&str>,
|
||||||
context: Context,
|
context: Context,
|
||||||
exports: Rc<RefCell<HashMap<String, Option<wasmtime_runtime::Export>>>>,
|
exports: Rc<RefCell<HashMap<String, Option<wasmtime_runtime::Export>>>>,
|
||||||
) -> Result<(InstanceHandle, HashSet<Context>), Error> {
|
) -> Result<(InstanceHandle, HashSet<Context>), Error> {
|
||||||
let mut contexts = HashSet::new();
|
let mut contexts = HashSet::new();
|
||||||
let debug_info = context.debug_info();
|
let debug_info = context.debug_info();
|
||||||
let mut resolver = SimpleResolver { imports };
|
let mut resolver = SimpleResolver { imports };
|
||||||
let instance = instantiate(
|
let mut compiled_module = CompiledModule::new(
|
||||||
&mut context.compiler(),
|
&mut context.compiler(),
|
||||||
data,
|
data,
|
||||||
module_name,
|
module_name,
|
||||||
&mut resolver,
|
&mut resolver,
|
||||||
exports,
|
exports,
|
||||||
debug_info,
|
debug_info,
|
||||||
)
|
)?;
|
||||||
.map_err(|e| -> Error {
|
|
||||||
|
// Register all module signatures
|
||||||
|
for signature in compiled_module.module().signatures.values() {
|
||||||
|
store.register_wasmtime_signature(signature);
|
||||||
|
}
|
||||||
|
|
||||||
|
let instance = compiled_module.instantiate().map_err(|e| -> Error {
|
||||||
if let Some(trap) = take_api_trap() {
|
if let Some(trap) = take_api_trap() {
|
||||||
trap.into()
|
trap.into()
|
||||||
} else if let SetupError::Instantiate(InstantiationError::StartTrap(msg)) = e {
|
} else if let InstantiationError::StartTrap(msg) = e {
|
||||||
Trap::new(msg).into()
|
Trap::new(msg).into()
|
||||||
} else {
|
} else {
|
||||||
e.into()
|
e.into()
|
||||||
@@ -70,19 +75,15 @@ pub struct Instance {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Instance {
|
impl Instance {
|
||||||
pub fn new(store: &Store, module: &Module, externs: &[Extern]) -> Result<Instance, Error> {
|
pub fn new(module: &Module, externs: &[Extern]) -> Result<Instance, Error> {
|
||||||
|
let store = module.store();
|
||||||
let context = store.context().clone();
|
let context = store.context().clone();
|
||||||
let exports = store.global_exports().clone();
|
let exports = store.global_exports().clone();
|
||||||
let imports = module
|
|
||||||
.imports()
|
|
||||||
.iter()
|
|
||||||
.zip(externs.iter())
|
|
||||||
.map(|(i, e)| (i.module().to_string(), i.name().to_string(), e.clone()))
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
let (mut instance_handle, contexts) = instantiate_in_context(
|
let (mut instance_handle, contexts) = instantiate_in_context(
|
||||||
|
module.store(),
|
||||||
module.binary().expect("binary"),
|
module.binary().expect("binary"),
|
||||||
imports,
|
externs,
|
||||||
module.name().cloned(),
|
module.name(),
|
||||||
context,
|
context,
|
||||||
exports,
|
exports,
|
||||||
)?;
|
)?;
|
||||||
@@ -108,14 +109,27 @@ impl Instance {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn exports(&self) -> &[Extern] {
|
/// Returns the associated [`Store`] that this `Instance` is compiled into.
|
||||||
&self.exports
|
///
|
||||||
|
/// This is the [`Store`] that generally serves as a sort of global cache
|
||||||
|
/// for various instance-related things.
|
||||||
|
pub fn store(&self) -> &Store {
|
||||||
|
self.module.store()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the associated [`Module`] that this `Instance` instantiated.
|
||||||
|
///
|
||||||
|
/// The corresponding [`Module`] here is a static version of this `Instance`
|
||||||
|
/// which can be used to learn information such as naming information about
|
||||||
|
/// various functions.
|
||||||
pub fn module(&self) -> &Module {
|
pub fn module(&self) -> &Module {
|
||||||
&self.module
|
&self.module
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn exports(&self) -> &[Extern] {
|
||||||
|
&self.exports
|
||||||
|
}
|
||||||
|
|
||||||
pub fn find_export_by_name(&self, name: &str) -> Option<&Extern> {
|
pub fn find_export_by_name(&self, name: &str) -> Option<&Extern> {
|
||||||
let (i, _) = self
|
let (i, _) = self
|
||||||
.module
|
.module
|
||||||
@@ -140,7 +154,14 @@ impl Instance {
|
|||||||
// imported into this store using the from_handle() method.
|
// imported into this store using the from_handle() method.
|
||||||
let _ = store.register_wasmtime_signature(signature);
|
let _ = store.register_wasmtime_signature(signature);
|
||||||
}
|
}
|
||||||
let extern_type = ExternType::from_wasmtime_export(&export);
|
|
||||||
|
// We should support everything supported by wasmtime_runtime, or
|
||||||
|
// otherwise we've got a bug in this crate, so panic if anything
|
||||||
|
// fails to convert here.
|
||||||
|
let extern_type = match ExternType::from_wasmtime_export(&export) {
|
||||||
|
Some(ty) => ty,
|
||||||
|
None => panic!("unsupported core wasm external type {:?}", export),
|
||||||
|
};
|
||||||
exports_types.push(ExportType::new(name, extern_type));
|
exports_types.push(ExportType::new(name, extern_type));
|
||||||
exports.push(Extern::from_wasmtime_export(
|
exports.push(Extern::from_wasmtime_export(
|
||||||
store,
|
store,
|
||||||
@@ -175,29 +196,29 @@ cfg_if::cfg_if! {
|
|||||||
impl Instance {
|
impl Instance {
|
||||||
/// The signal handler must be
|
/// The signal handler must be
|
||||||
/// [async-signal-safe](http://man7.org/linux/man-pages/man7/signal-safety.7.html).
|
/// [async-signal-safe](http://man7.org/linux/man-pages/man7/signal-safety.7.html).
|
||||||
pub fn set_signal_handler<H>(&mut self, handler: H)
|
pub fn set_signal_handler<H>(&self, handler: H)
|
||||||
where
|
where
|
||||||
H: 'static + Fn(libc::c_int, *const libc::siginfo_t, *const libc::c_void) -> bool,
|
H: 'static + Fn(libc::c_int, *const libc::siginfo_t, *const libc::c_void) -> bool,
|
||||||
{
|
{
|
||||||
self.instance_handle.set_signal_handler(handler);
|
self.instance_handle.clone().set_signal_handler(handler);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if #[cfg(target_os = "windows")] {
|
} else if #[cfg(target_os = "windows")] {
|
||||||
impl Instance {
|
impl Instance {
|
||||||
pub fn set_signal_handler<H>(&mut self, handler: H)
|
pub fn set_signal_handler<H>(&self, handler: H)
|
||||||
where
|
where
|
||||||
H: 'static + Fn(winapi::um::winnt::EXCEPTION_POINTERS) -> bool,
|
H: 'static + Fn(winapi::um::winnt::EXCEPTION_POINTERS) -> bool,
|
||||||
{
|
{
|
||||||
self.instance_handle.set_signal_handler(handler);
|
self.instance_handle.clone().set_signal_handler(handler);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if #[cfg(target_os = "macos")] {
|
} else if #[cfg(target_os = "macos")] {
|
||||||
impl Instance {
|
impl Instance {
|
||||||
pub fn set_signal_handler<H>(&mut self, handler: H)
|
pub fn set_signal_handler<H>(&self, handler: H)
|
||||||
where
|
where
|
||||||
H: 'static + Fn(libc::c_int, *const libc::siginfo_t, *const libc::c_void) -> bool,
|
H: 'static + Fn(libc::c_int, *const libc::siginfo_t, *const libc::c_void) -> bool,
|
||||||
{
|
{
|
||||||
self.instance_handle.set_signal_handler(handler);
|
self.instance_handle.clone().set_signal_handler(handler);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,8 +6,6 @@
|
|||||||
//! and there to implement Rust idioms. This crate also defines the actual C API
|
//! and there to implement Rust idioms. This crate also defines the actual C API
|
||||||
//! itself for consumption from other languages.
|
//! itself for consumption from other languages.
|
||||||
|
|
||||||
#![allow(improper_ctypes)]
|
|
||||||
|
|
||||||
mod callable;
|
mod callable;
|
||||||
mod context;
|
mod context;
|
||||||
mod externals;
|
mod externals;
|
||||||
@@ -26,7 +24,7 @@ pub use crate::callable::Callable;
|
|||||||
pub use crate::externals::*;
|
pub use crate::externals::*;
|
||||||
pub use crate::instance::Instance;
|
pub use crate::instance::Instance;
|
||||||
pub use crate::module::Module;
|
pub use crate::module::Module;
|
||||||
pub use crate::r#ref::{AnyRef, HostInfo, HostRef};
|
pub use crate::r#ref::AnyRef;
|
||||||
pub use crate::runtime::{Config, Engine, OptLevel, Store, Strategy};
|
pub use crate::runtime::{Config, Engine, OptLevel, Store, Strategy};
|
||||||
pub use crate::trap::{FrameInfo, Trap};
|
pub use crate::trap::{FrameInfo, Trap};
|
||||||
pub use crate::types::*;
|
pub use crate::types::*;
|
||||||
|
|||||||
@@ -56,138 +56,6 @@ fn into_table_type(tt: wasmparser::TableType) -> TableType {
|
|||||||
TableType::new(ty, limits)
|
TableType::new(ty, limits)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_imports_and_exports(
|
|
||||||
binary: &[u8],
|
|
||||||
) -> Result<(Box<[ImportType]>, Box<[ExportType]>, Option<String>)> {
|
|
||||||
let mut reader = ModuleReader::new(binary)?;
|
|
||||||
let mut imports = Vec::new();
|
|
||||||
let mut exports = Vec::new();
|
|
||||||
let mut memories = Vec::new();
|
|
||||||
let mut tables = Vec::new();
|
|
||||||
let mut func_sig = Vec::new();
|
|
||||||
let mut sigs = Vec::new();
|
|
||||||
let mut globals = Vec::new();
|
|
||||||
let mut module_name = None;
|
|
||||||
while !reader.eof() {
|
|
||||||
let section = reader.read()?;
|
|
||||||
match section.code {
|
|
||||||
SectionCode::Memory => {
|
|
||||||
let section = section.get_memory_section_reader()?;
|
|
||||||
memories.reserve_exact(section.get_count() as usize);
|
|
||||||
for entry in section {
|
|
||||||
memories.push(into_memory_type(entry?));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SectionCode::Type => {
|
|
||||||
let section = section.get_type_section_reader()?;
|
|
||||||
sigs.reserve_exact(section.get_count() as usize);
|
|
||||||
for entry in section {
|
|
||||||
sigs.push(into_func_type(entry?));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SectionCode::Function => {
|
|
||||||
let section = section.get_function_section_reader()?;
|
|
||||||
func_sig.reserve_exact(section.get_count() as usize);
|
|
||||||
for entry in section {
|
|
||||||
func_sig.push(entry?);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SectionCode::Global => {
|
|
||||||
let section = section.get_global_section_reader()?;
|
|
||||||
globals.reserve_exact(section.get_count() as usize);
|
|
||||||
for entry in section {
|
|
||||||
globals.push(into_global_type(entry?.ty));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SectionCode::Table => {
|
|
||||||
let section = section.get_table_section_reader()?;
|
|
||||||
tables.reserve_exact(section.get_count() as usize);
|
|
||||||
for entry in section {
|
|
||||||
tables.push(into_table_type(entry?))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SectionCode::Import => {
|
|
||||||
let section = section.get_import_section_reader()?;
|
|
||||||
imports.reserve_exact(section.get_count() as usize);
|
|
||||||
for entry in section {
|
|
||||||
let entry = entry?;
|
|
||||||
let r#type = match entry.ty {
|
|
||||||
ImportSectionEntryType::Function(index) => {
|
|
||||||
func_sig.push(index);
|
|
||||||
let sig = &sigs[index as usize];
|
|
||||||
ExternType::Func(sig.clone())
|
|
||||||
}
|
|
||||||
ImportSectionEntryType::Table(tt) => {
|
|
||||||
let table = into_table_type(tt);
|
|
||||||
tables.push(table.clone());
|
|
||||||
ExternType::Table(table)
|
|
||||||
}
|
|
||||||
ImportSectionEntryType::Memory(mt) => {
|
|
||||||
let memory = into_memory_type(mt);
|
|
||||||
memories.push(memory.clone());
|
|
||||||
ExternType::Memory(memory)
|
|
||||||
}
|
|
||||||
ImportSectionEntryType::Global(gt) => {
|
|
||||||
let global = into_global_type(gt);
|
|
||||||
globals.push(global.clone());
|
|
||||||
ExternType::Global(global)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
imports.push(ImportType::new(entry.module, entry.field, r#type));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SectionCode::Export => {
|
|
||||||
let section = section.get_export_section_reader()?;
|
|
||||||
exports.reserve_exact(section.get_count() as usize);
|
|
||||||
for entry in section {
|
|
||||||
let entry = entry?;
|
|
||||||
let r#type = match entry.kind {
|
|
||||||
ExternalKind::Function => {
|
|
||||||
let sig_index = func_sig[entry.index as usize] as usize;
|
|
||||||
let sig = &sigs[sig_index];
|
|
||||||
ExternType::Func(sig.clone())
|
|
||||||
}
|
|
||||||
ExternalKind::Table => {
|
|
||||||
ExternType::Table(tables[entry.index as usize].clone())
|
|
||||||
}
|
|
||||||
ExternalKind::Memory => {
|
|
||||||
ExternType::Memory(memories[entry.index as usize].clone())
|
|
||||||
}
|
|
||||||
ExternalKind::Global => {
|
|
||||||
ExternType::Global(globals[entry.index as usize].clone())
|
|
||||||
}
|
|
||||||
};
|
|
||||||
exports.push(ExportType::new(entry.field, r#type));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SectionCode::Custom {
|
|
||||||
kind: CustomSectionKind::Name,
|
|
||||||
..
|
|
||||||
} => {
|
|
||||||
// Read name section. Per spec, ignore invalid custom section.
|
|
||||||
if let Ok(mut reader) = section.get_name_section_reader() {
|
|
||||||
while let Ok(entry) = reader.read() {
|
|
||||||
if let Name::Module(name) = entry {
|
|
||||||
if let Ok(name) = name.get_name() {
|
|
||||||
module_name = Some(name.to_string());
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
// skip other sections
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok((
|
|
||||||
imports.into_boxed_slice(),
|
|
||||||
exports.into_boxed_slice(),
|
|
||||||
module_name,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub(crate) enum ModuleCodeSource {
|
pub(crate) enum ModuleCodeSource {
|
||||||
Binary(Box<[u8]>),
|
Binary(Box<[u8]>),
|
||||||
@@ -259,20 +127,21 @@ impl Module {
|
|||||||
///
|
///
|
||||||
/// [binary]: https://webassembly.github.io/spec/core/binary/index.html
|
/// [binary]: https://webassembly.github.io/spec/core/binary/index.html
|
||||||
pub fn new(store: &Store, binary: &[u8]) -> Result<Module> {
|
pub fn new(store: &Store, binary: &[u8]) -> Result<Module> {
|
||||||
Self::validate(store, binary)?;
|
Module::validate(store, binary)?;
|
||||||
// Note that the call to `unsafe` here should be ok because we
|
// Note that the call to `unsafe` here should be ok because we
|
||||||
// previously validated the binary, meaning we're guaranteed to pass a
|
// previously validated the binary, meaning we're guaranteed to pass a
|
||||||
// valid binary for `store`.
|
// valid binary for `store`.
|
||||||
unsafe { Self::create(store, binary, None) }
|
unsafe { Module::new_unchecked(store, binary) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new WebAssembly `Module` from the given in-memory `binary`
|
/// Creates a new WebAssembly `Module` from the given in-memory `binary`
|
||||||
/// data. The provided `name` will be used in traps/backtrace details.
|
/// data. The provided `name` will be used in traps/backtrace details.
|
||||||
///
|
///
|
||||||
/// See [`Module::new`] for other details.
|
/// See [`Module::new`] for other details.
|
||||||
pub fn new_with_name(store: &Store, binary: &[u8], name: String) -> Result<Module> {
|
pub fn new_with_name(store: &Store, binary: &[u8], name: &str) -> Result<Module> {
|
||||||
Self::validate(store, binary)?;
|
let mut ret = Module::new(store, binary)?;
|
||||||
unsafe { Self::create(store, binary, Some(name)) }
|
Rc::get_mut(&mut ret.inner).unwrap().name = Some(name.to_string());
|
||||||
|
Ok(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new WebAssembly `Module` from the given in-memory `binary`
|
/// Creates a new WebAssembly `Module` from the given in-memory `binary`
|
||||||
@@ -302,24 +171,9 @@ impl Module {
|
|||||||
/// be somewhat valid for decoding purposes, and the basics of decoding can
|
/// be somewhat valid for decoding purposes, and the basics of decoding can
|
||||||
/// still fail.
|
/// still fail.
|
||||||
pub unsafe fn new_unchecked(store: &Store, binary: &[u8]) -> Result<Module> {
|
pub unsafe fn new_unchecked(store: &Store, binary: &[u8]) -> Result<Module> {
|
||||||
Self::create(store, binary, None)
|
let mut ret = Module::empty(store);
|
||||||
}
|
ret.read_imports_and_exports(binary)?;
|
||||||
|
Ok(ret)
|
||||||
unsafe fn create(
|
|
||||||
store: &Store,
|
|
||||||
binary: &[u8],
|
|
||||||
name_override: Option<String>,
|
|
||||||
) -> Result<Module> {
|
|
||||||
let (imports, exports, name) = read_imports_and_exports(binary)?;
|
|
||||||
Ok(Module {
|
|
||||||
inner: Rc::new(ModuleInner {
|
|
||||||
store: store.clone(),
|
|
||||||
source: ModuleCodeSource::Binary(binary.into()),
|
|
||||||
imports,
|
|
||||||
exports,
|
|
||||||
name: name_override.or(name),
|
|
||||||
}),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Validates `binary` input data as a WebAssembly binary given the
|
/// Validates `binary` input data as a WebAssembly binary given the
|
||||||
@@ -356,12 +210,18 @@ impl Module {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_exports(store: &Store, exports: Box<[ExportType]>) -> Self {
|
pub fn from_exports(store: &Store, exports: Box<[ExportType]>) -> Self {
|
||||||
|
let mut ret = Module::empty(store);
|
||||||
|
Rc::get_mut(&mut ret.inner).unwrap().exports = exports;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn empty(store: &Store) -> Self {
|
||||||
Module {
|
Module {
|
||||||
inner: Rc::new(ModuleInner {
|
inner: Rc::new(ModuleInner {
|
||||||
store: store.clone(),
|
store: store.clone(),
|
||||||
source: ModuleCodeSource::Unknown,
|
source: ModuleCodeSource::Unknown,
|
||||||
imports: Box::new([]),
|
imports: Box::new([]),
|
||||||
exports,
|
exports: Box::new([]),
|
||||||
name: None,
|
name: None,
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
@@ -376,8 +236,8 @@ impl Module {
|
|||||||
|
|
||||||
/// Returns identifier/name that this [`Module`] has. This name
|
/// Returns identifier/name that this [`Module`] has. This name
|
||||||
/// is used in traps/backtrace details.
|
/// is used in traps/backtrace details.
|
||||||
pub fn name(&self) -> Option<&String> {
|
pub fn name(&self) -> Option<&str> {
|
||||||
self.inner.name.as_ref()
|
self.inner.name.as_deref()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the list of imports that this [`Module`] has and must be
|
/// Returns the list of imports that this [`Module`] has and must be
|
||||||
@@ -396,4 +256,134 @@ impl Module {
|
|||||||
pub fn store(&self) -> &Store {
|
pub fn store(&self) -> &Store {
|
||||||
&self.inner.store
|
&self.inner.store
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn read_imports_and_exports(&mut self, binary: &[u8]) -> Result<()> {
|
||||||
|
let inner = Rc::get_mut(&mut self.inner).unwrap();
|
||||||
|
inner.source = ModuleCodeSource::Binary(binary.into());
|
||||||
|
let mut reader = ModuleReader::new(binary)?;
|
||||||
|
let mut imports = Vec::new();
|
||||||
|
let mut exports = Vec::new();
|
||||||
|
let mut memories = Vec::new();
|
||||||
|
let mut tables = Vec::new();
|
||||||
|
let mut func_sig = Vec::new();
|
||||||
|
let mut sigs = Vec::new();
|
||||||
|
let mut globals = Vec::new();
|
||||||
|
while !reader.eof() {
|
||||||
|
let section = reader.read()?;
|
||||||
|
match section.code {
|
||||||
|
SectionCode::Memory => {
|
||||||
|
let section = section.get_memory_section_reader()?;
|
||||||
|
memories.reserve_exact(section.get_count() as usize);
|
||||||
|
for entry in section {
|
||||||
|
memories.push(into_memory_type(entry?));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SectionCode::Type => {
|
||||||
|
let section = section.get_type_section_reader()?;
|
||||||
|
sigs.reserve_exact(section.get_count() as usize);
|
||||||
|
for entry in section {
|
||||||
|
sigs.push(into_func_type(entry?));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SectionCode::Function => {
|
||||||
|
let section = section.get_function_section_reader()?;
|
||||||
|
func_sig.reserve_exact(section.get_count() as usize);
|
||||||
|
for entry in section {
|
||||||
|
func_sig.push(entry?);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SectionCode::Global => {
|
||||||
|
let section = section.get_global_section_reader()?;
|
||||||
|
globals.reserve_exact(section.get_count() as usize);
|
||||||
|
for entry in section {
|
||||||
|
globals.push(into_global_type(entry?.ty));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SectionCode::Table => {
|
||||||
|
let section = section.get_table_section_reader()?;
|
||||||
|
tables.reserve_exact(section.get_count() as usize);
|
||||||
|
for entry in section {
|
||||||
|
tables.push(into_table_type(entry?))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SectionCode::Import => {
|
||||||
|
let section = section.get_import_section_reader()?;
|
||||||
|
imports.reserve_exact(section.get_count() as usize);
|
||||||
|
for entry in section {
|
||||||
|
let entry = entry?;
|
||||||
|
let r#type = match entry.ty {
|
||||||
|
ImportSectionEntryType::Function(index) => {
|
||||||
|
func_sig.push(index);
|
||||||
|
let sig = &sigs[index as usize];
|
||||||
|
ExternType::Func(sig.clone())
|
||||||
|
}
|
||||||
|
ImportSectionEntryType::Table(tt) => {
|
||||||
|
let table = into_table_type(tt);
|
||||||
|
tables.push(table.clone());
|
||||||
|
ExternType::Table(table)
|
||||||
|
}
|
||||||
|
ImportSectionEntryType::Memory(mt) => {
|
||||||
|
let memory = into_memory_type(mt);
|
||||||
|
memories.push(memory.clone());
|
||||||
|
ExternType::Memory(memory)
|
||||||
|
}
|
||||||
|
ImportSectionEntryType::Global(gt) => {
|
||||||
|
let global = into_global_type(gt);
|
||||||
|
globals.push(global.clone());
|
||||||
|
ExternType::Global(global)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
imports.push(ImportType::new(entry.module, entry.field, r#type));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SectionCode::Export => {
|
||||||
|
let section = section.get_export_section_reader()?;
|
||||||
|
exports.reserve_exact(section.get_count() as usize);
|
||||||
|
for entry in section {
|
||||||
|
let entry = entry?;
|
||||||
|
let r#type = match entry.kind {
|
||||||
|
ExternalKind::Function => {
|
||||||
|
let sig_index = func_sig[entry.index as usize] as usize;
|
||||||
|
let sig = &sigs[sig_index];
|
||||||
|
ExternType::Func(sig.clone())
|
||||||
|
}
|
||||||
|
ExternalKind::Table => {
|
||||||
|
ExternType::Table(tables[entry.index as usize].clone())
|
||||||
|
}
|
||||||
|
ExternalKind::Memory => {
|
||||||
|
ExternType::Memory(memories[entry.index as usize].clone())
|
||||||
|
}
|
||||||
|
ExternalKind::Global => {
|
||||||
|
ExternType::Global(globals[entry.index as usize].clone())
|
||||||
|
}
|
||||||
|
};
|
||||||
|
exports.push(ExportType::new(entry.field, r#type));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SectionCode::Custom {
|
||||||
|
kind: CustomSectionKind::Name,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
// Read name section. Per spec, ignore invalid custom section.
|
||||||
|
if let Ok(mut reader) = section.get_name_section_reader() {
|
||||||
|
while let Ok(entry) = reader.read() {
|
||||||
|
if let Name::Module(name) = entry {
|
||||||
|
if let Ok(name) = name.get_name() {
|
||||||
|
inner.name = Some(name.to_string());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
// skip other sections
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inner.imports = imports.into();
|
||||||
|
inner.exports = exports.into();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -397,6 +397,10 @@ impl Store {
|
|||||||
.get(&type_index)
|
.get(&type_index)
|
||||||
.cloned()
|
.cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn ptr_eq(a: &Store, b: &Store) -> bool {
|
||||||
|
Rc::ptr_eq(&a.inner, &b.inner)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Store {
|
impl Default for Store {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
use super::create_handle::create_handle;
|
use super::create_handle::create_handle;
|
||||||
use super::trap::{record_api_trap, TrapSink, API_TRAP_CODE};
|
use super::trap::{record_api_trap, TrapSink, API_TRAP_CODE};
|
||||||
use crate::{Callable, FuncType, Store, Val};
|
use crate::{Callable, FuncType, Store, Val};
|
||||||
use anyhow::Result;
|
use anyhow::{bail, Result};
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
@@ -234,7 +234,10 @@ pub fn create_handle_with_function(
|
|||||||
func: &Rc<dyn Callable + 'static>,
|
func: &Rc<dyn Callable + 'static>,
|
||||||
store: &Store,
|
store: &Store,
|
||||||
) -> Result<InstanceHandle> {
|
) -> Result<InstanceHandle> {
|
||||||
let sig = ft.get_wasmtime_signature().clone();
|
let sig = match ft.get_wasmtime_signature() {
|
||||||
|
Some(sig) => sig.clone(),
|
||||||
|
None => bail!("not a supported core wasm signature {:?}", ft),
|
||||||
|
};
|
||||||
|
|
||||||
let isa = {
|
let isa = {
|
||||||
let isa_builder = native::builder();
|
let isa_builder = native::builder();
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use super::create_handle::create_handle;
|
use super::create_handle::create_handle;
|
||||||
use crate::{GlobalType, Mutability, Val};
|
use crate::{GlobalType, Mutability, Val};
|
||||||
use anyhow::Result;
|
use anyhow::{bail, Result};
|
||||||
use wasmtime_environ::entity::PrimaryMap;
|
use wasmtime_environ::entity::PrimaryMap;
|
||||||
use wasmtime_environ::{wasm, Module};
|
use wasmtime_environ::{wasm, Module};
|
||||||
use wasmtime_runtime::{InstanceHandle, VMGlobalDefinition};
|
use wasmtime_runtime::{InstanceHandle, VMGlobalDefinition};
|
||||||
@@ -24,7 +24,10 @@ pub fn create_global(gt: &GlobalType, val: Val) -> Result<(wasmtime_runtime::Exp
|
|||||||
}
|
}
|
||||||
|
|
||||||
let global = wasm::Global {
|
let global = wasm::Global {
|
||||||
ty: gt.content().get_wasmtime_type(),
|
ty: match gt.content().get_wasmtime_type() {
|
||||||
|
Some(t) => t,
|
||||||
|
None => bail!("cannot support {:?} as a wasm global type", gt.content()),
|
||||||
|
},
|
||||||
mutability: match gt.mutability() {
|
mutability: match gt.mutability() {
|
||||||
Mutability::Const => false,
|
Mutability::Const => false,
|
||||||
Mutability::Var => true,
|
Mutability::Var => true,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use super::create_handle::create_handle;
|
use super::create_handle::create_handle;
|
||||||
use crate::{TableType, ValType};
|
use crate::{TableType, ValType};
|
||||||
use anyhow::Result;
|
use anyhow::{bail, Result};
|
||||||
use wasmtime_environ::entity::PrimaryMap;
|
use wasmtime_environ::entity::PrimaryMap;
|
||||||
use wasmtime_environ::{wasm, Module};
|
use wasmtime_environ::{wasm, Module};
|
||||||
use wasmtime_runtime::InstanceHandle;
|
use wasmtime_runtime::InstanceHandle;
|
||||||
@@ -13,7 +13,10 @@ pub fn create_handle_with_table(table: &TableType) -> Result<InstanceHandle> {
|
|||||||
maximum: table.limits().max(),
|
maximum: table.limits().max(),
|
||||||
ty: match table.element() {
|
ty: match table.element() {
|
||||||
ValType::FuncRef => wasm::TableElementType::Func,
|
ValType::FuncRef => wasm::TableElementType::Func,
|
||||||
_ => wasm::TableElementType::Val(table.element().get_wasmtime_type()),
|
_ => match table.element().get_wasmtime_type() {
|
||||||
|
Some(t) => wasm::TableElementType::Val(t),
|
||||||
|
None => bail!("cannot support {:?} as a table element", table.element()),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
let tunable = Default::default();
|
let tunable = Default::default();
|
||||||
|
|||||||
@@ -84,25 +84,25 @@ impl ValType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn get_wasmtime_type(&self) -> ir::Type {
|
pub(crate) fn get_wasmtime_type(&self) -> Option<ir::Type> {
|
||||||
match self {
|
match self {
|
||||||
ValType::I32 => ir::types::I32,
|
ValType::I32 => Some(ir::types::I32),
|
||||||
ValType::I64 => ir::types::I64,
|
ValType::I64 => Some(ir::types::I64),
|
||||||
ValType::F32 => ir::types::F32,
|
ValType::F32 => Some(ir::types::F32),
|
||||||
ValType::F64 => ir::types::F64,
|
ValType::F64 => Some(ir::types::F64),
|
||||||
ValType::V128 => ir::types::I8X16,
|
ValType::V128 => Some(ir::types::I8X16),
|
||||||
_ => unimplemented!("get_wasmtime_type other"),
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn from_wasmtime_type(ty: ir::Type) -> ValType {
|
pub(crate) fn from_wasmtime_type(ty: ir::Type) -> Option<ValType> {
|
||||||
match ty {
|
match ty {
|
||||||
ir::types::I32 => ValType::I32,
|
ir::types::I32 => Some(ValType::I32),
|
||||||
ir::types::I64 => ValType::I64,
|
ir::types::I64 => Some(ValType::I64),
|
||||||
ir::types::F32 => ValType::F32,
|
ir::types::F32 => Some(ValType::F32),
|
||||||
ir::types::F64 => ValType::F64,
|
ir::types::F64 => Some(ValType::F64),
|
||||||
ir::types::I8X16 => ValType::V128,
|
ir::types::I8X16 => Some(ValType::V128),
|
||||||
_ => unimplemented!("from_wasmtime_type other"),
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -153,26 +153,29 @@ impl ExternType {
|
|||||||
(Table(TableType) table unwrap_table)
|
(Table(TableType) table unwrap_table)
|
||||||
(Memory(MemoryType) memory unwrap_memory)
|
(Memory(MemoryType) memory unwrap_memory)
|
||||||
}
|
}
|
||||||
pub(crate) fn from_wasmtime_export(export: &wasmtime_runtime::Export) -> Self {
|
|
||||||
match export {
|
/// Returns `None` if the sub-type fails to get converted, see documentation
|
||||||
|
/// for sub-types about what may fail.
|
||||||
|
pub(crate) fn from_wasmtime_export(export: &wasmtime_runtime::Export) -> Option<Self> {
|
||||||
|
Some(match export {
|
||||||
wasmtime_runtime::Export::Function { signature, .. } => {
|
wasmtime_runtime::Export::Function { signature, .. } => {
|
||||||
ExternType::Func(FuncType::from_wasmtime_signature(signature.clone()))
|
ExternType::Func(FuncType::from_wasmtime_signature(signature.clone())?)
|
||||||
}
|
}
|
||||||
wasmtime_runtime::Export::Memory { memory, .. } => {
|
wasmtime_runtime::Export::Memory { memory, .. } => {
|
||||||
ExternType::Memory(MemoryType::from_wasmtime_memory(&memory.memory))
|
ExternType::Memory(MemoryType::from_wasmtime_memory(&memory.memory))
|
||||||
}
|
}
|
||||||
wasmtime_runtime::Export::Global { global, .. } => {
|
wasmtime_runtime::Export::Global { global, .. } => {
|
||||||
ExternType::Global(GlobalType::from_wasmtime_global(&global))
|
ExternType::Global(GlobalType::from_wasmtime_global(&global)?)
|
||||||
}
|
}
|
||||||
wasmtime_runtime::Export::Table { table, .. } => {
|
wasmtime_runtime::Export::Table { table, .. } => {
|
||||||
ExternType::Table(TableType::from_wasmtime_table(&table.table))
|
ExternType::Table(TableType::from_wasmtime_table(&table.table))
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function Types
|
// Function Types
|
||||||
fn from_wasmtime_abiparam(param: &ir::AbiParam) -> ValType {
|
fn from_wasmtime_abiparam(param: &ir::AbiParam) -> Option<ValType> {
|
||||||
assert_eq!(param.purpose, ir::ArgumentPurpose::Normal);
|
assert_eq!(param.purpose, ir::ArgumentPurpose::Normal);
|
||||||
ValType::from_wasmtime_type(param.value_type)
|
ValType::from_wasmtime_type(param.value_type)
|
||||||
}
|
}
|
||||||
@@ -184,7 +187,12 @@ fn from_wasmtime_abiparam(param: &ir::AbiParam) -> ValType {
|
|||||||
pub struct FuncType {
|
pub struct FuncType {
|
||||||
params: Box<[ValType]>,
|
params: Box<[ValType]>,
|
||||||
results: Box<[ValType]>,
|
results: Box<[ValType]>,
|
||||||
signature: ir::Signature,
|
// `None` if params/results aren't wasm-compatible (e.g. use wasm interface
|
||||||
|
// types), or if they're not implemented (like anyref at the time of this
|
||||||
|
// writing)
|
||||||
|
//
|
||||||
|
// `Some` if they're all wasm-compatible.
|
||||||
|
signature: Option<ir::Signature>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FuncType {
|
impl FuncType {
|
||||||
@@ -196,23 +204,26 @@ impl FuncType {
|
|||||||
use wasmtime_environ::ir::{types, AbiParam, ArgumentPurpose, Signature};
|
use wasmtime_environ::ir::{types, AbiParam, ArgumentPurpose, Signature};
|
||||||
use wasmtime_jit::native;
|
use wasmtime_jit::native;
|
||||||
let call_conv = native::call_conv();
|
let call_conv = native::call_conv();
|
||||||
let signature: Signature = {
|
let signature = params
|
||||||
let mut params = params
|
.iter()
|
||||||
.iter()
|
.map(|p| p.get_wasmtime_type().map(AbiParam::new))
|
||||||
.map(|p| AbiParam::new(p.get_wasmtime_type()))
|
.collect::<Option<Vec<_>>>()
|
||||||
.collect::<Vec<_>>();
|
.and_then(|params| {
|
||||||
let returns = results
|
results
|
||||||
.iter()
|
.iter()
|
||||||
.map(|p| AbiParam::new(p.get_wasmtime_type()))
|
.map(|p| p.get_wasmtime_type().map(AbiParam::new))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Option<Vec<_>>>()
|
||||||
params.insert(0, AbiParam::special(types::I64, ArgumentPurpose::VMContext));
|
.map(|results| (params, results))
|
||||||
|
})
|
||||||
|
.map(|(mut params, returns)| {
|
||||||
|
params.insert(0, AbiParam::special(types::I64, ArgumentPurpose::VMContext));
|
||||||
|
|
||||||
Signature {
|
Signature {
|
||||||
params,
|
params,
|
||||||
returns,
|
returns,
|
||||||
call_conv,
|
call_conv,
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
FuncType {
|
FuncType {
|
||||||
params,
|
params,
|
||||||
results,
|
results,
|
||||||
@@ -230,27 +241,33 @@ impl FuncType {
|
|||||||
&self.results
|
&self.results
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn get_wasmtime_signature(&self) -> &ir::Signature {
|
/// Returns `Some` if this function signature was compatible with cranelift,
|
||||||
&self.signature
|
/// or `None` if one of the types/results wasn't supported or compatible
|
||||||
|
/// with cranelift.
|
||||||
|
pub(crate) fn get_wasmtime_signature(&self) -> Option<&ir::Signature> {
|
||||||
|
self.signature.as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn from_wasmtime_signature(signature: ir::Signature) -> FuncType {
|
/// Returns `None` if any types in the signature can't be converted to the
|
||||||
|
/// types in this crate, but that should very rarely happen and largely only
|
||||||
|
/// indicate a bug in our cranelift integration.
|
||||||
|
pub(crate) fn from_wasmtime_signature(signature: ir::Signature) -> Option<FuncType> {
|
||||||
let params = signature
|
let params = signature
|
||||||
.params
|
.params
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|p| p.purpose == ir::ArgumentPurpose::Normal)
|
.filter(|p| p.purpose == ir::ArgumentPurpose::Normal)
|
||||||
.map(|p| from_wasmtime_abiparam(p))
|
.map(|p| from_wasmtime_abiparam(p))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Option<Vec<_>>>()?;
|
||||||
let results = signature
|
let results = signature
|
||||||
.returns
|
.returns
|
||||||
.iter()
|
.iter()
|
||||||
.map(|p| from_wasmtime_abiparam(p))
|
.map(|p| from_wasmtime_abiparam(p))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Option<Vec<_>>>()?;
|
||||||
FuncType {
|
Some(FuncType {
|
||||||
params: params.into_boxed_slice(),
|
params: params.into_boxed_slice(),
|
||||||
results: results.into_boxed_slice(),
|
results: results.into_boxed_slice(),
|
||||||
signature,
|
signature: Some(signature),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -287,14 +304,16 @@ impl GlobalType {
|
|||||||
self.mutability
|
self.mutability
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn from_wasmtime_global(global: &wasm::Global) -> GlobalType {
|
/// Returns `None` if the wasmtime global has a type that we can't
|
||||||
let ty = ValType::from_wasmtime_type(global.ty);
|
/// represent, but that should only very rarely happen and indicate a bug.
|
||||||
|
pub(crate) fn from_wasmtime_global(global: &wasm::Global) -> Option<GlobalType> {
|
||||||
|
let ty = ValType::from_wasmtime_type(global.ty)?;
|
||||||
let mutability = if global.mutability {
|
let mutability = if global.mutability {
|
||||||
Mutability::Var
|
Mutability::Var
|
||||||
} else {
|
} else {
|
||||||
Mutability::Const
|
Mutability::Const
|
||||||
};
|
};
|
||||||
GlobalType::new(ty, mutability)
|
Some(GlobalType::new(ty, mutability))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use crate::externals::Func;
|
use crate::externals::Func;
|
||||||
use crate::r#ref::{AnyRef, HostRef};
|
use crate::r#ref::AnyRef;
|
||||||
use crate::runtime::Store;
|
use crate::runtime::Store;
|
||||||
use crate::types::ValType;
|
use crate::types::ValType;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
@@ -34,7 +34,7 @@ pub enum Val {
|
|||||||
AnyRef(AnyRef),
|
AnyRef(AnyRef),
|
||||||
|
|
||||||
/// A first-class reference to a WebAssembly function.
|
/// A first-class reference to a WebAssembly function.
|
||||||
FuncRef(HostRef<Func>),
|
FuncRef(Func),
|
||||||
|
|
||||||
/// A 128-bit number
|
/// A 128-bit number
|
||||||
V128(u128),
|
V128(u128),
|
||||||
@@ -71,7 +71,7 @@ impl Val {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the corresponding [`ValType`] for this `Val`.
|
/// Returns the corresponding [`ValType`] for this `Val`.
|
||||||
pub fn r#type(&self) -> ValType {
|
pub fn ty(&self) -> ValType {
|
||||||
match self {
|
match self {
|
||||||
Val::I32(_) => ValType::I32,
|
Val::I32(_) => ValType::I32,
|
||||||
Val::I64(_) => ValType::I64,
|
Val::I64(_) => ValType::I64,
|
||||||
@@ -111,7 +111,7 @@ impl Val {
|
|||||||
(I64(i64) i64 unwrap_i64 *e)
|
(I64(i64) i64 unwrap_i64 *e)
|
||||||
(F32(f32) f32 unwrap_f32 f32::from_bits(*e))
|
(F32(f32) f32 unwrap_f32 f32::from_bits(*e))
|
||||||
(F64(f64) f64 unwrap_f64 f64::from_bits(*e))
|
(F64(f64) f64 unwrap_f64 f64::from_bits(*e))
|
||||||
(FuncRef(&HostRef<Func>) funcref unwrap_funcref e)
|
(FuncRef(&Func) funcref unwrap_funcref e)
|
||||||
(V128(u128) v128 unwrap_v128 *e)
|
(V128(u128) v128 unwrap_v128 *e)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,7 +122,6 @@ impl Val {
|
|||||||
pub fn anyref(&self) -> Option<AnyRef> {
|
pub fn anyref(&self) -> Option<AnyRef> {
|
||||||
match self {
|
match self {
|
||||||
Val::AnyRef(e) => Some(e.clone()),
|
Val::AnyRef(e) => Some(e.clone()),
|
||||||
Val::FuncRef(e) => Some(e.anyref()),
|
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -164,21 +163,12 @@ impl From<f64> for Val {
|
|||||||
|
|
||||||
impl From<AnyRef> for Val {
|
impl From<AnyRef> for Val {
|
||||||
fn from(val: AnyRef) -> Val {
|
fn from(val: AnyRef) -> Val {
|
||||||
match &val {
|
Val::AnyRef(val)
|
||||||
AnyRef::Ref(r) => {
|
|
||||||
if r.is_ref::<Func>() {
|
|
||||||
Val::FuncRef(r.get_ref())
|
|
||||||
} else {
|
|
||||||
Val::AnyRef(val)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => unimplemented!("AnyRef::Other"),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<HostRef<Func>> for Val {
|
impl From<Func> for Val {
|
||||||
fn from(val: HostRef<Func>) -> Val {
|
fn from(val: Func) -> Val {
|
||||||
Val::FuncRef(val)
|
Val::FuncRef(val)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -206,7 +196,6 @@ pub(crate) fn into_checked_anyfunc(
|
|||||||
vmctx: ptr::null_mut(),
|
vmctx: ptr::null_mut(),
|
||||||
},
|
},
|
||||||
Val::FuncRef(f) => {
|
Val::FuncRef(f) => {
|
||||||
let f = f.borrow();
|
|
||||||
let (vmctx, func_ptr, signature) = match f.wasmtime_export() {
|
let (vmctx, func_ptr, signature) = match f.wasmtime_export() {
|
||||||
wasmtime_runtime::Export::Function {
|
wasmtime_runtime::Export::Function {
|
||||||
vmctx,
|
vmctx,
|
||||||
@@ -243,5 +232,5 @@ pub(crate) fn from_checked_anyfunc(
|
|||||||
vmctx: item.vmctx,
|
vmctx: item.vmctx,
|
||||||
};
|
};
|
||||||
let f = Func::from_wasmtime_function(export, store, instance_handle);
|
let f = Func::from_wasmtime_function(export, store, instance_handle);
|
||||||
Val::FuncRef(HostRef::new(f))
|
Val::FuncRef(f)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,9 +7,11 @@
|
|||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
AnyRef, Callable, Engine, ExportType, Extern, ExternType, Func, FuncType, Global, GlobalType,
|
AnyRef, Callable, Engine, ExportType, Extern, ExternType, Func, FuncType, Global, GlobalType,
|
||||||
HostInfo, HostRef, ImportType, Instance, Limits, Memory, MemoryType, Module, Store, Table,
|
ImportType, Instance, Limits, Memory, MemoryType, Module, Store, Table, TableType, Trap, Val,
|
||||||
TableType, Trap, Val, ValType,
|
ValType,
|
||||||
};
|
};
|
||||||
|
use crate::r#ref::{HostInfo, HostRef};
|
||||||
|
use std::cell::RefCell;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::{mem, ptr, slice};
|
use std::{mem, ptr, slice};
|
||||||
|
|
||||||
@@ -243,6 +245,12 @@ enum wasm_externtype_t_type_cache {
|
|||||||
declare_vec!(wasm_externtype_vec_t, *mut wasm_externtype_t);
|
declare_vec!(wasm_externtype_vec_t, *mut wasm_externtype_t);
|
||||||
|
|
||||||
pub type wasm_externkind_t = u8;
|
pub type wasm_externkind_t = u8;
|
||||||
|
|
||||||
|
const WASM_EXTERN_FUNC: wasm_externkind_t = 0;
|
||||||
|
const WASM_EXTERN_GLOBAL: wasm_externkind_t = 1;
|
||||||
|
const WASM_EXTERN_TABLE: wasm_externkind_t = 2;
|
||||||
|
const WASM_EXTERN_MEMORY: wasm_externkind_t = 3;
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct wasm_importtype_t {
|
pub struct wasm_importtype_t {
|
||||||
@@ -312,6 +320,7 @@ declare_vec!(wasm_frame_vec_t, *mut wasm_frame_t);
|
|||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct wasm_instance_t {
|
pub struct wasm_instance_t {
|
||||||
instance: HostRef<Instance>,
|
instance: HostRef<Instance>,
|
||||||
|
exports_cache: RefCell<Option<Vec<ExternHost>>>,
|
||||||
}
|
}
|
||||||
pub type wasm_message_t = wasm_name_t;
|
pub type wasm_message_t = wasm_name_t;
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
@@ -336,12 +345,22 @@ pub struct wasm_module_t {
|
|||||||
pub struct wasm_shared_module_t {
|
pub struct wasm_shared_module_t {
|
||||||
_unused: [u8; 0],
|
_unused: [u8; 0],
|
||||||
}
|
}
|
||||||
#[repr(C)]
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
#[repr(transparent)]
|
||||||
pub struct wasm_func_t {
|
pub struct wasm_func_t {
|
||||||
func: HostRef<Func>,
|
ext: wasm_extern_t,
|
||||||
ext: Option<Box<wasm_extern_t>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl wasm_func_t {
|
||||||
|
fn func(&self) -> &HostRef<Func> {
|
||||||
|
match &self.ext.which {
|
||||||
|
ExternHost::Func(f) => f,
|
||||||
|
_ => unsafe { std::hint::unreachable_unchecked() },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub type wasm_func_callback_t = std::option::Option<
|
pub type wasm_func_callback_t = std::option::Option<
|
||||||
unsafe extern "C" fn(args: *const wasm_val_t, results: *mut wasm_val_t) -> *mut wasm_trap_t,
|
unsafe extern "C" fn(args: *const wasm_val_t, results: *mut wasm_val_t) -> *mut wasm_trap_t,
|
||||||
>;
|
>;
|
||||||
@@ -352,40 +371,67 @@ pub type wasm_func_callback_with_env_t = std::option::Option<
|
|||||||
results: *mut wasm_val_t,
|
results: *mut wasm_val_t,
|
||||||
) -> *mut wasm_trap_t,
|
) -> *mut wasm_trap_t,
|
||||||
>;
|
>;
|
||||||
#[repr(C)]
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
#[repr(transparent)]
|
||||||
pub struct wasm_global_t {
|
pub struct wasm_global_t {
|
||||||
global: HostRef<Global>,
|
ext: wasm_extern_t,
|
||||||
ext: Option<Box<wasm_extern_t>>,
|
|
||||||
}
|
}
|
||||||
#[repr(C)]
|
|
||||||
#[derive(Clone)]
|
impl wasm_global_t {
|
||||||
pub struct wasm_table_t {
|
fn global(&self) -> &HostRef<Global> {
|
||||||
table: HostRef<Table>,
|
match &self.ext.which {
|
||||||
ext: Option<Box<wasm_extern_t>>,
|
ExternHost::Global(g) => g,
|
||||||
}
|
_ => unsafe { std::hint::unreachable_unchecked() },
|
||||||
pub type wasm_table_size_t = u32;
|
}
|
||||||
#[repr(C)]
|
}
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct wasm_memory_t {
|
|
||||||
memory: HostRef<Memory>,
|
|
||||||
ext: Option<Box<wasm_extern_t>>,
|
|
||||||
}
|
|
||||||
pub type wasm_memory_pages_t = u32;
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct wasm_extern_t {
|
|
||||||
ext: Extern,
|
|
||||||
cache: wasm_extern_t_type_cache,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
enum wasm_extern_t_type_cache {
|
#[repr(transparent)]
|
||||||
Empty,
|
pub struct wasm_table_t {
|
||||||
Func(wasm_func_t),
|
ext: wasm_extern_t,
|
||||||
Global(wasm_global_t),
|
}
|
||||||
Memory(wasm_memory_t),
|
|
||||||
Table(wasm_table_t),
|
impl wasm_table_t {
|
||||||
|
fn table(&self) -> &HostRef<Table> {
|
||||||
|
match &self.ext.which {
|
||||||
|
ExternHost::Table(t) => t,
|
||||||
|
_ => unsafe { std::hint::unreachable_unchecked() },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type wasm_table_size_t = u32;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
#[repr(transparent)]
|
||||||
|
pub struct wasm_memory_t {
|
||||||
|
ext: wasm_extern_t,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl wasm_memory_t {
|
||||||
|
fn memory(&self) -> &HostRef<Memory> {
|
||||||
|
match &self.ext.which {
|
||||||
|
ExternHost::Memory(m) => m,
|
||||||
|
_ => unsafe { std::hint::unreachable_unchecked() },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type wasm_memory_pages_t = u32;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct wasm_extern_t {
|
||||||
|
which: ExternHost,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
enum ExternHost {
|
||||||
|
Func(HostRef<Func>),
|
||||||
|
Global(HostRef<Global>),
|
||||||
|
Memory(HostRef<Memory>),
|
||||||
|
Table(HostRef<Table>),
|
||||||
}
|
}
|
||||||
|
|
||||||
declare_vec!(wasm_extern_vec_t, *mut wasm_extern_t);
|
declare_vec!(wasm_extern_vec_t, *mut wasm_extern_t);
|
||||||
@@ -415,16 +461,9 @@ pub unsafe extern "C" fn wasm_engine_new() -> *mut wasm_engine_t {
|
|||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn wasm_extern_as_func(e: *mut wasm_extern_t) -> *mut wasm_func_t {
|
pub unsafe extern "C" fn wasm_extern_as_func(e: *mut wasm_extern_t) -> *mut wasm_func_t {
|
||||||
if let wasm_extern_t_type_cache::Empty = (*e).cache {
|
match &(*e).which {
|
||||||
(*e).cache = wasm_extern_t_type_cache::Func(wasm_func_t {
|
ExternHost::Func(_) => e.cast(),
|
||||||
func: (*e).ext.func().unwrap().clone(),
|
_ => ptr::null_mut(),
|
||||||
ext: None,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
match &mut (*e).cache {
|
|
||||||
wasm_extern_t_type_cache::Func(f) => f,
|
|
||||||
_ => panic!("wasm_extern_as_func"),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -435,17 +474,7 @@ pub unsafe extern "C" fn wasm_extern_vec_delete(v: *mut wasm_extern_vec_t) {
|
|||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn wasm_func_as_extern(f: *mut wasm_func_t) -> *mut wasm_extern_t {
|
pub unsafe extern "C" fn wasm_func_as_extern(f: *mut wasm_func_t) -> *mut wasm_extern_t {
|
||||||
if (*f).ext.is_none() {
|
&mut (*f).ext
|
||||||
(*f).ext = Some(Box::new(wasm_extern_t {
|
|
||||||
ext: Extern::Func((*f).func.clone()),
|
|
||||||
cache: wasm_extern_t_type_cache::Empty,
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
match &mut (*f).ext {
|
|
||||||
Some(e) => e.as_mut(),
|
|
||||||
_ => panic!("wasm_func_as_extern"),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
@@ -454,7 +483,7 @@ pub unsafe extern "C" fn wasm_func_call(
|
|||||||
args: *const wasm_val_t,
|
args: *const wasm_val_t,
|
||||||
results: *mut wasm_val_t,
|
results: *mut wasm_val_t,
|
||||||
) -> *mut wasm_trap_t {
|
) -> *mut wasm_trap_t {
|
||||||
let func = (*func).func.borrow();
|
let func = (*func).func().borrow();
|
||||||
let mut params = Vec::with_capacity(func.param_arity());
|
let mut params = Vec::with_capacity(func.param_arity());
|
||||||
for i in 0..func.param_arity() {
|
for i in 0..func.param_arity() {
|
||||||
let val = &(*args.add(i));
|
let val = &(*args.add(i));
|
||||||
@@ -606,8 +635,9 @@ pub unsafe extern "C" fn wasm_func_new(
|
|||||||
let ty = (*ty).functype.clone();
|
let ty = (*ty).functype.clone();
|
||||||
let callback = Rc::new(callback);
|
let callback = Rc::new(callback);
|
||||||
let func = Box::new(wasm_func_t {
|
let func = Box::new(wasm_func_t {
|
||||||
func: HostRef::new(Func::new(store, ty, callback)),
|
ext: wasm_extern_t {
|
||||||
ext: None,
|
which: ExternHost::Func(HostRef::new(Func::new(store, ty, callback))),
|
||||||
|
},
|
||||||
});
|
});
|
||||||
Box::into_raw(func)
|
Box::into_raw(func)
|
||||||
}
|
}
|
||||||
@@ -656,17 +686,35 @@ pub unsafe extern "C" fn wasm_instance_new(
|
|||||||
imports: *const *const wasm_extern_t,
|
imports: *const *const wasm_extern_t,
|
||||||
result: *mut *mut wasm_trap_t,
|
result: *mut *mut wasm_trap_t,
|
||||||
) -> *mut wasm_instance_t {
|
) -> *mut wasm_instance_t {
|
||||||
let store = &(*store).store.borrow();
|
|
||||||
let mut externs: Vec<Extern> = Vec::with_capacity((*module).imports.len());
|
let mut externs: Vec<Extern> = Vec::with_capacity((*module).imports.len());
|
||||||
for i in 0..(*module).imports.len() {
|
for i in 0..(*module).imports.len() {
|
||||||
let import = *imports.add(i);
|
let import = *imports.add(i);
|
||||||
externs.push((*import).ext.clone());
|
externs.push(match &(*import).which {
|
||||||
|
ExternHost::Func(e) => Extern::Func(e.borrow().clone()),
|
||||||
|
ExternHost::Table(e) => Extern::Table(e.borrow().clone()),
|
||||||
|
ExternHost::Global(e) => Extern::Global(e.borrow().clone()),
|
||||||
|
ExternHost::Memory(e) => Extern::Memory(e.borrow().clone()),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
let store = &(*store).store.borrow();
|
||||||
let module = &(*module).module.borrow();
|
let module = &(*module).module.borrow();
|
||||||
match Instance::new(store, module, &externs) {
|
// FIXME(WebAssembly/wasm-c-api#126) what else can we do with the `store`
|
||||||
|
// argument?
|
||||||
|
if !Store::ptr_eq(&store, module.store()) {
|
||||||
|
if !result.is_null() {
|
||||||
|
let trap = Trap::new("wasm_store_t must match store in wasm_module_t");
|
||||||
|
let trap = Box::new(wasm_trap_t {
|
||||||
|
trap: HostRef::new(trap),
|
||||||
|
});
|
||||||
|
(*result) = Box::into_raw(trap);
|
||||||
|
}
|
||||||
|
return ptr::null_mut();
|
||||||
|
}
|
||||||
|
match Instance::new(module, &externs) {
|
||||||
Ok(instance) => {
|
Ok(instance) => {
|
||||||
let instance = Box::new(wasm_instance_t {
|
let instance = Box::new(wasm_instance_t {
|
||||||
instance: HostRef::new(instance),
|
instance: HostRef::new(instance),
|
||||||
|
exports_cache: RefCell::new(None),
|
||||||
});
|
});
|
||||||
if !result.is_null() {
|
if !result.is_null() {
|
||||||
(*result) = ptr::null_mut();
|
(*result) = ptr::null_mut();
|
||||||
@@ -694,14 +742,23 @@ pub unsafe extern "C" fn wasm_instance_exports(
|
|||||||
instance: *const wasm_instance_t,
|
instance: *const wasm_instance_t,
|
||||||
out: *mut wasm_extern_vec_t,
|
out: *mut wasm_extern_vec_t,
|
||||||
) {
|
) {
|
||||||
let instance = &(*instance).instance.borrow();
|
let mut cache = (*instance).exports_cache.borrow_mut();
|
||||||
let exports = instance.exports();
|
let exports = cache.get_or_insert_with(|| {
|
||||||
|
let instance = &(*instance).instance.borrow();
|
||||||
|
instance
|
||||||
|
.exports()
|
||||||
|
.iter()
|
||||||
|
.map(|e| match e {
|
||||||
|
Extern::Func(f) => ExternHost::Func(HostRef::new(f.clone())),
|
||||||
|
Extern::Global(f) => ExternHost::Global(HostRef::new(f.clone())),
|
||||||
|
Extern::Memory(f) => ExternHost::Memory(HostRef::new(f.clone())),
|
||||||
|
Extern::Table(f) => ExternHost::Table(HostRef::new(f.clone())),
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
});
|
||||||
let mut buffer = Vec::with_capacity(exports.len());
|
let mut buffer = Vec::with_capacity(exports.len());
|
||||||
for e in exports.iter() {
|
for e in exports {
|
||||||
let ext = Box::new(wasm_extern_t {
|
let ext = Box::new(wasm_extern_t { which: e.clone() });
|
||||||
ext: e.clone(),
|
|
||||||
cache: wasm_extern_t_type_cache::Empty,
|
|
||||||
});
|
|
||||||
buffer.push(Box::into_raw(ext));
|
buffer.push(Box::into_raw(ext));
|
||||||
}
|
}
|
||||||
(*out).set_buffer(buffer);
|
(*out).set_buffer(buffer);
|
||||||
@@ -817,8 +874,9 @@ pub unsafe extern "C" fn wasm_func_new_with_env(
|
|||||||
finalizer,
|
finalizer,
|
||||||
});
|
});
|
||||||
let func = Box::new(wasm_func_t {
|
let func = Box::new(wasm_func_t {
|
||||||
func: HostRef::new(Func::new(store, ty, callback)),
|
ext: wasm_extern_t {
|
||||||
ext: None,
|
which: ExternHost::Func(HostRef::new(Func::new(store, ty, callback))),
|
||||||
|
},
|
||||||
});
|
});
|
||||||
Box::into_raw(func)
|
Box::into_raw(func)
|
||||||
}
|
}
|
||||||
@@ -1012,24 +1070,25 @@ pub unsafe extern "C" fn wasm_exporttype_vec_delete(et: *mut wasm_exporttype_vec
|
|||||||
(*et).uninitialize();
|
(*et).uninitialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_externtype(ty: &ExternType) -> wasm_externkind_t {
|
|
||||||
match ty {
|
|
||||||
ExternType::Func(_) => 0,
|
|
||||||
ExternType::Global(_) => 1,
|
|
||||||
ExternType::Table(_) => 2,
|
|
||||||
ExternType::Memory(_) => 3,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn wasm_extern_kind(e: *const wasm_extern_t) -> wasm_externkind_t {
|
pub unsafe extern "C" fn wasm_extern_kind(e: *const wasm_extern_t) -> wasm_externkind_t {
|
||||||
from_externtype(&(*e).ext.r#type())
|
match (*e).which {
|
||||||
|
ExternHost::Func(_) => WASM_EXTERN_FUNC,
|
||||||
|
ExternHost::Global(_) => WASM_EXTERN_GLOBAL,
|
||||||
|
ExternHost::Table(_) => WASM_EXTERN_TABLE,
|
||||||
|
ExternHost::Memory(_) => WASM_EXTERN_MEMORY,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn wasm_extern_type(e: *const wasm_extern_t) -> *mut wasm_externtype_t {
|
pub unsafe extern "C" fn wasm_extern_type(e: *const wasm_extern_t) -> *mut wasm_externtype_t {
|
||||||
let et = Box::new(wasm_externtype_t {
|
let et = Box::new(wasm_externtype_t {
|
||||||
ty: (*e).ext.r#type(),
|
ty: match &(*e).which {
|
||||||
|
ExternHost::Func(f) => ExternType::Func(f.borrow().ty().clone()),
|
||||||
|
ExternHost::Global(f) => ExternType::Global(f.borrow().ty().clone()),
|
||||||
|
ExternHost::Table(f) => ExternType::Table(f.borrow().ty().clone()),
|
||||||
|
ExternHost::Memory(f) => ExternType::Memory(f.borrow().ty().clone()),
|
||||||
|
},
|
||||||
cache: wasm_externtype_t_type_cache::Empty,
|
cache: wasm_externtype_t_type_cache::Empty,
|
||||||
});
|
});
|
||||||
Box::into_raw(et)
|
Box::into_raw(et)
|
||||||
@@ -1120,17 +1179,22 @@ pub unsafe extern "C" fn wasm_externtype_delete(et: *mut wasm_externtype_t) {
|
|||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn wasm_externtype_kind(et: *const wasm_externtype_t) -> wasm_externkind_t {
|
pub unsafe extern "C" fn wasm_externtype_kind(et: *const wasm_externtype_t) -> wasm_externkind_t {
|
||||||
from_externtype(&(*et).ty)
|
match &(*et).ty {
|
||||||
|
ExternType::Func(_) => WASM_EXTERN_FUNC,
|
||||||
|
ExternType::Table(_) => WASM_EXTERN_TABLE,
|
||||||
|
ExternType::Global(_) => WASM_EXTERN_GLOBAL,
|
||||||
|
ExternType::Memory(_) => WASM_EXTERN_MEMORY,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn wasm_func_param_arity(f: *const wasm_func_t) -> usize {
|
pub unsafe extern "C" fn wasm_func_param_arity(f: *const wasm_func_t) -> usize {
|
||||||
(*f).func.borrow().param_arity()
|
(*f).func().borrow().param_arity()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn wasm_func_result_arity(f: *const wasm_func_t) -> usize {
|
pub unsafe extern "C" fn wasm_func_result_arity(f: *const wasm_func_t) -> usize {
|
||||||
(*f).func.borrow().result_arity()
|
(*f).func().borrow().result_arity()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
@@ -1279,32 +1343,15 @@ pub unsafe extern "C" fn wasm_valtype_kind(vt: *const wasm_valtype_t) -> wasm_va
|
|||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn wasm_extern_as_global(e: *mut wasm_extern_t) -> *mut wasm_global_t {
|
pub unsafe extern "C" fn wasm_extern_as_global(e: *mut wasm_extern_t) -> *mut wasm_global_t {
|
||||||
if let wasm_extern_t_type_cache::Empty = (*e).cache {
|
match &(*e).which {
|
||||||
(*e).cache = wasm_extern_t_type_cache::Global(wasm_global_t {
|
ExternHost::Global(_) => e.cast(),
|
||||||
global: (*e).ext.global().unwrap().clone(),
|
_ => ptr::null_mut(),
|
||||||
ext: None,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
match &mut (*e).cache {
|
|
||||||
wasm_extern_t_type_cache::Global(g) => g,
|
|
||||||
_ => panic!("wasm_extern_as_global"),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn wasm_global_as_extern(g: *mut wasm_global_t) -> *mut wasm_extern_t {
|
pub unsafe extern "C" fn wasm_global_as_extern(g: *mut wasm_global_t) -> *mut wasm_extern_t {
|
||||||
if (*g).ext.is_none() {
|
&mut (*g).ext
|
||||||
(*g).ext = Some(Box::new(wasm_extern_t {
|
|
||||||
ext: Extern::Global((*g).global.clone()),
|
|
||||||
cache: wasm_extern_t_type_cache::Empty,
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
match &mut (*g).ext {
|
|
||||||
Some(e) => e.as_mut(),
|
|
||||||
_ => panic!("wasm_global_as_extern"),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
@@ -1322,7 +1369,7 @@ pub unsafe extern "C" fn wasm_global_same(
|
|||||||
g1: *const wasm_global_t,
|
g1: *const wasm_global_t,
|
||||||
g2: *const wasm_global_t,
|
g2: *const wasm_global_t,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
(*g1).global.ptr_eq(&(*g2).global)
|
(*g1).global().ptr_eq(&(*g2).global())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
@@ -1336,18 +1383,22 @@ pub unsafe extern "C" fn wasm_global_new(
|
|||||||
(*gt).globaltype.clone(),
|
(*gt).globaltype.clone(),
|
||||||
(*val).val(),
|
(*val).val(),
|
||||||
));
|
));
|
||||||
let g = Box::new(wasm_global_t { global, ext: None });
|
let g = Box::new(wasm_global_t {
|
||||||
|
ext: wasm_extern_t {
|
||||||
|
which: ExternHost::Global(global),
|
||||||
|
},
|
||||||
|
});
|
||||||
Box::into_raw(g)
|
Box::into_raw(g)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn wasm_global_get(g: *const wasm_global_t, out: *mut wasm_val_t) {
|
pub unsafe extern "C" fn wasm_global_get(g: *const wasm_global_t, out: *mut wasm_val_t) {
|
||||||
(*out).set((*g).global.borrow_mut().get());
|
(*out).set((*g).global().borrow().get());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn wasm_global_set(g: *mut wasm_global_t, val: *const wasm_val_t) {
|
pub unsafe extern "C" fn wasm_global_set(g: *mut wasm_global_t, val: *const wasm_val_t) {
|
||||||
(*g).global.borrow_mut().set((*val).val())
|
(*g).global().borrow().set((*val).val())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
@@ -1377,32 +1428,15 @@ pub unsafe extern "C" fn wasm_globaltype_new(
|
|||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn wasm_extern_as_memory(e: *mut wasm_extern_t) -> *mut wasm_memory_t {
|
pub unsafe extern "C" fn wasm_extern_as_memory(e: *mut wasm_extern_t) -> *mut wasm_memory_t {
|
||||||
if let wasm_extern_t_type_cache::Empty = (*e).cache {
|
match &(*e).which {
|
||||||
(*e).cache = wasm_extern_t_type_cache::Memory(wasm_memory_t {
|
ExternHost::Memory(_) => e.cast(),
|
||||||
memory: (*e).ext.memory().unwrap().clone(),
|
_ => ptr::null_mut(),
|
||||||
ext: None,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
match &mut (*e).cache {
|
|
||||||
wasm_extern_t_type_cache::Memory(m) => m,
|
|
||||||
_ => panic!("wasm_extern_as_memory"),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn wasm_memory_as_extern(m: *mut wasm_memory_t) -> *mut wasm_extern_t {
|
pub unsafe extern "C" fn wasm_memory_as_extern(m: *mut wasm_memory_t) -> *mut wasm_extern_t {
|
||||||
if (*m).ext.is_none() {
|
&mut (*m).ext
|
||||||
(*m).ext = Some(Box::new(wasm_extern_t {
|
|
||||||
ext: Extern::Memory((*m).memory.clone()),
|
|
||||||
cache: wasm_extern_t_type_cache::Empty,
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
match &mut (*m).ext {
|
|
||||||
Some(e) => e.as_mut(),
|
|
||||||
_ => panic!("wasm_global_as_extern"),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
@@ -1420,22 +1454,22 @@ pub unsafe extern "C" fn wasm_memory_same(
|
|||||||
m1: *const wasm_memory_t,
|
m1: *const wasm_memory_t,
|
||||||
m2: *const wasm_memory_t,
|
m2: *const wasm_memory_t,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
(*m1).memory.ptr_eq(&(*m2).memory)
|
(*m1).memory().ptr_eq(&(*m2).memory())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn wasm_memory_data(m: *mut wasm_memory_t) -> *mut u8 {
|
pub unsafe extern "C" fn wasm_memory_data(m: *mut wasm_memory_t) -> *mut u8 {
|
||||||
(*m).memory.borrow().data_ptr()
|
(*m).memory().borrow().data_ptr()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn wasm_memory_data_size(m: *const wasm_memory_t) -> usize {
|
pub unsafe extern "C" fn wasm_memory_data_size(m: *const wasm_memory_t) -> usize {
|
||||||
(*m).memory.borrow().data_size()
|
(*m).memory().borrow().data_size()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn wasm_memory_size(m: *const wasm_memory_t) -> wasm_memory_pages_t {
|
pub unsafe extern "C" fn wasm_memory_size(m: *const wasm_memory_t) -> wasm_memory_pages_t {
|
||||||
(*m).memory.borrow().size()
|
(*m).memory().borrow().size()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
@@ -1443,7 +1477,7 @@ pub unsafe extern "C" fn wasm_memory_grow(
|
|||||||
m: *mut wasm_memory_t,
|
m: *mut wasm_memory_t,
|
||||||
delta: wasm_memory_pages_t,
|
delta: wasm_memory_pages_t,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
(*m).memory.borrow_mut().grow(delta)
|
(*m).memory().borrow().grow(delta)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
@@ -1455,7 +1489,11 @@ pub unsafe extern "C" fn wasm_memory_new(
|
|||||||
&(*store).store.borrow(),
|
&(*store).store.borrow(),
|
||||||
(*mt).memorytype.clone(),
|
(*mt).memorytype.clone(),
|
||||||
));
|
));
|
||||||
let m = Box::new(wasm_memory_t { memory, ext: None });
|
let m = Box::new(wasm_memory_t {
|
||||||
|
ext: wasm_extern_t {
|
||||||
|
which: ExternHost::Memory(memory),
|
||||||
|
},
|
||||||
|
});
|
||||||
Box::into_raw(m)
|
Box::into_raw(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1483,37 +1521,20 @@ pub unsafe extern "C" fn wasm_memorytype_new(
|
|||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn wasm_extern_as_table(e: *mut wasm_extern_t) -> *mut wasm_table_t {
|
pub unsafe extern "C" fn wasm_extern_as_table(e: *mut wasm_extern_t) -> *mut wasm_table_t {
|
||||||
if let wasm_extern_t_type_cache::Empty = (*e).cache {
|
match &(*e).which {
|
||||||
(*e).cache = wasm_extern_t_type_cache::Table(wasm_table_t {
|
ExternHost::Table(_) => e.cast(),
|
||||||
table: (*e).ext.table().unwrap().clone(),
|
_ => ptr::null_mut(),
|
||||||
ext: None,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
match &mut (*e).cache {
|
|
||||||
wasm_extern_t_type_cache::Table(t) => t,
|
|
||||||
_ => panic!("wasm_extern_as_table"),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn wasm_table_as_extern(t: *mut wasm_table_t) -> *mut wasm_extern_t {
|
pub unsafe extern "C" fn wasm_table_as_extern(t: *mut wasm_table_t) -> *mut wasm_extern_t {
|
||||||
if (*t).ext.is_none() {
|
&mut (*t).ext
|
||||||
(*t).ext = Some(Box::new(wasm_extern_t {
|
|
||||||
ext: Extern::Table((*t).table.clone()),
|
|
||||||
cache: wasm_extern_t_type_cache::Empty,
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
match &mut (*t).ext {
|
|
||||||
Some(e) => e.as_mut(),
|
|
||||||
_ => panic!("wasm_table_as_extern"),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn wasm_func_as_ref(f: *mut wasm_func_t) -> *mut wasm_ref_t {
|
pub unsafe extern "C" fn wasm_func_as_ref(f: *mut wasm_func_t) -> *mut wasm_ref_t {
|
||||||
let r = (*f).func.anyref();
|
let r = (*f).func().anyref();
|
||||||
let f = Box::new(wasm_ref_t { r });
|
let f = Box::new(wasm_ref_t { r });
|
||||||
Box::into_raw(f)
|
Box::into_raw(f)
|
||||||
}
|
}
|
||||||
@@ -1547,12 +1568,13 @@ pub unsafe extern "C" fn wasm_table_new(
|
|||||||
Val::AnyRef(AnyRef::Null)
|
Val::AnyRef(AnyRef::Null)
|
||||||
};
|
};
|
||||||
let t = Box::new(wasm_table_t {
|
let t = Box::new(wasm_table_t {
|
||||||
table: HostRef::new(Table::new(
|
ext: wasm_extern_t {
|
||||||
&(*store).store.borrow(),
|
which: ExternHost::Table(HostRef::new(Table::new(
|
||||||
(*tt).tabletype.clone(),
|
&(*store).store.borrow(),
|
||||||
init,
|
(*tt).tabletype.clone(),
|
||||||
)),
|
init,
|
||||||
ext: None,
|
))),
|
||||||
|
},
|
||||||
});
|
});
|
||||||
Box::into_raw(t)
|
Box::into_raw(t)
|
||||||
}
|
}
|
||||||
@@ -1582,7 +1604,7 @@ pub unsafe extern "C" fn wasm_table_get(
|
|||||||
t: *const wasm_table_t,
|
t: *const wasm_table_t,
|
||||||
index: wasm_table_size_t,
|
index: wasm_table_size_t,
|
||||||
) -> *mut wasm_ref_t {
|
) -> *mut wasm_ref_t {
|
||||||
let val = (*t).table.borrow().get(index);
|
let val = (*t).table().borrow().get(index);
|
||||||
into_funcref(val)
|
into_funcref(val)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1593,12 +1615,12 @@ pub unsafe extern "C" fn wasm_table_set(
|
|||||||
r: *mut wasm_ref_t,
|
r: *mut wasm_ref_t,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let val = from_funcref(r);
|
let val = from_funcref(r);
|
||||||
(*t).table.borrow().set(index, val)
|
(*t).table().borrow().set(index, val)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn wasm_table_size(t: *const wasm_table_t) -> wasm_table_size_t {
|
pub unsafe extern "C" fn wasm_table_size(t: *const wasm_table_t) -> wasm_table_size_t {
|
||||||
(*t).table.borrow().size()
|
(*t).table().borrow().size()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
@@ -1608,12 +1630,12 @@ pub unsafe extern "C" fn wasm_table_grow(
|
|||||||
init: *mut wasm_ref_t,
|
init: *mut wasm_ref_t,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let init = from_funcref(init);
|
let init = from_funcref(init);
|
||||||
(*t).table.borrow_mut().grow(delta, init)
|
(*t).table().borrow().grow(delta, init)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn wasm_table_same(t1: *const wasm_table_t, t2: *const wasm_table_t) -> bool {
|
pub unsafe extern "C" fn wasm_table_same(t1: *const wasm_table_t, t2: *const wasm_table_t) -> bool {
|
||||||
(*t1).table.ptr_eq(&(*t2).table)
|
(*t1).table().ptr_eq((*t2).table())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
|||||||
68
crates/api/tests/import-indexes.rs
Normal file
68
crates/api/tests/import-indexes.rs
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
use std::rc::Rc;
|
||||||
|
use wasmtime::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn same_import_names_still_distinct() -> anyhow::Result<()> {
|
||||||
|
const WAT: &str = r#"
|
||||||
|
(module
|
||||||
|
(import "" "" (func $a (result i32)))
|
||||||
|
(import "" "" (func $b (result f32)))
|
||||||
|
(func (export "foo") (result i32)
|
||||||
|
call $a
|
||||||
|
call $b
|
||||||
|
i32.trunc_f32_u
|
||||||
|
i32.add)
|
||||||
|
)
|
||||||
|
"#;
|
||||||
|
|
||||||
|
struct Ret1;
|
||||||
|
|
||||||
|
impl Callable for Ret1 {
|
||||||
|
fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), Trap> {
|
||||||
|
assert!(params.is_empty());
|
||||||
|
assert_eq!(results.len(), 1);
|
||||||
|
results[0] = 1i32.into();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Ret2;
|
||||||
|
|
||||||
|
impl Callable for Ret2 {
|
||||||
|
fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), Trap> {
|
||||||
|
assert!(params.is_empty());
|
||||||
|
assert_eq!(results.len(), 1);
|
||||||
|
results[0] = 2.0f32.into();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let store = Store::default();
|
||||||
|
let wasm = wat::parse_str(WAT)?;
|
||||||
|
let module = Module::new(&store, &wasm)?;
|
||||||
|
|
||||||
|
let imports = [
|
||||||
|
Func::new(
|
||||||
|
&store,
|
||||||
|
FuncType::new(Box::new([]), Box::new([ValType::I32])),
|
||||||
|
Rc::new(Ret1),
|
||||||
|
)
|
||||||
|
.into(),
|
||||||
|
Func::new(
|
||||||
|
&store,
|
||||||
|
FuncType::new(Box::new([]), Box::new([ValType::F32])),
|
||||||
|
Rc::new(Ret2),
|
||||||
|
)
|
||||||
|
.into(),
|
||||||
|
];
|
||||||
|
let instance = Instance::new(&module, &imports)?;
|
||||||
|
|
||||||
|
let func = instance.find_export_by_name("foo").unwrap().func().unwrap();
|
||||||
|
let results = func.call(&[])?;
|
||||||
|
assert_eq!(results.len(), 1);
|
||||||
|
match results[0] {
|
||||||
|
Val::I32(n) => assert_eq!(n, 3),
|
||||||
|
_ => panic!("unexpected type of return"),
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
use std::cell::{Ref, RefCell};
|
use std::cell::RefCell;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use wasmtime::*;
|
use wasmtime::*;
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@ fn test_import_calling_export() {
|
|||||||
"#;
|
"#;
|
||||||
|
|
||||||
struct Callback {
|
struct Callback {
|
||||||
pub other: RefCell<Option<HostRef<Func>>>,
|
pub other: RefCell<Option<Func>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Callable for Callback {
|
impl Callable for Callback {
|
||||||
@@ -25,7 +25,6 @@ fn test_import_calling_export() {
|
|||||||
.borrow()
|
.borrow()
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.expect("expected a function ref")
|
.expect("expected a function ref")
|
||||||
.borrow()
|
|
||||||
.call(&[])
|
.call(&[])
|
||||||
.expect("expected function not to trap");
|
.expect("expected function not to trap");
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -40,18 +39,17 @@ fn test_import_calling_export() {
|
|||||||
other: RefCell::new(None),
|
other: RefCell::new(None),
|
||||||
});
|
});
|
||||||
|
|
||||||
let callback_func = HostRef::new(Func::new(
|
let callback_func = Func::new(
|
||||||
&store,
|
&store,
|
||||||
FuncType::new(Box::new([]), Box::new([])),
|
FuncType::new(Box::new([]), Box::new([])),
|
||||||
callback.clone(),
|
callback.clone(),
|
||||||
));
|
|
||||||
|
|
||||||
let imports = vec![callback_func.into()];
|
|
||||||
let instance = HostRef::new(
|
|
||||||
Instance::new(&store, &module, imports.as_slice()).expect("failed to instantiate module"),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let exports = Ref::map(instance.borrow(), |instance| instance.exports());
|
let imports = vec![callback_func.into()];
|
||||||
|
let instance =
|
||||||
|
Instance::new(&module, imports.as_slice()).expect("failed to instantiate module");
|
||||||
|
|
||||||
|
let exports = instance.exports();
|
||||||
assert!(!exports.is_empty());
|
assert!(!exports.is_empty());
|
||||||
|
|
||||||
let run_func = exports[0]
|
let run_func = exports[0]
|
||||||
@@ -65,8 +63,5 @@ fn test_import_calling_export() {
|
|||||||
.clone(),
|
.clone(),
|
||||||
);
|
);
|
||||||
|
|
||||||
run_func
|
run_func.call(&[]).expect("expected function not to trap");
|
||||||
.borrow()
|
|
||||||
.call(&[])
|
|
||||||
.expect("expected function not to trap");
|
|
||||||
}
|
}
|
||||||
|
|||||||
33
crates/api/tests/invoke_func_via_table.rs
Normal file
33
crates/api/tests/invoke_func_via_table.rs
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
use anyhow::{Context as _, Result};
|
||||||
|
use wasmtime::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_invoke_func_via_table() -> Result<()> {
|
||||||
|
let store = Store::default();
|
||||||
|
|
||||||
|
let binary = wat::parse_str(
|
||||||
|
r#"
|
||||||
|
(module
|
||||||
|
(func $f (result i64) (i64.const 42))
|
||||||
|
|
||||||
|
(table (export "table") 1 1 anyfunc)
|
||||||
|
(elem (i32.const 0) $f)
|
||||||
|
)
|
||||||
|
"#,
|
||||||
|
)?;
|
||||||
|
let module = Module::new(&store, &binary).context("> Error compiling module!")?;
|
||||||
|
let instance = Instance::new(&store, &module, &[]).context("> Error instantiating module!")?;
|
||||||
|
|
||||||
|
let f = instance
|
||||||
|
.find_export_by_name("table")
|
||||||
|
.unwrap()
|
||||||
|
.table()
|
||||||
|
.unwrap()
|
||||||
|
.get(0)
|
||||||
|
.funcref()
|
||||||
|
.unwrap()
|
||||||
|
.clone();
|
||||||
|
let result = f.call(&[]).unwrap();
|
||||||
|
assert_eq!(result[0].unwrap_i64(), 42);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
@@ -1,54 +1,38 @@
|
|||||||
use wasmtime::*;
|
use wasmtime::*;
|
||||||
use wat::parse_str;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_module_no_name() -> Result<(), String> {
|
fn test_module_no_name() -> anyhow::Result<()> {
|
||||||
let store = Store::default();
|
let store = Store::default();
|
||||||
let binary = parse_str(
|
let binary = wat::parse_str(
|
||||||
r#"
|
r#"
|
||||||
(module
|
(module
|
||||||
(func (export "run") (nop))
|
(func (export "run") (nop))
|
||||||
)
|
)
|
||||||
"#,
|
"#,
|
||||||
)
|
)?;
|
||||||
.map_err(|e| format!("failed to parse WebAssembly text source: {}", e))?;
|
|
||||||
|
|
||||||
let module = HostRef::new(
|
let module = Module::new(&store, &binary)?;
|
||||||
Module::new(&store, &binary).map_err(|e| format!("failed to compile module: {}", e))?,
|
assert_eq!(module.name(), None);
|
||||||
);
|
|
||||||
assert_eq!(module.borrow().name().cloned(), None);
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_module_name() -> Result<(), String> {
|
fn test_module_name() -> anyhow::Result<()> {
|
||||||
let store = Store::default();
|
let store = Store::default();
|
||||||
let binary = parse_str(
|
let binary = wat::parse_str(
|
||||||
r#"
|
r#"
|
||||||
(module $from_name_section
|
(module $from_name_section
|
||||||
(func (export "run") (nop))
|
(func (export "run") (nop))
|
||||||
)
|
)
|
||||||
"#,
|
"#,
|
||||||
)
|
)?;
|
||||||
.map_err(|e| format!("failed to parse WebAssembly text source: {}", e))?;
|
|
||||||
|
|
||||||
let module = HostRef::new(
|
let module = Module::new(&store, &binary)?;
|
||||||
Module::new(&store, &binary).map_err(|e| format!("failed to compile module: {}", e))?,
|
assert_eq!(module.name(), Some("from_name_section"));
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
module.borrow().name().cloned(),
|
|
||||||
Some("from_name_section".to_string())
|
|
||||||
);
|
|
||||||
|
|
||||||
let module = HostRef::new(
|
let module = Module::new_with_name(&store, &binary, "override")?;
|
||||||
Module::new_with_name(&store, &binary, "override".to_string())
|
assert_eq!(module.name(), Some("override"));
|
||||||
.map_err(|e| format!("failed to compile module: {}", e))?,
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
module.borrow().name().cloned(),
|
|
||||||
Some("override".to_string())
|
|
||||||
);
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,20 +26,16 @@ fn test_trap_return() -> Result<(), String> {
|
|||||||
let module =
|
let module =
|
||||||
Module::new(&store, &binary).map_err(|e| format!("failed to compile module: {}", e))?;
|
Module::new(&store, &binary).map_err(|e| format!("failed to compile module: {}", e))?;
|
||||||
let hello_type = FuncType::new(Box::new([]), Box::new([]));
|
let hello_type = FuncType::new(Box::new([]), Box::new([]));
|
||||||
let hello_func = HostRef::new(Func::new(&store, hello_type, Rc::new(HelloCallback)));
|
let hello_func = Func::new(&store, hello_type, Rc::new(HelloCallback));
|
||||||
|
|
||||||
let imports = vec![hello_func.into()];
|
let imports = vec![hello_func.into()];
|
||||||
let instance = Instance::new(&store, &module, imports.as_slice())
|
let instance = Instance::new(&module, &imports)
|
||||||
.map_err(|e| format!("failed to instantiate module: {:?}", e))?;
|
.map_err(|e| format!("failed to instantiate module: {:?}", e))?;
|
||||||
let run_func = instance.exports()[0]
|
let run_func = instance.exports()[0]
|
||||||
.func()
|
.func()
|
||||||
.expect("expected function export");
|
.expect("expected function export");
|
||||||
|
|
||||||
let e = run_func
|
let e = run_func.call(&[]).err().expect("error calling function");
|
||||||
.borrow()
|
|
||||||
.call(&[])
|
|
||||||
.err()
|
|
||||||
.expect("error calling function");
|
|
||||||
|
|
||||||
assert_eq!(e.message(), "test 123");
|
assert_eq!(e.message(), "test 123");
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "wasmtime-debug"
|
name = "wasmtime-debug"
|
||||||
version = "0.7.0"
|
version = "0.9.0"
|
||||||
authors = ["The Wasmtime Project Developers"]
|
authors = ["The Wasmtime Project Developers"]
|
||||||
description = "Debug utils for WebAsssembly code in Cranelift"
|
description = "Debug utils for WebAsssembly code in Cranelift"
|
||||||
license = "Apache-2.0 WITH LLVM-exception"
|
license = "Apache-2.0 WITH LLVM-exception"
|
||||||
@@ -13,10 +13,10 @@ edition = "2018"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
gimli = "0.19.0"
|
gimli = "0.19.0"
|
||||||
wasmparser = "0.45.1"
|
wasmparser = "0.47.0"
|
||||||
faerie = "0.13.0"
|
faerie = "0.14.0"
|
||||||
wasmtime-environ = { path = "../environ" }
|
wasmtime-environ = { path = "../environ", version = "0.9.0" }
|
||||||
target-lexicon = { version = "0.9.0", default-features = false }
|
target-lexicon = { version = "0.10.0", default-features = false }
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
thiserror = "1.0.4"
|
thiserror = "1.0.4"
|
||||||
more-asserts = "0.2.1"
|
more-asserts = "0.2.1"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "wasmtime-environ"
|
name = "wasmtime-environ"
|
||||||
version = "0.7.0"
|
version = "0.9.0"
|
||||||
authors = ["The Wasmtime Project Developers"]
|
authors = ["The Wasmtime Project Developers"]
|
||||||
description = "Standalone environment support for WebAsssembly code in Cranelift"
|
description = "Standalone environment support for WebAsssembly code in Cranelift"
|
||||||
license = "Apache-2.0 WITH LLVM-exception"
|
license = "Apache-2.0 WITH LLVM-exception"
|
||||||
@@ -13,11 +13,11 @@ edition = "2018"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
cranelift-codegen = { version = "0.52.0", features = ["enable-serde"] }
|
cranelift-codegen = { version = "0.54", features = ["enable-serde"] }
|
||||||
cranelift-entity = { version = "0.52.0", features = ["enable-serde"] }
|
cranelift-entity = { version = "0.54", features = ["enable-serde"] }
|
||||||
cranelift-wasm = { version = "0.52.0", features = ["enable-serde"] }
|
cranelift-wasm = { version = "0.54", features = ["enable-serde"] }
|
||||||
wasmparser = "0.45.1"
|
wasmparser = "0.47.0"
|
||||||
lightbeam = { path = "../lightbeam", optional = true }
|
lightbeam = { path = "../lightbeam", optional = true, version = "0.9.0" }
|
||||||
indexmap = "1.0.2"
|
indexmap = "1.0.2"
|
||||||
rayon = "1.2.1"
|
rayon = "1.2.1"
|
||||||
thiserror = "1.0.4"
|
thiserror = "1.0.4"
|
||||||
@@ -43,10 +43,10 @@ errno = "0.2.4"
|
|||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
tempfile = "3"
|
tempfile = "3"
|
||||||
target-lexicon = { version = "0.9.0", default-features = false }
|
target-lexicon = { version = "0.10.0", default-features = false }
|
||||||
pretty_env_logger = "0.3.0"
|
pretty_env_logger = "0.3.0"
|
||||||
rand = { version = "0.7.0", default-features = false, features = ["small_rng"] }
|
rand = { version = "0.7.0", default-features = false, features = ["small_rng"] }
|
||||||
cranelift-codegen = { version = "0.52.0", features = ["enable-serde", "all-arch"] }
|
cranelift-codegen = { version = "0.54", features = ["enable-serde", "all-arch"] }
|
||||||
filetime = "0.2.7"
|
filetime = "0.2.7"
|
||||||
|
|
||||||
[badges]
|
[badges]
|
||||||
|
|||||||
@@ -362,6 +362,10 @@ impl<'module_environment> TargetEnvironment for FuncEnvironment<'module_environm
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'module_environment> {
|
impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'module_environment> {
|
||||||
|
fn is_wasm_parameter(&self, func: &ir::Function, index: usize) -> bool {
|
||||||
|
func.signature.params[index].purpose == ir::ArgumentPurpose::Normal
|
||||||
|
}
|
||||||
|
|
||||||
fn make_table(&mut self, func: &mut ir::Function, index: TableIndex) -> WasmResult<ir::Table> {
|
fn make_table(&mut self, func: &mut ir::Function, index: TableIndex) -> WasmResult<ir::Table> {
|
||||||
let pointer_type = self.pointer_type();
|
let pointer_type = self.pointer_type();
|
||||||
|
|
||||||
|
|||||||
@@ -136,17 +136,18 @@ pub struct Module {
|
|||||||
/// Unprocessed signatures exactly as provided by `declare_signature()`.
|
/// Unprocessed signatures exactly as provided by `declare_signature()`.
|
||||||
pub signatures: PrimaryMap<SignatureIndex, ir::Signature>,
|
pub signatures: PrimaryMap<SignatureIndex, ir::Signature>,
|
||||||
|
|
||||||
/// Names of imported functions.
|
/// Names of imported functions, as well as the index of the import that
|
||||||
pub imported_funcs: PrimaryMap<FuncIndex, (String, String)>,
|
/// performed this import.
|
||||||
|
pub imported_funcs: PrimaryMap<FuncIndex, (String, String, u32)>,
|
||||||
|
|
||||||
/// Names of imported tables.
|
/// Names of imported tables.
|
||||||
pub imported_tables: PrimaryMap<TableIndex, (String, String)>,
|
pub imported_tables: PrimaryMap<TableIndex, (String, String, u32)>,
|
||||||
|
|
||||||
/// Names of imported memories.
|
/// Names of imported memories.
|
||||||
pub imported_memories: PrimaryMap<MemoryIndex, (String, String)>,
|
pub imported_memories: PrimaryMap<MemoryIndex, (String, String, u32)>,
|
||||||
|
|
||||||
/// Names of imported globals.
|
/// Names of imported globals.
|
||||||
pub imported_globals: PrimaryMap<GlobalIndex, (String, String)>,
|
pub imported_globals: PrimaryMap<GlobalIndex, (String, String, u32)>,
|
||||||
|
|
||||||
/// Types of functions, imported and local.
|
/// Types of functions, imported and local.
|
||||||
pub functions: PrimaryMap<FuncIndex, SignatureIndex>,
|
pub functions: PrimaryMap<FuncIndex, SignatureIndex>,
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ impl<'data> ModuleTranslation<'data> {
|
|||||||
pub struct ModuleEnvironment<'data> {
|
pub struct ModuleEnvironment<'data> {
|
||||||
/// The result to be filled in.
|
/// The result to be filled in.
|
||||||
result: ModuleTranslation<'data>,
|
result: ModuleTranslation<'data>,
|
||||||
|
imports: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'data> ModuleEnvironment<'data> {
|
impl<'data> ModuleEnvironment<'data> {
|
||||||
@@ -69,6 +70,7 @@ impl<'data> ModuleEnvironment<'data> {
|
|||||||
tunables,
|
tunables,
|
||||||
module_translation: None,
|
module_translation: None,
|
||||||
},
|
},
|
||||||
|
imports: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,10 +125,12 @@ impl<'data> cranelift_wasm::ModuleEnvironment<'data> for ModuleEnvironment<'data
|
|||||||
);
|
);
|
||||||
self.result.module.functions.push(sig_index);
|
self.result.module.functions.push(sig_index);
|
||||||
|
|
||||||
self.result
|
self.result.module.imported_funcs.push((
|
||||||
.module
|
String::from(module),
|
||||||
.imported_funcs
|
String::from(field),
|
||||||
.push((String::from(module), String::from(field)));
|
self.imports,
|
||||||
|
));
|
||||||
|
self.imports += 1;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,10 +143,12 @@ impl<'data> cranelift_wasm::ModuleEnvironment<'data> for ModuleEnvironment<'data
|
|||||||
let plan = TablePlan::for_table(table, &self.result.tunables);
|
let plan = TablePlan::for_table(table, &self.result.tunables);
|
||||||
self.result.module.table_plans.push(plan);
|
self.result.module.table_plans.push(plan);
|
||||||
|
|
||||||
self.result
|
self.result.module.imported_tables.push((
|
||||||
.module
|
String::from(module),
|
||||||
.imported_tables
|
String::from(field),
|
||||||
.push((String::from(module), String::from(field)));
|
self.imports,
|
||||||
|
));
|
||||||
|
self.imports += 1;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,10 +166,12 @@ impl<'data> cranelift_wasm::ModuleEnvironment<'data> for ModuleEnvironment<'data
|
|||||||
let plan = MemoryPlan::for_memory(memory, &self.result.tunables);
|
let plan = MemoryPlan::for_memory(memory, &self.result.tunables);
|
||||||
self.result.module.memory_plans.push(plan);
|
self.result.module.memory_plans.push(plan);
|
||||||
|
|
||||||
self.result
|
self.result.module.imported_memories.push((
|
||||||
.module
|
String::from(module),
|
||||||
.imported_memories
|
String::from(field),
|
||||||
.push((String::from(module), String::from(field)));
|
self.imports,
|
||||||
|
));
|
||||||
|
self.imports += 1;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -180,10 +188,12 @@ impl<'data> cranelift_wasm::ModuleEnvironment<'data> for ModuleEnvironment<'data
|
|||||||
);
|
);
|
||||||
self.result.module.globals.push(global);
|
self.result.module.globals.push(global);
|
||||||
|
|
||||||
self.result
|
self.result.module.imported_globals.push((
|
||||||
.module
|
String::from(module),
|
||||||
.imported_globals
|
String::from(field),
|
||||||
.push((String::from(module), String::from(field)));
|
self.imports,
|
||||||
|
));
|
||||||
|
self.imports += 1;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ description = "Fuzzing infrastructure for Wasmtime"
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
name = "wasmtime-fuzzing"
|
name = "wasmtime-fuzzing"
|
||||||
publish = false
|
publish = false
|
||||||
version = "0.1.0"
|
version = "0.9.0"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
@@ -14,11 +14,11 @@ arbitrary = "0.2.0"
|
|||||||
binaryen = "0.8.2"
|
binaryen = "0.8.2"
|
||||||
env_logger = { version = "0.7.1", optional = true }
|
env_logger = { version = "0.7.1", optional = true }
|
||||||
log = "0.4.8"
|
log = "0.4.8"
|
||||||
wasmparser = "0.45.1"
|
wasmparser = "0.47.0"
|
||||||
wasmprinter = "0.2.0"
|
wasmprinter = "0.2.0"
|
||||||
wasmtime = { path = "../api" }
|
wasmtime = { path = "../api", version = "0.9.0" }
|
||||||
wasmtime-environ = { path = "../environ" }
|
wasmtime-environ = { path = "../environ", version = "0.9.0" }
|
||||||
wasmtime-jit = { path = "../jit" }
|
wasmtime-jit = { path = "../jit", version = "0.9.0" }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
wat = "1.0"
|
wat = "1.0"
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ pub fn instantiate(wasm: &[u8], strategy: Strategy) {
|
|||||||
// aren't caught during validation or compilation. For example, an imported
|
// aren't caught during validation or compilation. For example, an imported
|
||||||
// table might not have room for an element segment that we want to
|
// table might not have room for an element segment that we want to
|
||||||
// initialize into it.
|
// initialize into it.
|
||||||
let _result = Instance::new(&store, &module, &imports);
|
let _result = Instance::new(&module, &imports);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Compile the Wasm buffer, and implicitly fail if we have an unexpected
|
/// Compile the Wasm buffer, and implicitly fail if we have an unexpected
|
||||||
@@ -96,7 +96,7 @@ pub fn make_api_calls(api: crate::generators::api::ApiCalls) {
|
|||||||
let mut engine: Option<Engine> = None;
|
let mut engine: Option<Engine> = None;
|
||||||
let mut store: Option<Store> = None;
|
let mut store: Option<Store> = None;
|
||||||
let mut modules: HashMap<usize, Module> = Default::default();
|
let mut modules: HashMap<usize, Module> = Default::default();
|
||||||
let mut instances: HashMap<usize, HostRef<Instance>> = Default::default();
|
let mut instances: HashMap<usize, Instance> = Default::default();
|
||||||
|
|
||||||
for call in api.calls {
|
for call in api.calls {
|
||||||
match call {
|
match call {
|
||||||
@@ -152,8 +152,8 @@ pub fn make_api_calls(api: crate::generators::api::ApiCalls) {
|
|||||||
// aren't caught during validation or compilation. For example, an imported
|
// aren't caught during validation or compilation. For example, an imported
|
||||||
// table might not have room for an element segment that we want to
|
// table might not have room for an element segment that we want to
|
||||||
// initialize into it.
|
// initialize into it.
|
||||||
if let Ok(instance) = Instance::new(store.as_ref().unwrap(), &module, &imports) {
|
if let Ok(instance) = Instance::new(&module, &imports) {
|
||||||
instances.insert(id, HostRef::new(instance));
|
instances.insert(id, instance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -175,25 +175,22 @@ pub fn make_api_calls(api: crate::generators::api::ApiCalls) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let funcs = {
|
let funcs = instance
|
||||||
let instance = instance.borrow();
|
.exports()
|
||||||
instance
|
.iter()
|
||||||
.exports()
|
.filter_map(|e| match e {
|
||||||
.iter()
|
Extern::Func(f) => Some(f.clone()),
|
||||||
.filter_map(|e| match e {
|
_ => None,
|
||||||
Extern::Func(f) => Some(f.clone()),
|
})
|
||||||
_ => None,
|
.collect::<Vec<_>>();
|
||||||
})
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
};
|
|
||||||
|
|
||||||
if funcs.is_empty() {
|
if funcs.is_empty() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let nth = nth % funcs.len();
|
let nth = nth % funcs.len();
|
||||||
let f = funcs[nth].borrow();
|
let f = &funcs[nth];
|
||||||
let ty = f.r#type();
|
let ty = f.ty();
|
||||||
let params = match ty
|
let params = match ty
|
||||||
.params()
|
.params()
|
||||||
.iter()
|
.iter()
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use wasmtime::{
|
use wasmtime::{
|
||||||
Callable, Extern, ExternType, Func, FuncType, Global, GlobalType, HostRef, ImportType, Memory,
|
Callable, Extern, ExternType, Func, FuncType, Global, GlobalType, ImportType, Memory,
|
||||||
MemoryType, Store, Table, TableType, Trap, Val, ValType,
|
MemoryType, Store, Table, TableType, Trap, Val, ValType,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -11,18 +11,12 @@ pub fn dummy_imports(store: &Store, import_tys: &[ImportType]) -> Result<Vec<Ext
|
|||||||
let mut imports = Vec::with_capacity(import_tys.len());
|
let mut imports = Vec::with_capacity(import_tys.len());
|
||||||
for imp in import_tys {
|
for imp in import_tys {
|
||||||
imports.push(match imp.ty() {
|
imports.push(match imp.ty() {
|
||||||
ExternType::Func(func_ty) => {
|
ExternType::Func(func_ty) => Extern::Func(DummyFunc::new(&store, func_ty.clone())),
|
||||||
Extern::Func(HostRef::new(DummyFunc::new(&store, func_ty.clone())))
|
|
||||||
}
|
|
||||||
ExternType::Global(global_ty) => {
|
ExternType::Global(global_ty) => {
|
||||||
Extern::Global(HostRef::new(dummy_global(&store, global_ty.clone())?))
|
Extern::Global(dummy_global(&store, global_ty.clone())?)
|
||||||
}
|
|
||||||
ExternType::Table(table_ty) => {
|
|
||||||
Extern::Table(HostRef::new(dummy_table(&store, table_ty.clone())?))
|
|
||||||
}
|
|
||||||
ExternType::Memory(mem_ty) => {
|
|
||||||
Extern::Memory(HostRef::new(dummy_memory(&store, mem_ty.clone())))
|
|
||||||
}
|
}
|
||||||
|
ExternType::Table(table_ty) => Extern::Table(dummy_table(&store, table_ty.clone())?),
|
||||||
|
ExternType::Memory(mem_ty) => Extern::Memory(dummy_memory(&store, mem_ty.clone())),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Ok(imports)
|
Ok(imports)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "wasmtime-interface-types"
|
name = "wasmtime-interface-types"
|
||||||
version = "0.7.0"
|
version = "0.9.0"
|
||||||
authors = ["The Wasmtime Project Developers"]
|
authors = ["The Wasmtime Project Developers"]
|
||||||
description = "Support for wasm interface types with wasmtime"
|
description = "Support for wasm interface types with wasmtime"
|
||||||
license = "Apache-2.0 WITH LLVM-exception"
|
license = "Apache-2.0 WITH LLVM-exception"
|
||||||
@@ -13,13 +13,13 @@ edition = "2018"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.19"
|
anyhow = "1.0.19"
|
||||||
walrus = "0.13"
|
walrus = "0.13"
|
||||||
wasmparser = { version = "0.45.1", default-features = false }
|
wasmparser = { version = "0.47.0", default-features = false }
|
||||||
wasm-webidl-bindings = "0.6"
|
wasm-webidl-bindings = "0.6"
|
||||||
wasmtime = { path = '../api' }
|
wasmtime = { path = "../api", version = "0.9.0" }
|
||||||
wasmtime-jit = { path = '../jit' }
|
wasmtime-jit = { path = "../jit", version = "0.9.0" }
|
||||||
wasmtime-environ = { path = '../environ' }
|
wasmtime-environ = { path = "../environ", version = "0.9.0" }
|
||||||
wasmtime-runtime = { path = '../runtime' }
|
wasmtime-runtime = { path = "../runtime", version = "0.9.0" }
|
||||||
wasmtime-wasi = { path = '../wasi' }
|
wasmtime-wasi = { path = "../wasi", version = "0.9.0" }
|
||||||
|
|
||||||
[badges]
|
[badges]
|
||||||
maintenance = { status = "actively-developed" }
|
maintenance = { status = "actively-developed" }
|
||||||
|
|||||||
@@ -125,18 +125,17 @@ impl ModuleData {
|
|||||||
/// wasm interface types.
|
/// wasm interface types.
|
||||||
pub fn invoke_export(
|
pub fn invoke_export(
|
||||||
&self,
|
&self,
|
||||||
instance: &wasmtime::HostRef<wasmtime::Instance>,
|
instance: &wasmtime::Instance,
|
||||||
export: &str,
|
export: &str,
|
||||||
args: &[Value],
|
args: &[Value],
|
||||||
) -> Result<Vec<Value>> {
|
) -> Result<Vec<Value>> {
|
||||||
let mut handle = instance.borrow().handle().clone();
|
let mut handle = instance.handle().clone();
|
||||||
|
|
||||||
let binding = self.binding_for_export(&mut handle, export)?;
|
let binding = self.binding_for_export(&mut handle, export)?;
|
||||||
let incoming = binding.param_bindings()?;
|
let incoming = binding.param_bindings()?;
|
||||||
let outgoing = binding.result_bindings()?;
|
let outgoing = binding.result_bindings()?;
|
||||||
|
|
||||||
let f = instance
|
let f = instance
|
||||||
.borrow()
|
|
||||||
.find_export_by_name(export)
|
.find_export_by_name(export)
|
||||||
.ok_or_else(|| format_err!("failed to find export `{}`", export))?
|
.ok_or_else(|| format_err!("failed to find export `{}`", export))?
|
||||||
.func()
|
.func()
|
||||||
@@ -148,7 +147,7 @@ impl ModuleData {
|
|||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|rv| rv.into())
|
.map(|rv| rv.into())
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
let wasm_results = match f.borrow().call(&wasm_args) {
|
let wasm_results = match f.call(&wasm_args) {
|
||||||
Ok(values) => values
|
Ok(values) => values
|
||||||
.to_vec()
|
.to_vec()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
@@ -322,20 +321,19 @@ trait TranslateContext {
|
|||||||
unsafe fn get_memory(&mut self) -> Result<&mut [u8]>;
|
unsafe fn get_memory(&mut self) -> Result<&mut [u8]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct InstanceTranslateContext(pub wasmtime::HostRef<wasmtime::Instance>);
|
struct InstanceTranslateContext(pub wasmtime::Instance);
|
||||||
|
|
||||||
impl TranslateContext for InstanceTranslateContext {
|
impl TranslateContext for InstanceTranslateContext {
|
||||||
fn invoke_alloc(&mut self, alloc_func_name: &str, len: i32) -> Result<i32> {
|
fn invoke_alloc(&mut self, alloc_func_name: &str, len: i32) -> Result<i32> {
|
||||||
let alloc = self
|
let alloc = self
|
||||||
.0
|
.0
|
||||||
.borrow()
|
|
||||||
.find_export_by_name(alloc_func_name)
|
.find_export_by_name(alloc_func_name)
|
||||||
.ok_or_else(|| format_err!("failed to find alloc function `{}`", alloc_func_name))?
|
.ok_or_else(|| format_err!("failed to find alloc function `{}`", alloc_func_name))?
|
||||||
.func()
|
.func()
|
||||||
.ok_or_else(|| format_err!("`{}` is not a (alloc) function", alloc_func_name))?
|
.ok_or_else(|| format_err!("`{}` is not a (alloc) function", alloc_func_name))?
|
||||||
.clone();
|
.clone();
|
||||||
let alloc_args = vec![wasmtime::Val::I32(len)];
|
let alloc_args = vec![wasmtime::Val::I32(len)];
|
||||||
let results = match alloc.borrow().call(&alloc_args) {
|
let results = match alloc.call(&alloc_args) {
|
||||||
Ok(values) => values,
|
Ok(values) => values,
|
||||||
Err(trap) => bail!("trapped: {:?}", trap),
|
Err(trap) => bail!("trapped: {:?}", trap),
|
||||||
};
|
};
|
||||||
@@ -350,14 +348,13 @@ impl TranslateContext for InstanceTranslateContext {
|
|||||||
unsafe fn get_memory(&mut self) -> Result<&mut [u8]> {
|
unsafe fn get_memory(&mut self) -> Result<&mut [u8]> {
|
||||||
let memory = self
|
let memory = self
|
||||||
.0
|
.0
|
||||||
.borrow()
|
|
||||||
.find_export_by_name("memory")
|
.find_export_by_name("memory")
|
||||||
.ok_or_else(|| format_err!("failed to find `memory` export"))?
|
.ok_or_else(|| format_err!("failed to find `memory` export"))?
|
||||||
.memory()
|
.memory()
|
||||||
.ok_or_else(|| format_err!("`memory` is not a memory"))?
|
.ok_or_else(|| format_err!("`memory` is not a memory"))?
|
||||||
.clone();
|
.clone();
|
||||||
let ptr = memory.borrow().data_ptr();
|
let ptr = memory.data_ptr();
|
||||||
let len = memory.borrow().data_size();
|
let len = memory.data_size();
|
||||||
Ok(std::slice::from_raw_parts_mut(ptr, len))
|
Ok(std::slice::from_raw_parts_mut(ptr, len))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "wasmtime-jit"
|
name = "wasmtime-jit"
|
||||||
version = "0.7.0"
|
version = "0.9.0"
|
||||||
authors = ["The Wasmtime Project Developers"]
|
authors = ["The Wasmtime Project Developers"]
|
||||||
description = "JIT-style execution for WebAsssembly code in Cranelift"
|
description = "JIT-style execution for WebAsssembly code in Cranelift"
|
||||||
license = "Apache-2.0 WITH LLVM-exception"
|
license = "Apache-2.0 WITH LLVM-exception"
|
||||||
@@ -11,18 +11,18 @@ readme = "README.md"
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
cranelift-codegen = { version = "0.52.0", features = ["enable-serde"] }
|
cranelift-codegen = { version = "0.54", features = ["enable-serde"] }
|
||||||
cranelift-entity = { version = "0.52.0", features = ["enable-serde"] }
|
cranelift-entity = { version = "0.54", features = ["enable-serde"] }
|
||||||
cranelift-wasm = { version = "0.52.0", features = ["enable-serde"] }
|
cranelift-wasm = { version = "0.54", features = ["enable-serde"] }
|
||||||
cranelift-native = "0.52.0"
|
cranelift-native = "0.54"
|
||||||
cranelift-frontend = "0.52.0"
|
cranelift-frontend = "0.54"
|
||||||
wasmtime-environ = { path = "../environ" }
|
wasmtime-environ = { path = "../environ", version = "0.9.0" }
|
||||||
wasmtime-runtime = { path = "../runtime" }
|
wasmtime-runtime = { path = "../runtime", version = "0.9.0" }
|
||||||
wasmtime-debug = { path = "../debug" }
|
wasmtime-debug = { path = "../debug", version = "0.9.0" }
|
||||||
region = "2.0.0"
|
region = "2.0.0"
|
||||||
thiserror = "1.0.4"
|
thiserror = "1.0.4"
|
||||||
target-lexicon = { version = "0.9.0", default-features = false }
|
target-lexicon = { version = "0.10.0", default-features = false }
|
||||||
wasmparser = { version = "0.45.1", default-features = false }
|
wasmparser = { version = "0.47.0", default-features = false }
|
||||||
more-asserts = "0.2.1"
|
more-asserts = "0.2.1"
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,11 @@ pub struct CodeMemory {
|
|||||||
published: usize,
|
published: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn _assert() {
|
||||||
|
fn _assert_send_sync<T: Send + Sync>() {}
|
||||||
|
_assert_send_sync::<CodeMemory>();
|
||||||
|
}
|
||||||
|
|
||||||
impl CodeMemory {
|
impl CodeMemory {
|
||||||
/// Create a new `CodeMemory` instance.
|
/// Create a new `CodeMemory` instance.
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ impl<'data> RawCompiledModule<'data> {
|
|||||||
fn new(
|
fn new(
|
||||||
compiler: &mut Compiler,
|
compiler: &mut Compiler,
|
||||||
data: &'data [u8],
|
data: &'data [u8],
|
||||||
module_name: Option<String>,
|
module_name: Option<&str>,
|
||||||
resolver: &mut dyn Resolver,
|
resolver: &mut dyn Resolver,
|
||||||
debug_info: bool,
|
debug_info: bool,
|
||||||
) -> Result<Self, SetupError> {
|
) -> Result<Self, SetupError> {
|
||||||
@@ -76,7 +76,7 @@ impl<'data> RawCompiledModule<'data> {
|
|||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
translation.module.name = module_name;
|
translation.module.name = module_name.map(|s| s.to_string());
|
||||||
|
|
||||||
let (allocated_functions, jt_offsets, relocations, dbg_image) = compiler.compile(
|
let (allocated_functions, jt_offsets, relocations, dbg_image) = compiler.compile(
|
||||||
&translation.module,
|
&translation.module,
|
||||||
@@ -155,7 +155,7 @@ impl CompiledModule {
|
|||||||
pub fn new<'data>(
|
pub fn new<'data>(
|
||||||
compiler: &mut Compiler,
|
compiler: &mut Compiler,
|
||||||
data: &'data [u8],
|
data: &'data [u8],
|
||||||
module_name: Option<String>,
|
module_name: Option<&str>,
|
||||||
resolver: &mut dyn Resolver,
|
resolver: &mut dyn Resolver,
|
||||||
global_exports: Rc<RefCell<HashMap<String, Option<Export>>>>,
|
global_exports: Rc<RefCell<HashMap<String, Option<Export>>>>,
|
||||||
debug_info: bool,
|
debug_info: bool,
|
||||||
@@ -263,7 +263,7 @@ impl OwnedDataInitializer {
|
|||||||
pub fn instantiate(
|
pub fn instantiate(
|
||||||
compiler: &mut Compiler,
|
compiler: &mut Compiler,
|
||||||
data: &[u8],
|
data: &[u8],
|
||||||
module_name: Option<String>,
|
module_name: Option<&str>,
|
||||||
resolver: &mut dyn Resolver,
|
resolver: &mut dyn Resolver,
|
||||||
global_exports: Rc<RefCell<HashMap<String, Option<Export>>>>,
|
global_exports: Rc<RefCell<HashMap<String, Option<Export>>>>,
|
||||||
debug_info: bool,
|
debug_info: bool,
|
||||||
|
|||||||
@@ -30,8 +30,8 @@ pub fn link_module(
|
|||||||
let mut dependencies = HashSet::new();
|
let mut dependencies = HashSet::new();
|
||||||
|
|
||||||
let mut function_imports = PrimaryMap::with_capacity(module.imported_funcs.len());
|
let mut function_imports = PrimaryMap::with_capacity(module.imported_funcs.len());
|
||||||
for (index, (ref module_name, ref field)) in module.imported_funcs.iter() {
|
for (index, (module_name, field, import_idx)) in module.imported_funcs.iter() {
|
||||||
match resolver.resolve(module_name, field) {
|
match resolver.resolve(*import_idx, module_name, field) {
|
||||||
Some(export_value) => match export_value {
|
Some(export_value) => match export_value {
|
||||||
Export::Function {
|
Export::Function {
|
||||||
address,
|
address,
|
||||||
@@ -71,8 +71,8 @@ pub fn link_module(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut table_imports = PrimaryMap::with_capacity(module.imported_tables.len());
|
let mut table_imports = PrimaryMap::with_capacity(module.imported_tables.len());
|
||||||
for (index, (ref module_name, ref field)) in module.imported_tables.iter() {
|
for (index, (module_name, field, import_idx)) in module.imported_tables.iter() {
|
||||||
match resolver.resolve(module_name, field) {
|
match resolver.resolve(*import_idx, module_name, field) {
|
||||||
Some(export_value) => match export_value {
|
Some(export_value) => match export_value {
|
||||||
Export::Table {
|
Export::Table {
|
||||||
definition,
|
definition,
|
||||||
@@ -110,8 +110,8 @@ pub fn link_module(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut memory_imports = PrimaryMap::with_capacity(module.imported_memories.len());
|
let mut memory_imports = PrimaryMap::with_capacity(module.imported_memories.len());
|
||||||
for (index, (ref module_name, ref field)) in module.imported_memories.iter() {
|
for (index, (module_name, field, import_idx)) in module.imported_memories.iter() {
|
||||||
match resolver.resolve(module_name, field) {
|
match resolver.resolve(*import_idx, module_name, field) {
|
||||||
Some(export_value) => match export_value {
|
Some(export_value) => match export_value {
|
||||||
Export::Memory {
|
Export::Memory {
|
||||||
definition,
|
definition,
|
||||||
@@ -163,8 +163,8 @@ pub fn link_module(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut global_imports = PrimaryMap::with_capacity(module.imported_globals.len());
|
let mut global_imports = PrimaryMap::with_capacity(module.imported_globals.len());
|
||||||
for (index, (ref module_name, ref field)) in module.imported_globals.iter() {
|
for (index, (module_name, field, import_idx)) in module.imported_globals.iter() {
|
||||||
match resolver.resolve(module_name, field) {
|
match resolver.resolve(*import_idx, module_name, field) {
|
||||||
Some(export_value) => match export_value {
|
Some(export_value) => match export_value {
|
||||||
Export::Table { .. } | Export::Memory { .. } | Export::Function { .. } => {
|
Export::Table { .. } | Export::Memory { .. } | Export::Function { .. } => {
|
||||||
return Err(LinkError(format!(
|
return Err(LinkError(format!(
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ impl Namespace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Resolver for Namespace {
|
impl Resolver for Namespace {
|
||||||
fn resolve(&mut self, name: &str, field: &str) -> Option<Export> {
|
fn resolve(&mut self, _idx: u32, name: &str, field: &str) -> Option<Export> {
|
||||||
if let Some(instance) = self.names.get_mut(name) {
|
if let Some(instance) = self.names.get_mut(name) {
|
||||||
instance.lookup(field)
|
instance.lookup(field)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -5,15 +5,22 @@ use wasmtime_runtime::Export;
|
|||||||
|
|
||||||
/// Import resolver connects imports with available exported values.
|
/// Import resolver connects imports with available exported values.
|
||||||
pub trait Resolver {
|
pub trait Resolver {
|
||||||
/// Resolve the given module/field combo.
|
/// Resolves an import a WebAssembly module to an export it's hooked up to.
|
||||||
fn resolve(&mut self, module: &str, field: &str) -> Option<Export>;
|
///
|
||||||
|
/// The `index` provided is the index of the import in the wasm module
|
||||||
|
/// that's being resolved. For example 1 means that it's the second import
|
||||||
|
/// listed in the wasm module.
|
||||||
|
///
|
||||||
|
/// The `module` and `field` arguments provided are the module/field names
|
||||||
|
/// listed on the import itself.
|
||||||
|
fn resolve(&mut self, index: u32, module: &str, field: &str) -> Option<Export>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `Resolver` implementation that always resolves to `None`.
|
/// `Resolver` implementation that always resolves to `None`.
|
||||||
pub struct NullResolver {}
|
pub struct NullResolver {}
|
||||||
|
|
||||||
impl Resolver for NullResolver {
|
impl Resolver for NullResolver {
|
||||||
fn resolve(&mut self, _module: &str, _field: &str) -> Option<Export> {
|
fn resolve(&mut self, _idx: u32, _module: &str, _field: &str) -> Option<Export> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "lightbeam"
|
name = "lightbeam"
|
||||||
version = "0.7.0"
|
version = "0.9.0"
|
||||||
authors = ["The Lightbeam Project Developers"]
|
authors = ["The Lightbeam Project Developers"]
|
||||||
description = "An optimising one-pass streaming compiler for WebAssembly"
|
description = "An optimising one-pass streaming compiler for WebAssembly"
|
||||||
license = "Apache-2.0 WITH LLVM-exception"
|
license = "Apache-2.0 WITH LLVM-exception"
|
||||||
@@ -14,12 +14,12 @@ edition = "2018"
|
|||||||
smallvec = "1.0.0"
|
smallvec = "1.0.0"
|
||||||
dynasm = "0.5.2"
|
dynasm = "0.5.2"
|
||||||
dynasmrt = "0.5.2"
|
dynasmrt = "0.5.2"
|
||||||
wasmparser = "0.45.1"
|
wasmparser = "0.47.0"
|
||||||
memoffset = "0.5.3"
|
memoffset = "0.5.3"
|
||||||
itertools = "0.8.2"
|
itertools = "0.8.2"
|
||||||
capstone = "0.6.0"
|
capstone = "0.6.0"
|
||||||
thiserror = "1.0.9"
|
thiserror = "1.0.9"
|
||||||
cranelift-codegen = "0.52.0"
|
cranelift-codegen = "0.54"
|
||||||
multi_mut = "0.1"
|
multi_mut = "0.1"
|
||||||
either = "1.5"
|
either = "1.5"
|
||||||
typemap = "0.3"
|
typemap = "0.3"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "wasmtime-py"
|
name = "wasmtime-py"
|
||||||
version = "0.7.0"
|
version = "0.9.0"
|
||||||
authors = ["The Wasmtime Project Developers"]
|
authors = ["The Wasmtime Project Developers"]
|
||||||
description = "Python extension for Wasmtime"
|
description = "Python extension for Wasmtime"
|
||||||
license = "Apache-2.0 WITH LLVM-exception"
|
license = "Apache-2.0 WITH LLVM-exception"
|
||||||
@@ -17,15 +17,15 @@ test = false
|
|||||||
doc = false
|
doc = false
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
wasmtime = { path = "../../api" }
|
wasmtime = { path = "../../api", version = "0.9.0" }
|
||||||
wasmtime-environ = { path = "../../environ" }
|
wasmtime-environ = { path = "../../environ", version = "0.9.0" }
|
||||||
wasmtime-interface-types = { path = "../../interface-types" }
|
wasmtime-interface-types = { path = "../../interface-types", version = "0.9.0" }
|
||||||
wasmtime-runtime = { path = "../../runtime" }
|
wasmtime-runtime = { path = "../../runtime", version = "0.9.0" }
|
||||||
wasmtime-wasi = { path = "../../wasi" }
|
wasmtime-wasi = { path = "../../wasi", version = "0.9.0" }
|
||||||
target-lexicon = { version = "0.9.0", default-features = false }
|
target-lexicon = { version = "0.10.0", default-features = false }
|
||||||
anyhow = "1.0.19"
|
anyhow = "1.0.19"
|
||||||
region = "2.0.0"
|
region = "2.0.0"
|
||||||
wasmparser = "0.45.1"
|
wasmparser = "0.47.0"
|
||||||
pyo3 = { version = "0.8.0", features = ["extension-module"] }
|
pyo3 = { version = "0.8.0", features = ["extension-module"] }
|
||||||
|
|
||||||
[badges]
|
[badges]
|
||||||
|
|||||||
@@ -10,17 +10,16 @@ use wasmtime_interface_types::ModuleData;
|
|||||||
// TODO support non-export functions
|
// TODO support non-export functions
|
||||||
#[pyclass]
|
#[pyclass]
|
||||||
pub struct Function {
|
pub struct Function {
|
||||||
pub instance: wasmtime::HostRef<wasmtime::Instance>,
|
pub instance: wasmtime::Instance,
|
||||||
pub export_name: String,
|
pub export_name: String,
|
||||||
pub args_types: Vec<wasmtime::ValType>,
|
pub args_types: Vec<wasmtime::ValType>,
|
||||||
pub data: Rc<ModuleData>,
|
pub data: Rc<ModuleData>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Function {
|
impl Function {
|
||||||
pub fn func(&self) -> wasmtime::HostRef<wasmtime::Func> {
|
pub fn func(&self) -> wasmtime::Func {
|
||||||
let e = self
|
let e = self
|
||||||
.instance
|
.instance
|
||||||
.borrow()
|
|
||||||
.find_export_by_name(&self.export_name)
|
.find_export_by_name(&self.export_name)
|
||||||
.expect("named export")
|
.expect("named export")
|
||||||
.clone();
|
.clone();
|
||||||
@@ -125,10 +124,7 @@ impl wasmtime::Callable for WrappedFn {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn wrap_into_pyfunction(
|
pub fn wrap_into_pyfunction(store: &wasmtime::Store, callable: &PyAny) -> PyResult<wasmtime::Func> {
|
||||||
store: &wasmtime::Store,
|
|
||||||
callable: &PyAny,
|
|
||||||
) -> PyResult<wasmtime::HostRef<wasmtime::Func>> {
|
|
||||||
if !callable.hasattr("__annotations__")? {
|
if !callable.hasattr("__annotations__")? {
|
||||||
// TODO support calls without annotations?
|
// TODO support calls without annotations?
|
||||||
return Err(PyErr::new::<Exception, _>(
|
return Err(PyErr::new::<Exception, _>(
|
||||||
@@ -154,6 +150,5 @@ pub fn wrap_into_pyfunction(
|
|||||||
|
|
||||||
let gil = Python::acquire_gil();
|
let gil = Python::acquire_gil();
|
||||||
let wrapped = WrappedFn::new(callable.to_object(gil.python()), returns);
|
let wrapped = WrappedFn::new(callable.to_object(gil.python()), returns);
|
||||||
let f = wasmtime::Func::new(store, ft, Rc::new(wrapped));
|
Ok(wasmtime::Func::new(store, ft, Rc::new(wrapped)))
|
||||||
Ok(wasmtime::HostRef::new(f))
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ use wasmtime_interface_types::ModuleData;
|
|||||||
|
|
||||||
#[pyclass]
|
#[pyclass]
|
||||||
pub struct Instance {
|
pub struct Instance {
|
||||||
pub instance: wasmtime::HostRef<wasmtime::Instance>,
|
pub instance: wasmtime::Instance,
|
||||||
pub data: Rc<ModuleData>,
|
pub data: Rc<ModuleData>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@ impl Instance {
|
|||||||
let gil = Python::acquire_gil();
|
let gil = Python::acquire_gil();
|
||||||
let py = gil.python();
|
let py = gil.python();
|
||||||
let exports = PyDict::new(py);
|
let exports = PyDict::new(py);
|
||||||
let module = self.instance.borrow().module().clone();
|
let module = self.instance.module().clone();
|
||||||
for (i, e) in module.exports().iter().enumerate() {
|
for (i, e) in module.exports().iter().enumerate() {
|
||||||
match e.ty() {
|
match e.ty() {
|
||||||
wasmtime::ExternType::Func(ft) => {
|
wasmtime::ExternType::Func(ft) => {
|
||||||
@@ -43,10 +43,7 @@ impl Instance {
|
|||||||
let f = Py::new(
|
let f = Py::new(
|
||||||
py,
|
py,
|
||||||
Memory {
|
Memory {
|
||||||
memory: self.instance.borrow().exports()[i]
|
memory: self.instance.exports()[i].memory().unwrap().clone(),
|
||||||
.memory()
|
|
||||||
.unwrap()
|
|
||||||
.clone(),
|
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
exports.set_item(e.name().to_string(), f)?;
|
exports.set_item(e.name().to_string(), f)?;
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
#![allow(improper_ctypes)]
|
|
||||||
|
|
||||||
use crate::function::{wrap_into_pyfunction, Function};
|
use crate::function::{wrap_into_pyfunction, Function};
|
||||||
use crate::instance::Instance;
|
use crate::instance::Instance;
|
||||||
use crate::memory::Memory;
|
use crate::memory::Memory;
|
||||||
@@ -122,10 +120,8 @@ pub fn instantiate(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let instance = wasmtime::HostRef::new(
|
let instance = wasmtime::Instance::new(&module, &imports)
|
||||||
wasmtime::Instance::new(&store, &module, &imports)
|
.map_err(|t| PyErr::new::<Exception, _>(format!("instantiated with trap {:?}", t)))?;
|
||||||
.map_err(|t| PyErr::new::<Exception, _>(format!("instantiated with trap {:?}", t)))?,
|
|
||||||
);
|
|
||||||
|
|
||||||
let module = Py::new(py, Module { module })?;
|
let module = Py::new(py, Module { module })?;
|
||||||
|
|
||||||
|
|||||||
@@ -10,14 +10,14 @@ use std::ptr;
|
|||||||
|
|
||||||
#[pyclass]
|
#[pyclass]
|
||||||
pub struct Memory {
|
pub struct Memory {
|
||||||
pub memory: wasmtime::HostRef<wasmtime::Memory>,
|
pub memory: wasmtime::Memory,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pymethods]
|
#[pymethods]
|
||||||
impl Memory {
|
impl Memory {
|
||||||
#[getter(current)]
|
#[getter(current)]
|
||||||
pub fn current(&self) -> u32 {
|
pub fn current(&self) -> u32 {
|
||||||
self.memory.borrow().size()
|
self.memory.size()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn grow(&self, _number: u32) -> u32 {
|
pub fn grow(&self, _number: u32) -> u32 {
|
||||||
@@ -48,8 +48,8 @@ impl PyBufferProtocol for Memory {
|
|||||||
};
|
};
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let base = self.memory.borrow().data_ptr();
|
let base = self.memory.data_ptr();
|
||||||
let current_length = self.memory.borrow().data_size();
|
let current_length = self.memory.data_size();
|
||||||
|
|
||||||
(*view).buf = base as *mut c_void;
|
(*view).buf = base as *mut c_void;
|
||||||
(*view).len = current_length as isize;
|
(*view).len = current_length as isize;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "wasmtime-rust"
|
name = "wasmtime-rust"
|
||||||
version = "0.7.0"
|
version = "0.9.0"
|
||||||
authors = ["Alex Crichton <alex@alexcrichton.com>"]
|
authors = ["Alex Crichton <alex@alexcrichton.com>"]
|
||||||
description = "Rust extension for Wasmtime"
|
description = "Rust extension for Wasmtime"
|
||||||
license = "Apache-2.0 WITH LLVM-exception"
|
license = "Apache-2.0 WITH LLVM-exception"
|
||||||
@@ -15,10 +15,10 @@ test = false
|
|||||||
doctest = false
|
doctest = false
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
wasmtime-interface-types = { path = "../../interface-types" }
|
wasmtime-interface-types = { path = "../../interface-types", version = "0.9.0" }
|
||||||
wasmtime-rust-macro = { path = "./macro" }
|
wasmtime-rust-macro = { path = "./macro", version = "0.9.0" }
|
||||||
wasmtime-wasi = { path = "../../wasi" }
|
wasmtime-wasi = { path = "../../wasi", version = "0.9.0" }
|
||||||
wasmtime = { path = "../../api" }
|
wasmtime = { path = "../../api", version = "0.9.0" }
|
||||||
anyhow = "1.0.19"
|
anyhow = "1.0.19"
|
||||||
|
|
||||||
[badges]
|
[badges]
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "wasmtime-rust-macro"
|
name = "wasmtime-rust-macro"
|
||||||
version = "0.7.0"
|
version = "0.9.0"
|
||||||
authors = ["Alex Crichton <alex@alexcrichton.com>"]
|
authors = ["Alex Crichton <alex@alexcrichton.com>"]
|
||||||
description = "Macro support crate for wasmtime-rust"
|
description = "Macro support crate for wasmtime-rust"
|
||||||
license = "Apache-2.0 WITH LLVM-exception"
|
license = "Apache-2.0 WITH LLVM-exception"
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ fn generate_struct(item: &syn::ItemTrait) -> syn::Result<TokenStream> {
|
|||||||
let root = root();
|
let root = root();
|
||||||
Ok(quote! {
|
Ok(quote! {
|
||||||
#vis struct #name {
|
#vis struct #name {
|
||||||
instance: #root::wasmtime::HostRef<#root::wasmtime::Instance>,
|
instance: #root::wasmtime::Instance,
|
||||||
data: #root::wasmtime_interface_types::ModuleData,
|
data: #root::wasmtime_interface_types::ModuleData,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -48,7 +48,7 @@ fn generate_load(item: &syn::ItemTrait) -> syn::Result<TokenStream> {
|
|||||||
#vis fn load_file(path: impl AsRef<std::path::Path>) -> #root::anyhow::Result<#name> {
|
#vis fn load_file(path: impl AsRef<std::path::Path>) -> #root::anyhow::Result<#name> {
|
||||||
let bytes = std::fs::read(path)?;
|
let bytes = std::fs::read(path)?;
|
||||||
|
|
||||||
use #root::wasmtime::{HostRef, Config, Extern, Engine, Store, Instance, Module};
|
use #root::wasmtime::{Config, Extern, Engine, Store, Instance, Module};
|
||||||
use #root::anyhow::{bail, format_err};
|
use #root::anyhow::{bail, format_err};
|
||||||
|
|
||||||
let engine = Engine::new(Config::new().wasm_multi_value(true));
|
let engine = Engine::new(Config::new().wasm_multi_value(true));
|
||||||
@@ -74,9 +74,8 @@ fn generate_load(item: &syn::ItemTrait) -> syn::Result<TokenStream> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let instance = HostRef::new(
|
let instance =
|
||||||
Instance::new(&store, &module, &imports).map_err(|t| format_err!("instantiation trap: {:?}", t))?
|
Instance::new(&module, &imports).map_err(|t| format_err!("instantiation trap: {:?}", t))?;
|
||||||
);
|
|
||||||
|
|
||||||
Ok(#name { instance, data })
|
Ok(#name { instance, data })
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "wasmtime-obj"
|
name = "wasmtime-obj"
|
||||||
version = "0.7.0"
|
version = "0.9.0"
|
||||||
authors = ["The Wasmtime Project Developers"]
|
authors = ["The Wasmtime Project Developers"]
|
||||||
description = "Native object file output for WebAsssembly code in Wasmtime"
|
description = "Native object file output for WebAsssembly code in Wasmtime"
|
||||||
license = "Apache-2.0 WITH LLVM-exception"
|
license = "Apache-2.0 WITH LLVM-exception"
|
||||||
@@ -12,8 +12,8 @@ edition = "2018"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
wasmtime-environ = { path = "../environ" }
|
wasmtime-environ = { path = "../environ", version = "0.9.0" }
|
||||||
faerie = "0.13.0"
|
faerie = "0.14.0"
|
||||||
more-asserts = "0.2.1"
|
more-asserts = "0.2.1"
|
||||||
|
|
||||||
[badges]
|
[badges]
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "wasmtime-runtime"
|
name = "wasmtime-runtime"
|
||||||
version = "0.7.0"
|
version = "0.9.0"
|
||||||
authors = ["The Wasmtime Project Developers"]
|
authors = ["The Wasmtime Project Developers"]
|
||||||
description = "Runtime library support for Wasmtime"
|
description = "Runtime library support for Wasmtime"
|
||||||
license = "Apache-2.0 WITH LLVM-exception"
|
license = "Apache-2.0 WITH LLVM-exception"
|
||||||
@@ -11,7 +11,7 @@ readme = "README.md"
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
wasmtime-environ = { path = "../environ" }
|
wasmtime-environ = { path = "../environ", version = "0.9.0" }
|
||||||
region = "2.0.0"
|
region = "2.0.0"
|
||||||
lazy_static = "1.2.0"
|
lazy_static = "1.2.0"
|
||||||
libc = { version = "0.2.60", default-features = false }
|
libc = { version = "0.2.60", default-features = false }
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
//! Runtime library support for Wasmtime.
|
//! Runtime library support for Wasmtime.
|
||||||
|
|
||||||
#![allow(improper_ctypes)]
|
|
||||||
#![deny(missing_docs, trivial_numeric_casts, unused_extern_crates)]
|
#![deny(missing_docs, trivial_numeric_casts, unused_extern_crates)]
|
||||||
#![warn(unused_import_braces)]
|
#![warn(unused_import_braces)]
|
||||||
#![cfg_attr(feature = "clippy", plugin(clippy(conf_file = "../../clippy.toml")))]
|
#![cfg_attr(feature = "clippy", plugin(clippy(conf_file = "../../clippy.toml")))]
|
||||||
|
|||||||
@@ -1,11 +1,8 @@
|
|||||||
//! Low-level abstraction for allocating and managing zero-filled pages
|
//! Low-level abstraction for allocating and managing zero-filled pages
|
||||||
//! of memory.
|
//! of memory.
|
||||||
|
|
||||||
#[cfg(not(target_os = "windows"))]
|
|
||||||
use libc;
|
|
||||||
use more_asserts::assert_le;
|
use more_asserts::assert_le;
|
||||||
use more_asserts::assert_lt;
|
use more_asserts::assert_lt;
|
||||||
use region;
|
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::slice;
|
use std::slice;
|
||||||
@@ -19,7 +16,11 @@ fn round_up_to_page_size(size: usize, page_size: usize) -> usize {
|
|||||||
/// and initially-zeroed memory and a length.
|
/// and initially-zeroed memory and a length.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Mmap {
|
pub struct Mmap {
|
||||||
ptr: *mut u8,
|
// Note that this is stored as a `usize` instead of a `*const` or `*mut`
|
||||||
|
// pointer to allow this structure to be natively `Send` and `Sync` without
|
||||||
|
// `unsafe impl`. This type is sendable across threads and shareable since
|
||||||
|
// the coordination all happens at the OS layer.
|
||||||
|
ptr: usize,
|
||||||
len: usize,
|
len: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,8 +30,9 @@ impl Mmap {
|
|||||||
// Rust's slices require non-null pointers, even when empty. `Vec`
|
// Rust's slices require non-null pointers, even when empty. `Vec`
|
||||||
// contains code to create a non-null dangling pointer value when
|
// contains code to create a non-null dangling pointer value when
|
||||||
// constructed empty, so we reuse that here.
|
// constructed empty, so we reuse that here.
|
||||||
|
let empty = Vec::<u8>::new();
|
||||||
Self {
|
Self {
|
||||||
ptr: Vec::new().as_mut_ptr(),
|
ptr: empty.as_ptr() as usize,
|
||||||
len: 0,
|
len: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -78,7 +80,7 @@ impl Mmap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
ptr: ptr as *mut u8,
|
ptr: ptr as usize,
|
||||||
len: mapping_size,
|
len: mapping_size,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -98,7 +100,7 @@ impl Mmap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut result = Self {
|
let mut result = Self {
|
||||||
ptr: ptr as *mut u8,
|
ptr: ptr as usize,
|
||||||
len: mapping_size,
|
len: mapping_size,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -142,7 +144,7 @@ impl Mmap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
ptr: ptr as *mut u8,
|
ptr: ptr as usize,
|
||||||
len: mapping_size,
|
len: mapping_size,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -154,7 +156,7 @@ impl Mmap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut result = Self {
|
let mut result = Self {
|
||||||
ptr: ptr as *mut u8,
|
ptr: ptr as usize,
|
||||||
len: mapping_size,
|
len: mapping_size,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -179,7 +181,8 @@ impl Mmap {
|
|||||||
assert_lt!(start, self.len - len);
|
assert_lt!(start, self.len - len);
|
||||||
|
|
||||||
// Commit the accessible size.
|
// Commit the accessible size.
|
||||||
unsafe { region::protect(self.ptr.add(start), len, region::Protection::ReadWrite) }
|
let ptr = self.ptr as *const u8;
|
||||||
|
unsafe { region::protect(ptr.add(start), len, region::Protection::ReadWrite) }
|
||||||
.map_err(|e| e.to_string())
|
.map_err(|e| e.to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -198,9 +201,10 @@ impl Mmap {
|
|||||||
assert_lt!(start, self.len - len);
|
assert_lt!(start, self.len - len);
|
||||||
|
|
||||||
// Commit the accessible size.
|
// Commit the accessible size.
|
||||||
|
let ptr = self.ptr as *const u8;
|
||||||
if unsafe {
|
if unsafe {
|
||||||
VirtualAlloc(
|
VirtualAlloc(
|
||||||
self.ptr.add(start) as *mut c_void,
|
ptr.add(start) as *mut c_void,
|
||||||
len,
|
len,
|
||||||
MEM_COMMIT,
|
MEM_COMMIT,
|
||||||
PAGE_READWRITE,
|
PAGE_READWRITE,
|
||||||
@@ -216,22 +220,22 @@ impl Mmap {
|
|||||||
|
|
||||||
/// Return the allocated memory as a slice of u8.
|
/// Return the allocated memory as a slice of u8.
|
||||||
pub fn as_slice(&self) -> &[u8] {
|
pub fn as_slice(&self) -> &[u8] {
|
||||||
unsafe { slice::from_raw_parts(self.ptr, self.len) }
|
unsafe { slice::from_raw_parts(self.ptr as *const u8, self.len) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the allocated memory as a mutable slice of u8.
|
/// Return the allocated memory as a mutable slice of u8.
|
||||||
pub fn as_mut_slice(&mut self) -> &mut [u8] {
|
pub fn as_mut_slice(&mut self) -> &mut [u8] {
|
||||||
unsafe { slice::from_raw_parts_mut(self.ptr, self.len) }
|
unsafe { slice::from_raw_parts_mut(self.ptr as *mut u8, self.len) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the allocated memory as a pointer to u8.
|
/// Return the allocated memory as a pointer to u8.
|
||||||
pub fn as_ptr(&self) -> *const u8 {
|
pub fn as_ptr(&self) -> *const u8 {
|
||||||
self.ptr
|
self.ptr as *const u8
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the allocated memory as a mutable pointer to u8.
|
/// Return the allocated memory as a mutable pointer to u8.
|
||||||
pub fn as_mut_ptr(&mut self) -> *mut u8 {
|
pub fn as_mut_ptr(&mut self) -> *mut u8 {
|
||||||
self.ptr
|
self.ptr as *mut u8
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the length of the allocated memory.
|
/// Return the length of the allocated memory.
|
||||||
@@ -266,6 +270,11 @@ impl Drop for Mmap {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn _assert() {
|
||||||
|
fn _assert_send_sync<T: Send + Sync>() {}
|
||||||
|
_assert_send_sync::<Mmap>();
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "test-programs"
|
name = "test-programs"
|
||||||
version = "0.7.0"
|
version = "0.9.0"
|
||||||
authors = ["The Wasmtime Project Developers"]
|
authors = ["The Wasmtime Project Developers"]
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
@@ -10,13 +10,13 @@ publish = false
|
|||||||
cfg-if = "0.1.9"
|
cfg-if = "0.1.9"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
wasi-common = { path = "../wasi-common" }
|
wasi-common = { path = "../wasi-common", version = "0.9.0" }
|
||||||
wasmtime-runtime = { path = "../runtime" }
|
wasmtime-runtime = { path = "../runtime", version = "0.9.0" }
|
||||||
wasmtime-environ = { path = "../environ" }
|
wasmtime-environ = { path = "../environ", version = "0.9.0" }
|
||||||
wasmtime-jit = { path = "../jit" }
|
wasmtime-jit = { path = "../jit", version = "0.9.0" }
|
||||||
wasmtime-wasi = { path = "../wasi" }
|
wasmtime-wasi = { path = "../wasi", version = "0.9.0" }
|
||||||
wasmtime = { path = "../api" }
|
wasmtime = { path = "../api", version = "0.9.0" }
|
||||||
target-lexicon = "0.9.0"
|
target-lexicon = "0.10.0"
|
||||||
pretty_env_logger = "0.3.0"
|
pretty_env_logger = "0.3.0"
|
||||||
tempfile = "3.1.0"
|
tempfile = "3.1.0"
|
||||||
os_pipe = "0.9"
|
os_pipe = "0.9"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use anyhow::{bail, Context};
|
use anyhow::{bail, Context};
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use wasmtime::{HostRef, Instance, Module, Store};
|
use wasmtime::{Instance, Module, Store};
|
||||||
|
|
||||||
pub fn instantiate(data: &[u8], bin_name: &str, workspace: Option<&Path>) -> anyhow::Result<()> {
|
pub fn instantiate(data: &[u8], bin_name: &str, workspace: Option<&Path>) -> anyhow::Result<()> {
|
||||||
let store = Store::default();
|
let store = Store::default();
|
||||||
@@ -61,13 +61,12 @@ pub fn instantiate(data: &[u8], bin_name: &str, workspace: Option<&Path>) -> any
|
|||||||
})
|
})
|
||||||
.collect::<Result<Vec<_>, _>>()?;
|
.collect::<Result<Vec<_>, _>>()?;
|
||||||
|
|
||||||
let instance = HostRef::new(Instance::new(&store, &module, &imports).context(format!(
|
let instance = Instance::new(&module, &imports).context(format!(
|
||||||
"error while instantiating Wasm module '{}'",
|
"error while instantiating Wasm module '{}'",
|
||||||
bin_name,
|
bin_name,
|
||||||
))?);
|
))?;
|
||||||
|
|
||||||
let export = instance
|
let export = instance
|
||||||
.borrow()
|
|
||||||
.find_export_by_name("_start")
|
.find_export_by_name("_start")
|
||||||
.context("expected a _start export")?
|
.context("expected a _start export")?
|
||||||
.clone();
|
.clone();
|
||||||
@@ -75,7 +74,6 @@ pub fn instantiate(data: &[u8], bin_name: &str, workspace: Option<&Path>) -> any
|
|||||||
if let Err(trap) = export
|
if let Err(trap) = export
|
||||||
.func()
|
.func()
|
||||||
.context("expected export to be a func")?
|
.context("expected export to be a func")?
|
||||||
.borrow()
|
|
||||||
.call(&[])
|
.call(&[])
|
||||||
{
|
{
|
||||||
bail!("trapped: {:?}", trap);
|
bail!("trapped: {:?}", trap);
|
||||||
|
|||||||
30
crates/test-programs/wasi-tests/Cargo.lock
generated
Normal file
30
crates/test-programs/wasi-tests/Cargo.lock
generated
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.66"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "more-asserts"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasi"
|
||||||
|
version = "0.9.0+wasi-snapshot-preview1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasi-tests"
|
||||||
|
version = "0.9.0"
|
||||||
|
dependencies = [
|
||||||
|
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"more-asserts 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"wasi 0.9.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[metadata]
|
||||||
|
"checksum libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)" = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558"
|
||||||
|
"checksum more-asserts 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0debeb9fcf88823ea64d64e4a815ab1643f33127d995978e099942ce38f25238"
|
||||||
|
"checksum wasi 0.9.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)" = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "wasi-tests"
|
name = "wasi-tests"
|
||||||
version = "0.7.0"
|
version = "0.9.0"
|
||||||
authors = ["The Wasmtime Project Developers"]
|
authors = ["The Wasmtime Project Developers"]
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|||||||
@@ -9,7 +9,11 @@ unsafe fn test_fd_advise(dir_fd: wasi::Fd) {
|
|||||||
0,
|
0,
|
||||||
"file",
|
"file",
|
||||||
wasi::OFLAGS_CREAT,
|
wasi::OFLAGS_CREAT,
|
||||||
wasi::RIGHTS_FD_READ | wasi::RIGHTS_FD_WRITE,
|
wasi::RIGHTS_FD_READ
|
||||||
|
| wasi::RIGHTS_FD_WRITE
|
||||||
|
| wasi::RIGHTS_FD_ADVISE
|
||||||
|
| wasi::RIGHTS_FD_FILESTAT_GET
|
||||||
|
| wasi::RIGHTS_FD_ALLOCATE,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -9,7 +9,11 @@ unsafe fn test_fd_filestat_set(dir_fd: wasi::Fd) {
|
|||||||
0,
|
0,
|
||||||
"file",
|
"file",
|
||||||
wasi::OFLAGS_CREAT,
|
wasi::OFLAGS_CREAT,
|
||||||
wasi::RIGHTS_FD_READ | wasi::RIGHTS_FD_WRITE,
|
wasi::RIGHTS_FD_READ
|
||||||
|
| wasi::RIGHTS_FD_WRITE
|
||||||
|
| wasi::RIGHTS_FD_FILESTAT_GET
|
||||||
|
| wasi::RIGHTS_FD_FILESTAT_SET_SIZE
|
||||||
|
| wasi::RIGHTS_FD_FILESTAT_SET_TIMES,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
)
|
)
|
||||||
|
|||||||
165
crates/test-programs/wasi-tests/src/bin/fd_flags_set.rs
Normal file
165
crates/test-programs/wasi-tests/src/bin/fd_flags_set.rs
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
use std::{env, process};
|
||||||
|
use wasi;
|
||||||
|
use wasi_tests::open_scratch_directory;
|
||||||
|
|
||||||
|
unsafe fn test_fd_fdstat_set_flags(dir_fd: wasi::Fd) {
|
||||||
|
const FILE_NAME: &str = "file";
|
||||||
|
let data = &[0u8; 100];
|
||||||
|
|
||||||
|
let file_fd = wasi::path_open(
|
||||||
|
dir_fd,
|
||||||
|
0,
|
||||||
|
FILE_NAME,
|
||||||
|
wasi::OFLAGS_CREAT,
|
||||||
|
wasi::RIGHTS_FD_READ
|
||||||
|
| wasi::RIGHTS_FD_WRITE
|
||||||
|
| wasi::RIGHTS_FD_SEEK
|
||||||
|
| wasi::RIGHTS_FD_TELL
|
||||||
|
| wasi::RIGHTS_FD_FDSTAT_SET_FLAGS,
|
||||||
|
0,
|
||||||
|
wasi::FDFLAGS_APPEND,
|
||||||
|
)
|
||||||
|
.expect("opening a file");
|
||||||
|
|
||||||
|
// Write some data and then verify the written data
|
||||||
|
assert_eq!(
|
||||||
|
wasi::fd_write(
|
||||||
|
file_fd,
|
||||||
|
&[wasi::Ciovec {
|
||||||
|
buf: data.as_ptr(),
|
||||||
|
buf_len: data.len(),
|
||||||
|
}],
|
||||||
|
)
|
||||||
|
.expect("writing to a file"),
|
||||||
|
data.len(),
|
||||||
|
"should write {} bytes",
|
||||||
|
data.len(),
|
||||||
|
);
|
||||||
|
|
||||||
|
wasi::fd_seek(file_fd, 0, wasi::WHENCE_SET).expect("seeking file");
|
||||||
|
|
||||||
|
let buffer = &mut [0u8; 100];
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
wasi::fd_read(
|
||||||
|
file_fd,
|
||||||
|
&[wasi::Iovec {
|
||||||
|
buf: buffer.as_mut_ptr(),
|
||||||
|
buf_len: buffer.len(),
|
||||||
|
}]
|
||||||
|
)
|
||||||
|
.expect("reading file"),
|
||||||
|
buffer.len(),
|
||||||
|
"shoudl read {} bytes",
|
||||||
|
buffer.len()
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(&data[..], &buffer[..]);
|
||||||
|
|
||||||
|
let data = &[1u8; 100];
|
||||||
|
|
||||||
|
// Seek back to the start to ensure we're in append-only mode
|
||||||
|
wasi::fd_seek(file_fd, 0, wasi::WHENCE_SET).expect("seeking file");
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
wasi::fd_write(
|
||||||
|
file_fd,
|
||||||
|
&[wasi::Ciovec {
|
||||||
|
buf: data.as_ptr(),
|
||||||
|
buf_len: data.len(),
|
||||||
|
}],
|
||||||
|
)
|
||||||
|
.expect("writing to a file"),
|
||||||
|
data.len(),
|
||||||
|
"should write {} bytes",
|
||||||
|
data.len(),
|
||||||
|
);
|
||||||
|
|
||||||
|
wasi::fd_seek(file_fd, 100, wasi::WHENCE_SET).expect("seeking file");
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
wasi::fd_read(
|
||||||
|
file_fd,
|
||||||
|
&[wasi::Iovec {
|
||||||
|
buf: buffer.as_mut_ptr(),
|
||||||
|
buf_len: buffer.len(),
|
||||||
|
}]
|
||||||
|
)
|
||||||
|
.expect("reading file"),
|
||||||
|
buffer.len(),
|
||||||
|
"shoudl read {} bytes",
|
||||||
|
buffer.len()
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(&data[..], &buffer[..]);
|
||||||
|
|
||||||
|
wasi::fd_fdstat_set_flags(file_fd, 0).expect("disabling flags");
|
||||||
|
|
||||||
|
// Overwrite some existing data to ensure the append mode is now off
|
||||||
|
wasi::fd_seek(file_fd, 0, wasi::WHENCE_SET).expect("seeking file");
|
||||||
|
|
||||||
|
let data = &[2u8; 100];
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
wasi::fd_write(
|
||||||
|
file_fd,
|
||||||
|
&[wasi::Ciovec {
|
||||||
|
buf: data.as_ptr(),
|
||||||
|
buf_len: data.len(),
|
||||||
|
}],
|
||||||
|
)
|
||||||
|
.expect("writing to a file"),
|
||||||
|
data.len(),
|
||||||
|
"should write {} bytes",
|
||||||
|
data.len(),
|
||||||
|
);
|
||||||
|
|
||||||
|
wasi::fd_seek(file_fd, 0, wasi::WHENCE_SET).expect("seeking file");
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
wasi::fd_read(
|
||||||
|
file_fd,
|
||||||
|
&[wasi::Iovec {
|
||||||
|
buf: buffer.as_mut_ptr(),
|
||||||
|
buf_len: buffer.len(),
|
||||||
|
}]
|
||||||
|
)
|
||||||
|
.expect("reading file"),
|
||||||
|
buffer.len(),
|
||||||
|
"shoudl read {} bytes",
|
||||||
|
buffer.len()
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(&data[..], &buffer[..]);
|
||||||
|
|
||||||
|
wasi::fd_close(file_fd).expect("close file");
|
||||||
|
|
||||||
|
let stat = wasi::path_filestat_get(dir_fd, 0, FILE_NAME).expect("stat path");
|
||||||
|
|
||||||
|
assert_eq!(stat.size, 200, "expected a file size of 200");
|
||||||
|
|
||||||
|
wasi::path_unlink_file(dir_fd, FILE_NAME).expect("unlinking file");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let mut args = env::args();
|
||||||
|
let prog = args.next().unwrap();
|
||||||
|
let arg = if let Some(arg) = args.next() {
|
||||||
|
arg
|
||||||
|
} else {
|
||||||
|
eprintln!("usage: {} <scratch directory>", prog);
|
||||||
|
process::exit(1);
|
||||||
|
};
|
||||||
|
|
||||||
|
let dir_fd = match open_scratch_directory(&arg) {
|
||||||
|
Ok(dir_fd) => dir_fd,
|
||||||
|
Err(err) => {
|
||||||
|
eprintln!("{}", err);
|
||||||
|
process::exit(1)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
test_fd_fdstat_set_flags(dir_fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -90,7 +90,10 @@ unsafe fn test_fd_readdir(dir_fd: wasi::Fd) {
|
|||||||
0,
|
0,
|
||||||
"file",
|
"file",
|
||||||
wasi::OFLAGS_CREAT,
|
wasi::OFLAGS_CREAT,
|
||||||
wasi::RIGHTS_FD_READ | wasi::RIGHTS_FD_WRITE,
|
wasi::RIGHTS_FD_READ
|
||||||
|
| wasi::RIGHTS_FD_WRITE
|
||||||
|
| wasi::RIGHTS_FD_READDIR
|
||||||
|
| wasi::RIGHTS_FD_FILESTAT_GET,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -9,7 +9,10 @@ unsafe fn test_file_allocate(dir_fd: wasi::Fd) {
|
|||||||
0,
|
0,
|
||||||
"file",
|
"file",
|
||||||
wasi::OFLAGS_CREAT,
|
wasi::OFLAGS_CREAT,
|
||||||
wasi::RIGHTS_FD_READ | wasi::RIGHTS_FD_WRITE,
|
wasi::RIGHTS_FD_READ
|
||||||
|
| wasi::RIGHTS_FD_WRITE
|
||||||
|
| wasi::RIGHTS_FD_ALLOCATE
|
||||||
|
| wasi::RIGHTS_FD_FILESTAT_GET,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ unsafe fn test_file_seek_tell(dir_fd: wasi::Fd) {
|
|||||||
0,
|
0,
|
||||||
"file",
|
"file",
|
||||||
wasi::OFLAGS_CREAT,
|
wasi::OFLAGS_CREAT,
|
||||||
wasi::RIGHTS_FD_READ | wasi::RIGHTS_FD_WRITE,
|
wasi::RIGHTS_FD_READ | wasi::RIGHTS_FD_WRITE | wasi::RIGHTS_FD_SEEK | wasi::RIGHTS_FD_TELL,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -2,8 +2,15 @@ use more_asserts::assert_gt;
|
|||||||
use std::{env, process};
|
use std::{env, process};
|
||||||
use wasi_tests::{create_file, open_scratch_directory};
|
use wasi_tests::{create_file, open_scratch_directory};
|
||||||
|
|
||||||
|
const TEST_RIGHTS: wasi::Rights = wasi::RIGHTS_FD_READ
|
||||||
|
| wasi::RIGHTS_PATH_LINK_SOURCE
|
||||||
|
| wasi::RIGHTS_PATH_LINK_TARGET
|
||||||
|
| wasi::RIGHTS_FD_FILESTAT_GET
|
||||||
|
| wasi::RIGHTS_PATH_OPEN
|
||||||
|
| wasi::RIGHTS_PATH_UNLINK_FILE;
|
||||||
|
|
||||||
unsafe fn create_or_open(dir_fd: wasi::Fd, name: &str, flags: wasi::Oflags) -> wasi::Fd {
|
unsafe fn create_or_open(dir_fd: wasi::Fd, name: &str, flags: wasi::Oflags) -> wasi::Fd {
|
||||||
let file_fd = wasi::path_open(dir_fd, 0, name, flags, 0, 0, 0)
|
let file_fd = wasi::path_open(dir_fd, 0, name, flags, TEST_RIGHTS, TEST_RIGHTS, 0)
|
||||||
.unwrap_or_else(|_| panic!("opening '{}'", name));
|
.unwrap_or_else(|_| panic!("opening '{}'", name));
|
||||||
assert_gt!(
|
assert_gt!(
|
||||||
file_fd,
|
file_fd,
|
||||||
@@ -14,7 +21,7 @@ unsafe fn create_or_open(dir_fd: wasi::Fd, name: &str, flags: wasi::Oflags) -> w
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn open_link(dir_fd: wasi::Fd, name: &str) -> wasi::Fd {
|
unsafe fn open_link(dir_fd: wasi::Fd, name: &str) -> wasi::Fd {
|
||||||
let file_fd = wasi::path_open(dir_fd, 0, name, 0, 0, 0, 0)
|
let file_fd = wasi::path_open(dir_fd, 0, name, 0, TEST_RIGHTS, TEST_RIGHTS, 0)
|
||||||
.unwrap_or_else(|_| panic!("opening a link '{}'", name));
|
.unwrap_or_else(|_| panic!("opening a link '{}'", name));
|
||||||
assert_gt!(
|
assert_gt!(
|
||||||
file_fd,
|
file_fd,
|
||||||
|
|||||||
@@ -0,0 +1,79 @@
|
|||||||
|
use std::{env, process};
|
||||||
|
use wasi_tests::open_scratch_directory;
|
||||||
|
use wasi_tests::{create_file, drop_rights, fd_get_rights};
|
||||||
|
|
||||||
|
const TEST_FILENAME: &'static str = "file";
|
||||||
|
|
||||||
|
unsafe fn try_read_file(dir_fd: wasi::Fd) {
|
||||||
|
let fd = wasi::path_open(dir_fd, 0, TEST_FILENAME, 0, 0, 0, 0).expect("opening the file");
|
||||||
|
|
||||||
|
// Check that we don't have the right to exeucute fd_read
|
||||||
|
let (rbase, rinher) = fd_get_rights(fd);
|
||||||
|
assert_eq!(
|
||||||
|
rbase & wasi::RIGHTS_FD_READ,
|
||||||
|
0,
|
||||||
|
"should not have base RIGHTS_FD_READ"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
rinher & wasi::RIGHTS_FD_READ,
|
||||||
|
0,
|
||||||
|
"should not have inheriting RIGHTS_FD_READ"
|
||||||
|
);
|
||||||
|
|
||||||
|
let contents = &mut [0u8; 1];
|
||||||
|
let iovec = wasi::Iovec {
|
||||||
|
buf: contents.as_mut_ptr() as *mut _,
|
||||||
|
buf_len: contents.len(),
|
||||||
|
};
|
||||||
|
// Since we no longer have the right to fd_read, trying to read a file
|
||||||
|
// should be an error.
|
||||||
|
assert_eq!(
|
||||||
|
wasi::fd_read(fd, &[iovec])
|
||||||
|
.expect_err("reading bytes from file should fail")
|
||||||
|
.raw_error(),
|
||||||
|
wasi::ERRNO_NOTCAPABLE,
|
||||||
|
"the errno should be ENOTCAPABLE"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn test_read_rights(dir_fd: wasi::Fd) {
|
||||||
|
create_file(dir_fd, TEST_FILENAME);
|
||||||
|
drop_rights(dir_fd, wasi::RIGHTS_FD_READ, wasi::RIGHTS_FD_READ);
|
||||||
|
|
||||||
|
let (rbase, rinher) = fd_get_rights(dir_fd);
|
||||||
|
assert_eq!(
|
||||||
|
rbase & wasi::RIGHTS_FD_READ,
|
||||||
|
0,
|
||||||
|
"dir should not have base RIGHTS_FD_READ"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
rinher & wasi::RIGHTS_FD_READ,
|
||||||
|
0,
|
||||||
|
"dir should not have inheriting RIGHTS_FD_READ"
|
||||||
|
);
|
||||||
|
|
||||||
|
try_read_file(dir_fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let mut args = env::args();
|
||||||
|
let prog = args.next().unwrap();
|
||||||
|
let arg = if let Some(arg) = args.next() {
|
||||||
|
arg
|
||||||
|
} else {
|
||||||
|
eprintln!("usage: {} <scratch directory>", prog);
|
||||||
|
process::exit(1);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Open scratch directory
|
||||||
|
let dir_fd = match open_scratch_directory(&arg) {
|
||||||
|
Ok(dir_fd) => dir_fd,
|
||||||
|
Err(err) => {
|
||||||
|
eprintln!("{}", err);
|
||||||
|
process::exit(1)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Run the tests.
|
||||||
|
unsafe { test_read_rights(dir_fd) }
|
||||||
|
}
|
||||||
@@ -198,7 +198,7 @@ unsafe fn test_fd_readwrite_valid_fd(dir_fd: wasi::Fd) {
|
|||||||
0,
|
0,
|
||||||
"file",
|
"file",
|
||||||
wasi::OFLAGS_CREAT,
|
wasi::OFLAGS_CREAT,
|
||||||
wasi::RIGHTS_FD_READ | wasi::RIGHTS_FD_WRITE,
|
wasi::RIGHTS_FD_READ | wasi::RIGHTS_FD_WRITE | wasi::RIGHTS_POLL_FD_READWRITE,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -24,8 +24,11 @@ pub fn open_scratch_directory(path: &str) -> Result<wasi::Fd, String> {
|
|||||||
}
|
}
|
||||||
dst.set_len(stat.u.dir.pr_name_len);
|
dst.set_len(stat.u.dir.pr_name_len);
|
||||||
if dst == path.as_bytes() {
|
if dst == path.as_bytes() {
|
||||||
return Ok(wasi::path_open(i, 0, ".", wasi::OFLAGS_DIRECTORY, 0, 0, 0)
|
let (base, inherit) = fd_get_rights(i);
|
||||||
.expect("failed to open dir"));
|
return Ok(
|
||||||
|
wasi::path_open(i, 0, ".", wasi::OFLAGS_DIRECTORY, base, inherit, 0)
|
||||||
|
.expect("failed to open dir"),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,3 +46,18 @@ pub unsafe fn create_file(dir_fd: wasi::Fd, filename: &str) {
|
|||||||
);
|
);
|
||||||
wasi::fd_close(file_fd).expect("closing a file");
|
wasi::fd_close(file_fd).expect("closing a file");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns: (rights_base, rights_inheriting)
|
||||||
|
pub unsafe fn fd_get_rights(fd: wasi::Fd) -> (wasi::Rights, wasi::Rights) {
|
||||||
|
let fdstat = wasi::fd_fdstat_get(fd).expect("fd_fdstat_get failed");
|
||||||
|
(fdstat.fs_rights_base, fdstat.fs_rights_inheriting)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn drop_rights(fd: wasi::Fd, drop_base: wasi::Rights, drop_inheriting: wasi::Rights) {
|
||||||
|
let (current_base, current_inheriting) = fd_get_rights(fd);
|
||||||
|
|
||||||
|
let new_base = current_base & !drop_base;
|
||||||
|
let new_inheriting = current_inheriting & !drop_inheriting;
|
||||||
|
|
||||||
|
wasi::fd_fdstat_set_rights(fd, new_base, new_inheriting).expect("dropping fd rights");
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "wasmtime-wasi-c"
|
name = "wasmtime-wasi-c"
|
||||||
version = "0.7.0"
|
version = "0.9.0"
|
||||||
authors = ["The Cranelift Project Developers"]
|
authors = ["The Cranelift Project Developers"]
|
||||||
description = "WASI API support for Wasmtime"
|
description = "WASI API support for Wasmtime"
|
||||||
license = "Apache-2.0 WITH LLVM-exception"
|
license = "Apache-2.0 WITH LLVM-exception"
|
||||||
@@ -11,20 +11,20 @@ readme = "README.md"
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
wasmtime-runtime = { path = "../runtime" }
|
wasmtime-runtime = { path = "../runtime", version = "0.9.0" }
|
||||||
wasmtime-environ = { path = "../environ" }
|
wasmtime-environ = { path = "../environ", version = "0.9.0" }
|
||||||
wasmtime-jit = { path = "../jit" }
|
wasmtime-jit = { path = "../jit", version = "0.9.0" }
|
||||||
cranelift-codegen = { version = "0.52.0", features = ["enable-serde"] }
|
cranelift-codegen = { version = "0.54", features = ["enable-serde"] }
|
||||||
cranelift-entity = { version = "0.52.0", features = ["enable-serde"] }
|
cranelift-entity = { version = "0.54", features = ["enable-serde"] }
|
||||||
cranelift-wasm = { version = "0.52.0", features = ["enable-serde"] }
|
cranelift-wasm = { version = "0.54", features = ["enable-serde"] }
|
||||||
target-lexicon = "0.9.0"
|
target-lexicon = "0.10.0"
|
||||||
log = { version = "0.4.8", default-features = false }
|
log = { version = "0.4.8", default-features = false }
|
||||||
libc = "0.2.60"
|
libc = "0.2.60"
|
||||||
more-asserts = "0.2.1"
|
more-asserts = "0.2.1"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
cmake = "0.1.35"
|
cmake = "0.1.35"
|
||||||
bindgen = "0.51.0"
|
bindgen = "0.52.0"
|
||||||
|
|
||||||
[badges]
|
[badges]
|
||||||
maintenance = { status = "actively-developed" }
|
maintenance = { status = "actively-developed" }
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "wasi-common"
|
name = "wasi-common"
|
||||||
version = "0.7.0"
|
version = "0.9.0"
|
||||||
authors = ["The Wasmtime Project Developers"]
|
authors = ["The Wasmtime Project Developers"]
|
||||||
description = "WASI implementation in Rust"
|
description = "WASI implementation in Rust"
|
||||||
license = "Apache-2.0 WITH LLVM-exception"
|
license = "Apache-2.0 WITH LLVM-exception"
|
||||||
@@ -11,7 +11,7 @@ readme = "README.md"
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
wasi-common-cbindgen = { path = "wasi-common-cbindgen" }
|
wasi-common-cbindgen = { path = "wasi-common-cbindgen", version = "0.9.0" }
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
@@ -21,14 +21,14 @@ log = "0.4"
|
|||||||
filetime = "0.2.7"
|
filetime = "0.2.7"
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
num = { version = "0.2.0", default-features = false }
|
num = { version = "0.2.0", default-features = false }
|
||||||
wig = { path = "wig" }
|
|
||||||
crossbeam = "0.7.3"
|
crossbeam = "0.7.3"
|
||||||
|
wig = { path = "wig", version = "0.9.2" }
|
||||||
|
|
||||||
[target.'cfg(unix)'.dependencies]
|
[target.'cfg(unix)'.dependencies]
|
||||||
yanix = { path = "yanix" }
|
yanix = { path = "yanix", version = "0.9.0" }
|
||||||
|
|
||||||
[target.'cfg(windows)'.dependencies]
|
[target.'cfg(windows)'.dependencies]
|
||||||
winx = { path = "winx" }
|
winx = { path = "winx", version = "0.9.0" }
|
||||||
winapi = "0.3"
|
winapi = "0.3"
|
||||||
cpu-time = "1.0"
|
cpu-time = "1.0"
|
||||||
|
|
||||||
|
|||||||
Submodule crates/wasi-common/WASI deleted from 9150e66a34
@@ -155,8 +155,21 @@ impl FdEntry {
|
|||||||
rights_base: wasi::__wasi_rights_t,
|
rights_base: wasi::__wasi_rights_t,
|
||||||
rights_inheriting: wasi::__wasi_rights_t,
|
rights_inheriting: wasi::__wasi_rights_t,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
if !self.rights_base & rights_base != 0 || !self.rights_inheriting & rights_inheriting != 0
|
let missing_base = !self.rights_base & rights_base;
|
||||||
{
|
let missing_inheriting = !self.rights_inheriting & rights_inheriting;
|
||||||
|
if missing_base != 0 || missing_inheriting != 0 {
|
||||||
|
log::trace!(
|
||||||
|
" | validate_rights failed: required: \
|
||||||
|
rights_base = {:#x}, rights_inheriting = {:#x}; \
|
||||||
|
actual: rights_base = {:#x}, rights_inheriting = {:#x}; \
|
||||||
|
missing_base = {:#x}, missing_inheriting = {:#x}",
|
||||||
|
rights_base,
|
||||||
|
rights_inheriting,
|
||||||
|
self.rights_base,
|
||||||
|
self.rights_inheriting,
|
||||||
|
missing_base,
|
||||||
|
missing_inheriting
|
||||||
|
);
|
||||||
Err(Error::ENOTCAPABLE)
|
Err(Error::ENOTCAPABLE)
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ hostcalls! {
|
|||||||
) -> wasi::__wasi_errno_t;
|
) -> wasi::__wasi_errno_t;
|
||||||
|
|
||||||
pub unsafe fn fd_fdstat_set_flags(
|
pub unsafe fn fd_fdstat_set_flags(
|
||||||
wasi_ctx: &WasiCtx,
|
wasi_ctx: &mut WasiCtx,
|
||||||
memory: &mut [u8],
|
memory: &mut [u8],
|
||||||
fd: wasi::__wasi_fd_t,
|
fd: wasi::__wasi_fd_t,
|
||||||
fdflags: wasi::__wasi_fdflags_t,
|
fdflags: wasi::__wasi_fdflags_t,
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ use crate::fdentry::{Descriptor, FdEntry};
|
|||||||
use crate::helpers::*;
|
use crate::helpers::*;
|
||||||
use crate::memory::*;
|
use crate::memory::*;
|
||||||
use crate::sandboxed_tty_writer::SandboxedTTYWriter;
|
use crate::sandboxed_tty_writer::SandboxedTTYWriter;
|
||||||
use crate::sys::fdentry_impl::determine_type_rights;
|
|
||||||
use crate::sys::hostcalls_impl::fs_helpers::path_open_rights;
|
use crate::sys::hostcalls_impl::fs_helpers::path_open_rights;
|
||||||
use crate::sys::{host_impl, hostcalls_impl};
|
use crate::sys::{host_impl, hostcalls_impl};
|
||||||
use crate::{helpers, host, wasi, wasi32, Error, Result};
|
use crate::{helpers, host, wasi, wasi32, Error, Result};
|
||||||
@@ -299,19 +298,24 @@ pub(crate) unsafe fn fd_fdstat_get(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) unsafe fn fd_fdstat_set_flags(
|
pub(crate) unsafe fn fd_fdstat_set_flags(
|
||||||
wasi_ctx: &WasiCtx,
|
wasi_ctx: &mut WasiCtx,
|
||||||
_memory: &mut [u8],
|
_memory: &mut [u8],
|
||||||
fd: wasi::__wasi_fd_t,
|
fd: wasi::__wasi_fd_t,
|
||||||
fdflags: wasi::__wasi_fdflags_t,
|
fdflags: wasi::__wasi_fdflags_t,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
trace!("fd_fdstat_set_flags(fd={:?}, fdflags={:#x?})", fd, fdflags);
|
trace!("fd_fdstat_set_flags(fd={:?}, fdflags={:#x?})", fd, fdflags);
|
||||||
|
|
||||||
let fd = wasi_ctx
|
let descriptor = wasi_ctx
|
||||||
.get_fd_entry(fd)?
|
.get_fd_entry_mut(fd)?
|
||||||
.as_descriptor(0, 0)?
|
.as_descriptor_mut(wasi::__WASI_RIGHTS_FD_FDSTAT_SET_FLAGS, 0)?;
|
||||||
.as_os_handle();
|
|
||||||
|
|
||||||
hostcalls_impl::fd_fdstat_set_flags(&fd, fdflags)
|
if let Some(new_handle) =
|
||||||
|
hostcalls_impl::fd_fdstat_set_flags(&descriptor.as_os_handle(), fdflags)?
|
||||||
|
{
|
||||||
|
*descriptor = Descriptor::OsHandle(new_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) unsafe fn fd_fdstat_set_rights(
|
pub(crate) unsafe fn fd_fdstat_set_rights(
|
||||||
@@ -574,6 +578,11 @@ pub(crate) unsafe fn path_open(
|
|||||||
|
|
||||||
let (needed_base, needed_inheriting) =
|
let (needed_base, needed_inheriting) =
|
||||||
path_open_rights(fs_rights_base, fs_rights_inheriting, oflags, fs_flags);
|
path_open_rights(fs_rights_base, fs_rights_inheriting, oflags, fs_flags);
|
||||||
|
trace!(
|
||||||
|
" | needed_base = {}, needed_inheriting = {}",
|
||||||
|
needed_base,
|
||||||
|
needed_inheriting
|
||||||
|
);
|
||||||
let fe = wasi_ctx.get_fd_entry(dirfd)?;
|
let fe = wasi_ctx.get_fd_entry(dirfd)?;
|
||||||
let resolved = path_get(
|
let resolved = path_get(
|
||||||
fe,
|
fe,
|
||||||
@@ -593,13 +602,20 @@ pub(crate) unsafe fn path_open(
|
|||||||
| wasi::__WASI_RIGHTS_FD_FILESTAT_SET_SIZE)
|
| wasi::__WASI_RIGHTS_FD_FILESTAT_SET_SIZE)
|
||||||
!= 0;
|
!= 0;
|
||||||
|
|
||||||
|
trace!(
|
||||||
|
" | calling path_open impl: read={}, write={}",
|
||||||
|
read,
|
||||||
|
write
|
||||||
|
);
|
||||||
let fd = hostcalls_impl::path_open(resolved, read, write, oflags, fs_flags)?;
|
let fd = hostcalls_impl::path_open(resolved, read, write, oflags, fs_flags)?;
|
||||||
|
|
||||||
// Determine the type of the new file descriptor and which rights contradict with this type
|
|
||||||
let (_ty, max_base, max_inheriting) = determine_type_rights(&fd)?;
|
|
||||||
let mut fe = FdEntry::from(fd)?;
|
let mut fe = FdEntry::from(fd)?;
|
||||||
fe.rights_base &= max_base;
|
// We need to manually deny the rights which are not explicitly requested.
|
||||||
fe.rights_inheriting &= max_inheriting;
|
// This should not be needed, but currently determine_type_and_access_rights,
|
||||||
|
// which is used by FdEntry::from, may grant extra rights while inferring it
|
||||||
|
// from the open mode.
|
||||||
|
fe.rights_base &= fs_rights_base;
|
||||||
|
fe.rights_inheriting &= fs_rights_inheriting;
|
||||||
let guest_fd = wasi_ctx.insert_fd_entry(fe)?;
|
let guest_fd = wasi_ctx.insert_fd_entry(fe)?;
|
||||||
|
|
||||||
trace!(" | *fd={:?}", guest_fd);
|
trace!(" | *fd={:?}", guest_fd);
|
||||||
@@ -709,7 +725,10 @@ pub(crate) unsafe fn fd_filestat_get(
|
|||||||
filestat_ptr
|
filestat_ptr
|
||||||
);
|
);
|
||||||
|
|
||||||
let fd = wasi_ctx.get_fd_entry(fd)?.as_descriptor(0, 0)?.as_file()?;
|
let fd = wasi_ctx
|
||||||
|
.get_fd_entry(fd)?
|
||||||
|
.as_descriptor(wasi::__WASI_RIGHTS_FD_FILESTAT_GET, 0)?
|
||||||
|
.as_file()?;
|
||||||
let host_filestat = hostcalls_impl::fd_filestat_get(fd)?;
|
let host_filestat = hostcalls_impl::fd_filestat_get(fd)?;
|
||||||
|
|
||||||
trace!(" | *filestat_ptr={:?}", host_filestat);
|
trace!(" | *filestat_ptr={:?}", host_filestat);
|
||||||
|
|||||||
@@ -242,9 +242,9 @@ pub(crate) fn poll_oneoff(
|
|||||||
{
|
{
|
||||||
let wasi_fd = unsafe { subscription.u.fd_readwrite.file_descriptor };
|
let wasi_fd = unsafe { subscription.u.fd_readwrite.file_descriptor };
|
||||||
let rights = if r#type == wasi::__WASI_EVENTTYPE_FD_READ {
|
let rights = if r#type == wasi::__WASI_EVENTTYPE_FD_READ {
|
||||||
wasi::__WASI_RIGHTS_FD_READ
|
wasi::__WASI_RIGHTS_FD_READ | wasi::__WASI_RIGHTS_POLL_FD_READWRITE
|
||||||
} else {
|
} else {
|
||||||
wasi::__WASI_RIGHTS_FD_WRITE
|
wasi::__WASI_RIGHTS_FD_WRITE | wasi::__WASI_RIGHTS_POLL_FD_READWRITE
|
||||||
};
|
};
|
||||||
|
|
||||||
match unsafe {
|
match unsafe {
|
||||||
|
|||||||
@@ -29,9 +29,14 @@ pub(crate) fn fd_fdstat_get(fd: &File) -> Result<wasi::__wasi_fdflags_t> {
|
|||||||
.map_err(Into::into)
|
.map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn fd_fdstat_set_flags(fd: &File, fdflags: wasi::__wasi_fdflags_t) -> Result<()> {
|
pub(crate) fn fd_fdstat_set_flags(
|
||||||
|
fd: &File,
|
||||||
|
fdflags: wasi::__wasi_fdflags_t,
|
||||||
|
) -> Result<Option<OsHandle>> {
|
||||||
let nix_flags = host_impl::nix_from_fdflags(fdflags);
|
let nix_flags = host_impl::nix_from_fdflags(fdflags);
|
||||||
unsafe { yanix::fcntl::set_status_flags(fd.as_raw_fd(), nix_flags) }.map_err(Into::into)
|
unsafe { yanix::fcntl::set_status_flags(fd.as_raw_fd(), nix_flags) }
|
||||||
|
.map(|_| None)
|
||||||
|
.map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn fd_advise(
|
pub(crate) fn fd_advise(
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ use crate::ctx::WasiCtx;
|
|||||||
use crate::fdentry::FdEntry;
|
use crate::fdentry::FdEntry;
|
||||||
use crate::host::{Dirent, FileType};
|
use crate::host::{Dirent, FileType};
|
||||||
use crate::hostcalls_impl::{fd_filestat_set_times_impl, PathGet};
|
use crate::hostcalls_impl::{fd_filestat_set_times_impl, PathGet};
|
||||||
use crate::sys::fdentry_impl::determine_type_rights;
|
use crate::sys::fdentry_impl::{determine_type_rights, OsHandle};
|
||||||
use crate::sys::host_impl::{self, path_from_host};
|
use crate::sys::host_impl::{self, path_from_host};
|
||||||
use crate::sys::hostcalls_impl::fs_helpers::PathGetExt;
|
use crate::sys::hostcalls_impl::fs_helpers::PathGetExt;
|
||||||
use crate::{wasi, Error, Result};
|
use crate::{wasi, Error, Result};
|
||||||
@@ -78,8 +78,26 @@ pub(crate) fn fd_fdstat_get(fd: &File) -> Result<wasi::__wasi_fdflags_t> {
|
|||||||
Ok(fdflags)
|
Ok(fdflags)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn fd_fdstat_set_flags(fd: &File, fdflags: wasi::__wasi_fdflags_t) -> Result<()> {
|
pub(crate) fn fd_fdstat_set_flags(
|
||||||
unimplemented!("fd_fdstat_set_flags")
|
fd: &File,
|
||||||
|
fdflags: wasi::__wasi_fdflags_t,
|
||||||
|
) -> Result<Option<OsHandle>> {
|
||||||
|
let handle = unsafe { fd.as_raw_handle() };
|
||||||
|
|
||||||
|
let access_mode = winx::file::query_access_information(handle)?;
|
||||||
|
|
||||||
|
let new_access_mode = file_access_mode_from_fdflags(
|
||||||
|
fdflags,
|
||||||
|
access_mode.contains(AccessMode::FILE_READ_DATA),
|
||||||
|
access_mode.contains(AccessMode::FILE_WRITE_DATA)
|
||||||
|
| access_mode.contains(AccessMode::FILE_APPEND_DATA),
|
||||||
|
);
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
Ok(Some(OsHandle::from(File::from_raw_handle(
|
||||||
|
winx::file::reopen_file(handle, new_access_mode, file_flags_from_fdflags(fdflags))?,
|
||||||
|
))))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn fd_advise(
|
pub(crate) fn fd_advise(
|
||||||
@@ -119,9 +137,20 @@ pub(crate) fn path_open(
|
|||||||
) -> Result<File> {
|
) -> Result<File> {
|
||||||
use winx::file::{AccessMode, CreationDisposition, Flags};
|
use winx::file::{AccessMode, CreationDisposition, Flags};
|
||||||
|
|
||||||
|
let is_trunc = oflags & wasi::__WASI_OFLAGS_TRUNC != 0;
|
||||||
|
|
||||||
|
if is_trunc {
|
||||||
|
// Windows does not support append mode when opening for truncation
|
||||||
|
// This is because truncation requires `GENERIC_WRITE` access, which will override the removal
|
||||||
|
// of the `FILE_WRITE_DATA` permission.
|
||||||
|
if fdflags & wasi::__WASI_FDFLAGS_APPEND != 0 {
|
||||||
|
return Err(Error::ENOTSUP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// convert open flags
|
// convert open flags
|
||||||
// note: the calls to `write(true)` are to bypass an internal OpenOption check
|
// note: the calls to `write(true)` are to bypass an internal OpenOption check
|
||||||
// the write flag will ultimately be ignored when `access_mode` is called below.
|
// the write flag will ultimately be ignored when `access_mode` is calculated below.
|
||||||
let mut opts = OpenOptions::new();
|
let mut opts = OpenOptions::new();
|
||||||
match creation_disposition_from_oflags(oflags) {
|
match creation_disposition_from_oflags(oflags) {
|
||||||
CreationDisposition::CREATE_ALWAYS => {
|
CreationDisposition::CREATE_ALWAYS => {
|
||||||
@@ -168,7 +197,14 @@ pub(crate) fn path_open(
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
opts.access_mode(file_access_mode_from_fdflags(fdflags, read, write).bits())
|
let mut access_mode = file_access_mode_from_fdflags(fdflags, read, write);
|
||||||
|
|
||||||
|
// Truncation requires the special `GENERIC_WRITE` bit set (this is why it doesn't work with append-only mode)
|
||||||
|
if is_trunc {
|
||||||
|
access_mode |= AccessMode::GENERIC_WRITE;
|
||||||
|
}
|
||||||
|
|
||||||
|
opts.access_mode(access_mode.bits())
|
||||||
.custom_flags(file_flags_from_fdflags(fdflags).bits())
|
.custom_flags(file_flags_from_fdflags(fdflags).bits())
|
||||||
.open(&path)
|
.open(&path)
|
||||||
.map_err(Into::into)
|
.map_err(Into::into)
|
||||||
@@ -195,12 +231,15 @@ fn file_access_mode_from_fdflags(
|
|||||||
) -> AccessMode {
|
) -> AccessMode {
|
||||||
let mut access_mode = AccessMode::READ_CONTROL;
|
let mut access_mode = AccessMode::READ_CONTROL;
|
||||||
|
|
||||||
|
// Note that `GENERIC_READ` and `GENERIC_WRITE` cannot be used to properly support append-only mode
|
||||||
|
// The file-specific flags `FILE_GENERIC_READ` and `FILE_GENERIC_WRITE` are used here instead
|
||||||
|
// These flags have the same semantic meaning for file objects, but allow removal of specific permissions (see below)
|
||||||
if read {
|
if read {
|
||||||
access_mode.insert(AccessMode::GENERIC_READ);
|
access_mode.insert(AccessMode::FILE_GENERIC_READ);
|
||||||
}
|
}
|
||||||
|
|
||||||
if write {
|
if write {
|
||||||
access_mode.insert(AccessMode::GENERIC_WRITE);
|
access_mode.insert(AccessMode::FILE_GENERIC_WRITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// For append, grant the handle FILE_APPEND_DATA access but *not* FILE_WRITE_DATA.
|
// For append, grant the handle FILE_APPEND_DATA access but *not* FILE_WRITE_DATA.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "wasi-common-cbindgen"
|
name = "wasi-common-cbindgen"
|
||||||
version = "0.7.0"
|
version = "0.9.0"
|
||||||
authors = ["Jakub Konka <kubkon@jakubkonka.com>"]
|
authors = ["Jakub Konka <kubkon@jakubkonka.com>"]
|
||||||
description = "Interface generator utilities used by wasi-common"
|
description = "Interface generator utilities used by wasi-common"
|
||||||
license = "Apache-2.0 WITH LLVM-exception"
|
license = "Apache-2.0 WITH LLVM-exception"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "wig"
|
name = "wig"
|
||||||
version = "0.7.0"
|
version = "0.9.2"
|
||||||
authors = ["Dan Gohman <sunfish@mozilla.com>"]
|
authors = ["Dan Gohman <sunfish@mozilla.com>"]
|
||||||
description = "WebAssembly Interface Generator"
|
description = "WebAssembly Interface Generator"
|
||||||
license = "Apache-2.0 WITH LLVM-exception"
|
license = "Apache-2.0 WITH LLVM-exception"
|
||||||
@@ -8,6 +8,7 @@ categories = ["wasm"]
|
|||||||
keywords = ["webassembly", "wasm"]
|
keywords = ["webassembly", "wasm"]
|
||||||
repository = "https://github.com/bytecodealliance/wasmtime"
|
repository = "https://github.com/bytecodealliance/wasmtime"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
include = ["src/**/*", "LICENSE", "WASI"]
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
proc-macro = true
|
proc-macro = true
|
||||||
@@ -19,7 +20,7 @@ heck = "0.3.1"
|
|||||||
# We include the WASI repo primarily for the witx files, but it's also useful
|
# We include the WASI repo primarily for the witx files, but it's also useful
|
||||||
# to use the witx parser it contains, rather than the witx crate from
|
# to use the witx parser it contains, rather than the witx crate from
|
||||||
# crates.io, so that it always matches the version of the witx files.
|
# crates.io, so that it always matches the version of the witx files.
|
||||||
witx = { path = "../WASI/tools/witx" }
|
witx = "0.6.0"
|
||||||
|
|
||||||
[badges]
|
[badges]
|
||||||
maintenance = { status = "actively-developed" }
|
maintenance = { status = "actively-developed" }
|
||||||
|
|||||||
1
crates/wasi-common/wig/WASI
Submodule
1
crates/wasi-common/wig/WASI
Submodule
Submodule crates/wasi-common/wig/WASI added at 04d4eba571
@@ -28,7 +28,7 @@ pub(crate) fn witx_path_from_args(args: TokenStream) -> (String, String) {
|
|||||||
|
|
||||||
fn witx_path(phase: &str, id: &str) -> String {
|
fn witx_path(phase: &str, id: &str) -> String {
|
||||||
let root = env!("CARGO_MANIFEST_DIR");
|
let root = env!("CARGO_MANIFEST_DIR");
|
||||||
format!("{}/../WASI/phases/{}/witx/{}.witx", root, phase, id)
|
format!("{}/WASI/phases/{}/witx/{}.witx", root, phase, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert a `Literal` holding a string literal into the `String`.
|
// Convert a `Literal` holding a string literal into the `String`.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "winx"
|
name = "winx"
|
||||||
version = "0.7.0"
|
version = "0.9.0"
|
||||||
authors = ["Jakub Konka <kubkon@jakubkonka.com>"]
|
authors = ["Jakub Konka <kubkon@jakubkonka.com>"]
|
||||||
description = "Windows API helper library"
|
description = "Windows API helper library"
|
||||||
license = "Apache-2.0 WITH LLVM-exception"
|
license = "Apache-2.0 WITH LLVM-exception"
|
||||||
|
|||||||
@@ -434,3 +434,22 @@ pub fn query_mode_information(handle: RawHandle) -> Result<FileModeInformation>
|
|||||||
|
|
||||||
Ok(FileModeInformation::from_bits_truncate(info.Mode))
|
Ok(FileModeInformation::from_bits_truncate(info.Mode))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn reopen_file(handle: RawHandle, access_mode: AccessMode, flags: Flags) -> Result<RawHandle> {
|
||||||
|
// Files on Windows are opened with DELETE, READ, and WRITE share mode by default (see OpenOptions in stdlib)
|
||||||
|
// This keeps the same share mode when reopening the file handle
|
||||||
|
let new_handle = unsafe {
|
||||||
|
winbase::ReOpenFile(
|
||||||
|
handle,
|
||||||
|
access_mode.bits(),
|
||||||
|
winnt::FILE_SHARE_DELETE | winnt::FILE_SHARE_READ | winnt::FILE_SHARE_WRITE,
|
||||||
|
flags.bits(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
if new_handle == winapi::um::handleapi::INVALID_HANDLE_VALUE {
|
||||||
|
return Err(winerror::WinError::last());
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(new_handle)
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "yanix"
|
name = "yanix"
|
||||||
version = "0.1.0"
|
version = "0.9.0"
|
||||||
authors = ["The Wasmtime Project Developers"]
|
authors = ["The Wasmtime Project Developers"]
|
||||||
description = "Yet Another Nix crate: a Unix API helper library"
|
description = "Yet Another Nix crate: a Unix API helper library"
|
||||||
license = "Apache-2.0 WITH LLVM-exception"
|
license = "Apache-2.0 WITH LLVM-exception"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "wasmtime-wasi"
|
name = "wasmtime-wasi"
|
||||||
version = "0.7.0"
|
version = "0.9.0"
|
||||||
authors = ["The Cranelift Project Developers"]
|
authors = ["The Cranelift Project Developers"]
|
||||||
description = "WASI API support for Wasmtime"
|
description = "WASI API support for Wasmtime"
|
||||||
license = "Apache-2.0 WITH LLVM-exception"
|
license = "Apache-2.0 WITH LLVM-exception"
|
||||||
@@ -11,17 +11,17 @@ readme = "README.md"
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
wasmtime = { path = "../api" }
|
wasmtime = { path = "../api", version = "0.9.0" }
|
||||||
wasmtime-runtime = { path = "../runtime" }
|
wasmtime-runtime = { path = "../runtime", version = "0.9.0" }
|
||||||
wasmtime-environ = { path = "../environ" }
|
wasmtime-environ = { path = "../environ", version = "0.9.0" }
|
||||||
wasmtime-jit = { path = "../jit" }
|
wasmtime-jit = { path = "../jit", version = "0.9.0" }
|
||||||
wasi-common = { path = "../wasi-common" }
|
wasi-common = { path = "../wasi-common", version = "0.9.0" }
|
||||||
cranelift-codegen = { version = "0.52.0", features = ["enable-serde"] }
|
cranelift-codegen = { version = "0.54", features = ["enable-serde"] }
|
||||||
cranelift-entity = { version = "0.52.0", features = ["enable-serde"] }
|
cranelift-entity = { version = "0.54", features = ["enable-serde"] }
|
||||||
cranelift-wasm = { version = "0.52.0", features = ["enable-serde"] }
|
cranelift-wasm = { version = "0.54", features = ["enable-serde"] }
|
||||||
target-lexicon = "0.9.0"
|
target-lexicon = "0.10.0"
|
||||||
log = { version = "0.4.8", default-features = false }
|
log = { version = "0.4.8", default-features = false }
|
||||||
wig = { path = "../wasi-common/wig" }
|
wig = { path = "../wasi-common/wig", version = "0.9.2" }
|
||||||
|
|
||||||
[badges]
|
[badges]
|
||||||
maintenance = { status = "actively-developed" }
|
maintenance = { status = "actively-developed" }
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
#![allow(improper_ctypes)]
|
|
||||||
|
|
||||||
mod instantiate;
|
mod instantiate;
|
||||||
pub mod old;
|
pub mod old;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
#![allow(improper_ctypes)]
|
|
||||||
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
|
|
||||||
mod instantiate;
|
mod instantiate;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "wasmtime-wast"
|
name = "wasmtime-wast"
|
||||||
version = "0.7.0"
|
version = "0.9.0"
|
||||||
authors = ["The Wasmtime Project Developers"]
|
authors = ["The Wasmtime Project Developers"]
|
||||||
description = "wast testing support for wasmtime"
|
description = "wast testing support for wasmtime"
|
||||||
license = "Apache-2.0 WITH LLVM-exception"
|
license = "Apache-2.0 WITH LLVM-exception"
|
||||||
@@ -12,8 +12,8 @@ edition = "2018"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.19"
|
anyhow = "1.0.19"
|
||||||
wasmtime = { path = "../api" }
|
wasmtime = { path = "../api", version = "0.9.0" }
|
||||||
wast = "5.0.1"
|
wast = "6.0.0"
|
||||||
|
|
||||||
[badges]
|
[badges]
|
||||||
maintenance = { status = "actively-developed" }
|
maintenance = { status = "actively-developed" }
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
#![allow(improper_ctypes)]
|
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
@@ -31,35 +29,35 @@ pub fn instantiate_spectest(store: &Store) -> HashMap<&'static str, Extern> {
|
|||||||
|
|
||||||
let ty = FuncType::new(Box::new([]), Box::new([]));
|
let ty = FuncType::new(Box::new([]), Box::new([]));
|
||||||
let func = wrap(store, ty, |_params, _results| Ok(()));
|
let func = wrap(store, ty, |_params, _results| Ok(()));
|
||||||
ret.insert("print", Extern::Func(HostRef::new(func)));
|
ret.insert("print", Extern::Func(func));
|
||||||
|
|
||||||
let ty = FuncType::new(Box::new([ValType::I32]), Box::new([]));
|
let ty = FuncType::new(Box::new([ValType::I32]), Box::new([]));
|
||||||
let func = wrap(store, ty, |params, _results| {
|
let func = wrap(store, ty, |params, _results| {
|
||||||
println!("{}: i32", params[0].unwrap_i32());
|
println!("{}: i32", params[0].unwrap_i32());
|
||||||
Ok(())
|
Ok(())
|
||||||
});
|
});
|
||||||
ret.insert("print_i32", Extern::Func(HostRef::new(func)));
|
ret.insert("print_i32", Extern::Func(func));
|
||||||
|
|
||||||
let ty = FuncType::new(Box::new([ValType::I64]), Box::new([]));
|
let ty = FuncType::new(Box::new([ValType::I64]), Box::new([]));
|
||||||
let func = wrap(store, ty, |params, _results| {
|
let func = wrap(store, ty, |params, _results| {
|
||||||
println!("{}: i64", params[0].unwrap_i64());
|
println!("{}: i64", params[0].unwrap_i64());
|
||||||
Ok(())
|
Ok(())
|
||||||
});
|
});
|
||||||
ret.insert("print_i64", Extern::Func(HostRef::new(func)));
|
ret.insert("print_i64", Extern::Func(func));
|
||||||
|
|
||||||
let ty = FuncType::new(Box::new([ValType::F32]), Box::new([]));
|
let ty = FuncType::new(Box::new([ValType::F32]), Box::new([]));
|
||||||
let func = wrap(store, ty, |params, _results| {
|
let func = wrap(store, ty, |params, _results| {
|
||||||
println!("{}: f32", params[0].unwrap_f32());
|
println!("{}: f32", params[0].unwrap_f32());
|
||||||
Ok(())
|
Ok(())
|
||||||
});
|
});
|
||||||
ret.insert("print_f32", Extern::Func(HostRef::new(func)));
|
ret.insert("print_f32", Extern::Func(func));
|
||||||
|
|
||||||
let ty = FuncType::new(Box::new([ValType::F64]), Box::new([]));
|
let ty = FuncType::new(Box::new([ValType::F64]), Box::new([]));
|
||||||
let func = wrap(store, ty, |params, _results| {
|
let func = wrap(store, ty, |params, _results| {
|
||||||
println!("{}: f64", params[0].unwrap_f64());
|
println!("{}: f64", params[0].unwrap_f64());
|
||||||
Ok(())
|
Ok(())
|
||||||
});
|
});
|
||||||
ret.insert("print_f64", Extern::Func(HostRef::new(func)));
|
ret.insert("print_f64", Extern::Func(func));
|
||||||
|
|
||||||
let ty = FuncType::new(Box::new([ValType::I32, ValType::F32]), Box::new([]));
|
let ty = FuncType::new(Box::new([ValType::I32, ValType::F32]), Box::new([]));
|
||||||
let func = wrap(store, ty, |params, _results| {
|
let func = wrap(store, ty, |params, _results| {
|
||||||
@@ -67,7 +65,7 @@ pub fn instantiate_spectest(store: &Store) -> HashMap<&'static str, Extern> {
|
|||||||
println!("{}: f32", params[1].unwrap_f32());
|
println!("{}: f32", params[1].unwrap_f32());
|
||||||
Ok(())
|
Ok(())
|
||||||
});
|
});
|
||||||
ret.insert("print_i32_f32", Extern::Func(HostRef::new(func)));
|
ret.insert("print_i32_f32", Extern::Func(func));
|
||||||
|
|
||||||
let ty = FuncType::new(Box::new([ValType::F64, ValType::F64]), Box::new([]));
|
let ty = FuncType::new(Box::new([ValType::F64, ValType::F64]), Box::new([]));
|
||||||
let func = wrap(store, ty, |params, _results| {
|
let func = wrap(store, ty, |params, _results| {
|
||||||
@@ -75,31 +73,31 @@ pub fn instantiate_spectest(store: &Store) -> HashMap<&'static str, Extern> {
|
|||||||
println!("{}: f64", params[1].unwrap_f64());
|
println!("{}: f64", params[1].unwrap_f64());
|
||||||
Ok(())
|
Ok(())
|
||||||
});
|
});
|
||||||
ret.insert("print_f64_f64", Extern::Func(HostRef::new(func)));
|
ret.insert("print_f64_f64", Extern::Func(func));
|
||||||
|
|
||||||
let ty = GlobalType::new(ValType::I32, Mutability::Const);
|
let ty = GlobalType::new(ValType::I32, Mutability::Const);
|
||||||
let g = Global::new(store, ty, Val::I32(666));
|
let g = Global::new(store, ty, Val::I32(666));
|
||||||
ret.insert("global_i32", Extern::Global(HostRef::new(g)));
|
ret.insert("global_i32", Extern::Global(g));
|
||||||
|
|
||||||
let ty = GlobalType::new(ValType::I64, Mutability::Const);
|
let ty = GlobalType::new(ValType::I64, Mutability::Const);
|
||||||
let g = Global::new(store, ty, Val::I64(666));
|
let g = Global::new(store, ty, Val::I64(666));
|
||||||
ret.insert("global_i64", Extern::Global(HostRef::new(g)));
|
ret.insert("global_i64", Extern::Global(g));
|
||||||
|
|
||||||
let ty = GlobalType::new(ValType::F32, Mutability::Const);
|
let ty = GlobalType::new(ValType::F32, Mutability::Const);
|
||||||
let g = Global::new(store, ty, Val::F32(0x4426_8000));
|
let g = Global::new(store, ty, Val::F32(0x4426_8000));
|
||||||
ret.insert("global_f32", Extern::Global(HostRef::new(g)));
|
ret.insert("global_f32", Extern::Global(g));
|
||||||
|
|
||||||
let ty = GlobalType::new(ValType::F64, Mutability::Const);
|
let ty = GlobalType::new(ValType::F64, Mutability::Const);
|
||||||
let g = Global::new(store, ty, Val::F64(0x4084_d000_0000_0000));
|
let g = Global::new(store, ty, Val::F64(0x4084_d000_0000_0000));
|
||||||
ret.insert("global_f64", Extern::Global(HostRef::new(g)));
|
ret.insert("global_f64", Extern::Global(g));
|
||||||
|
|
||||||
let ty = TableType::new(ValType::FuncRef, Limits::new(10, Some(20)));
|
let ty = TableType::new(ValType::FuncRef, Limits::new(10, Some(20)));
|
||||||
let table = Table::new(store, ty, Val::AnyRef(AnyRef::Null));
|
let table = Table::new(store, ty, Val::AnyRef(AnyRef::Null));
|
||||||
ret.insert("table", Extern::Table(HostRef::new(table)));
|
ret.insert("table", Extern::Table(table));
|
||||||
|
|
||||||
let ty = MemoryType::new(Limits::new(1, Some(2)));
|
let ty = MemoryType::new(Limits::new(1, Some(2)));
|
||||||
let memory = Memory::new(store, ty);
|
let memory = Memory::new(store, ty);
|
||||||
ret.insert("memory", Extern::Memory(HostRef::new(memory)));
|
ret.insert("memory", Extern::Memory(memory));
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,9 +27,9 @@ fn runtime_value(v: &wast::Expression<'_>) -> Result<Val> {
|
|||||||
pub struct WastContext {
|
pub struct WastContext {
|
||||||
/// Wast files have a concept of a "current" module, which is the most
|
/// Wast files have a concept of a "current" module, which is the most
|
||||||
/// recently defined.
|
/// recently defined.
|
||||||
current: Option<HostRef<Instance>>,
|
current: Option<Instance>,
|
||||||
|
|
||||||
instances: HashMap<String, HostRef<Instance>>,
|
instances: HashMap<String, Instance>,
|
||||||
store: Store,
|
store: Store,
|
||||||
spectest: Option<HashMap<&'static str, Extern>>,
|
spectest: Option<HashMap<&'static str, Extern>>,
|
||||||
}
|
}
|
||||||
@@ -39,6 +39,15 @@ enum Outcome<T = Vec<Val>> {
|
|||||||
Trap(Trap),
|
Trap(Trap),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T> Outcome<T> {
|
||||||
|
fn into_result(self) -> Result<T, Trap> {
|
||||||
|
match self {
|
||||||
|
Outcome::Ok(t) => Ok(t),
|
||||||
|
Outcome::Trap(t) => Err(t),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl WastContext {
|
impl WastContext {
|
||||||
/// Construct a new instance of `WastContext`.
|
/// Construct a new instance of `WastContext`.
|
||||||
pub fn new(store: Store) -> Self {
|
pub fn new(store: Store) -> Self {
|
||||||
@@ -50,7 +59,7 @@ impl WastContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_instance(&self, instance_name: Option<&str>) -> Result<HostRef<Instance>> {
|
fn get_instance(&self, instance_name: Option<&str>) -> Result<Instance> {
|
||||||
match instance_name {
|
match instance_name {
|
||||||
Some(name) => self
|
Some(name) => self
|
||||||
.instances
|
.instances
|
||||||
@@ -64,7 +73,7 @@ impl WastContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn instantiate(&self, module: &[u8]) -> Result<Outcome<HostRef<Instance>>> {
|
fn instantiate(&self, module: &[u8]) -> Result<Outcome<Instance>> {
|
||||||
let module = Module::new(&self.store, module)?;
|
let module = Module::new(&self.store, module)?;
|
||||||
let mut imports = Vec::new();
|
let mut imports = Vec::new();
|
||||||
for import in module.imports() {
|
for import in module.imports() {
|
||||||
@@ -85,23 +94,16 @@ impl WastContext {
|
|||||||
.get(import.module())
|
.get(import.module())
|
||||||
.ok_or_else(|| anyhow!("no module named `{}`", import.module()))?;
|
.ok_or_else(|| anyhow!("no module named `{}`", import.module()))?;
|
||||||
let export = instance
|
let export = instance
|
||||||
.borrow()
|
|
||||||
.find_export_by_name(import.name())
|
.find_export_by_name(import.name())
|
||||||
.ok_or_else(|| anyhow!("unknown import `{}::{}`", import.name(), import.module()))?
|
.ok_or_else(|| anyhow!("unknown import `{}::{}`", import.name(), import.module()))?
|
||||||
.clone();
|
.clone();
|
||||||
imports.push(export);
|
imports.push(export);
|
||||||
}
|
}
|
||||||
let instance = match Instance::new(&self.store, &module, &imports) {
|
let instance = match Instance::new(&module, &imports) {
|
||||||
Ok(i) => i,
|
Ok(i) => i,
|
||||||
Err(e) => {
|
Err(e) => return e.downcast::<Trap>().map(Outcome::Trap),
|
||||||
let err = e.chain().filter_map(|e| e.downcast_ref::<Trap>()).next();
|
|
||||||
if let Some(trap) = err {
|
|
||||||
return Ok(Outcome::Trap(trap.clone()));
|
|
||||||
}
|
|
||||||
return Err(e);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
Ok(Outcome::Ok(HostRef::new(instance)))
|
Ok(Outcome::Ok(instance))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Register "spectest" which is used by the spec testsuite.
|
/// Register "spectest" which is used by the spec testsuite.
|
||||||
@@ -127,7 +129,12 @@ impl WastContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn perform_invoke(&mut self, exec: wast::WastInvoke<'_>) -> Result<Outcome> {
|
fn perform_invoke(&mut self, exec: wast::WastInvoke<'_>) -> Result<Outcome> {
|
||||||
self.invoke(exec.module.map(|i| i.name()), exec.name, &exec.args)
|
let values = exec
|
||||||
|
.args
|
||||||
|
.iter()
|
||||||
|
.map(runtime_value)
|
||||||
|
.collect::<Result<Vec<_>>>()?;
|
||||||
|
self.invoke(exec.module.map(|i| i.name()), exec.name, &values)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Define a module and register it.
|
/// Define a module and register it.
|
||||||
@@ -155,19 +162,17 @@ impl WastContext {
|
|||||||
&mut self,
|
&mut self,
|
||||||
instance_name: Option<&str>,
|
instance_name: Option<&str>,
|
||||||
field: &str,
|
field: &str,
|
||||||
args: &[wast::Expression],
|
args: &[Val],
|
||||||
) -> Result<Outcome> {
|
) -> Result<Outcome> {
|
||||||
let values = args.iter().map(runtime_value).collect::<Result<Vec<_>>>()?;
|
|
||||||
let instance = self.get_instance(instance_name.as_ref().map(|x| &**x))?;
|
let instance = self.get_instance(instance_name.as_ref().map(|x| &**x))?;
|
||||||
let instance = instance.borrow();
|
|
||||||
let export = instance
|
let export = instance
|
||||||
.find_export_by_name(field)
|
.find_export_by_name(field)
|
||||||
.ok_or_else(|| anyhow!("no global named `{}`", field))?;
|
.ok_or_else(|| anyhow!("no global named `{}`", field))?;
|
||||||
let func = match export {
|
let func = match export {
|
||||||
Extern::Func(f) => f.borrow(),
|
Extern::Func(f) => f,
|
||||||
_ => bail!("export of `{}` wasn't a global", field),
|
_ => bail!("export of `{}` wasn't a global", field),
|
||||||
};
|
};
|
||||||
Ok(match func.call(&values) {
|
Ok(match func.call(args) {
|
||||||
Ok(result) => Outcome::Ok(result.into()),
|
Ok(result) => Outcome::Ok(result.into()),
|
||||||
Err(e) => Outcome::Trap(e),
|
Err(e) => Outcome::Trap(e),
|
||||||
})
|
})
|
||||||
@@ -176,21 +181,44 @@ impl WastContext {
|
|||||||
/// Get the value of an exported global from an instance.
|
/// Get the value of an exported global from an instance.
|
||||||
fn get(&mut self, instance_name: Option<&str>, field: &str) -> Result<Outcome> {
|
fn get(&mut self, instance_name: Option<&str>, field: &str) -> Result<Outcome> {
|
||||||
let instance = self.get_instance(instance_name.as_ref().map(|x| &**x))?;
|
let instance = self.get_instance(instance_name.as_ref().map(|x| &**x))?;
|
||||||
let instance = instance.borrow();
|
|
||||||
let export = instance
|
let export = instance
|
||||||
.find_export_by_name(field)
|
.find_export_by_name(field)
|
||||||
.ok_or_else(|| anyhow!("no global named `{}`", field))?;
|
.ok_or_else(|| anyhow!("no global named `{}`", field))?;
|
||||||
let global = match export {
|
let global = match export {
|
||||||
Extern::Global(g) => g.borrow(),
|
Extern::Global(g) => g,
|
||||||
_ => bail!("export of `{}` wasn't a global", field),
|
_ => bail!("export of `{}` wasn't a global", field),
|
||||||
};
|
};
|
||||||
Ok(Outcome::Ok(vec![global.get()]))
|
Ok(Outcome::Ok(vec![global.get()]))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn assert_return(&self, result: Outcome, results: &[wast::AssertExpression]) -> Result<()> {
|
||||||
|
let values = result.into_result()?;
|
||||||
|
for (v, e) in values.iter().zip(results) {
|
||||||
|
if val_matches(v, e)? {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
bail!("expected {:?}, got {:?}", e, v)
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn assert_trap(&self, result: Outcome, message: &str) -> Result<()> {
|
||||||
|
let trap = match result {
|
||||||
|
Outcome::Ok(values) => bail!("expected trap, got {:?}", values),
|
||||||
|
Outcome::Trap(t) => t,
|
||||||
|
};
|
||||||
|
if trap.message().contains(message) {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
if cfg!(feature = "lightbeam") {
|
||||||
|
println!("TODO: Check the assert_trap message: {}", message);
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
bail!("expected {}, got {}", message, trap.message())
|
||||||
|
}
|
||||||
|
|
||||||
/// Run a wast script from a byte buffer.
|
/// Run a wast script from a byte buffer.
|
||||||
pub fn run_buffer(&mut self, filename: &str, wast: &[u8]) -> Result<()> {
|
pub fn run_buffer(&mut self, filename: &str, wast: &[u8]) -> Result<()> {
|
||||||
use wast::WastDirective::*;
|
|
||||||
|
|
||||||
let wast = str::from_utf8(wast)?;
|
let wast = str::from_utf8(wast)?;
|
||||||
|
|
||||||
let adjust_wast = |mut err: wast::Error| {
|
let adjust_wast = |mut err: wast::Error| {
|
||||||
@@ -198,311 +226,126 @@ impl WastContext {
|
|||||||
err.set_text(wast);
|
err.set_text(wast);
|
||||||
err
|
err
|
||||||
};
|
};
|
||||||
let context = |sp: wast::Span| {
|
|
||||||
let (line, col) = sp.linecol_in(wast);
|
|
||||||
format!("for directive on {}:{}:{}", filename, line + 1, col)
|
|
||||||
};
|
|
||||||
|
|
||||||
let buf = wast::parser::ParseBuffer::new(wast).map_err(adjust_wast)?;
|
let buf = wast::parser::ParseBuffer::new(wast).map_err(adjust_wast)?;
|
||||||
let wast = wast::parser::parse::<wast::Wast>(&buf).map_err(adjust_wast)?;
|
let ast = wast::parser::parse::<wast::Wast>(&buf).map_err(adjust_wast)?;
|
||||||
|
|
||||||
for directive in wast.directives {
|
for directive in ast.directives {
|
||||||
match directive {
|
let sp = directive.span();
|
||||||
Module(mut module) => {
|
self.run_directive(directive).with_context(|| {
|
||||||
let binary = module.encode().map_err(adjust_wast)?;
|
let (line, col) = sp.linecol_in(wast);
|
||||||
self.module(module.name.map(|s| s.name()), &binary)
|
format!("failed directive on {}:{}:{}", filename, line + 1, col)
|
||||||
.with_context(|| context(module.span))?;
|
})?;
|
||||||
}
|
}
|
||||||
Register { span, name, module } => {
|
Ok(())
|
||||||
self.register(module.map(|s| s.name()), name)
|
}
|
||||||
.with_context(|| context(span))?;
|
|
||||||
}
|
fn run_directive(&mut self, directive: wast::WastDirective) -> Result<()> {
|
||||||
Invoke(i) => {
|
use wast::WastDirective::*;
|
||||||
let span = i.span;
|
|
||||||
self.perform_invoke(i).with_context(|| context(span))?;
|
match directive {
|
||||||
}
|
Module(mut module) => {
|
||||||
AssertReturn {
|
let binary = module.encode()?;
|
||||||
span,
|
self.module(module.name.map(|s| s.name()), &binary)?;
|
||||||
exec,
|
|
||||||
results,
|
|
||||||
} => match self.perform_execute(exec).with_context(|| context(span))? {
|
|
||||||
Outcome::Ok(values) => {
|
|
||||||
for (v, e) in values.iter().zip(results.iter().map(runtime_value)) {
|
|
||||||
let e = e?;
|
|
||||||
if values_equal(v, &e)? {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
bail!("{}\nexpected {:?}, got {:?}", context(span), e, v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Outcome::Trap(t) => {
|
|
||||||
bail!("{}\nunexpected trap: {}", context(span), t.message())
|
|
||||||
}
|
|
||||||
},
|
|
||||||
AssertTrap {
|
|
||||||
span,
|
|
||||||
exec,
|
|
||||||
message,
|
|
||||||
} => match self.perform_execute(exec).with_context(|| context(span))? {
|
|
||||||
Outcome::Ok(values) => {
|
|
||||||
bail!("{}\nexpected trap, got {:?}", context(span), values)
|
|
||||||
}
|
|
||||||
Outcome::Trap(t) => {
|
|
||||||
if t.message().contains(message) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if cfg!(feature = "lightbeam") {
|
|
||||||
println!(
|
|
||||||
"{}\nTODO: Check the assert_trap message: {}",
|
|
||||||
context(span),
|
|
||||||
message
|
|
||||||
);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
bail!(
|
|
||||||
"{}\nexpected {}, got {}",
|
|
||||||
context(span),
|
|
||||||
message,
|
|
||||||
t.message(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
AssertExhaustion {
|
|
||||||
span,
|
|
||||||
call,
|
|
||||||
message,
|
|
||||||
} => match self.perform_invoke(call).with_context(|| context(span))? {
|
|
||||||
Outcome::Ok(values) => {
|
|
||||||
bail!("{}\nexpected trap, got {:?}", context(span), values)
|
|
||||||
}
|
|
||||||
Outcome::Trap(t) => {
|
|
||||||
if t.message().contains(message) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
bail!(
|
|
||||||
"{}\nexpected exhaustion with {}, got {}",
|
|
||||||
context(span),
|
|
||||||
message,
|
|
||||||
t.message(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
AssertReturnCanonicalNan { span, invoke } => {
|
|
||||||
match self.perform_invoke(invoke).with_context(|| context(span))? {
|
|
||||||
Outcome::Ok(values) => {
|
|
||||||
for v in values.iter() {
|
|
||||||
match v {
|
|
||||||
Val::F32(x) => {
|
|
||||||
if !is_canonical_f32_nan(*x) {
|
|
||||||
bail!("{}\nexpected canonical NaN", context(span))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Val::F64(x) => {
|
|
||||||
if !is_canonical_f64_nan(*x) {
|
|
||||||
bail!("{}\nexpected canonical NaN", context(span))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
other => bail!("expected float, got {:?}", other),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Outcome::Trap(t) => {
|
|
||||||
bail!("{}\nunexpected trap: {}", context(span), t.message())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
AssertReturnCanonicalNanF32x4 { span, invoke } => {
|
|
||||||
match self.perform_invoke(invoke).with_context(|| context(span))? {
|
|
||||||
Outcome::Ok(values) => {
|
|
||||||
for v in values.iter() {
|
|
||||||
let val = match v {
|
|
||||||
Val::V128(x) => x,
|
|
||||||
other => bail!("expected v128, got {:?}", other),
|
|
||||||
};
|
|
||||||
for l in 0..4 {
|
|
||||||
if !is_canonical_f32_nan(extract_lane_as_u32(val, l)?) {
|
|
||||||
bail!(
|
|
||||||
"{}\nexpected f32x4 canonical NaN in lane {}",
|
|
||||||
context(span),
|
|
||||||
l
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Outcome::Trap(t) => {
|
|
||||||
bail!("{}\nunexpected trap: {}", context(span), t.message())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
AssertReturnCanonicalNanF64x2 { span, invoke } => {
|
|
||||||
match self.perform_invoke(invoke).with_context(|| context(span))? {
|
|
||||||
Outcome::Ok(values) => {
|
|
||||||
for v in values.iter() {
|
|
||||||
let val = match v {
|
|
||||||
Val::V128(x) => x,
|
|
||||||
other => bail!("expected v128, got {:?}", other),
|
|
||||||
};
|
|
||||||
for l in 0..2 {
|
|
||||||
if !is_canonical_f64_nan(extract_lane_as_u64(val, l)?) {
|
|
||||||
bail!(
|
|
||||||
"{}\nexpected f64x2 canonical NaN in lane {}",
|
|
||||||
context(span),
|
|
||||||
l
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Outcome::Trap(t) => {
|
|
||||||
bail!("{}\nunexpected trap: {}", context(span), t.message())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
AssertReturnArithmeticNan { span, invoke } => {
|
|
||||||
match self.perform_invoke(invoke).with_context(|| context(span))? {
|
|
||||||
Outcome::Ok(values) => {
|
|
||||||
for v in values.iter() {
|
|
||||||
match v {
|
|
||||||
Val::F32(x) => {
|
|
||||||
if !is_arithmetic_f32_nan(*x) {
|
|
||||||
bail!("{}\nexpected arithmetic NaN", context(span))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Val::F64(x) => {
|
|
||||||
if !is_arithmetic_f64_nan(*x) {
|
|
||||||
bail!("{}\nexpected arithmetic NaN", context(span))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
other => bail!("expected float, got {:?}", other),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Outcome::Trap(t) => {
|
|
||||||
bail!("{}\nunexpected trap: {}", context(span), t.message())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
AssertReturnArithmeticNanF32x4 { span, invoke } => {
|
|
||||||
match self.perform_invoke(invoke).with_context(|| context(span))? {
|
|
||||||
Outcome::Ok(values) => {
|
|
||||||
for v in values.iter() {
|
|
||||||
let val = match v {
|
|
||||||
Val::V128(x) => x,
|
|
||||||
other => bail!("expected v128, got {:?}", other),
|
|
||||||
};
|
|
||||||
for l in 0..4 {
|
|
||||||
if !is_arithmetic_f32_nan(extract_lane_as_u32(val, l)?) {
|
|
||||||
bail!(
|
|
||||||
"{}\nexpected f32x4 arithmetic NaN in lane {}",
|
|
||||||
context(span),
|
|
||||||
l
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Outcome::Trap(t) => {
|
|
||||||
bail!("{}\nunexpected trap: {}", context(span), t.message())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
AssertReturnArithmeticNanF64x2 { span, invoke } => {
|
|
||||||
match self.perform_invoke(invoke).with_context(|| context(span))? {
|
|
||||||
Outcome::Ok(values) => {
|
|
||||||
for v in values.iter() {
|
|
||||||
let val = match v {
|
|
||||||
Val::V128(x) => x,
|
|
||||||
other => bail!("expected v128, got {:?}", other),
|
|
||||||
};
|
|
||||||
for l in 0..2 {
|
|
||||||
if !is_arithmetic_f64_nan(extract_lane_as_u64(val, l)?) {
|
|
||||||
bail!(
|
|
||||||
"{}\nexpected f64x2 arithmetic NaN in lane {}",
|
|
||||||
context(span),
|
|
||||||
l
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Outcome::Trap(t) => {
|
|
||||||
bail!("{}\nunexpected trap: {}", context(span), t.message())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
AssertInvalid {
|
|
||||||
span,
|
|
||||||
mut module,
|
|
||||||
message,
|
|
||||||
} => {
|
|
||||||
let bytes = module.encode().map_err(adjust_wast)?;
|
|
||||||
let err = match self.module(None, &bytes) {
|
|
||||||
Ok(()) => bail!("{}\nexpected module to fail to build", context(span)),
|
|
||||||
Err(e) => e,
|
|
||||||
};
|
|
||||||
let error_message = format!("{:?}", err);
|
|
||||||
if !error_message.contains(&message) {
|
|
||||||
// TODO: change to bail!
|
|
||||||
println!(
|
|
||||||
"{}\nassert_invalid: expected {}, got {}",
|
|
||||||
context(span),
|
|
||||||
message,
|
|
||||||
error_message
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
AssertMalformed {
|
|
||||||
span,
|
|
||||||
module,
|
|
||||||
message,
|
|
||||||
} => {
|
|
||||||
let mut module = match module {
|
|
||||||
wast::QuoteModule::Module(m) => m,
|
|
||||||
// this is a `*.wat` parser test which we're not
|
|
||||||
// interested in
|
|
||||||
wast::QuoteModule::Quote(_) => return Ok(()),
|
|
||||||
};
|
|
||||||
let bytes = module.encode().map_err(adjust_wast)?;
|
|
||||||
let err = match self.module(None, &bytes) {
|
|
||||||
Ok(()) => {
|
|
||||||
bail!("{}\nexpected module to fail to instantiate", context(span))
|
|
||||||
}
|
|
||||||
Err(e) => e,
|
|
||||||
};
|
|
||||||
let error_message = format!("{:?}", err);
|
|
||||||
if !error_message.contains(&message) {
|
|
||||||
// TODO: change to bail!
|
|
||||||
println!(
|
|
||||||
"{}\nassert_malformed: expected {}, got {}",
|
|
||||||
context(span),
|
|
||||||
message,
|
|
||||||
error_message
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
AssertUnlinkable {
|
|
||||||
span,
|
|
||||||
mut module,
|
|
||||||
message,
|
|
||||||
} => {
|
|
||||||
let bytes = module.encode().map_err(adjust_wast)?;
|
|
||||||
let err = match self.module(None, &bytes) {
|
|
||||||
Ok(()) => bail!("{}\nexpected module to fail to link", context(span)),
|
|
||||||
Err(e) => e,
|
|
||||||
};
|
|
||||||
let error_message = format!("{:?}", err);
|
|
||||||
if !error_message.contains(&message) {
|
|
||||||
bail!(
|
|
||||||
"{}\nassert_unlinkable: expected {}, got {}",
|
|
||||||
context(span),
|
|
||||||
message,
|
|
||||||
error_message
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
AssertReturnFunc { .. } => bail!("need to implement assert_return_func"),
|
|
||||||
}
|
}
|
||||||
|
Register {
|
||||||
|
span: _,
|
||||||
|
name,
|
||||||
|
module,
|
||||||
|
} => {
|
||||||
|
self.register(module.map(|s| s.name()), name)?;
|
||||||
|
}
|
||||||
|
Invoke(i) => {
|
||||||
|
self.perform_invoke(i)?;
|
||||||
|
}
|
||||||
|
AssertReturn {
|
||||||
|
span: _,
|
||||||
|
exec,
|
||||||
|
results,
|
||||||
|
} => {
|
||||||
|
let result = self.perform_execute(exec)?;
|
||||||
|
self.assert_return(result, &results)?;
|
||||||
|
}
|
||||||
|
AssertTrap {
|
||||||
|
span: _,
|
||||||
|
exec,
|
||||||
|
message,
|
||||||
|
} => {
|
||||||
|
let result = self.perform_execute(exec)?;
|
||||||
|
self.assert_trap(result, message)?;
|
||||||
|
}
|
||||||
|
AssertExhaustion {
|
||||||
|
span: _,
|
||||||
|
call,
|
||||||
|
message,
|
||||||
|
} => {
|
||||||
|
let result = self.perform_invoke(call)?;
|
||||||
|
self.assert_trap(result, message)?;
|
||||||
|
}
|
||||||
|
AssertInvalid {
|
||||||
|
span: _,
|
||||||
|
mut module,
|
||||||
|
message,
|
||||||
|
} => {
|
||||||
|
let bytes = module.encode()?;
|
||||||
|
let err = match self.module(None, &bytes) {
|
||||||
|
Ok(()) => bail!("expected module to fail to build"),
|
||||||
|
Err(e) => e,
|
||||||
|
};
|
||||||
|
let error_message = format!("{:?}", err);
|
||||||
|
if !error_message.contains(&message) {
|
||||||
|
// TODO: change to bail!
|
||||||
|
println!(
|
||||||
|
"assert_invalid: expected {}, got {}",
|
||||||
|
message, error_message
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AssertMalformed {
|
||||||
|
span: _,
|
||||||
|
module,
|
||||||
|
message,
|
||||||
|
} => {
|
||||||
|
let mut module = match module {
|
||||||
|
wast::QuoteModule::Module(m) => m,
|
||||||
|
// this is a `*.wat` parser test which we're not
|
||||||
|
// interested in
|
||||||
|
wast::QuoteModule::Quote(_) => return Ok(()),
|
||||||
|
};
|
||||||
|
let bytes = module.encode()?;
|
||||||
|
let err = match self.module(None, &bytes) {
|
||||||
|
Ok(()) => bail!("expected module to fail to instantiate"),
|
||||||
|
Err(e) => e,
|
||||||
|
};
|
||||||
|
let error_message = format!("{:?}", err);
|
||||||
|
if !error_message.contains(&message) {
|
||||||
|
// TODO: change to bail!
|
||||||
|
println!(
|
||||||
|
"assert_malformed: expected {}, got {}",
|
||||||
|
message, error_message
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AssertUnlinkable {
|
||||||
|
span: _,
|
||||||
|
mut module,
|
||||||
|
message,
|
||||||
|
} => {
|
||||||
|
let bytes = module.encode()?;
|
||||||
|
let err = match self.module(None, &bytes) {
|
||||||
|
Ok(()) => bail!("expected module to fail to link"),
|
||||||
|
Err(e) => e,
|
||||||
|
};
|
||||||
|
let error_message = format!("{:?}", err);
|
||||||
|
if !error_message.contains(&message) {
|
||||||
|
bail!(
|
||||||
|
"assert_unlinkable: expected {}, got {}",
|
||||||
|
message,
|
||||||
|
error_message
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AssertReturnFunc { .. } => bail!("need to implement assert_return_func"),
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -516,12 +359,20 @@ impl WastContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extract_lane_as_u32(bytes: &u128, lane: usize) -> Result<u32> {
|
fn extract_lane_as_i8(bytes: u128, lane: usize) -> i8 {
|
||||||
Ok((*bytes >> (lane * 32)) as u32)
|
(bytes >> (lane * 8)) as i8
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extract_lane_as_u64(bytes: &u128, lane: usize) -> Result<u64> {
|
fn extract_lane_as_i16(bytes: u128, lane: usize) -> i16 {
|
||||||
Ok((*bytes >> (lane * 64)) as u64)
|
(bytes >> (lane * 16)) as i16
|
||||||
|
}
|
||||||
|
|
||||||
|
fn extract_lane_as_i32(bytes: u128, lane: usize) -> i32 {
|
||||||
|
(bytes >> (lane * 32)) as i32
|
||||||
|
}
|
||||||
|
|
||||||
|
fn extract_lane_as_i64(bytes: u128, lane: usize) -> i64 {
|
||||||
|
(bytes >> (lane * 64)) as i64
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_canonical_f32_nan(bits: u32) -> bool {
|
fn is_canonical_f32_nan(bits: u32) -> bool {
|
||||||
@@ -542,15 +393,64 @@ fn is_arithmetic_f64_nan(bits: u64) -> bool {
|
|||||||
(bits & AF64_NAN) == AF64_NAN
|
(bits & AF64_NAN) == AF64_NAN
|
||||||
}
|
}
|
||||||
|
|
||||||
fn values_equal(v1: &Val, v2: &Val) -> Result<bool> {
|
fn val_matches(actual: &Val, expected: &wast::AssertExpression) -> Result<bool> {
|
||||||
Ok(match (v1, v2) {
|
Ok(match (actual, expected) {
|
||||||
(Val::I32(a), Val::I32(b)) => a == b,
|
(Val::I32(a), wast::AssertExpression::I32(b)) => a == b,
|
||||||
(Val::I64(a), Val::I64(b)) => a == b,
|
(Val::I64(a), wast::AssertExpression::I64(b)) => a == b,
|
||||||
// Note that these float comparisons are comparing bits, not float
|
// Note that these float comparisons are comparing bits, not float
|
||||||
// values, so we're testing for bit-for-bit equivalence
|
// values, so we're testing for bit-for-bit equivalence
|
||||||
(Val::F32(a), Val::F32(b)) => a == b,
|
(Val::F32(a), wast::AssertExpression::F32(b)) => f32_matches(*a, b),
|
||||||
(Val::F64(a), Val::F64(b)) => a == b,
|
(Val::F64(a), wast::AssertExpression::F64(b)) => f64_matches(*a, b),
|
||||||
(Val::V128(a), Val::V128(b)) => a == b,
|
(Val::V128(a), wast::AssertExpression::V128(b)) => v128_matches(*a, b),
|
||||||
_ => bail!("don't know how to compare {:?} and {:?} yet", v1, v2),
|
_ => bail!(
|
||||||
|
"don't know how to compare {:?} and {:?} yet",
|
||||||
|
actual,
|
||||||
|
expected
|
||||||
|
),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn f32_matches(actual: u32, expected: &wast::NanPattern<wast::Float32>) -> bool {
|
||||||
|
match expected {
|
||||||
|
wast::NanPattern::CanonicalNan => is_canonical_f32_nan(actual),
|
||||||
|
wast::NanPattern::ArithmeticNan => is_arithmetic_f32_nan(actual),
|
||||||
|
wast::NanPattern::Value(expected_value) => actual == expected_value.bits,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn f64_matches(actual: u64, expected: &wast::NanPattern<wast::Float64>) -> bool {
|
||||||
|
match expected {
|
||||||
|
wast::NanPattern::CanonicalNan => is_canonical_f64_nan(actual),
|
||||||
|
wast::NanPattern::ArithmeticNan => is_arithmetic_f64_nan(actual),
|
||||||
|
wast::NanPattern::Value(expected_value) => actual == expected_value.bits,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn v128_matches(actual: u128, expected: &wast::V128Pattern) -> bool {
|
||||||
|
match expected {
|
||||||
|
wast::V128Pattern::I8x16(b) => b
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.all(|(i, b)| *b == extract_lane_as_i8(actual, i)),
|
||||||
|
wast::V128Pattern::I16x8(b) => b
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.all(|(i, b)| *b == extract_lane_as_i16(actual, i)),
|
||||||
|
wast::V128Pattern::I32x4(b) => b
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.all(|(i, b)| *b == extract_lane_as_i32(actual, i)),
|
||||||
|
wast::V128Pattern::I64x2(b) => b
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.all(|(i, b)| *b == extract_lane_as_i64(actual, i)),
|
||||||
|
wast::V128Pattern::F32x4(b) => b.iter().enumerate().all(|(i, b)| {
|
||||||
|
let a = extract_lane_as_i32(actual, i) as u32;
|
||||||
|
f32_matches(a, b)
|
||||||
|
}),
|
||||||
|
wast::V128Pattern::F64x2(b) => b.iter().enumerate().all(|(i, b)| {
|
||||||
|
let a = extract_lane_as_i64(actual, i) as u64;
|
||||||
|
f64_matches(a, b)
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "wasmtime-fuzz"
|
name = "wasmtime-fuzz"
|
||||||
version = "0.7.0"
|
version = "0.9.0"
|
||||||
authors = ["The Wasmtime Project Developers"]
|
authors = ["The Wasmtime Project Developers"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
publish = false
|
publish = false
|
||||||
|
|||||||
@@ -9,16 +9,16 @@ topdir=$(dirname "$0")/..
|
|||||||
cd "$topdir"
|
cd "$topdir"
|
||||||
|
|
||||||
# All the cranelift-* crates have the same version number
|
# All the cranelift-* crates have the same version number
|
||||||
version="0.49"
|
version="0.53"
|
||||||
|
|
||||||
# Update all of the Cargo.toml files.
|
# Update all of the Cargo.toml files.
|
||||||
echo "Updating crate versions to $version"
|
echo "Updating crate versions to $version"
|
||||||
for crate in . crates/* crates/misc/* fuzz; do
|
for toml in Cargo.toml crates/*/Cargo.toml crates/misc/*/Cargo.toml fuzz/Cargo.toml; do
|
||||||
# Update the version number of this crate to $version.
|
# Update the version number of this crate to $version.
|
||||||
sed -i.bk -e "/^cranelift-/s/\"[^\"]*\"/\"$version\"/" \
|
sed -i.bk -e "/^cranelift-/s/\"[^\"]*\"/\"$version\"/" \
|
||||||
"$crate/Cargo.toml"
|
"$toml"
|
||||||
|
|
||||||
# Update the required version number of any cranelift* dependencies.
|
# Update the required version number of any cranelift* dependencies.
|
||||||
sed -i.bk -e "/^cranelift-/s/version = \"[^\"]*\"/version = \"$version\"/" \
|
sed -i.bk -e "/^cranelift-/s/version = \"[^\"]*\"/version = \"$version\"/" \
|
||||||
"$crate/Cargo.toml"
|
"$toml"
|
||||||
done
|
done
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ topdir=$(dirname "$0")/..
|
|||||||
cd "$topdir"
|
cd "$topdir"
|
||||||
|
|
||||||
# All the wasmtime-* crates have the same version number
|
# All the wasmtime-* crates have the same version number
|
||||||
version="0.7.0"
|
version="0.9.0"
|
||||||
|
|
||||||
# Update the version numbers of the crates to $version.
|
# Update the version numbers of the crates to $version.
|
||||||
echo "Updating crate versions to $version"
|
echo "Updating crate versions to $version"
|
||||||
@@ -17,6 +17,13 @@ find -name Cargo.toml \
|
|||||||
-not -path ./crates/wasi-common/WASI/tools/witx/Cargo.toml \
|
-not -path ./crates/wasi-common/WASI/tools/witx/Cargo.toml \
|
||||||
-exec sed -i.bk -e "s/^version = \"[[:digit:]].*/version = \"$version\"/" {} \;
|
-exec sed -i.bk -e "s/^version = \"[[:digit:]].*/version = \"$version\"/" {} \;
|
||||||
|
|
||||||
|
# Update the required version numbers of path dependencies.
|
||||||
|
find -name Cargo.toml \
|
||||||
|
-not -path ./crates/wasi-common/wig/WASI/tools/witx/Cargo.toml \
|
||||||
|
-exec sed -i.bk \
|
||||||
|
-e "/\> *= *{.*\<path *= *\"/s/version = \"[^\"]*\"/version = \"$version\"/" \
|
||||||
|
{} \;
|
||||||
|
|
||||||
# Update our local Cargo.lock (not checked in).
|
# Update our local Cargo.lock (not checked in).
|
||||||
cargo update
|
cargo update
|
||||||
scripts/test-all.sh
|
scripts/test-all.sh
|
||||||
@@ -42,10 +49,10 @@ for cargo_toml in \
|
|||||||
crates/runtime/Cargo.toml \
|
crates/runtime/Cargo.toml \
|
||||||
crates/debug/Cargo.toml \
|
crates/debug/Cargo.toml \
|
||||||
crates/jit/Cargo.toml \
|
crates/jit/Cargo.toml \
|
||||||
crates/wast/Cargo.toml \
|
|
||||||
crates/wasi-c/Cargo.toml \
|
crates/wasi-c/Cargo.toml \
|
||||||
crates/wasi/Cargo.toml \
|
|
||||||
crates/api/Cargo.toml \
|
crates/api/Cargo.toml \
|
||||||
|
crates/wasi/Cargo.toml \
|
||||||
|
crates/wast/Cargo.toml \
|
||||||
crates/interface-types/Cargo.toml \
|
crates/interface-types/Cargo.toml \
|
||||||
crates/misc/py/Cargo.toml \
|
crates/misc/py/Cargo.toml \
|
||||||
crates/misc/rust/macro/Cargo.toml \
|
crates/misc/rust/macro/Cargo.toml \
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ use std::{
|
|||||||
};
|
};
|
||||||
use structopt::{clap::AppSettings, StructOpt};
|
use structopt::{clap::AppSettings, StructOpt};
|
||||||
use wasi_common::preopen_dir;
|
use wasi_common::preopen_dir;
|
||||||
use wasmtime::{Config, Engine, HostRef, Instance, Module, Store};
|
use wasmtime::{Config, Engine, Instance, Module, Store};
|
||||||
use wasmtime_environ::cache_init;
|
use wasmtime_environ::cache_init;
|
||||||
use wasmtime_interface_types::ModuleData;
|
use wasmtime_interface_types::ModuleData;
|
||||||
use wasmtime_wasi::{
|
use wasmtime_wasi::{
|
||||||
@@ -148,7 +148,7 @@ impl RunCommand {
|
|||||||
let preopen_dirs = self.compute_preopen_dirs()?;
|
let preopen_dirs = self.compute_preopen_dirs()?;
|
||||||
let argv = self.compute_argv();
|
let argv = self.compute_argv();
|
||||||
|
|
||||||
let wasi_unstable = HostRef::new(if self.enable_wasi_c {
|
let wasi_unstable = if self.enable_wasi_c {
|
||||||
#[cfg(feature = "wasi-c")]
|
#[cfg(feature = "wasi-c")]
|
||||||
{
|
{
|
||||||
let global_exports = store.global_exports().clone();
|
let global_exports = store.global_exports().clone();
|
||||||
@@ -161,14 +161,10 @@ impl RunCommand {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
create_wasi_instance_snapshot_0(&store, &preopen_dirs, &argv, &self.vars)?
|
create_wasi_instance_snapshot_0(&store, &preopen_dirs, &argv, &self.vars)?
|
||||||
});
|
};
|
||||||
|
|
||||||
let wasi_snapshot_preview1 = HostRef::new(create_wasi_instance(
|
let wasi_snapshot_preview1 =
|
||||||
&store,
|
create_wasi_instance(&store, &preopen_dirs, &argv, &self.vars)?;
|
||||||
&preopen_dirs,
|
|
||||||
&argv,
|
|
||||||
&self.vars,
|
|
||||||
)?);
|
|
||||||
|
|
||||||
module_registry.insert("wasi_unstable".to_owned(), wasi_unstable);
|
module_registry.insert("wasi_unstable".to_owned(), wasi_unstable);
|
||||||
module_registry.insert("wasi_snapshot_preview1".to_owned(), wasi_snapshot_preview1);
|
module_registry.insert("wasi_snapshot_preview1".to_owned(), wasi_snapshot_preview1);
|
||||||
@@ -232,9 +228,9 @@ impl RunCommand {
|
|||||||
|
|
||||||
fn instantiate_module(
|
fn instantiate_module(
|
||||||
store: &Store,
|
store: &Store,
|
||||||
module_registry: &HashMap<String, HostRef<Instance>>,
|
module_registry: &HashMap<String, Instance>,
|
||||||
path: &Path,
|
path: &Path,
|
||||||
) -> Result<(HostRef<Instance>, Module, Vec<u8>)> {
|
) -> Result<(Instance, Module, Vec<u8>)> {
|
||||||
// Read the wasm module binary either as `*.wat` or a raw binary
|
// Read the wasm module binary either as `*.wat` or a raw binary
|
||||||
let data = wat::parse_file(path)?;
|
let data = wat::parse_file(path)?;
|
||||||
|
|
||||||
@@ -248,7 +244,7 @@ impl RunCommand {
|
|||||||
let module_name = i.module();
|
let module_name = i.module();
|
||||||
if let Some(instance) = module_registry.get(module_name) {
|
if let Some(instance) = module_registry.get(module_name) {
|
||||||
let field_name = i.name();
|
let field_name = i.name();
|
||||||
if let Some(export) = instance.borrow().find_export_by_name(field_name) {
|
if let Some(export) = instance.find_export_by_name(field_name) {
|
||||||
Ok(export.clone())
|
Ok(export.clone())
|
||||||
} else {
|
} else {
|
||||||
bail!(
|
bail!(
|
||||||
@@ -263,10 +259,8 @@ impl RunCommand {
|
|||||||
})
|
})
|
||||||
.collect::<Result<Vec<_>, _>>()?;
|
.collect::<Result<Vec<_>, _>>()?;
|
||||||
|
|
||||||
let instance = HostRef::new(
|
let instance = Instance::new(&module, &imports)
|
||||||
Instance::new(store, &module, &imports)
|
.context(format!("failed to instantiate {:?}", path))?;
|
||||||
.context(format!("failed to instantiate {:?}", path))?,
|
|
||||||
);
|
|
||||||
|
|
||||||
Ok((instance, module, data))
|
Ok((instance, module, data))
|
||||||
}
|
}
|
||||||
@@ -274,7 +268,7 @@ impl RunCommand {
|
|||||||
fn handle_module(
|
fn handle_module(
|
||||||
&self,
|
&self,
|
||||||
store: &Store,
|
store: &Store,
|
||||||
module_registry: &HashMap<String, HostRef<Instance>>,
|
module_registry: &HashMap<String, Instance>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let (instance, module, data) =
|
let (instance, module, data) =
|
||||||
Self::instantiate_module(store, module_registry, &self.module)?;
|
Self::instantiate_module(store, module_registry, &self.module)?;
|
||||||
@@ -301,16 +295,11 @@ impl RunCommand {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn invoke_export(
|
fn invoke_export(&self, instance: Instance, data: &ModuleData, name: &str) -> Result<()> {
|
||||||
&self,
|
|
||||||
instance: HostRef<Instance>,
|
|
||||||
data: &ModuleData,
|
|
||||||
name: &str,
|
|
||||||
) -> Result<()> {
|
|
||||||
use wasm_webidl_bindings::ast;
|
use wasm_webidl_bindings::ast;
|
||||||
use wasmtime_interface_types::Value;
|
use wasmtime_interface_types::Value;
|
||||||
|
|
||||||
let mut handle = instance.borrow().handle().clone();
|
let mut handle = instance.handle().clone();
|
||||||
|
|
||||||
// Use the binding information in `ModuleData` to figure out what arguments
|
// Use the binding information in `ModuleData` to figure out what arguments
|
||||||
// need to be passed to the function that we're invoking. Currently we take
|
// need to be passed to the function that we're invoking. Currently we take
|
||||||
|
|||||||
@@ -154,7 +154,7 @@ impl WasmToObjCommand {
|
|||||||
&module_translation,
|
&module_translation,
|
||||||
lazy_function_body_inputs,
|
lazy_function_body_inputs,
|
||||||
&*isa,
|
&*isa,
|
||||||
generate_debug_info,
|
self.common.debug_info,
|
||||||
),
|
),
|
||||||
#[cfg(not(feature = "lightbeam"))]
|
#[cfg(not(feature = "lightbeam"))]
|
||||||
Strategy::Lightbeam => bail!("lightbeam support not enabled"),
|
Strategy::Lightbeam => bail!("lightbeam support not enabled"),
|
||||||
|
|||||||
@@ -1,24 +1,54 @@
|
|||||||
#[cfg(not(target_os = "windows"))]
|
#[cfg(not(target_os = "windows"))]
|
||||||
mod tests {
|
mod tests {
|
||||||
use core::cell::Ref;
|
use anyhow::Result;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
use wasmtime::*;
|
use wasmtime::*;
|
||||||
use wasmtime_interface_types::{ModuleData, Value};
|
|
||||||
|
|
||||||
fn invoke_export(
|
const WAT1: &str = r#"
|
||||||
instance: &HostRef<Instance>,
|
(module
|
||||||
data: &[u8],
|
(func $read (export "read") (result i32)
|
||||||
func_name: &str,
|
(i32.load (i32.const 0))
|
||||||
) -> Result<Vec<Value>, anyhow::Error> {
|
)
|
||||||
ModuleData::new(&data)
|
(func $read_out_of_bounds (export "read_out_of_bounds") (result i32)
|
||||||
.expect("module data")
|
(i32.load
|
||||||
.invoke_export(instance, func_name, &[])
|
(i32.mul
|
||||||
|
;; memory size in Wasm pages
|
||||||
|
(memory.size)
|
||||||
|
;; Wasm page size
|
||||||
|
(i32.const 65536)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(func $start
|
||||||
|
(i32.store (i32.const 0) (i32.const 123))
|
||||||
|
)
|
||||||
|
(start $start)
|
||||||
|
(memory (export "memory") 1 4)
|
||||||
|
)
|
||||||
|
"#;
|
||||||
|
|
||||||
|
const WAT2: &str = r#"
|
||||||
|
(module
|
||||||
|
(import "other_module" "read" (func $other_module.read (result i32)))
|
||||||
|
(func $run (export "run") (result i32)
|
||||||
|
call $other_module.read)
|
||||||
|
)
|
||||||
|
"#;
|
||||||
|
|
||||||
|
fn invoke_export(instance: &Instance, func_name: &str) -> Result<Box<[Val]>, Trap> {
|
||||||
|
let ret = instance
|
||||||
|
.find_export_by_name(func_name)
|
||||||
|
.unwrap()
|
||||||
|
.func()
|
||||||
|
.unwrap()
|
||||||
|
.call(&[])?;
|
||||||
|
Ok(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Locate "memory" export, get base address and size and set memory protection to PROT_NONE
|
// Locate "memory" export, get base address and size and set memory protection to PROT_NONE
|
||||||
fn set_up_memory(instance: &HostRef<Instance>) -> (*mut u8, usize) {
|
fn set_up_memory(instance: &Instance) -> (*mut u8, usize) {
|
||||||
let mem_export = instance.borrow().get_wasmtime_memory().expect("memory");
|
let mem_export = instance.get_wasmtime_memory().expect("memory");
|
||||||
|
|
||||||
let (base, length) = if let wasmtime_runtime::Export::Memory {
|
let (base, length) = if let wasmtime_runtime::Export::Memory {
|
||||||
definition,
|
definition,
|
||||||
@@ -73,39 +103,34 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_custom_signal_handler_single_instance() {
|
fn test_custom_signal_handler_single_instance() -> Result<()> {
|
||||||
let engine = HostRef::new(Engine::new(&Config::default()));
|
let engine = Engine::new(&Config::default());
|
||||||
let store = HostRef::new(Store::new(&engine));
|
let store = Store::new(&engine);
|
||||||
let data =
|
let data = wat::parse_str(WAT1)?;
|
||||||
std::fs::read("tests/custom_signal_handler.wasm").expect("failed to read wasm file");
|
let module = Module::new(&store, &data)?;
|
||||||
let module = HostRef::new(Module::new(&store, &data).expect("failed to create module"));
|
let instance = Instance::new(&module, &[])?;
|
||||||
let instance = HostRef::new(
|
|
||||||
Instance::new(&store, &module, &[]).expect("failed to instantiate module"),
|
|
||||||
);
|
|
||||||
|
|
||||||
let (base, length) = set_up_memory(&instance);
|
let (base, length) = set_up_memory(&instance);
|
||||||
instance
|
instance.set_signal_handler(move |signum, siginfo, _| {
|
||||||
.borrow_mut()
|
handle_sigsegv(base, length, signum, siginfo)
|
||||||
.set_signal_handler(move |signum, siginfo, _| {
|
});
|
||||||
handle_sigsegv(base, length, signum, siginfo)
|
|
||||||
});
|
|
||||||
|
|
||||||
let exports = Ref::map(instance.borrow(), |instance| instance.exports());
|
let exports = instance.exports();
|
||||||
assert!(!exports.is_empty());
|
assert!(!exports.is_empty());
|
||||||
|
|
||||||
// these invoke wasmtime_call_trampoline from action.rs
|
// these invoke wasmtime_call_trampoline from action.rs
|
||||||
{
|
{
|
||||||
println!("calling read...");
|
println!("calling read...");
|
||||||
let result = invoke_export(&instance, &data, "read").expect("read succeeded");
|
let result = invoke_export(&instance, "read").expect("read succeeded");
|
||||||
assert_eq!("123", result[0].clone().to_string());
|
assert_eq!(123, result[0].unwrap_i32());
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
println!("calling read_out_of_bounds...");
|
println!("calling read_out_of_bounds...");
|
||||||
let trap = invoke_export(&instance, &data, "read_out_of_bounds").unwrap_err();
|
let trap = invoke_export(&instance, "read_out_of_bounds").unwrap_err();
|
||||||
assert!(trap.root_cause().to_string().starts_with(
|
assert!(trap
|
||||||
"trapped: Ref(Trap { message: \"wasm trap: out of bounds memory access"
|
.message()
|
||||||
));
|
.starts_with("call error: wasm trap: out of bounds memory access"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// these invoke wasmtime_call_trampoline from callable.rs
|
// these invoke wasmtime_call_trampoline from callable.rs
|
||||||
@@ -114,10 +139,7 @@ mod tests {
|
|||||||
.func()
|
.func()
|
||||||
.expect("expected a 'read' func in the module");
|
.expect("expected a 'read' func in the module");
|
||||||
println!("calling read...");
|
println!("calling read...");
|
||||||
let result = read_func
|
let result = read_func.call(&[]).expect("expected function not to trap");
|
||||||
.borrow()
|
|
||||||
.call(&[])
|
|
||||||
.expect("expected function not to trap");
|
|
||||||
assert_eq!(123i32, result[0].clone().unwrap_i32());
|
assert_eq!(123i32, result[0].clone().unwrap_i32());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,33 +148,30 @@ mod tests {
|
|||||||
.func()
|
.func()
|
||||||
.expect("expected a 'read_out_of_bounds' func in the module");
|
.expect("expected a 'read_out_of_bounds' func in the module");
|
||||||
println!("calling read_out_of_bounds...");
|
println!("calling read_out_of_bounds...");
|
||||||
let trap = read_out_of_bounds_func.borrow().call(&[]).unwrap_err();
|
let trap = read_out_of_bounds_func.call(&[]).unwrap_err();
|
||||||
assert!(trap
|
assert!(trap
|
||||||
.borrow()
|
|
||||||
.message()
|
.message()
|
||||||
.starts_with("wasm trap: out of bounds memory access"));
|
.starts_with("call error: wasm trap: out of bounds memory access"));
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_custom_signal_handler_multiple_instances() {
|
fn test_custom_signal_handler_multiple_instances() -> Result<()> {
|
||||||
let engine = HostRef::new(Engine::new(&Config::default()));
|
let engine = Engine::new(&Config::default());
|
||||||
let store = HostRef::new(Store::new(&engine));
|
let store = Store::new(&engine);
|
||||||
let data =
|
let data = wat::parse_str(WAT1)?;
|
||||||
std::fs::read("tests/custom_signal_handler.wasm").expect("failed to read wasm file");
|
let module = Module::new(&store, &data)?;
|
||||||
let module = HostRef::new(Module::new(&store, &data).expect("failed to create module"));
|
|
||||||
|
|
||||||
// Set up multiple instances
|
// Set up multiple instances
|
||||||
|
|
||||||
let instance1 = HostRef::new(
|
let instance1 = Instance::new(&module, &[])?;
|
||||||
Instance::new(&store, &module, &[]).expect("failed to instantiate module"),
|
|
||||||
);
|
|
||||||
let instance1_handler_triggered = Rc::new(AtomicBool::new(false));
|
let instance1_handler_triggered = Rc::new(AtomicBool::new(false));
|
||||||
|
|
||||||
{
|
{
|
||||||
let (base1, length1) = set_up_memory(&instance1);
|
let (base1, length1) = set_up_memory(&instance1);
|
||||||
|
|
||||||
instance1.borrow_mut().set_signal_handler({
|
instance1.set_signal_handler({
|
||||||
let instance1_handler_triggered = instance1_handler_triggered.clone();
|
let instance1_handler_triggered = instance1_handler_triggered.clone();
|
||||||
move |_signum, _siginfo, _context| {
|
move |_signum, _siginfo, _context| {
|
||||||
// Remove protections so the execution may resume
|
// Remove protections so the execution may resume
|
||||||
@@ -173,15 +192,13 @@ mod tests {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let instance2 = HostRef::new(
|
let instance2 = Instance::new(&module, &[]).expect("failed to instantiate module");
|
||||||
Instance::new(&store, &module, &[]).expect("failed to instantiate module"),
|
|
||||||
);
|
|
||||||
let instance2_handler_triggered = Rc::new(AtomicBool::new(false));
|
let instance2_handler_triggered = Rc::new(AtomicBool::new(false));
|
||||||
|
|
||||||
{
|
{
|
||||||
let (base2, length2) = set_up_memory(&instance2);
|
let (base2, length2) = set_up_memory(&instance2);
|
||||||
|
|
||||||
instance2.borrow_mut().set_signal_handler({
|
instance2.set_signal_handler({
|
||||||
let instance2_handler_triggered = instance2_handler_triggered.clone();
|
let instance2_handler_triggered = instance2_handler_triggered.clone();
|
||||||
move |_signum, _siginfo, _context| {
|
move |_signum, _siginfo, _context| {
|
||||||
// Remove protections so the execution may resume
|
// Remove protections so the execution may resume
|
||||||
@@ -206,12 +223,12 @@ mod tests {
|
|||||||
|
|
||||||
// First instance1
|
// First instance1
|
||||||
{
|
{
|
||||||
let exports1 = Ref::map(instance1.borrow(), |i| i.exports());
|
let exports1 = instance1.exports();
|
||||||
assert!(!exports1.is_empty());
|
assert!(!exports1.is_empty());
|
||||||
|
|
||||||
println!("calling instance1.read...");
|
println!("calling instance1.read...");
|
||||||
let result = invoke_export(&instance1, &data, "read").expect("read succeeded");
|
let result = invoke_export(&instance1, "read").expect("read succeeded");
|
||||||
assert_eq!("123", result[0].clone().to_string());
|
assert_eq!(123, result[0].unwrap_i32());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
instance1_handler_triggered.load(Ordering::SeqCst),
|
instance1_handler_triggered.load(Ordering::SeqCst),
|
||||||
true,
|
true,
|
||||||
@@ -221,62 +238,53 @@ mod tests {
|
|||||||
|
|
||||||
// And then instance2
|
// And then instance2
|
||||||
{
|
{
|
||||||
let exports2 = Ref::map(instance2.borrow(), |i| i.exports());
|
let exports2 = instance2.exports();
|
||||||
assert!(!exports2.is_empty());
|
assert!(!exports2.is_empty());
|
||||||
|
|
||||||
println!("calling instance2.read...");
|
println!("calling instance2.read...");
|
||||||
let result = invoke_export(&instance2, &data, "read").expect("read succeeded");
|
let result = invoke_export(&instance2, "read").expect("read succeeded");
|
||||||
assert_eq!("123", result[0].clone().to_string());
|
assert_eq!(123, result[0].unwrap_i32());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
instance2_handler_triggered.load(Ordering::SeqCst),
|
instance2_handler_triggered.load(Ordering::SeqCst),
|
||||||
true,
|
true,
|
||||||
"instance1 signal handler has been triggered"
|
"instance1 signal handler has been triggered"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_custom_signal_handler_instance_calling_another_instance() {
|
fn test_custom_signal_handler_instance_calling_another_instance() -> Result<()> {
|
||||||
let engine = HostRef::new(Engine::new(&Config::default()));
|
let engine = Engine::new(&Config::default());
|
||||||
let store = HostRef::new(Store::new(&engine));
|
let store = Store::new(&engine);
|
||||||
|
|
||||||
// instance1 which defines 'read'
|
// instance1 which defines 'read'
|
||||||
let data1 =
|
let data1 = wat::parse_str(WAT1)?;
|
||||||
std::fs::read("tests/custom_signal_handler.wasm").expect("failed to read wasm file");
|
let module1 = Module::new(&store, &data1)?;
|
||||||
let module1 = HostRef::new(Module::new(&store, &data1).expect("failed to create module"));
|
let instance1 = Instance::new(&module1, &[])?;
|
||||||
let instance1: HostRef<Instance> = HostRef::new(
|
|
||||||
Instance::new(&store, &module1, &[]).expect("failed to instantiate module"),
|
|
||||||
);
|
|
||||||
let (base1, length1) = set_up_memory(&instance1);
|
let (base1, length1) = set_up_memory(&instance1);
|
||||||
instance1
|
instance1.set_signal_handler(move |signum, siginfo, _| {
|
||||||
.borrow_mut()
|
println!("instance1");
|
||||||
.set_signal_handler(move |signum, siginfo, _| {
|
handle_sigsegv(base1, length1, signum, siginfo)
|
||||||
println!("instance1");
|
});
|
||||||
handle_sigsegv(base1, length1, signum, siginfo)
|
|
||||||
});
|
|
||||||
|
|
||||||
let instance1_exports = Ref::map(instance1.borrow(), |i| i.exports());
|
let instance1_exports = instance1.exports();
|
||||||
assert!(!instance1_exports.is_empty());
|
assert!(!instance1_exports.is_empty());
|
||||||
let instance1_read = instance1_exports[0].clone();
|
let instance1_read = instance1_exports[0].clone();
|
||||||
|
|
||||||
// instance2 wich calls 'instance1.read'
|
// instance2 wich calls 'instance1.read'
|
||||||
let data2 =
|
let data2 = wat::parse_str(WAT2)?;
|
||||||
std::fs::read("tests/custom_signal_handler_2.wasm").expect("failed to read wasm file");
|
let module2 = Module::new(&store, &data2)?;
|
||||||
let module2 = HostRef::new(Module::new(&store, &data2).expect("failed to create module"));
|
let instance2 = Instance::new(&module2, &[instance1_read])?;
|
||||||
let instance2 = HostRef::new(
|
|
||||||
Instance::new(&store, &module2, &[instance1_read])
|
|
||||||
.expect("failed to instantiate module"),
|
|
||||||
);
|
|
||||||
// since 'instance2.run' calls 'instance1.read' we need to set up the signal handler to handle
|
// since 'instance2.run' calls 'instance1.read' we need to set up the signal handler to handle
|
||||||
// SIGSEGV originating from within the memory of instance1
|
// SIGSEGV originating from within the memory of instance1
|
||||||
instance2
|
instance2.set_signal_handler(move |signum, siginfo, _| {
|
||||||
.borrow_mut()
|
handle_sigsegv(base1, length1, signum, siginfo)
|
||||||
.set_signal_handler(move |signum, siginfo, _| {
|
});
|
||||||
handle_sigsegv(base1, length1, signum, siginfo)
|
|
||||||
});
|
|
||||||
|
|
||||||
println!("calling instance2.run");
|
println!("calling instance2.run");
|
||||||
let result = invoke_export(&instance2, &data2, "run").expect("instance2.run succeeded");
|
let result = invoke_export(&instance2, "run")?;
|
||||||
assert_eq!("123", result[0].clone().to_string());
|
assert_eq!(123, result[0].unwrap_i32());
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
@@ -1,20 +0,0 @@
|
|||||||
(module
|
|
||||||
(func $read (export "read") (result i32)
|
|
||||||
(i32.load (i32.const 0))
|
|
||||||
)
|
|
||||||
(func $read_out_of_bounds (export "read_out_of_bounds") (result i32)
|
|
||||||
(i32.load
|
|
||||||
(i32.mul
|
|
||||||
;; memory size in Wasm pages
|
|
||||||
(memory.size)
|
|
||||||
;; Wasm page size
|
|
||||||
(i32.const 65536)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
(func $start
|
|
||||||
(i32.store (i32.const 0) (i32.const 123))
|
|
||||||
)
|
|
||||||
(start $start)
|
|
||||||
(memory (export "memory") 1 4)
|
|
||||||
)
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user