Merge branch 'master' into fix-c-api-wasi-version

This commit is contained in:
Ivan Enderlin
2021-01-28 09:18:30 +01:00
28 changed files with 634 additions and 504 deletions

View File

@@ -8,7 +8,10 @@
## **[Unreleased]** ## **[Unreleased]**
### Added ### Added
- [#2059](https://github.com/wasmerio/wasmer/pull/2059) Ability to capture `stdout` and `stderr` with WASI in the C API.
- [#2040](https://github.com/wasmerio/wasmer/pull/2040) Add `InstanceHandle::vmoffsets` to expose the offsets of the `vmctx` region.
- [#2026](https://github.com/wasmerio/wasmer/pull/2010) Expose trap code of a `RuntimeError`, if it's a `Trap`. - [#2026](https://github.com/wasmerio/wasmer/pull/2010) Expose trap code of a `RuntimeError`, if it's a `Trap`.
- [#2054](https://github.com/wasmerio/wasmer/pull/2054) Add `wasm_config_delete` to the Wasm C API.
### Changed ### Changed
- [#2042](https://github.com/wasmerio/wasmer/pull/2042) Parse more exotic environment variables in `wasmer run`. - [#2042](https://github.com/wasmerio/wasmer/pull/2042) Parse more exotic environment variables in `wasmer run`.

295
Cargo.lock generated
View File

@@ -93,12 +93,6 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "autocfg"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2"
[[package]] [[package]]
name = "autocfg" name = "autocfg"
version = "1.0.1" version = "1.0.1"
@@ -268,12 +262,12 @@ dependencies = [
] ]
[[package]] [[package]]
name = "cloudabi" name = "cmake"
version = "0.0.3" version = "0.1.45"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" checksum = "eb6210b637171dfba4cda12e579ac6dc73f5165ad56133e5d72ef3131f320855"
dependencies = [ dependencies = [
"bitflags", "cc",
] ]
[[package]] [[package]]
@@ -536,7 +530,7 @@ 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 = "02d96d1e189ef58269ebe5b97953da3274d83a93af647c2ddd6f9dab28cedb8d" checksum = "02d96d1e189ef58269ebe5b97953da3274d83a93af647c2ddd6f9dab28cedb8d"
dependencies = [ dependencies = [
"autocfg 1.0.1", "autocfg",
"cfg-if 1.0.0", "cfg-if 1.0.0",
"lazy_static", "lazy_static",
] ]
@@ -710,6 +704,15 @@ version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
[[package]]
name = "encoding_rs"
version = "0.8.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "801bbab217d7f79c0062f4f7205b5d4427c6d1a7bd7aafdd1475f7c59d62b283"
dependencies = [
"cfg-if 1.0.0",
]
[[package]] [[package]]
name = "enumset" name = "enumset"
version = "1.0.2" version = "1.0.2"
@@ -764,10 +767,22 @@ checksum = "0c122a393ea57648015bf06fbd3d372378992e86b9ff5a7a497b076a28c79efe"
dependencies = [ dependencies = [
"cfg-if 1.0.0", "cfg-if 1.0.0",
"libc", "libc",
"redox_syscall", "redox_syscall 0.1.57",
"winapi", "winapi",
] ]
[[package]]
name = "flate2"
version = "1.0.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7411863d55df97a419aa64cb4d2f167103ea9d767e2c54a1868b7ac3f6b47129"
dependencies = [
"cfg-if 1.0.0",
"crc32fast",
"libc",
"miniz_oxide",
]
[[package]] [[package]]
name = "float-cmp" name = "float-cmp"
version = "0.8.0" version = "0.8.0"
@@ -783,12 +798,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 = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "fuchsia-cprng"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
[[package]] [[package]]
name = "generational-arena" name = "generational-arena"
version = "0.2.8" version = "0.2.8"
@@ -907,7 +916,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96282e96bfcd3da0d3aa9938bedf1e50df3269b6db08b4876d2da0bb1a0841cf" checksum = "96282e96bfcd3da0d3aa9938bedf1e50df3269b6db08b4876d2da0bb1a0841cf"
dependencies = [ dependencies = [
"ahash 0.3.8", "ahash 0.3.8",
"autocfg 1.0.1", "autocfg",
] ]
[[package]] [[package]]
@@ -955,7 +964,7 @@ version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55e2e4c765aa53a0424761bf9f41aa7a6ac1efa87238f59560640e27fca028f2" checksum = "55e2e4c765aa53a0424761bf9f41aa7a6ac1efa87238f59560640e27fca028f2"
dependencies = [ dependencies = [
"autocfg 1.0.1", "autocfg",
"hashbrown 0.9.1", "hashbrown 0.9.1",
"serde", "serde",
] ]
@@ -1200,7 +1209,7 @@ version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "157b4208e3059a8f9e78d559edc658e13df41410cb3ae03979c83130067fdd87" checksum = "157b4208e3059a8f9e78d559edc658e13df41410cb3ae03979c83130067fdd87"
dependencies = [ dependencies = [
"autocfg 1.0.1", "autocfg",
] ]
[[package]] [[package]]
@@ -1229,7 +1238,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f2d26ec3309788e423cfbf68ad1800f061638098d76a83681af979dc4eda19d" checksum = "0f2d26ec3309788e423cfbf68ad1800f061638098d76a83681af979dc4eda19d"
dependencies = [ dependencies = [
"adler", "adler",
"autocfg 1.0.1", "autocfg",
] ]
[[package]] [[package]]
@@ -1277,45 +1286,13 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be"
[[package]]
name = "num"
version = "0.1.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4703ad64153382334aa8db57c637364c322d3372e097840c72000dabdcf6156e"
dependencies = [
"num-integer",
"num-iter",
"num-traits",
]
[[package]]
name = "num-integer"
version = "0.1.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"
dependencies = [
"autocfg 1.0.1",
"num-traits",
]
[[package]]
name = "num-iter"
version = "0.1.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2021c8337a54d21aca0d59a92577a029af9431cb59b909b03252b9c164fad59"
dependencies = [
"autocfg 1.0.1",
"num-integer",
"num-traits",
]
[[package]] [[package]]
name = "num-traits" name = "num-traits"
version = "0.2.14" 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 = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
dependencies = [ dependencies = [
"autocfg 1.0.1", "autocfg",
] ]
[[package]] [[package]]
@@ -1352,12 +1329,15 @@ checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575"
[[package]] [[package]]
name = "orbclient" name = "orbclient"
version = "0.3.27" version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8b18f57ab94fbd058e30aa57f712ec423c0bb7403f8493a6c58eef0c36d9402" checksum = "ee68c3c79e81d82127e0870f94479675774d34c7ad5b55eecb9c320ef9701187"
dependencies = [ dependencies = [
"redox_syscall", "libc",
"raw-window-handle",
"redox_syscall 0.2.4",
"sdl2", "sdl2",
"sdl2-sys",
] ]
[[package]] [[package]]
@@ -1380,7 +1360,7 @@ dependencies = [
"cfg-if 1.0.0", "cfg-if 1.0.0",
"instant", "instant",
"libc", "libc",
"redox_syscall", "redox_syscall 0.1.57",
"smallvec", "smallvec",
"winapi", "winapi",
] ]
@@ -1507,25 +1487,6 @@ dependencies = [
"proc-macro2", "proc-macro2",
] ]
[[package]]
name = "rand"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
dependencies = [
"autocfg 0.1.7",
"libc",
"rand_chacha 0.1.1",
"rand_core 0.4.2",
"rand_hc 0.1.0",
"rand_isaac",
"rand_jitter",
"rand_os",
"rand_pcg",
"rand_xorshift",
"winapi",
]
[[package]] [[package]]
name = "rand" name = "rand"
version = "0.7.3" version = "0.7.3"
@@ -1534,19 +1495,9 @@ checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
dependencies = [ dependencies = [
"getrandom 0.1.15", "getrandom 0.1.15",
"libc", "libc",
"rand_chacha 0.2.2", "rand_chacha",
"rand_core 0.5.1", "rand_core",
"rand_hc 0.2.0", "rand_hc",
]
[[package]]
name = "rand_chacha"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
dependencies = [
"autocfg 0.1.7",
"rand_core 0.3.1",
] ]
[[package]] [[package]]
@@ -1556,24 +1507,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
dependencies = [ dependencies = [
"ppv-lite86", "ppv-lite86",
"rand_core 0.5.1", "rand_core",
] ]
[[package]]
name = "rand_core"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
dependencies = [
"rand_core 0.4.2",
]
[[package]]
name = "rand_core"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
[[package]] [[package]]
name = "rand_core" name = "rand_core"
version = "0.5.1" version = "0.5.1"
@@ -1583,75 +1519,13 @@ dependencies = [
"getrandom 0.1.15", "getrandom 0.1.15",
] ]
[[package]]
name = "rand_hc"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4"
dependencies = [
"rand_core 0.3.1",
]
[[package]] [[package]]
name = "rand_hc" name = "rand_hc"
version = "0.2.0" version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
dependencies = [ dependencies = [
"rand_core 0.5.1", "rand_core",
]
[[package]]
name = "rand_isaac"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08"
dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "rand_jitter"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b"
dependencies = [
"libc",
"rand_core 0.4.2",
"winapi",
]
[[package]]
name = "rand_os"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071"
dependencies = [
"cloudabi",
"fuchsia-cprng",
"libc",
"rand_core 0.4.2",
"rdrand",
"winapi",
]
[[package]]
name = "rand_pcg"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44"
dependencies = [
"autocfg 0.1.7",
"rand_core 0.4.2",
]
[[package]]
name = "rand_xorshift"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c"
dependencies = [
"rand_core 0.3.1",
] ]
[[package]] [[package]]
@@ -1678,7 +1552,7 @@ version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b0d8e0819fadc20c74ea8373106ead0600e3a67ef1fe8da56e39b9ae7275674" checksum = "8b0d8e0819fadc20c74ea8373106ead0600e3a67ef1fe8da56e39b9ae7275674"
dependencies = [ dependencies = [
"autocfg 1.0.1", "autocfg",
"crossbeam-deque", "crossbeam-deque",
"either", "either",
"rayon-core", "rayon-core",
@@ -1697,21 +1571,21 @@ dependencies = [
"num_cpus", "num_cpus",
] ]
[[package]]
name = "rdrand"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
dependencies = [
"rand_core 0.3.1",
]
[[package]] [[package]]
name = "redox_syscall" name = "redox_syscall"
version = "0.1.57" version = "0.1.57"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
[[package]]
name = "redox_syscall"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05ec8ca9416c5ea37062b502703cd7fcb207736bc294f6e0cf367ac6fc234570"
dependencies = [
"bitflags",
]
[[package]] [[package]]
name = "redox_users" name = "redox_users"
version = "0.3.5" version = "0.3.5"
@@ -1719,7 +1593,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de0737333e7a9502c789a36d7c7fa6092a49895d4faa31ca5df163857ded2e9d" checksum = "de0737333e7a9502c789a36d7c7fa6092a49895d4faa31ca5df163857ded2e9d"
dependencies = [ dependencies = [
"getrandom 0.1.15", "getrandom 0.1.15",
"redox_syscall", "redox_syscall 0.1.57",
"rust-argon2", "rust-argon2",
] ]
@@ -1896,26 +1770,30 @@ dependencies = [
[[package]] [[package]]
name = "sdl2" name = "sdl2"
version = "0.32.2" version = "0.34.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d051a07231e303f5f719da78cb6f7394f6d5b54f733aef5b0b447804a83edd7b" checksum = "fcbb85f4211627a7291c83434d6bbfa723e28dcaa53c7606087e3c61929e4b9c"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"lazy_static", "lazy_static",
"libc", "libc",
"num", "raw-window-handle",
"rand 0.6.5",
"sdl2-sys", "sdl2-sys",
] ]
[[package]] [[package]]
name = "sdl2-sys" name = "sdl2-sys"
version = "0.32.6" version = "0.34.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34e71125077d297d57e4c1acfe8981b5bdfbf5a20e7b589abfdcb33bf1127f86" checksum = "28d81feded049b9c14eceb4a4f6d596a98cebbd59abdba949c5552a015466d33"
dependencies = [ dependencies = [
"cfg-if 0.1.10", "cfg-if 0.1.10",
"cmake",
"flate2",
"libc", "libc",
"tar",
"unidiff",
"version-compare",
] ]
[[package]] [[package]]
@@ -2015,7 +1893,7 @@ checksum = "2c29947abdee2a218277abeca306f25789c938e500ea5a9d4b12a5a504466902"
dependencies = [ dependencies = [
"cfg-if 1.0.0", "cfg-if 1.0.0",
"libc", "libc",
"redox_syscall", "redox_syscall 0.1.57",
"winapi", "winapi",
] ]
@@ -2078,6 +1956,17 @@ dependencies = [
"unicode-xid", "unicode-xid",
] ]
[[package]]
name = "tar"
version = "0.4.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0313546c01d59e29be4f09687bcb4fb6690cec931cc3607b6aec7a0e417f4cc6"
dependencies = [
"filetime",
"libc",
"xattr",
]
[[package]] [[package]]
name = "target-lexicon" name = "target-lexicon"
version = "0.11.1" version = "0.11.1"
@@ -2092,8 +1981,8 @@ checksum = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9"
dependencies = [ dependencies = [
"cfg-if 0.1.10", "cfg-if 0.1.10",
"libc", "libc",
"rand 0.7.3", "rand",
"redox_syscall", "redox_syscall 0.1.57",
"remove_dir_all", "remove_dir_all",
"winapi", "winapi",
] ]
@@ -2288,12 +2177,29 @@ 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 = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
[[package]]
name = "unidiff"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8a62719acf1933bfdbeb73a657ecd9ecece70b405125267dd549e2e2edc232c"
dependencies = [
"encoding_rs",
"lazy_static",
"regex",
]
[[package]] [[package]]
name = "vec_map" name = "vec_map"
version = "0.8.2" 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 = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
[[package]]
name = "version-compare"
version = "0.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d63556a25bae6ea31b52e640d7c41d1ab27faba4ccb600013837a3d0b3994ca1"
[[package]] [[package]]
name = "version_check" name = "version_check"
version = "0.9.2" version = "0.9.2"
@@ -2973,6 +2879,15 @@ dependencies = [
"pkg-config", "pkg-config",
] ]
[[package]]
name = "xattr"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "244c3741f4240ef46274860397c7c74e50eb23624996930e484c16679633a54c"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "xcursor" name = "xcursor"
version = "0.3.3" version = "0.3.3"

View File

@@ -100,7 +100,7 @@ where
Self { Self {
store: other.store, store: other.store,
definition: other.definition, definition: other.definition,
exported: other.exported.clone(), exported: other.exported,
} }
} }
} }

View File

@@ -240,6 +240,7 @@ fn new_builder(language: Language, crate_dir: &str, include_guard: &str, header:
Builder::new() Builder::new()
.with_config(cbindgen::Config { .with_config(cbindgen::Config {
sort_by: cbindgen::SortKey::Name, sort_by: cbindgen::SortKey::Name,
cpp_compat: true,
..cbindgen::Config::default() ..cbindgen::Config::default()
}) })
.with_language(language) .with_language(language)
@@ -401,13 +402,16 @@ fn exclude_items_from_deprecated(builder: Builder) -> Builder {
fn exclude_items_from_wasm_c_api(builder: Builder) -> Builder { fn exclude_items_from_wasm_c_api(builder: Builder) -> Builder {
builder builder
.exclude_item("wasi_config_arg") .exclude_item("wasi_config_arg")
.exclude_item("wasi_config_capture_stderr")
.exclude_item("wasi_config_capture_stdin")
.exclude_item("wasi_config_capture_stdout")
.exclude_item("wasi_config_env") .exclude_item("wasi_config_env")
.exclude_item("wasi_config_mapdir")
.exclude_item("wasi_config_preopen_dir")
.exclude_item("wasi_config_inherit_stderr") .exclude_item("wasi_config_inherit_stderr")
.exclude_item("wasi_config_inherit_stdin") .exclude_item("wasi_config_inherit_stdin")
.exclude_item("wasi_config_inherit_stdout") .exclude_item("wasi_config_inherit_stdout")
.exclude_item("wasi_config_mapdir")
.exclude_item("wasi_config_new") .exclude_item("wasi_config_new")
.exclude_item("wasi_config_preopen_dir")
.exclude_item("wasi_config_t") .exclude_item("wasi_config_t")
.exclude_item("wasi_env_delete") .exclude_item("wasi_env_delete")
.exclude_item("wasi_env_new") .exclude_item("wasi_env_new")

View File

@@ -131,6 +131,36 @@ pub extern "C" fn wasm_config_new() -> Box<wasm_config_t> {
Box::new(wasm_config_t::default()) Box::new(wasm_config_t::default())
} }
/// Delete a Wasmer config object.
///
/// This function does not need to be called if `wasm_engine_new_with_config` or
/// another function that takes ownership of the `wasm_config_t` is called.
///
/// # Example
///
/// ```rust
/// # use inline_c::assert_c;
/// # fn main() {
/// # (assert_c! {
/// # #include "tests/wasmer_wasm.h"
/// #
/// int main() {
/// // Create the configuration.
/// wasm_config_t* config = wasm_config_new();
///
/// // Delete the configuration
/// wasm_config_delete(config);
///
/// return 0;
/// }
/// # })
/// # .success();
/// # }
/// ```
/// cbindgen:ignore
#[no_mangle]
pub extern "C" fn wasm_config_delete(_config: Option<Box<wasm_config_t>>) {}
/// Updates the configuration to specify a particular compiler to use. /// Updates the configuration to specify a particular compiler to use.
/// ///
/// This is a Wasmer-specific function. /// This is a Wasmer-specific function.

View File

@@ -23,13 +23,12 @@ use wasmer_wasi::{
WasiStateBuilder, WasiVersion, WasiStateBuilder, WasiVersion,
}; };
#[derive(Debug, Default)] #[derive(Debug)]
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
pub struct wasi_config_t { pub struct wasi_config_t {
inherit_stdout: bool, inherit_stdout: bool,
inherit_stderr: bool, inherit_stderr: bool,
inherit_stdin: bool, inherit_stdin: bool,
/// cbindgen:ignore
state_builder: WasiStateBuilder, state_builder: WasiStateBuilder,
} }
@@ -43,8 +42,10 @@ pub unsafe extern "C" fn wasi_config_new(
let prog_name = c_try!(name_c_str.to_str()); let prog_name = c_try!(name_c_str.to_str());
Some(Box::new(wasi_config_t { Some(Box::new(wasi_config_t {
inherit_stdout: true,
inherit_stderr: true,
inherit_stdin: true,
state_builder: WasiState::new(prog_name), state_builder: WasiState::new(prog_name),
..wasi_config_t::default()
})) }))
} }
@@ -132,14 +133,31 @@ pub unsafe extern "C" fn wasi_config_mapdir(
true true
} }
#[no_mangle]
pub extern "C" fn wasi_config_capture_stdout(config: &mut wasi_config_t) {
config.inherit_stdout = false;
}
#[no_mangle] #[no_mangle]
pub extern "C" fn wasi_config_inherit_stdout(config: &mut wasi_config_t) { pub extern "C" fn wasi_config_inherit_stdout(config: &mut wasi_config_t) {
config.inherit_stdout = true; config.inherit_stdout = true;
} }
#[no_mangle]
pub extern "C" fn wasi_config_capture_stderr(config: &mut wasi_config_t) {
config.inherit_stderr = false;
}
#[no_mangle] #[no_mangle]
pub extern "C" fn wasi_config_inherit_stderr(config: &mut wasi_config_t) { pub extern "C" fn wasi_config_inherit_stderr(config: &mut wasi_config_t) {
config.inherit_stderr = true; config.inherit_stderr = true;
} }
//#[no_mangle]
//pub extern "C" fn wasi_config_capture_stdin(config: &mut wasi_config_t) {
// config.inherit_stdin = false;
//}
#[no_mangle] #[no_mangle]
pub extern "C" fn wasi_config_inherit_stdin(config: &mut wasi_config_t) { pub extern "C" fn wasi_config_inherit_stdin(config: &mut wasi_config_t) {
config.inherit_stdin = true; config.inherit_stdin = true;
@@ -154,18 +172,22 @@ pub struct wasi_env_t {
/// Takes ownership over the `wasi_config_t`. /// Takes ownership over the `wasi_config_t`.
#[no_mangle] #[no_mangle]
pub extern "C" fn wasi_env_new(mut config: Box<wasi_config_t>) -> Option<Box<wasi_env_t>> { pub extern "C" fn wasi_env_new(mut config: Box<wasi_config_t>) -> Option<Box<wasi_env_t>> {
if config.inherit_stdout { if !config.inherit_stdout {
config config
.state_builder .state_builder
.stdout(Box::new(capture_files::OutputCapturer::new())); .stdout(Box::new(capture_files::OutputCapturer::new()));
} }
if config.inherit_stderr {
if !config.inherit_stderr {
config config
.state_builder .state_builder
.stderr(Box::new(capture_files::OutputCapturer::new())); .stderr(Box::new(capture_files::OutputCapturer::new()));
} }
// TODO: impl capturer for stdin // TODO: impl capturer for stdin
let wasi_state = c_try!(config.state_builder.build()); let wasi_state = c_try!(config.state_builder.build());
Some(Box::new(wasi_env_t { Some(Box::new(wasi_env_t {
inner: WasiEnv::new(wasi_state), inner: WasiEnv::new(wasi_state),
})) }))

View File

@@ -55,7 +55,11 @@
#include <stdlib.h> #include <stdlib.h>
#if defined(WASMER_WASI_ENABLED) #if defined(WASMER_WASI_ENABLED)
enum Version { enum Version
#ifdef __cplusplus
: uint8_t
#endif // __cplusplus
{
#if defined(WASMER_WASI_ENABLED) #if defined(WASMER_WASI_ENABLED)
/** /**
* Version cannot be detected or is unknown. * Version cannot be detected or is unknown.
@@ -82,13 +86,19 @@ enum Version {
Snapshot1 = 3, Snapshot1 = 3,
#endif #endif
}; };
#ifndef __cplusplus
typedef uint8_t Version; typedef uint8_t Version;
#endif // __cplusplus
#endif #endif
/** /**
* List of export/import kinds. * List of export/import kinds.
*/ */
enum wasmer_import_export_kind { enum wasmer_import_export_kind
#ifdef __cplusplus
: uint32_t
#endif // __cplusplus
{
/** /**
* The export/import is a function. * The export/import is a function.
*/ */
@@ -106,7 +116,9 @@ enum wasmer_import_export_kind {
*/ */
WASM_TABLE = 3, WASM_TABLE = 3,
}; };
#ifndef __cplusplus
typedef uint32_t wasmer_import_export_kind; typedef uint32_t wasmer_import_export_kind;
#endif // __cplusplus
/** /**
* The `wasmer_result_t` enum is a type that represents either a * The `wasmer_result_t` enum is a type that represents either a
@@ -128,7 +140,11 @@ typedef enum {
* *
* See `wasmer_value_t` to get a complete example. * See `wasmer_value_t` to get a complete example.
*/ */
enum wasmer_value_tag { enum wasmer_value_tag
#ifdef __cplusplus
: uint32_t
#endif // __cplusplus
{
/** /**
* Represents the `i32` WebAssembly type. * Represents the `i32` WebAssembly type.
*/ */
@@ -146,7 +162,9 @@ enum wasmer_value_tag {
*/ */
WASM_F64, WASM_F64,
}; };
#ifndef __cplusplus
typedef uint32_t wasmer_value_tag; typedef uint32_t wasmer_value_tag;
#endif // __cplusplus
typedef struct { typedef struct {
@@ -409,6 +427,10 @@ typedef struct {
} wasmer_wasi_map_dir_entry_t; } wasmer_wasi_map_dir_entry_t;
#endif #endif
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
/** /**
* Creates a new Module from the given wasm bytes. * Creates a new Module from the given wasm bytes.
* *
@@ -1579,4 +1601,8 @@ wasmer_import_object_t *wasmer_wasi_generate_import_object_for_version(unsigned
Version wasmer_wasi_get_version(const wasmer_module_t *module); Version wasmer_wasi_get_version(const wasmer_module_t *module);
#endif #endif
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
#endif /* WASMER_H */ #endif /* WASMER_H */

View File

@@ -162,10 +162,26 @@ typedef struct wasi_config_t wasi_config_t;
typedef struct wasi_env_t wasi_env_t; typedef struct wasi_env_t wasi_env_t;
#endif #endif
#if defined(WASMER_WASI_ENABLED)
typedef struct wasi_version_t wasi_version_t;
#endif
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
#if defined(WASMER_WASI_ENABLED) #if defined(WASMER_WASI_ENABLED)
void wasi_config_arg(wasi_config_t *config, const char *arg); void wasi_config_arg(wasi_config_t *config, const char *arg);
#endif #endif
#if defined(WASMER_WASI_ENABLED)
void wasi_config_capture_stderr(wasi_config_t *config);
#endif
#if defined(WASMER_WASI_ENABLED)
void wasi_config_capture_stdout(wasi_config_t *config);
#endif
#if defined(WASMER_WASI_ENABLED) #if defined(WASMER_WASI_ENABLED)
void wasi_config_env(wasi_config_t *config, const char *key, const char *value); void wasi_config_env(wasi_config_t *config, const char *key, const char *value);
#endif #endif
@@ -597,4 +613,8 @@ const char *wasmer_version_pre(void);
*/ */
void wat2wasm(const wasm_byte_vec_t *wat, wasm_byte_vec_t *out); void wat2wasm(const wasm_byte_vec_t *wat, wasm_byte_vec_t *out);
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
#endif /* WASMER_WASM_H */ #endif /* WASMER_WASM_H */

View File

@@ -10,6 +10,9 @@ use inkwell::{
}; };
use wasmer_compiler::CompileError; use wasmer_compiler::CompileError;
use wasmer_types::{FunctionType as FuncSig, Type}; use wasmer_types::{FunctionType as FuncSig, Type};
use wasmer_vm::VMOffsets;
use std::convert::TryInto;
/// Implementation of the [`Abi`] trait for the Aarch64 ABI on Linux. /// Implementation of the [`Abi`] trait for the Aarch64 ABI on Linux.
pub struct Aarch64SystemV {} pub struct Aarch64SystemV {}
@@ -40,6 +43,7 @@ impl Abi for Aarch64SystemV {
&self, &self,
context: &'ctx Context, context: &'ctx Context,
intrinsics: &Intrinsics<'ctx>, intrinsics: &Intrinsics<'ctx>,
offsets: Option<&VMOffsets>,
sig: &FuncSig, sig: &FuncSig,
) -> Result<(FunctionType<'ctx>, Vec<(Attribute, AttributeLoc)>), CompileError> { ) -> Result<(FunctionType<'ctx>, Vec<(Attribute, AttributeLoc)>), CompileError> {
let user_param_types = sig.params().iter().map(|&ty| type_to_llvm(intrinsics, ty)); let user_param_types = sig.params().iter().map(|&ty| type_to_llvm(intrinsics, ty));
@@ -47,19 +51,49 @@ impl Abi for Aarch64SystemV {
let param_types = let param_types =
std::iter::once(Ok(intrinsics.ctx_ptr_ty.as_basic_type_enum())).chain(user_param_types); std::iter::once(Ok(intrinsics.ctx_ptr_ty.as_basic_type_enum())).chain(user_param_types);
let vmctx_attributes = |i: u32| {
vec![
(
context.create_enum_attribute(Attribute::get_named_enum_kind_id("nofree"), 0),
AttributeLoc::Param(i),
),
(
if let Some(offsets) = offsets {
context.create_enum_attribute(
Attribute::get_named_enum_kind_id("dereferenceable"),
offsets.size_of_vmctx().into(),
)
} else {
context
.create_enum_attribute(Attribute::get_named_enum_kind_id("nonnull"), 0)
},
AttributeLoc::Param(i),
),
(
context.create_enum_attribute(
Attribute::get_named_enum_kind_id("align"),
std::mem::align_of::<wasmer_vm::VMContext>()
.try_into()
.unwrap(),
),
AttributeLoc::Param(i),
),
]
};
Ok(match sig.results() { Ok(match sig.results() {
[] => ( [] => (
intrinsics intrinsics
.void_ty .void_ty
.fn_type(&param_types.collect::<Result<Vec<_>, _>>()?, false), .fn_type(&param_types.collect::<Result<Vec<_>, _>>()?, false),
vec![], vmctx_attributes(0),
), ),
[_] => { [_] => {
let single_value = sig.results()[0]; let single_value = sig.results()[0];
( (
type_to_llvm(intrinsics, single_value)? type_to_llvm(intrinsics, single_value)?
.fn_type(&param_types.collect::<Result<Vec<_>, _>>()?, false), .fn_type(&param_types.collect::<Result<Vec<_>, _>>()?, false),
vec![], vmctx_attributes(0),
) )
} }
[Type::F32, Type::F32] => { [Type::F32, Type::F32] => {
@@ -68,7 +102,7 @@ impl Abi for Aarch64SystemV {
context context
.struct_type(&[f32_ty, f32_ty], false) .struct_type(&[f32_ty, f32_ty], false)
.fn_type(&param_types.collect::<Result<Vec<_>, _>>()?, false), .fn_type(&param_types.collect::<Result<Vec<_>, _>>()?, false),
vec![], vmctx_attributes(0),
) )
} }
[Type::F64, Type::F64] => { [Type::F64, Type::F64] => {
@@ -77,7 +111,7 @@ impl Abi for Aarch64SystemV {
context context
.struct_type(&[f64_ty, f64_ty], false) .struct_type(&[f64_ty, f64_ty], false)
.fn_type(&param_types.collect::<Result<Vec<_>, _>>()?, false), .fn_type(&param_types.collect::<Result<Vec<_>, _>>()?, false),
vec![], vmctx_attributes(0),
) )
} }
[Type::F32, Type::F32, Type::F32] => { [Type::F32, Type::F32, Type::F32] => {
@@ -86,7 +120,7 @@ impl Abi for Aarch64SystemV {
context context
.struct_type(&[f32_ty, f32_ty, f32_ty], false) .struct_type(&[f32_ty, f32_ty, f32_ty], false)
.fn_type(&param_types.collect::<Result<Vec<_>, _>>()?, false), .fn_type(&param_types.collect::<Result<Vec<_>, _>>()?, false),
vec![], vmctx_attributes(0),
) )
} }
[Type::F32, Type::F32, Type::F32, Type::F32] => { [Type::F32, Type::F32, Type::F32, Type::F32] => {
@@ -95,7 +129,7 @@ impl Abi for Aarch64SystemV {
context context
.struct_type(&[f32_ty, f32_ty, f32_ty, f32_ty], false) .struct_type(&[f32_ty, f32_ty, f32_ty, f32_ty], false)
.fn_type(&param_types.collect::<Result<Vec<_>, _>>()?, false), .fn_type(&param_types.collect::<Result<Vec<_>, _>>()?, false),
vec![], vmctx_attributes(0),
) )
} }
_ => { _ => {
@@ -115,7 +149,7 @@ impl Abi for Aarch64SystemV {
intrinsics intrinsics
.i64_ty .i64_ty
.fn_type(&param_types.collect::<Result<Vec<_>, _>>()?, false), .fn_type(&param_types.collect::<Result<Vec<_>, _>>()?, false),
vec![], vmctx_attributes(0),
), ),
[32, 64] [32, 64]
| [64, 32] | [64, 32]
@@ -128,7 +162,7 @@ impl Abi for Aarch64SystemV {
.i64_ty .i64_ty
.array_type(2) .array_type(2)
.fn_type(&param_types.collect::<Result<Vec<_>, _>>()?, false), .fn_type(&param_types.collect::<Result<Vec<_>, _>>()?, false),
vec![], vmctx_attributes(0),
), ),
_ => { _ => {
let basic_types: Vec<_> = sig let basic_types: Vec<_> = sig
@@ -144,17 +178,20 @@ impl Abi for Aarch64SystemV {
let param_types = let param_types =
std::iter::once(Ok(sret.as_basic_type_enum())).chain(param_types); std::iter::once(Ok(sret.as_basic_type_enum())).chain(param_types);
( let mut attributes = vec![(
intrinsics
.void_ty
.fn_type(&param_types.collect::<Result<Vec<_>, _>>()?, false),
vec![(
context.create_enum_attribute( context.create_enum_attribute(
Attribute::get_named_enum_kind_id("sret"), Attribute::get_named_enum_kind_id("sret"),
0, 0,
), ),
AttributeLoc::Param(0), AttributeLoc::Param(0),
)], )];
attributes.append(&mut vmctx_attributes(1));
(
intrinsics
.void_ty
.fn_type(&param_types.collect::<Result<Vec<_>, _>>()?, false),
attributes,
) )
} }
} }
@@ -393,9 +430,9 @@ impl Abi for Aarch64SystemV {
}) })
.collect::<Result<Vec<i32>, _>>()?; .collect::<Result<Vec<i32>, _>>()?;
Ok(!matches!(func_sig_returns_bitwidths.as_slice(), Ok(!matches!(
[] func_sig_returns_bitwidths.as_slice(),
| [_] [] | [_]
| [32, 32] | [32, 32]
| [32, 64] | [32, 64]
| [64, 32] | [64, 32]
@@ -403,7 +440,8 @@ impl Abi for Aarch64SystemV {
| [32, 32, 32] | [32, 32, 32]
| [32, 32, 64] | [32, 32, 64]
| [64, 32, 32] | [64, 32, 32]
| [32, 32, 32, 32])) | [32, 32, 32, 32]
))
} }
fn pack_values_for_register_return<'ctx>( fn pack_values_for_register_return<'ctx>(

View File

@@ -16,6 +16,7 @@ use inkwell::{
}; };
use wasmer_compiler::CompileError; use wasmer_compiler::CompileError;
use wasmer_types::FunctionType as FuncSig; use wasmer_types::FunctionType as FuncSig;
use wasmer_vm::VMOffsets;
mod aarch64_systemv; mod aarch64_systemv;
mod x86_64_systemv; mod x86_64_systemv;
@@ -49,6 +50,7 @@ pub trait Abi {
&self, &self,
context: &'ctx Context, context: &'ctx Context,
intrinsics: &Intrinsics<'ctx>, intrinsics: &Intrinsics<'ctx>,
offsets: Option<&VMOffsets>,
sig: &FuncSig, sig: &FuncSig,
) -> Result<(FunctionType<'ctx>, Vec<(Attribute, AttributeLoc)>), CompileError>; ) -> Result<(FunctionType<'ctx>, Vec<(Attribute, AttributeLoc)>), CompileError>;

View File

@@ -13,6 +13,9 @@ use inkwell::{
}; };
use wasmer_compiler::CompileError; use wasmer_compiler::CompileError;
use wasmer_types::{FunctionType as FuncSig, Type}; use wasmer_types::{FunctionType as FuncSig, Type};
use wasmer_vm::VMOffsets;
use std::convert::TryInto;
/// Implementation of the [`Abi`] trait for the AMD64 SystemV ABI. /// Implementation of the [`Abi`] trait for the AMD64 SystemV ABI.
pub struct X86_64SystemV {} pub struct X86_64SystemV {}
@@ -43,6 +46,7 @@ impl Abi for X86_64SystemV {
&self, &self,
context: &'ctx Context, context: &'ctx Context,
intrinsics: &Intrinsics<'ctx>, intrinsics: &Intrinsics<'ctx>,
offsets: Option<&VMOffsets>,
sig: &FuncSig, sig: &FuncSig,
) -> Result<(FunctionType<'ctx>, Vec<(Attribute, AttributeLoc)>), CompileError> { ) -> Result<(FunctionType<'ctx>, Vec<(Attribute, AttributeLoc)>), CompileError> {
let user_param_types = sig.params().iter().map(|&ty| type_to_llvm(intrinsics, ty)); let user_param_types = sig.params().iter().map(|&ty| type_to_llvm(intrinsics, ty));
@@ -50,6 +54,37 @@ impl Abi for X86_64SystemV {
let param_types = let param_types =
std::iter::once(Ok(intrinsics.ctx_ptr_ty.as_basic_type_enum())).chain(user_param_types); std::iter::once(Ok(intrinsics.ctx_ptr_ty.as_basic_type_enum())).chain(user_param_types);
// TODO: figure out how many bytes long vmctx is, and mark it dereferenceable. (no need to mark it nonnull once we do this.)
let vmctx_attributes = |i: u32| {
vec![
(
context.create_enum_attribute(Attribute::get_named_enum_kind_id("nofree"), 0),
AttributeLoc::Param(i),
),
(
if let Some(offsets) = offsets {
context.create_enum_attribute(
Attribute::get_named_enum_kind_id("dereferenceable"),
offsets.size_of_vmctx().into(),
)
} else {
context
.create_enum_attribute(Attribute::get_named_enum_kind_id("nonnull"), 0)
},
AttributeLoc::Param(i),
),
(
context.create_enum_attribute(
Attribute::get_named_enum_kind_id("align"),
std::mem::align_of::<wasmer_vm::VMContext>()
.try_into()
.unwrap(),
),
AttributeLoc::Param(i),
),
]
};
let sig_returns_bitwidths = sig let sig_returns_bitwidths = sig
.results() .results()
.iter() .iter()
@@ -67,14 +102,14 @@ impl Abi for X86_64SystemV {
intrinsics intrinsics
.void_ty .void_ty
.fn_type(&param_types.collect::<Result<Vec<_>, _>>()?, false), .fn_type(&param_types.collect::<Result<Vec<_>, _>>()?, false),
vec![], vmctx_attributes(0),
), ),
[_] => { [_] => {
let single_value = sig.results()[0]; let single_value = sig.results()[0];
( (
type_to_llvm(intrinsics, single_value)? type_to_llvm(intrinsics, single_value)?
.fn_type(&param_types.collect::<Result<Vec<_>, _>>()?, false), .fn_type(&param_types.collect::<Result<Vec<_>, _>>()?, false),
vec![], vmctx_attributes(0),
) )
} }
[32, 64] | [64, 32] | [64, 64] => { [32, 64] | [64, 32] | [64, 64] => {
@@ -88,7 +123,7 @@ impl Abi for X86_64SystemV {
context context
.struct_type(&basic_types, false) .struct_type(&basic_types, false)
.fn_type(&param_types.collect::<Result<Vec<_>, _>>()?, false), .fn_type(&param_types.collect::<Result<Vec<_>, _>>()?, false),
vec![], vmctx_attributes(0),
) )
} }
[32, 32] if sig.results()[0] == Type::F32 && sig.results()[1] == Type::F32 => ( [32, 32] if sig.results()[0] == Type::F32 && sig.results()[1] == Type::F32 => (
@@ -96,13 +131,13 @@ impl Abi for X86_64SystemV {
.f32_ty .f32_ty
.vec_type(2) .vec_type(2)
.fn_type(&param_types.collect::<Result<Vec<_>, _>>()?, false), .fn_type(&param_types.collect::<Result<Vec<_>, _>>()?, false),
vec![], vmctx_attributes(0),
), ),
[32, 32] => ( [32, 32] => (
intrinsics intrinsics
.i64_ty .i64_ty
.fn_type(&param_types.collect::<Result<Vec<_>, _>>()?, false), .fn_type(&param_types.collect::<Result<Vec<_>, _>>()?, false),
vec![], vmctx_attributes(0),
), ),
[32, 32, _] if sig.results()[0] == Type::F32 && sig.results()[1] == Type::F32 => ( [32, 32, _] if sig.results()[0] == Type::F32 && sig.results()[1] == Type::F32 => (
context context
@@ -114,7 +149,7 @@ impl Abi for X86_64SystemV {
false, false,
) )
.fn_type(&param_types.collect::<Result<Vec<_>, _>>()?, false), .fn_type(&param_types.collect::<Result<Vec<_>, _>>()?, false),
vec![], vmctx_attributes(0),
), ),
[32, 32, _] => ( [32, 32, _] => (
context context
@@ -126,7 +161,7 @@ impl Abi for X86_64SystemV {
false, false,
) )
.fn_type(&param_types.collect::<Result<Vec<_>, _>>()?, false), .fn_type(&param_types.collect::<Result<Vec<_>, _>>()?, false),
vec![], vmctx_attributes(0),
), ),
[64, 32, 32] if sig.results()[1] == Type::F32 && sig.results()[2] == Type::F32 => ( [64, 32, 32] if sig.results()[1] == Type::F32 && sig.results()[2] == Type::F32 => (
context context
@@ -138,7 +173,7 @@ impl Abi for X86_64SystemV {
false, false,
) )
.fn_type(&param_types.collect::<Result<Vec<_>, _>>()?, false), .fn_type(&param_types.collect::<Result<Vec<_>, _>>()?, false),
vec![], vmctx_attributes(0),
), ),
[64, 32, 32] => ( [64, 32, 32] => (
context context
@@ -150,7 +185,7 @@ impl Abi for X86_64SystemV {
false, false,
) )
.fn_type(&param_types.collect::<Result<Vec<_>, _>>()?, false), .fn_type(&param_types.collect::<Result<Vec<_>, _>>()?, false),
vec![], vmctx_attributes(0),
), ),
[32, 32, 32, 32] => ( [32, 32, 32, 32] => (
context context
@@ -170,7 +205,7 @@ impl Abi for X86_64SystemV {
false, false,
) )
.fn_type(&param_types.collect::<Result<Vec<_>, _>>()?, false), .fn_type(&param_types.collect::<Result<Vec<_>, _>>()?, false),
vec![], vmctx_attributes(0),
), ),
_ => { _ => {
let basic_types: Vec<_> = sig let basic_types: Vec<_> = sig
@@ -185,14 +220,17 @@ impl Abi for X86_64SystemV {
let param_types = std::iter::once(Ok(sret.as_basic_type_enum())).chain(param_types); let param_types = std::iter::once(Ok(sret.as_basic_type_enum())).chain(param_types);
let mut attributes = vec![(
context.create_enum_attribute(Attribute::get_named_enum_kind_id("sret"), 0),
AttributeLoc::Param(0),
)];
attributes.append(&mut vmctx_attributes(1));
( (
intrinsics intrinsics
.void_ty .void_ty
.fn_type(&param_types.collect::<Result<Vec<_>, _>>()?, false), .fn_type(&param_types.collect::<Result<Vec<_>, _>>()?, false),
vec![( attributes,
context.create_enum_attribute(Attribute::get_named_enum_kind_id("sret"), 0),
AttributeLoc::Param(0),
)],
) )
} }
}) })
@@ -447,9 +485,9 @@ impl Abi for X86_64SystemV {
}) })
.collect::<Result<Vec<i32>, _>>()?; .collect::<Result<Vec<i32>, _>>()?;
Ok(!matches!(func_sig_returns_bitwidths.as_slice(), Ok(!matches!(
[] func_sig_returns_bitwidths.as_slice(),
| [_] [] | [_]
| [32, 32] | [32, 32]
| [32, 64] | [32, 64]
| [64, 32] | [64, 32]
@@ -457,7 +495,8 @@ impl Abi for X86_64SystemV {
| [32, 32, 32] | [32, 32, 32]
| [32, 32, 64] | [32, 32, 64]
| [64, 32, 32] | [64, 32, 32]
| [32, 32, 32, 32])) | [32, 32, 32, 32]
))
} }
fn pack_values_for_register_return<'ctx>( fn pack_values_for_register_return<'ctx>(

View File

@@ -50,7 +50,9 @@ impl FuncTrampoline {
module.set_data_layout(&target_machine.get_target_data().get_data_layout()); module.set_data_layout(&target_machine.get_target_data().get_data_layout());
let intrinsics = Intrinsics::declare(&module, &self.ctx); let intrinsics = Intrinsics::declare(&module, &self.ctx);
let (callee_ty, callee_attrs) = self.abi.func_type_to_llvm(&self.ctx, &intrinsics, ty)?; let (callee_ty, callee_attrs) =
self.abi
.func_type_to_llvm(&self.ctx, &intrinsics, None, ty)?;
let trampoline_ty = intrinsics.void_ty.fn_type( let trampoline_ty = intrinsics.void_ty.fn_type(
&[ &[
intrinsics.ctx_ptr_ty.as_basic_type_enum(), // vmctx ptr intrinsics.ctx_ptr_ty.as_basic_type_enum(), // vmctx ptr
@@ -181,7 +183,8 @@ impl FuncTrampoline {
let intrinsics = Intrinsics::declare(&module, &self.ctx); let intrinsics = Intrinsics::declare(&module, &self.ctx);
let (trampoline_ty, trampoline_attrs) = let (trampoline_ty, trampoline_attrs) =
self.abi.func_type_to_llvm(&self.ctx, &intrinsics, ty)?; self.abi
.func_type_to_llvm(&self.ctx, &intrinsics, None, ty)?;
let trampoline_func = module.add_function(name, trampoline_ty, Some(Linkage::External)); let trampoline_func = module.add_function(name, trampoline_ty, Some(Linkage::External));
for (attr, attr_loc) in trampoline_attrs { for (attr, attr_loc) in trampoline_attrs {
trampoline_func.add_attribute(attr_loc, attr); trampoline_func.add_attribute(attr_loc, attr);

View File

@@ -34,7 +34,7 @@ use wasmer_types::{
FunctionIndex, FunctionType, GlobalIndex, LocalFunctionIndex, MemoryIndex, SignatureIndex, FunctionIndex, FunctionType, GlobalIndex, LocalFunctionIndex, MemoryIndex, SignatureIndex,
TableIndex, Type, TableIndex, Type,
}; };
use wasmer_vm::{MemoryStyle, ModuleInfo, TableStyle}; use wasmer_vm::{MemoryStyle, ModuleInfo, TableStyle, VMOffsets};
const FUNCTION_SECTION: &str = "__TEXT,wasmer_function"; const FUNCTION_SECTION: &str = "__TEXT,wasmer_function";
@@ -101,19 +101,18 @@ impl FuncTranslator {
.get(wasm_module.functions[func_index]) .get(wasm_module.functions[func_index])
.unwrap(); .unwrap();
// TODO: pointer width
let offsets = VMOffsets::new(8, &wasm_module);
let intrinsics = Intrinsics::declare(&module, &self.ctx); let intrinsics = Intrinsics::declare(&module, &self.ctx);
let (func_type, func_attrs) = let (func_type, func_attrs) =
self.abi self.abi
.func_type_to_llvm(&self.ctx, &intrinsics, wasm_fn_type)?; .func_type_to_llvm(&self.ctx, &intrinsics, Some(&offsets), wasm_fn_type)?;
let func = module.add_function(&function_name, func_type, Some(Linkage::External)); let func = module.add_function(&function_name, func_type, Some(Linkage::External));
for (attr, attr_loc) in &func_attrs { for (attr, attr_loc) in &func_attrs {
func.add_attribute(*attr_loc, *attr); func.add_attribute(*attr_loc, *attr);
} }
// TODO: mark vmctx align 16
// TODO: figure out how many bytes long vmctx is, and mark it dereferenceable. (no need to mark it nonnull once we do this.)
// TODO: mark vmctx nofree
func.add_attribute(AttributeLoc::Function, intrinsics.stack_probe); func.add_attribute(AttributeLoc::Function, intrinsics.stack_probe);
func.set_personality_function(intrinsics.personality); func.set_personality_function(intrinsics.personality);
func.as_global_value().set_section(FUNCTION_SECTION); func.as_global_value().set_section(FUNCTION_SECTION);
@@ -2353,9 +2352,12 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> {
self.builder.build_unreachable(); self.builder.build_unreachable();
self.builder.position_at_end(continue_block); self.builder.position_at_end(continue_block);
let (llvm_func_type, llvm_func_attrs) = let (llvm_func_type, llvm_func_attrs) = self.abi.func_type_to_llvm(
self.abi &self.context,
.func_type_to_llvm(&self.context, &self.intrinsics, func_type)?; &self.intrinsics,
Some(self.ctx.get_offsets()),
func_type,
)?;
let params = self.state.popn_save_extra(func_type.params().len())?; let params = self.state.popn_save_extra(func_type.params().len())?;

View File

@@ -934,13 +934,18 @@ impl<'ctx, 'a> CtxType<'ctx, 'a> {
func_type: &FuncType, func_type: &FuncType,
function_name: &str, function_name: &str,
) -> Result<&FunctionCache<'ctx>, CompileError> { ) -> Result<&FunctionCache<'ctx>, CompileError> {
let (cached_functions, ctx_ptr_value) = (&mut self.cached_functions, &self.ctx_ptr_value); let (cached_functions, ctx_ptr_value, offsets) = (
&mut self.cached_functions,
&self.ctx_ptr_value,
&self.offsets,
);
Ok(match cached_functions.entry(function_index) { Ok(match cached_functions.entry(function_index) {
Entry::Occupied(entry) => entry.into_mut(), Entry::Occupied(entry) => entry.into_mut(),
Entry::Vacant(entry) => { Entry::Vacant(entry) => {
debug_assert!(module.get_function(function_name).is_none()); debug_assert!(module.get_function(function_name).is_none());
let (llvm_func_type, llvm_func_attrs) = let (llvm_func_type, llvm_func_attrs) =
self.abi.func_type_to_llvm(context, intrinsics, func_type)?; self.abi
.func_type_to_llvm(context, intrinsics, Some(offsets), func_type)?;
let func = let func =
module.add_function(function_name, llvm_func_type, Some(Linkage::External)); module.add_function(function_name, llvm_func_type, Some(Linkage::External));
for (attr, attr_loc) in &llvm_func_attrs { for (attr, attr_loc) in &llvm_func_attrs {
@@ -973,7 +978,8 @@ impl<'ctx, 'a> CtxType<'ctx, 'a> {
Entry::Occupied(entry) => entry.into_mut(), Entry::Occupied(entry) => entry.into_mut(),
Entry::Vacant(entry) => { Entry::Vacant(entry) => {
let (llvm_func_type, llvm_func_attrs) = let (llvm_func_type, llvm_func_attrs) =
self.abi.func_type_to_llvm(context, intrinsics, func_type)?; self.abi
.func_type_to_llvm(context, intrinsics, Some(offsets), func_type)?;
debug_assert!(wasm_module.local_func_index(function_index).is_none()); debug_assert!(wasm_module.local_func_index(function_index).is_none());
let offset = offsets.vmctx_vmfunction_import(function_index); let offset = offsets.vmctx_vmfunction_import(function_index);
let offset = intrinsics.i32_ty.const_int(offset.into(), false); let offset = intrinsics.i32_ty.const_int(offset.into(), false);
@@ -1097,6 +1103,10 @@ impl<'ctx, 'a> CtxType<'ctx, 'a> {
.into_pointer_value() .into_pointer_value()
}) })
} }
pub fn get_offsets(&self) -> &VMOffsets {
&self.offsets
}
} }
// Given an instruction that operates on memory, mark the access as not aliasing // Given an instruction that operates on memory, mark the access as not aliasing

View File

@@ -207,7 +207,7 @@ pub fn parse_memory_section(
environ.declare_memory(MemoryType { environ.declare_memory(MemoryType {
minimum: Pages(limits.initial), minimum: Pages(limits.initial),
maximum: limits.maximum.map(Pages), maximum: limits.maximum.map(Pages),
shared: shared, shared,
})?; })?;
} }
WPMemoryType::M64 { .. } => unimplemented!("64bit memory not implemented yet"), WPMemoryType::M64 { .. } => unimplemented!("64bit memory not implemented yet"),

View File

@@ -76,6 +76,7 @@ fn derive_struct_fields(data: &DataStruct) -> (TokenStream, TokenStream) {
Fields::Unnamed(fields) => fields.unnamed.iter().cloned().collect(), Fields::Unnamed(fields) => fields.unnamed.iter().cloned().collect(),
}; };
for (field_num, f) in fields.into_iter().enumerate() { for (field_num, f) in fields.into_iter().enumerate() {
let field_idx = syn::Index::from(field_num);
let name = f.ident.clone(); let name = f.ident.clone();
let top_level_ty: &Type = &f.ty; let top_level_ty: &Type = &f.ty;
touched_fields.push(name.clone()); touched_fields.push(name.clone());
@@ -177,7 +178,7 @@ fn derive_struct_fields(data: &DataStruct) -> (TokenStream, TokenStream) {
f.span()=> f.span()=>
match #access_expr { match #access_expr {
Ok(#local_var) => { Ok(#local_var) => {
self.#field_num.initialize(#local_var); self.#field_idx.initialize(#local_var);
}, },
Err(_) => (), Err(_) => (),
} }
@@ -186,7 +187,7 @@ fn derive_struct_fields(data: &DataStruct) -> (TokenStream, TokenStream) {
quote_spanned! { quote_spanned! {
f.span()=> f.span()=>
let #local_var: #inner_type = #access_expr?; let #local_var: #inner_type = #access_expr?;
self.#field_num.initialize(#local_var); self.#field_idx.initialize(#local_var);
} }
} }
} else { } else {

View File

@@ -1002,8 +1002,7 @@ pub fn generate_emscripten_env(
// Compatibility with newer versions of Emscripten // Compatibility with newer versions of Emscripten
let mut to_insert: Vec<(String, _)> = vec![]; let mut to_insert: Vec<(String, _)> = vec![];
for (k, v) in env_ns.iter() { for (k, v) in env_ns.iter() {
if k.starts_with('_') { if let Some(k) = k.strip_prefix('_') {
let k = &k[1..];
if !env_ns.contains(k) { if !env_ns.contains(k) {
to_insert.push((k.to_string(), v.clone())); to_insert.push((k.to_string(), v.clone()));
} }

View File

@@ -24,10 +24,10 @@ pub enum Export {
impl From<Export> for VMExport { impl From<Export> for VMExport {
fn from(other: Export) -> Self { fn from(other: Export) -> Self {
match other { match other {
Export::Function(ExportFunction { vm_function, .. }) => VMExport::Function(vm_function), Export::Function(ExportFunction { vm_function, .. }) => Self::Function(vm_function),
Export::Memory(ExportMemory { vm_memory }) => VMExport::Memory(vm_memory), Export::Memory(ExportMemory { vm_memory }) => Self::Memory(vm_memory),
Export::Table(ExportTable { vm_table }) => VMExport::Table(vm_table), Export::Table(ExportTable { vm_table }) => Self::Table(vm_table),
Export::Global(ExportGlobal { vm_global }) => VMExport::Global(vm_global), Export::Global(ExportGlobal { vm_global }) => Self::Global(vm_global),
} }
} }
} }
@@ -35,13 +35,13 @@ impl From<Export> for VMExport {
impl From<VMExport> for Export { impl From<VMExport> for Export {
fn from(other: VMExport) -> Self { fn from(other: VMExport) -> Self {
match other { match other {
VMExport::Function(vm_function) => Export::Function(ExportFunction { VMExport::Function(vm_function) => Self::Function(ExportFunction {
vm_function, vm_function,
metadata: None, metadata: None,
}), }),
VMExport::Memory(vm_memory) => Export::Memory(ExportMemory { vm_memory }), VMExport::Memory(vm_memory) => Self::Memory(ExportMemory { vm_memory }),
VMExport::Table(vm_table) => Export::Table(ExportTable { vm_table }), VMExport::Table(vm_table) => Self::Table(ExportTable { vm_table }),
VMExport::Global(vm_global) => Export::Global(ExportGlobal { vm_global }), VMExport::Global(vm_global) => Self::Global(ExportGlobal { vm_global }),
} }
} }
} }

View File

@@ -183,7 +183,7 @@ pub fn resolve_imports(
let env = if let Some(ExportFunctionMetadata { let env = if let Some(ExportFunctionMetadata {
host_env_clone_fn: clone, host_env_clone_fn: clone,
.. ..
}) = f.metadata.as_ref().map(|x| &**x) }) = f.metadata.as_deref()
{ {
// TODO: maybe start adding asserts in all these // TODO: maybe start adding asserts in all these
// unsafe blocks to prevent future changes from // unsafe blocks to prevent future changes from

View File

@@ -8,8 +8,10 @@
//! wrapper around an `InstanceRef`. //! wrapper around an `InstanceRef`.
mod allocator; mod allocator;
mod r#ref;
pub use allocator::InstanceAllocator; pub use allocator::InstanceAllocator;
pub use r#ref::InstanceRef;
use crate::export::VMExport; use crate::export::VMExport;
use crate::global::Global; use crate::global::Global;
@@ -27,7 +29,6 @@ use crate::{FunctionBodyPtr, ModuleInfo, VMOffsets};
use crate::{VMExportFunction, VMExportGlobal, VMExportMemory, VMExportTable}; use crate::{VMExportFunction, VMExportGlobal, VMExportMemory, VMExportTable};
use memoffset::offset_of; use memoffset::offset_of;
use more_asserts::assert_lt; use more_asserts::assert_lt;
use std::alloc::Layout;
use std::any::Any; use std::any::Any;
use std::cell::{Cell, RefCell}; use std::cell::{Cell, RefCell};
use std::collections::HashMap; use std::collections::HashMap;
@@ -35,7 +36,7 @@ use std::convert::{TryFrom, TryInto};
use std::ffi; use std::ffi;
use std::fmt; use std::fmt;
use std::ptr::NonNull; use std::ptr::NonNull;
use std::sync::{atomic, Arc}; use std::sync::Arc;
use std::{mem, ptr, slice}; use std::{mem, ptr, slice};
use wasmer_types::entity::{packed_option::ReservedValue, BoxedSlice, EntityRef, PrimaryMap}; use wasmer_types::entity::{packed_option::ReservedValue, BoxedSlice, EntityRef, PrimaryMap};
use wasmer_types::{ use wasmer_types::{
@@ -173,7 +174,7 @@ impl Clone for ImportFunctionEnv {
impl Drop for ImportFunctionEnv { impl Drop for ImportFunctionEnv {
fn drop(&mut self) { fn drop(&mut self) {
match self { match self {
ImportFunctionEnv::Env { Self::Env {
env, destructor, .. env, destructor, ..
} => { } => {
// # Safety // # Safety
@@ -183,7 +184,7 @@ impl Drop for ImportFunctionEnv {
(destructor)(*env); (destructor)(*env);
} }
} }
ImportFunctionEnv::NoEnv => (), Self::NoEnv => (),
} }
} }
} }
@@ -218,6 +219,11 @@ impl Instance {
&*self.module &*self.module
} }
/// Offsets in the `vmctx` region.
fn offsets(&self) -> &VMOffsets {
&self.offsets
}
/// Return a pointer to the `VMSharedSignatureIndex`s. /// Return a pointer to the `VMSharedSignatureIndex`s.
fn signature_ids_ptr(&self) -> *mut VMSharedSignatureIndex { fn signature_ids_ptr(&self) -> *mut VMSharedSignatureIndex {
unsafe { self.vmctx_plus_offset(self.offsets.vmctx_signature_ids_begin()) } unsafe { self.vmctx_plus_offset(self.offsets.vmctx_signature_ids_begin()) }
@@ -464,9 +470,7 @@ impl Instance {
.memories .memories
.get(memory_index) .get(memory_index)
.unwrap_or_else(|| panic!("no memory for index {}", memory_index.index())); .unwrap_or_else(|| panic!("no memory for index {}", memory_index.index()));
let result = mem.grow(delta.into()); mem.grow(delta.into())
result
} }
/// Grow imported memory by the specified amount of pages. /// Grow imported memory by the specified amount of pages.
@@ -767,212 +771,6 @@ impl Instance {
} }
} }
/// An `InstanceRef` is responsible to properly deallocate,
/// and to give access to an `Instance`, in such a way that `Instance`
/// is unique, can be shared, safely, across threads, without
/// duplicating the pointer in multiple locations. `InstanceRef`
/// must be the only “owner” of an `Instance`.
///
/// Consequently, one must not share `Instance` but
/// `InstanceRef`. It acts like an Atomically Reference Counter
/// to `Instance`. In short, `InstanceRef` is roughly a
/// simplified version of `std::sync::Arc`.
///
/// This `InstanceRef` must be freed with [`InstanceRef::deallocate_instance`]
/// if and only if it has been set correctly. The `Drop` implementation of
/// [`InstanceRef`] calls its `deallocate_instance` method without
/// checking if this property holds, only when `Self.strong` is equal to 1.
///
/// Note for the curious reader: [`InstanceAllocator::new`]
/// and [`InstanceHandle::new`] will respectively allocate a proper
/// `Instance` and will fill it correctly.
///
/// A little bit of background: The initial goal was to be able to
/// share an [`Instance`] between an [`InstanceHandle`] and the module
/// exports, so that one can drop a [`InstanceHandle`] but still being
/// able to use the exports properly.
///
/// This structure has a C representation because `Instance` is
/// dynamically-sized, and the `instance` field must be last.
#[derive(Debug)]
#[repr(C)]
pub struct InstanceRef {
/// Number of `Self` in the nature. It increases when `Self` is
/// cloned, and it decreases when `Self` is dropped.
strong: Arc<atomic::AtomicUsize>,
/// The layout of `Instance` (which can vary).
instance_layout: Layout,
/// The `Instance` itself. It must be the last field of
/// `InstanceRef` since `Instance` is dyamically-sized.
///
/// `Instance` must not be dropped manually by Rust, because it's
/// allocated manually with `alloc` and a specific layout (Rust
/// would be able to drop `Instance` itself but it will imply a
/// memory leak because of `alloc`).
///
/// No one in the code has a copy of the `Instance`'s
/// pointer. `Self` is the only one.
instance: NonNull<Instance>,
}
impl InstanceRef {
/// Create a new `InstanceRef`. It allocates nothing. It fills
/// nothing. The `Instance` must be already valid and
/// filled.
///
/// # Safety
///
/// `instance` must a non-null, non-dangling, properly aligned,
/// and correctly initialized pointer to `Instance`. See
/// [`InstanceAllocator`] for an example of how to correctly use
/// this API.
pub(self) unsafe fn new(instance: NonNull<Instance>, instance_layout: Layout) -> Self {
Self {
strong: Arc::new(atomic::AtomicUsize::new(1)),
instance_layout,
instance,
}
}
/// A soft limit on the amount of references that may be made to an `InstanceRef`.
///
/// Going above this limit will make the program to panic at exactly
/// `MAX_REFCOUNT` references.
const MAX_REFCOUNT: usize = std::usize::MAX - 1;
/// Deallocate `Instance`.
///
/// # Safety
///
/// `Self.instance` must be correctly set and filled before being
/// dropped and deallocated.
unsafe fn deallocate_instance(&mut self) {
let instance_ptr = self.instance.as_ptr();
ptr::drop_in_place(instance_ptr);
std::alloc::dealloc(instance_ptr as *mut u8, self.instance_layout);
}
/// Get the number of strong references pointing to this
/// `InstanceRef`.
pub fn strong_count(&self) -> usize {
self.strong.load(atomic::Ordering::SeqCst)
}
/// Get a reference to the `Instance`.
#[inline]
pub(crate) fn as_ref<'a>(&'a self) -> &'a Instance {
// SAFETY: The pointer is properly aligned, it is
// “dereferencable”, it points to an initialized memory of
// `Instance`, and the reference has the lifetime `'a`.
unsafe { self.instance.as_ref() }
}
#[inline]
unsafe fn as_mut<'a>(&'a mut self) -> &'a mut Instance {
self.instance.as_mut()
}
}
/// TODO: Review this super carefully.
unsafe impl Send for InstanceRef {}
unsafe impl Sync for InstanceRef {}
impl Clone for InstanceRef {
/// Makes a clone of `InstanceRef`.
///
/// This creates another `InstanceRef` using the same
/// `instance` pointer, increasing the strong reference count.
#[inline]
fn clone(&self) -> Self {
// Using a relaxed ordering is alright here, as knowledge of
// the original reference prevents other threads from
// erroneously deleting the object.
//
// As explained in the [Boost documentation][1]:
//
// > Increasing the reference counter can always be done with
// > `memory_order_relaxed`: New references to an object can
// > only be formed from an existing reference, and passing an
// > existing reference from one thread to another must already
// > provide any required synchronization.
//
// [1]: https://www.boost.org/doc/libs/1_55_0/doc/html/atomic/usage_examples.html
let old_size = self.strong.fetch_add(1, atomic::Ordering::Relaxed);
// However we need to guard against massive refcounts in case
// someone is `mem::forget`ing `InstanceRef`. If we
// don't do this the count can overflow and users will
// use-after free. We racily saturate to `isize::MAX` on the
// assumption that there aren't ~2 billion threads
// incrementing the reference count at once. This branch will
// never be taken in any realistic program.
//
// We abort because such a program is incredibly degenerate,
// and we don't care to support it.
if old_size > Self::MAX_REFCOUNT {
panic!("Too many references of `InstanceRef`");
}
Self {
strong: self.strong.clone(),
instance_layout: self.instance_layout,
instance: self.instance.clone(),
}
}
}
impl PartialEq for InstanceRef {
/// Two `InstanceRef` are equal if and only if
/// `Self.instance` points to the same location.
fn eq(&self, other: &Self) -> bool {
self.instance == other.instance
}
}
impl Drop for InstanceRef {
/// Drop the `InstanceRef`.
///
/// This will decrement the strong reference count. If it reaches
/// 1, then the `Self.instance` will be deallocated with
/// `Self::deallocate_instance`.
fn drop(&mut self) {
// Because `fetch_sub` is already atomic, we do not need to
// synchronize with other thread.
if self.strong.fetch_sub(1, atomic::Ordering::Release) != 1 {
return;
}
// This fence is needed to prevent reordering of use of the data and
// deletion of the data. Because it is marked `Release`, the decreasing
// of the reference count synchronizes with this `Acquire` fence. This
// means that use of the data happens before decreasing the reference
// count, which happens before this fence, which happens before the
// deletion of the data.
//
// As explained in the [Boost documentation][1]:
//
// > It is important to enforce any possible access to the object in one
// > thread (through an existing reference) to *happen before* deleting
// > the object in a different thread. This is achieved by a "release"
// > operation after dropping a reference (any access to the object
// > through this reference must obviously happened before), and an
// > "acquire" operation before deleting the object.
//
// [1]: https://www.boost.org/doc/libs/1_55_0/doc/html/atomic/usage_examples.html
atomic::fence(atomic::Ordering::Acquire);
// Now we can deallocate the instance. Note that we don't
// check the pointer to `Instance` is correctly initialized,
// but the way `InstanceHandle` creates the
// `InstanceRef` ensures that.
unsafe { Self::deallocate_instance(self) };
}
}
/// A handle holding an `InstanceRef`, which holds an `Instance` /// A handle holding an `InstanceRef`, which holds an `Instance`
/// of a WebAssembly module. /// of a WebAssembly module.
/// ///
@@ -1141,6 +939,13 @@ impl InstanceHandle {
self.instance().as_ref().vmctx_ptr() self.instance().as_ref().vmctx_ptr()
} }
/// Return a reference to the `VMOffsets` to get offsets in the
/// `Self::vmctx_ptr` region. Be careful when doing pointer
/// arithmetic!
pub fn vmoffsets(&self) -> &VMOffsets {
self.instance().as_ref().offsets()
}
/// Return a reference-counting pointer to a module. /// Return a reference-counting pointer to a module.
pub fn module(&self) -> &Arc<ModuleInfo> { pub fn module(&self) -> &Arc<ModuleInfo> {
self.instance().as_ref().module() self.instance().as_ref().module()

210
lib/vm/src/instance/ref.rs Normal file
View File

@@ -0,0 +1,210 @@
use super::Instance;
use std::alloc::Layout;
use std::ptr::{self, NonNull};
use std::sync::{atomic, Arc};
/// An `InstanceRef` is responsible to properly deallocate,
/// and to give access to an `Instance`, in such a way that `Instance`
/// is unique, can be shared, safely, across threads, without
/// duplicating the pointer in multiple locations. `InstanceRef`
/// must be the only “owner” of an `Instance`.
///
/// Consequently, one must not share `Instance` but
/// `InstanceRef`. It acts like an Atomically Reference Counter
/// to `Instance`. In short, `InstanceRef` is roughly a
/// simplified version of `std::sync::Arc`.
///
/// This `InstanceRef` must be freed with [`InstanceRef::deallocate_instance`]
/// if and only if it has been set correctly. The `Drop` implementation of
/// [`InstanceRef`] calls its `deallocate_instance` method without
/// checking if this property holds, only when `Self.strong` is equal to 1.
///
/// Note for the curious reader: [`InstanceAllocator::new`]
/// and [`InstanceHandle::new`] will respectively allocate a proper
/// `Instance` and will fill it correctly.
///
/// A little bit of background: The initial goal was to be able to
/// share an [`Instance`] between an [`InstanceHandle`] and the module
/// exports, so that one can drop a [`InstanceHandle`] but still being
/// able to use the exports properly.
///
/// This structure has a C representation because `Instance` is
/// dynamically-sized, and the `instance` field must be last.
#[derive(Debug)]
#[repr(C)]
pub struct InstanceRef {
/// Number of `Self` in the nature. It increases when `Self` is
/// cloned, and it decreases when `Self` is dropped.
strong: Arc<atomic::AtomicUsize>,
/// The layout of `Instance` (which can vary).
instance_layout: Layout,
/// The `Instance` itself. It must be the last field of
/// `InstanceRef` since `Instance` is dyamically-sized.
///
/// `Instance` must not be dropped manually by Rust, because it's
/// allocated manually with `alloc` and a specific layout (Rust
/// would be able to drop `Instance` itself but it will imply a
/// memory leak because of `alloc`).
///
/// No one in the code has a copy of the `Instance`'s
/// pointer. `Self` is the only one.
instance: NonNull<Instance>,
}
impl InstanceRef {
/// Create a new `InstanceRef`. It allocates nothing. It fills
/// nothing. The `Instance` must be already valid and
/// filled.
///
/// # Safety
///
/// `instance` must a non-null, non-dangling, properly aligned,
/// and correctly initialized pointer to `Instance`. See
/// [`InstanceAllocator`] for an example of how to correctly use
/// this API.
pub(super) unsafe fn new(instance: NonNull<Instance>, instance_layout: Layout) -> Self {
Self {
strong: Arc::new(atomic::AtomicUsize::new(1)),
instance_layout,
instance,
}
}
/// A soft limit on the amount of references that may be made to an `InstanceRef`.
///
/// Going above this limit will make the program to panic at exactly
/// `MAX_REFCOUNT` references.
const MAX_REFCOUNT: usize = std::usize::MAX - 1;
/// Deallocate `Instance`.
///
/// # Safety
///
/// `Self.instance` must be correctly set and filled before being
/// dropped and deallocated.
unsafe fn deallocate_instance(&mut self) {
let instance_ptr = self.instance.as_ptr();
ptr::drop_in_place(instance_ptr);
std::alloc::dealloc(instance_ptr as *mut u8, self.instance_layout);
}
/// Get the number of strong references pointing to this
/// `InstanceRef`.
pub fn strong_count(&self) -> usize {
self.strong.load(atomic::Ordering::SeqCst)
}
/// Get a reference to the `Instance`.
#[inline]
pub(crate) fn as_ref(&self) -> &Instance {
// SAFETY: The pointer is properly aligned, it is
// “dereferencable”, it points to an initialized memory of
// `Instance`, and the reference has the lifetime `'a`.
unsafe { self.instance.as_ref() }
}
#[inline]
pub(super) unsafe fn as_mut(&mut self) -> &mut Instance {
self.instance.as_mut()
}
}
/// TODO: Review this super carefully.
unsafe impl Send for InstanceRef {}
unsafe impl Sync for InstanceRef {}
impl Clone for InstanceRef {
/// Makes a clone of `InstanceRef`.
///
/// This creates another `InstanceRef` using the same
/// `instance` pointer, increasing the strong reference count.
#[inline]
fn clone(&self) -> Self {
// Using a relaxed ordering is alright here, as knowledge of
// the original reference prevents other threads from
// erroneously deleting the object.
//
// As explained in the [Boost documentation][1]:
//
// > Increasing the reference counter can always be done with
// > `memory_order_relaxed`: New references to an object can
// > only be formed from an existing reference, and passing an
// > existing reference from one thread to another must already
// > provide any required synchronization.
//
// [1]: https://www.boost.org/doc/libs/1_55_0/doc/html/atomic/usage_examples.html
let old_size = self.strong.fetch_add(1, atomic::Ordering::Relaxed);
// However we need to guard against massive refcounts in case
// someone is `mem::forget`ing `InstanceRef`. If we
// don't do this the count can overflow and users will
// use-after free. We racily saturate to `isize::MAX` on the
// assumption that there aren't ~2 billion threads
// incrementing the reference count at once. This branch will
// never be taken in any realistic program.
//
// We abort because such a program is incredibly degenerate,
// and we don't care to support it.
if old_size > Self::MAX_REFCOUNT {
panic!("Too many references of `InstanceRef`");
}
Self {
strong: self.strong.clone(),
instance_layout: self.instance_layout,
instance: self.instance.clone(),
}
}
}
impl PartialEq for InstanceRef {
/// Two `InstanceRef` are equal if and only if
/// `Self.instance` points to the same location.
fn eq(&self, other: &Self) -> bool {
self.instance == other.instance
}
}
impl Drop for InstanceRef {
/// Drop the `InstanceRef`.
///
/// This will decrement the strong reference count. If it reaches
/// 1, then the `Self.instance` will be deallocated with
/// `Self::deallocate_instance`.
fn drop(&mut self) {
// Because `fetch_sub` is already atomic, we do not need to
// synchronize with other thread.
if self.strong.fetch_sub(1, atomic::Ordering::Release) != 1 {
return;
}
// This fence is needed to prevent reordering of use of the data and
// deletion of the data. Because it is marked `Release`, the decreasing
// of the reference count synchronizes with this `Acquire` fence. This
// means that use of the data happens before decreasing the reference
// count, which happens before this fence, which happens before the
// deletion of the data.
//
// As explained in the [Boost documentation][1]:
//
// > It is important to enforce any possible access to the object in one
// > thread (through an existing reference) to *happen before* deleting
// > the object in a different thread. This is achieved by a "release"
// > operation after dropping a reference (any access to the object
// > through this reference must obviously happened before), and an
// > "acquire" operation before deleting the object.
//
// [1]: https://www.boost.org/doc/libs/1_55_0/doc/html/atomic/usage_examples.html
atomic::fence(atomic::Ordering::Acquire);
// Now we can deallocate the instance. Note that we don't
// check the pointer to `Instance` is correctly initialized,
// but the way `InstanceHandle` creates the
// `InstanceRef` ensures that.
unsafe { Self::deallocate_instance(self) };
}
}

View File

@@ -267,7 +267,7 @@ impl LinearMemory {
needs_signal_handlers, needs_signal_handlers,
vm_memory_definition: if let Some(mem_loc) = vm_memory_location { vm_memory_definition: if let Some(mem_loc) = vm_memory_location {
{ {
let mut ptr = mem_loc.clone(); let mut ptr = mem_loc;
let md = ptr.as_mut(); let md = ptr.as_mut();
md.base = base_ptr; md.base = base_ptr;
md.current_length = mem_length; md.current_length = mem_length;
@@ -293,7 +293,7 @@ impl LinearMemory {
/// this function. You can get this by locking the `mmap` mutex. /// this function. You can get this by locking the `mmap` mutex.
unsafe fn get_vm_memory_definition(&self) -> NonNull<VMMemoryDefinition> { unsafe fn get_vm_memory_definition(&self) -> NonNull<VMMemoryDefinition> {
match &self.vm_memory_definition { match &self.vm_memory_definition {
VMMemoryDefinitionOwnership::VMOwned(ptr) => ptr.clone(), VMMemoryDefinitionOwnership::VMOwned(ptr) => *ptr,
VMMemoryDefinitionOwnership::HostOwned(boxed_ptr) => { VMMemoryDefinitionOwnership::HostOwned(boxed_ptr) => {
NonNull::new_unchecked(boxed_ptr.get()) NonNull::new_unchecked(boxed_ptr.get())
} }

View File

@@ -187,7 +187,7 @@ impl LinearTable {
style: style.clone(), style: style.clone(),
vm_table_definition: if let Some(table_loc) = vm_table_location { vm_table_definition: if let Some(table_loc) = vm_table_location {
{ {
let mut ptr = table_loc.clone(); let mut ptr = table_loc;
let td = ptr.as_mut(); let td = ptr.as_mut();
td.base = base as _; td.base = base as _;
td.current_elements = table_minimum as _; td.current_elements = table_minimum as _;
@@ -212,7 +212,7 @@ impl LinearTable {
/// this function. You can get this by locking the `vec` mutex. /// this function. You can get this by locking the `vec` mutex.
unsafe fn get_vm_table_definition(&self) -> NonNull<VMTableDefinition> { unsafe fn get_vm_table_definition(&self) -> NonNull<VMTableDefinition> {
match &self.vm_table_definition { match &self.vm_table_definition {
VMTableDefinitionOwnership::VMOwned(ptr) => ptr.clone(), VMTableDefinitionOwnership::VMOwned(ptr) => *ptr,
VMTableDefinitionOwnership::HostOwned(boxed_ptr) => { VMTableDefinitionOwnership::HostOwned(boxed_ptr) => {
NonNull::new_unchecked(boxed_ptr.get()) NonNull::new_unchecked(boxed_ptr.get())
} }

View File

@@ -221,7 +221,7 @@ cfg_if::cfg_if! {
pub __pc: u64, /* Program counter */ pub __pc: u64, /* Program counter */
pub __cpsr: u32, /* Current program status register */ pub __cpsr: u32, /* Current program status register */
pub __pad: u32, /* Same size for 32-bit or 64-bit clients */ pub __pad: u32, /* Same size for 32-bit or 64-bit clients */
}; }
let cx = &*(cx as *const libc::ucontext_t); let cx = &*(cx as *const libc::ucontext_t);
let uc_mcontext = mem::transmute::<_, *const __darwin_arm_thread_state64>(&(*cx.uc_mcontext).__ss); let uc_mcontext = mem::transmute::<_, *const __darwin_arm_thread_state64>(&(*cx.uc_mcontext).__ss);

View File

@@ -128,7 +128,7 @@ pub fn generate_import_object_from_env(
// fail on Apple Silicon (with Cranelift). // fail on Apple Silicon (with Cranelift).
fn get_path_open_for_store(store: &Store, env: WasiEnv) -> Function { fn get_path_open_for_store(store: &Store, env: WasiEnv) -> Function {
#[cfg(not(all(target_os = "macos", target_arch = "aarch64",)))] #[cfg(not(all(target_os = "macos", target_arch = "aarch64",)))]
let path_open = Function::new_native_with_env(store, env.clone(), path_open); let path_open = Function::new_native_with_env(store, env, path_open);
#[cfg(all(target_os = "macos", target_arch = "aarch64",))] #[cfg(all(target_os = "macos", target_arch = "aarch64",))]
let path_open = Function::new_with_env( let path_open = Function::new_with_env(
store, store,

View File

@@ -349,7 +349,7 @@ impl WasiStateBuilder {
None => (), None => (),
} }
if env_value.iter().find(|&&ch| ch == 0).is_some() { if env_value.iter().any(|&ch| ch == 0) {
return Err(WasiStateCreationError::EnvironmentVariableFormatError( return Err(WasiStateCreationError::EnvironmentVariableFormatError(
format!( format!(
"found nul byte in env var value \"{}\" (key=value)", "found nul byte in env var value \"{}\" (key=value)",

View File

@@ -1027,7 +1027,8 @@ impl WasiFile for Pipe {
self.buffer.len() as u64 self.buffer.len() as u64
} }
fn set_len(&mut self, len: u64) -> Result<(), WasiFsError> { fn set_len(&mut self, len: u64) -> Result<(), WasiFsError> {
Ok(self.buffer.resize(len as usize, 0)) self.buffer.resize(len as usize, 0);
Ok(())
} }
fn unlink(&mut self) -> Result<(), WasiFsError> { fn unlink(&mut self) -> Result<(), WasiFsError> {
Ok(()) Ok(())

View File

@@ -224,10 +224,10 @@ impl<T> From<ExternRef> for Value<T> {
// } // }
// } // }
const NOT_I32: &'static str = "Value is not of Wasm type i32"; const NOT_I32: &str = "Value is not of Wasm type i32";
const NOT_I64: &'static str = "Value is not of Wasm type i64"; const NOT_I64: &str = "Value is not of Wasm type i64";
const NOT_F32: &'static str = "Value is not of Wasm type f32"; const NOT_F32: &str = "Value is not of Wasm type f32";
const NOT_F64: &'static str = "Value is not of Wasm type f64"; const NOT_F64: &str = "Value is not of Wasm type f64";
impl<T> TryFrom<Value<T>> for i32 { impl<T> TryFrom<Value<T>> for i32 {
type Error = &'static str; type Error = &'static str;