forked from mirrors/gecko-dev
Bug 1539406: Bump Cranelift to revision 542d799dd7a3b2cc; r=lth
This is the first time we pin a specific Cranelift commit hash to use in Gecko. The target-lexicon hack is removed and instead we introduce a vendor patch for cranelift-codegen/cranelift-wasm themselves. Notable changes happen in top-level Cargo.toml, .cargo/config.in and js/src/wasm/cranelift/Cargo.toml; the rest has been generated by `mach vendor rust`. Differential Revision: https://phabricator.services.mozilla.com/D27316 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
5deee43687
commit
da79779db2
93 changed files with 8293 additions and 824 deletions
|
|
@ -22,9 +22,9 @@ git = "https://github.com/hsivonen/packed_simd"
|
||||||
branch = "rust_1_32"
|
branch = "rust_1_32"
|
||||||
replace-with = "vendored-sources"
|
replace-with = "vendored-sources"
|
||||||
|
|
||||||
[source."https://github.com/CraneStation/target-lexicon"]
|
[source."https://github.com/CraneStation/Cranelift"]
|
||||||
git = "https://github.com/glandium/target-lexicon"
|
git = "https://github.com/CraneStation/Cranelift"
|
||||||
branch = "thumbv7neon-v0.2"
|
rev = "542d799dd7a3b2cc15b91eefdcd85cace8fe5cee"
|
||||||
replace-with = "vendored-sources"
|
replace-with = "vendored-sources"
|
||||||
|
|
||||||
[source.vendored-sources]
|
[source.vendored-sources]
|
||||||
|
|
|
||||||
76
Cargo.lock
generated
76
Cargo.lock
generated
|
|
@ -168,11 +168,11 @@ name = "baldrdash"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bindgen 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bindgen 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"cranelift-codegen 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cranelift-codegen 0.30.0 (git+https://github.com/CraneStation/Cranelift?rev=542d799dd7a3b2cc15b91eefdcd85cace8fe5cee)",
|
||||||
"cranelift-wasm 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cranelift-wasm 0.30.0 (git+https://github.com/CraneStation/Cranelift?rev=542d799dd7a3b2cc15b91eefdcd85cace8fe5cee)",
|
||||||
"env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"target-lexicon 0.2.0 (git+https://github.com/glandium/target-lexicon?branch=thumbv7neon-v0.2)",
|
"target-lexicon 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -568,62 +568,62 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cranelift-bforest"
|
name = "cranelift-bforest"
|
||||||
version = "0.29.0"
|
version = "0.30.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://github.com/CraneStation/Cranelift?rev=542d799dd7a3b2cc15b91eefdcd85cace8fe5cee#542d799dd7a3b2cc15b91eefdcd85cace8fe5cee"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cranelift-entity 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cranelift-entity 0.30.0 (git+https://github.com/CraneStation/Cranelift?rev=542d799dd7a3b2cc15b91eefdcd85cace8fe5cee)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cranelift-codegen"
|
name = "cranelift-codegen"
|
||||||
version = "0.29.0"
|
version = "0.30.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://github.com/CraneStation/Cranelift?rev=542d799dd7a3b2cc15b91eefdcd85cace8fe5cee#542d799dd7a3b2cc15b91eefdcd85cace8fe5cee"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cranelift-bforest 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cranelift-bforest 0.30.0 (git+https://github.com/CraneStation/Cranelift?rev=542d799dd7a3b2cc15b91eefdcd85cace8fe5cee)",
|
||||||
"cranelift-codegen-meta 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cranelift-codegen-meta 0.30.0 (git+https://github.com/CraneStation/Cranelift?rev=542d799dd7a3b2cc15b91eefdcd85cace8fe5cee)",
|
||||||
"cranelift-entity 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cranelift-entity 0.30.0 (git+https://github.com/CraneStation/Cranelift?rev=542d799dd7a3b2cc15b91eefdcd85cace8fe5cee)",
|
||||||
"failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"target-lexicon 0.2.0 (git+https://github.com/glandium/target-lexicon?branch=thumbv7neon-v0.2)",
|
"target-lexicon 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cranelift-codegen-meta"
|
name = "cranelift-codegen-meta"
|
||||||
version = "0.29.0"
|
version = "0.30.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://github.com/CraneStation/Cranelift?rev=542d799dd7a3b2cc15b91eefdcd85cace8fe5cee#542d799dd7a3b2cc15b91eefdcd85cace8fe5cee"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cranelift-entity 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cranelift-entity 0.30.0 (git+https://github.com/CraneStation/Cranelift?rev=542d799dd7a3b2cc15b91eefdcd85cace8fe5cee)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cranelift-entity"
|
name = "cranelift-entity"
|
||||||
version = "0.29.0"
|
version = "0.30.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://github.com/CraneStation/Cranelift?rev=542d799dd7a3b2cc15b91eefdcd85cace8fe5cee#542d799dd7a3b2cc15b91eefdcd85cace8fe5cee"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cranelift-frontend"
|
name = "cranelift-frontend"
|
||||||
version = "0.29.0"
|
version = "0.30.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://github.com/CraneStation/Cranelift?rev=542d799dd7a3b2cc15b91eefdcd85cace8fe5cee#542d799dd7a3b2cc15b91eefdcd85cace8fe5cee"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cranelift-codegen 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cranelift-codegen 0.30.0 (git+https://github.com/CraneStation/Cranelift?rev=542d799dd7a3b2cc15b91eefdcd85cace8fe5cee)",
|
||||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"target-lexicon 0.2.0 (git+https://github.com/glandium/target-lexicon?branch=thumbv7neon-v0.2)",
|
"target-lexicon 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cranelift-wasm"
|
name = "cranelift-wasm"
|
||||||
version = "0.29.0"
|
version = "0.30.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://github.com/CraneStation/Cranelift?rev=542d799dd7a3b2cc15b91eefdcd85cace8fe5cee#542d799dd7a3b2cc15b91eefdcd85cace8fe5cee"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"cranelift-codegen 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cranelift-codegen 0.30.0 (git+https://github.com/CraneStation/Cranelift?rev=542d799dd7a3b2cc15b91eefdcd85cace8fe5cee)",
|
||||||
"cranelift-entity 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cranelift-entity 0.30.0 (git+https://github.com/CraneStation/Cranelift?rev=542d799dd7a3b2cc15b91eefdcd85cace8fe5cee)",
|
||||||
"cranelift-frontend 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cranelift-frontend 0.30.0 (git+https://github.com/CraneStation/Cranelift?rev=542d799dd7a3b2cc15b91eefdcd85cace8fe5cee)",
|
||||||
"failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"wasmparser 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"wasmparser 0.29.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -2778,8 +2778,8 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "target-lexicon"
|
name = "target-lexicon"
|
||||||
version = "0.2.0"
|
version = "0.4.0"
|
||||||
source = "git+https://github.com/glandium/target-lexicon?branch=thumbv7neon-v0.2#b2d4b34509abb3e12b1c93d19b8593d02ddeed76"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
|
@ -3203,7 +3203,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasmparser"
|
name = "wasmparser"
|
||||||
version = "0.23.0"
|
version = "0.29.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -3495,12 +3495,12 @@ dependencies = [
|
||||||
"checksum core-text 13.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f3f46450d6f2397261af420b4ccce23807add2e45fa206410a03d66fb7f050ae"
|
"checksum core-text 13.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f3f46450d6f2397261af420b4ccce23807add2e45fa206410a03d66fb7f050ae"
|
||||||
"checksum cose 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "72fa26cb151d3ae4b70f63d67d0fed57ce04220feafafbae7f503bef7aae590d"
|
"checksum cose 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "72fa26cb151d3ae4b70f63d67d0fed57ce04220feafafbae7f503bef7aae590d"
|
||||||
"checksum cose-c 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "49726015ab0ca765144fcca61e4a7a543a16b795a777fa53f554da2fffff9a94"
|
"checksum cose-c 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "49726015ab0ca765144fcca61e4a7a543a16b795a777fa53f554da2fffff9a94"
|
||||||
"checksum cranelift-bforest 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a3a25dfe4a54449df63d592f2f6346a80350ac835d4be4bacb73c20b034ef763"
|
"checksum cranelift-bforest 0.30.0 (git+https://github.com/CraneStation/Cranelift?rev=542d799dd7a3b2cc15b91eefdcd85cace8fe5cee)" = "<none>"
|
||||||
"checksum cranelift-codegen 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6c3b15a20577e6c823475953a5e25e758d9d3a3148a937d686c09460e5f2f4a0"
|
"checksum cranelift-codegen 0.30.0 (git+https://github.com/CraneStation/Cranelift?rev=542d799dd7a3b2cc15b91eefdcd85cace8fe5cee)" = "<none>"
|
||||||
"checksum cranelift-codegen-meta 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e60ce3551e8172c966fbc6d9bfb90111d5d1cf37306c37dd7527467afe317d1"
|
"checksum cranelift-codegen-meta 0.30.0 (git+https://github.com/CraneStation/Cranelift?rev=542d799dd7a3b2cc15b91eefdcd85cace8fe5cee)" = "<none>"
|
||||||
"checksum cranelift-entity 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4e124e09cb7dc85fbe2162420aebbe8e9e3b8f9210901be7867416c5beec8226"
|
"checksum cranelift-entity 0.30.0 (git+https://github.com/CraneStation/Cranelift?rev=542d799dd7a3b2cc15b91eefdcd85cace8fe5cee)" = "<none>"
|
||||||
"checksum cranelift-frontend 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2833c6e1a93c524ce0c2ab31266cdc84d38c906349f79f19378a5e5995727b23"
|
"checksum cranelift-frontend 0.30.0 (git+https://github.com/CraneStation/Cranelift?rev=542d799dd7a3b2cc15b91eefdcd85cace8fe5cee)" = "<none>"
|
||||||
"checksum cranelift-wasm 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e75efb45cd8d8700b4bdc225f0077bc7c615f84a5807ce001d59b4da48d85573"
|
"checksum cranelift-wasm 0.30.0 (git+https://github.com/CraneStation/Cranelift?rev=542d799dd7a3b2cc15b91eefdcd85cace8fe5cee)" = "<none>"
|
||||||
"checksum crc 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bd5d02c0aac6bd68393ed69e00bbc2457f3e89075c6349db7189618dc4ddc1d7"
|
"checksum crc 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bd5d02c0aac6bd68393ed69e00bbc2457f3e89075c6349db7189618dc4ddc1d7"
|
||||||
"checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3"
|
"checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3"
|
||||||
"checksum crossbeam-deque 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fe8153ef04a7594ded05b427ffad46ddeaf22e63fd48d42b3e1e3bb4db07cae7"
|
"checksum crossbeam-deque 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fe8153ef04a7594ded05b427ffad46ddeaf22e63fd48d42b3e1e3bb4db07cae7"
|
||||||
|
|
@ -3691,7 +3691,7 @@ dependencies = [
|
||||||
"checksum syn 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4e4b5274d4a0a3d2749d5c158dc64d3403e60554dc61194648787ada5212473d"
|
"checksum syn 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4e4b5274d4a0a3d2749d5c158dc64d3403e60554dc61194648787ada5212473d"
|
||||||
"checksum syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)" = "66c8865bf5a7cbb662d8b011950060b3c8743dca141b054bf7195b20d314d8e2"
|
"checksum syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)" = "66c8865bf5a7cbb662d8b011950060b3c8743dca141b054bf7195b20d314d8e2"
|
||||||
"checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015"
|
"checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015"
|
||||||
"checksum target-lexicon 0.2.0 (git+https://github.com/glandium/target-lexicon?branch=thumbv7neon-v0.2)" = "<none>"
|
"checksum target-lexicon 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1b0ab4982b8945c35cc1c46a83a9094c414f6828a099ce5dcaa8ee2b04642dcb"
|
||||||
"checksum tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "87974a6f5c1dfb344d733055601650059a3363de2a6104819293baff662132d6"
|
"checksum tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "87974a6f5c1dfb344d733055601650059a3363de2a6104819293baff662132d6"
|
||||||
"checksum term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1"
|
"checksum term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1"
|
||||||
"checksum term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2b6b55df3198cc93372e85dd2ed817f0e38ce8cc0f22eb32391bfad9c4bf209"
|
"checksum term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2b6b55df3198cc93372e85dd2ed817f0e38ce8cc0f22eb32391bfad9c4bf209"
|
||||||
|
|
@ -3736,7 +3736,7 @@ dependencies = [
|
||||||
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
|
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
|
||||||
"checksum walkdir 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "63636bd0eb3d00ccb8b9036381b526efac53caf112b7783b730ab3f8e44da369"
|
"checksum walkdir 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "63636bd0eb3d00ccb8b9036381b526efac53caf112b7783b730ab3f8e44da369"
|
||||||
"checksum want 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "797464475f30ddb8830cc529aaaae648d581f99e2036a928877dfde027ddf6b3"
|
"checksum want 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "797464475f30ddb8830cc529aaaae648d581f99e2036a928877dfde027ddf6b3"
|
||||||
"checksum wasmparser 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b5e01c420bc7d36e778bd242e1167b079562ba8b34087122cc9057187026d060"
|
"checksum wasmparser 0.29.2 (registry+https://github.com/rust-lang/crates.io-index)" = "981a8797cf89762e0233ec45fae731cb79a4dfaee12d9f0fe6cee01e4ac58d00"
|
||||||
"checksum webidl 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0f807f7488d680893f7188aa09d7672a3a0a8461975a098a2edf0a52e3fee29"
|
"checksum webidl 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0f807f7488d680893f7188aa09d7672a3a0a8461975a098a2edf0a52e3fee29"
|
||||||
"checksum which 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4be6cfa54dab45266e98b5d7be2f8ce959ddd49abd141a05d52dce4b07f803bb"
|
"checksum which 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4be6cfa54dab45266e98b5d7be2f8ce959ddd49abd141a05d52dce4b07f803bb"
|
||||||
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
|
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
|
||||||
|
|
|
||||||
|
|
@ -61,4 +61,5 @@ libudev-sys = { path = "dom/webauthn/libudev-sys" }
|
||||||
serde_derive = { git = "https://github.com/servo/serde", branch = "deserialize_from_enums10" }
|
serde_derive = { git = "https://github.com/servo/serde", branch = "deserialize_from_enums10" }
|
||||||
winapi = { git = "https://github.com/froydnj/winapi-rs", branch = "aarch64" }
|
winapi = { git = "https://github.com/froydnj/winapi-rs", branch = "aarch64" }
|
||||||
packed_simd = { git = "https://github.com/hsivonen/packed_simd", branch = "rust_1_32" }
|
packed_simd = { git = "https://github.com/hsivonen/packed_simd", branch = "rust_1_32" }
|
||||||
target-lexicon = { git = "https://github.com/glandium/target-lexicon", branch = "thumbv7neon-v0.2" }
|
cranelift-codegen = { git = "https://github.com/CraneStation/Cranelift", rev = "542d799dd7a3b2cc15b91eefdcd85cace8fe5cee" }
|
||||||
|
cranelift-wasm = { git = "https://github.com/CraneStation/Cranelift", rev = "542d799dd7a3b2cc15b91eefdcd85cace8fe5cee" }
|
||||||
|
|
|
||||||
|
|
@ -8,9 +8,16 @@ crate-type = ["rlib"]
|
||||||
name = "baldrdash"
|
name = "baldrdash"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
cranelift-codegen = { version = "0.29.0", default-features = false }
|
# The build system redirects the versions of cranelift-codegen and
|
||||||
cranelift-wasm = "0.29.0"
|
# cranelift-wasm to pinned commits. If you want to update Cranelift in Gecko,
|
||||||
target-lexicon = "0.2.0"
|
# you should update the following files:
|
||||||
|
# - $TOP_LEVEL/Cargo.toml, look for the revision (rev) hashes of both cranelift
|
||||||
|
# dependencies (codegen and wasm).
|
||||||
|
# - $TOP_LEVEL/.cargo/config.in, look for the revision (rev) field of the
|
||||||
|
# Cranelift source.
|
||||||
|
cranelift-codegen = { version = "0.30", default-features = false }
|
||||||
|
cranelift-wasm = "0.30"
|
||||||
|
target-lexicon = "0.4.0"
|
||||||
log = { version = "0.4.6", default-features = false, features = ["release_max_level_info"] }
|
log = { version = "0.4.6", default-features = false, features = ["release_max_level_info"] }
|
||||||
env_logger = "0.5.6"
|
env_logger = "0.5.6"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
{"files":{"Cargo.toml":"d6c5cca60972e64e1abb435d2af6bf8af2fec2d5988d0fda9827f6bba1f6a47c","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"af367c67340fa7f6fb9a35b0aa637dcf303957f7ae7427a5f4f6356801c8bb04","src/lib.rs":"1b23abbfe5850a4cd77ae6ae5dcfc2f678ef36b4032fd7496f2b333c51e63301","src/map.rs":"5d891d62814941e19dfc88ff36538efa3da5479f3f97de8219a6f610c9a1ee32","src/node.rs":"e620c64e78488035f11723b14892c7986c06ad37dc5b115a35a453ff1ae66ca3","src/path.rs":"4868e59ff67db1c504747e4b7e202dd20c9da4cbd73d9fa82d53e5f3406dbb78","src/pool.rs":"6090f8c0e0da16ebee0e31bca66392d0075b3aff529d30d4e716fa20cd0aef99","src/set.rs":"b411158f813a310c7a6c337d4ada3bf0a021088c443875dc25233415dcbe0633"},"package":"a3a25dfe4a54449df63d592f2f6346a80350ac835d4be4bacb73c20b034ef763"}
|
{"files":{"Cargo.toml":"4fb2be5a108736ec2eeb257fd9c90d7e4384321e34eaef0fc7c5517a8e096650","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"af367c67340fa7f6fb9a35b0aa637dcf303957f7ae7427a5f4f6356801c8bb04","src/lib.rs":"1b23abbfe5850a4cd77ae6ae5dcfc2f678ef36b4032fd7496f2b333c51e63301","src/map.rs":"5d891d62814941e19dfc88ff36538efa3da5479f3f97de8219a6f610c9a1ee32","src/node.rs":"e620c64e78488035f11723b14892c7986c06ad37dc5b115a35a453ff1ae66ca3","src/path.rs":"4868e59ff67db1c504747e4b7e202dd20c9da4cbd73d9fa82d53e5f3406dbb78","src/pool.rs":"6090f8c0e0da16ebee0e31bca66392d0075b3aff529d30d4e716fa20cd0aef99","src/set.rs":"b411158f813a310c7a6c337d4ada3bf0a021088c443875dc25233415dcbe0633"},"package":null}
|
||||||
39
third_party/rust/cranelift-bforest/Cargo.toml
vendored
39
third_party/rust/cranelift-bforest/Cargo.toml
vendored
|
|
@ -1,37 +1,24 @@
|
||||||
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
|
|
||||||
#
|
|
||||||
# When uploading crates to the registry Cargo will automatically
|
|
||||||
# "normalize" Cargo.toml files for maximal compatibility
|
|
||||||
# with all versions of Cargo and also rewrite `path` dependencies
|
|
||||||
# to registry (e.g. crates.io) dependencies
|
|
||||||
#
|
|
||||||
# If you believe there's an error in this file please file an
|
|
||||||
# issue against the rust-lang/cargo repository. If you're
|
|
||||||
# editing this file be aware that the upstream Cargo.toml
|
|
||||||
# will likely look very different (and much more reasonable)
|
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
edition = "2018"
|
|
||||||
name = "cranelift-bforest"
|
|
||||||
version = "0.29.0"
|
|
||||||
authors = ["The Cranelift Project Developers"]
|
authors = ["The Cranelift Project Developers"]
|
||||||
|
name = "cranelift-bforest"
|
||||||
|
version = "0.30.0"
|
||||||
description = "A forest of B+-trees"
|
description = "A forest of B+-trees"
|
||||||
|
license = "Apache-2.0 WITH LLVM-exception"
|
||||||
documentation = "https://cranelift.readthedocs.io/"
|
documentation = "https://cranelift.readthedocs.io/"
|
||||||
|
repository = "https://github.com/CraneStation/cranelift"
|
||||||
|
categories = ["no-std"]
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
keywords = ["btree", "forest", "set", "map"]
|
keywords = ["btree", "forest", "set", "map"]
|
||||||
categories = ["no-std"]
|
edition = "2018"
|
||||||
license = "Apache-2.0 WITH LLVM-exception"
|
|
||||||
repository = "https://github.com/CraneStation/cranelift"
|
[dependencies]
|
||||||
[dependencies.cranelift-entity]
|
cranelift-entity = { path = "../cranelift-entity", version = "0.30.0", default-features = false }
|
||||||
version = "0.29.0"
|
|
||||||
default-features = false
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
core = []
|
|
||||||
default = ["std"]
|
default = ["std"]
|
||||||
std = ["cranelift-entity/std"]
|
std = ["cranelift-entity/std"]
|
||||||
[badges.maintenance]
|
core = []
|
||||||
status = "experimental"
|
|
||||||
|
|
||||||
[badges.travis-ci]
|
[badges]
|
||||||
repository = "CraneStation/cranelift"
|
maintenance = { status = "experimental" }
|
||||||
|
travis-ci = { repository = "CraneStation/cranelift" }
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
{"files":{"Cargo.toml":"f5ea16920dd3c3f9c1ef903e26b10a913cafb5ac30eb36deabca977de04a62ae","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"b123f056d0d458396679c5f7f2a16d2762af0258fcda4ac14b6655a95e5a0022","src/cdsl/isa.rs":"d3ddfc8bd3d691df034a1bacfa27b3e29eb2e7a30923508fa5c7af8d89e8a962","src/cdsl/mod.rs":"66ac1b5d095e431bcab88c4b9c5b1492a5d1ca87bcb9c9c3e544ede05b2ba925","src/cdsl/regs.rs":"b99f24c3ecb46691625dc177b4e18d53e02265bc85a2f827a8d18381fe8f39bb","src/cdsl/settings.rs":"4ddeadf1542cc2ddec0f9e6c22d1637050da519586cd9fec0243c3eab9619f82","src/cdsl/types.rs":"981ebe748973bdf2dee00fa71784f6dcaa6c7648442665f34a59ad97a05fe888","src/constant_hash.rs":"b8acd3f8712a4999819d9d9beced2938d9940a5748ba016c182f1132d97eefab","src/error.rs":"5110a4e3c1e97396ba02d9f5abbb8af4b586f0cc4d33a5c2473f1718cc4bef05","src/gen_registers.rs":"75bbbc0f8dd546c88ed52f350175656300e35e871382a7508e7123e32d4bee1e","src/gen_settings.rs":"4689ede4e460bfcc19511c1055ba359b52f248f4a6d3afd62b1d23bc493b37a1","src/gen_types.rs":"3935da6c6a53f9332e06f74bc3a46270656b4d4231ad28ed2648d7b1d2774e90","src/isa/arm32/mod.rs":"f5b0cbbb2f6c7f00bb9a9bc6f0b1120477ff7ff683a95a6cdbbeed1677b0c9c8","src/isa/arm64/mod.rs":"c234b0df3d36d6d8765ead548e43b5304480e79da9697e14f9d98525919921b3","src/isa/mod.rs":"7038e3aa629afc28707fea379237d3c161ab459d552160438ac75e1137c6246a","src/isa/riscv/mod.rs":"322220fa67cf8623eeb27c7d23f3cc34e05873860248ae99fd02af452c232383","src/isa/x86/mod.rs":"c9183448ffe378e599ec7dc6ae7180c97d3e11d15d7644b93eb1e4a3543222f2","src/lib.rs":"4c73b35cbd68aab9b9c8c86bb71f67555e0e15f36a22101e086a346b01ee8cfb","src/shared/mod.rs":"87b55c291c5e73a9d7cd9a0ebfc8e59501956195268673d0d980de58694f4741","src/shared/settings.rs":"bc6a15221d688bf63114c53493d31070860eb7fae208596374488404a65ee41a","src/shared/types.rs":"a3e449db1f515d268f3ad21301740ba415444d399f8433dbc48979f78557f66a","src/srcgen.rs":"72435db1e0c984d95c5c5aa758907ed79eaec41ca3203ac661c6acd64c19acce","src/unique_table.rs":"f6041df1fa85f2a1ee914b84791e80165a0858a6253c212eaa99ff67cb56af26"},"package":"3e60ce3551e8172c966fbc6d9bfb90111d5d1cf37306c37dd7527467afe317d1"}
|
{"files":{"Cargo.toml":"253c80832ab598570d604ae8a8108ea9835b8eef8d9b9645408ed025ce3b574a","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"b123f056d0d458396679c5f7f2a16d2762af0258fcda4ac14b6655a95e5a0022","src/cdsl/formats.rs":"98ab61698ad4c1fb81541b1820bd1c1561810bdcff2796dec541c98b4b1901d7","src/cdsl/inst.rs":"d5130c1a36a4e33d1374f9867119c3f2d79c384f12afc12e7b7b4518cf1f74b3","src/cdsl/isa.rs":"dd52d35fa963494b7da892a4a04a4f9978079bb2d86c6af4273a8dfdb82bdf51","src/cdsl/mod.rs":"2d2e216f8c3a81978a5113213559a5ab659bc112b6194cbe08a752313aad7f46","src/cdsl/operands.rs":"cc579fd543e36cf8e82938db331c145b77e29855ee2aa8c5dd949678f980796d","src/cdsl/regs.rs":"b99f24c3ecb46691625dc177b4e18d53e02265bc85a2f827a8d18381fe8f39bb","src/cdsl/settings.rs":"4ddeadf1542cc2ddec0f9e6c22d1637050da519586cd9fec0243c3eab9619f82","src/cdsl/type_inference.rs":"8aedb2e99dee299abbc327ce3a604d48f161580776225d2438a54bbec5b725fe","src/cdsl/types.rs":"4cc1f20eb8383fdee6a9e7ca0f7758e563a4fb715056b5edbd4db72f8dfd471b","src/cdsl/typevar.rs":"605786e2bf367879da500327fc003a4d2a663259c2dee76c87e5b99b6f6331ee","src/constant_hash.rs":"b8acd3f8712a4999819d9d9beced2938d9940a5748ba016c182f1132d97eefab","src/error.rs":"5110a4e3c1e97396ba02d9f5abbb8af4b586f0cc4d33a5c2473f1718cc4bef05","src/gen_registers.rs":"a544a2b91fafe08639e39e50bea0892fda89fe2f6eaf111b2d5f3e98e4d07b86","src/gen_settings.rs":"77ee330b85a255c49247222f4d071da839b0520eddd3dc561867f7ae84e199ac","src/gen_types.rs":"3935da6c6a53f9332e06f74bc3a46270656b4d4231ad28ed2648d7b1d2774e90","src/isa/arm32/mod.rs":"6ed3be790b28d3115421be282a06b8c376295e1776c4b77243443799015ab70d","src/isa/arm64/mod.rs":"5c46082f68c958e83ffc636de893e2ff49fd8ce21ef357f359837ca48a60eaa5","src/isa/mod.rs":"fce60d19dd3c099ebee3ac5ae64a2bee363f13da9ff5a4960d3c1a0bee71d29a","src/isa/riscv/mod.rs":"785f0da2b04458793cb2d493c5e1eeb7ea339bc721df76dda69db3b49bcdfd27","src/isa/x86/instructions.rs":"bd6b02ccc79984ed4a5615ae3b20a60a4da3777495b72f771762a886f87d2335","src/isa/x86/mod.rs":"ba7c11aedb190f58432226a6dec8a125b385cc18fd2f70c46703d077904a3112","src/lib.rs":"7ddb2d1f1a80d3dc3a7434309a6e0890dd054e88c549c20d2959236ffe986bd9","src/shared/entities.rs":"e7a44d5f621d726479c3812384e78dd25e8c063d074c64d0908b3667e7d28af1","src/shared/formats.rs":"20908b1048c5e71a185de6b6ded79cdff2c26ddb38ba7b134b7a27f37e8324f3","src/shared/immediates.rs":"1e64836f82045d05da7c151e60cf1e66666af3e0c19179de3f37e72dc81e1bbd","src/shared/instructions.rs":"2a0993279b3529b2c31aa8e83589636104a005351463ec2d3b81b5ffe569d276","src/shared/mod.rs":"696c166d3c19bd84604583a7b8d7ec4f6671622ed581bfce8bee375d02067cbe","src/shared/settings.rs":"bad2dc0e1d71ee6fec6418aa79234296aa918e499a1671c3e5c1d4b0d84b6f49","src/shared/types.rs":"158d73840185e6aa8385463bbf6568efdda0c8de8284cf6b4e565f425ec5d921","src/srcgen.rs":"ad39143ae50f3b19f18a43131bdd3308852c70a9e532cc99f97624e7380b00d8","src/unique_table.rs":"bec9d48ee040216a7c9deab6d2c5050d7ce70e38482cc8957105fd7cbca3c33a"},"package":null}
|
||||||
|
|
@ -1,28 +1,22 @@
|
||||||
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
|
|
||||||
#
|
|
||||||
# When uploading crates to the registry Cargo will automatically
|
|
||||||
# "normalize" Cargo.toml files for maximal compatibility
|
|
||||||
# with all versions of Cargo and also rewrite `path` dependencies
|
|
||||||
# to registry (e.g. crates.io) dependencies
|
|
||||||
#
|
|
||||||
# If you believe there's an error in this file please file an
|
|
||||||
# issue against the rust-lang/cargo repository. If you're
|
|
||||||
# editing this file be aware that the upstream Cargo.toml
|
|
||||||
# will likely look very different (and much more reasonable)
|
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
edition = "2018"
|
|
||||||
name = "cranelift-codegen-meta"
|
name = "cranelift-codegen-meta"
|
||||||
version = "0.29.0"
|
|
||||||
authors = ["The Cranelift Project Developers"]
|
authors = ["The Cranelift Project Developers"]
|
||||||
|
version = "0.30.0"
|
||||||
description = "Metaprogram for cranelift-codegen code generator library"
|
description = "Metaprogram for cranelift-codegen code generator library"
|
||||||
readme = "README.md"
|
|
||||||
license = "Apache-2.0 WITH LLVM-exception"
|
license = "Apache-2.0 WITH LLVM-exception"
|
||||||
repository = "https://github.com/CraneStation/cranelift"
|
repository = "https://github.com/CraneStation/cranelift"
|
||||||
[dependencies.cranelift-entity]
|
readme = "README.md"
|
||||||
version = "0.29.0"
|
edition = "2018"
|
||||||
[badges.maintenance]
|
|
||||||
status = "experimental"
|
|
||||||
|
|
||||||
[badges.travis-ci]
|
[dependencies]
|
||||||
repository = "CraneStation/cranelift"
|
cranelift-entity = { path = "../../cranelift-entity", version = "0.30.0", default-features = false }
|
||||||
|
|
||||||
|
[badges]
|
||||||
|
maintenance = { status = "experimental" }
|
||||||
|
travis-ci = { repository = "CraneStation/cranelift" }
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = ["std"]
|
||||||
|
std = ["cranelift-entity/std"]
|
||||||
|
# The "core" feature enables a workaround for Cargo #4866.
|
||||||
|
core = ["cranelift-entity/core"]
|
||||||
|
|
|
||||||
246
third_party/rust/cranelift-codegen-meta/src/cdsl/formats.rs
vendored
Normal file
246
third_party/rust/cranelift-codegen-meta/src/cdsl/formats.rs
vendored
Normal file
|
|
@ -0,0 +1,246 @@
|
||||||
|
use crate::cdsl::operands::{Operand, OperandKind};
|
||||||
|
|
||||||
|
use std::collections::{HashMap, HashSet};
|
||||||
|
use std::fmt;
|
||||||
|
use std::slice;
|
||||||
|
|
||||||
|
use cranelift_entity::{entity_impl, PrimaryMap};
|
||||||
|
|
||||||
|
/// An immediate field in an instruction format.
|
||||||
|
///
|
||||||
|
/// This corresponds to a single member of a variant of the `InstructionData`
|
||||||
|
/// data type.
|
||||||
|
///
|
||||||
|
/// :param iform: Parent `InstructionFormat`.
|
||||||
|
/// :param kind: Immediate Operand kind.
|
||||||
|
/// :param member: Member name in `InstructionData` variant.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct FormatField {
|
||||||
|
/// Immediate operand number in parent.
|
||||||
|
immnum: usize,
|
||||||
|
|
||||||
|
/// Immediate operand kind.
|
||||||
|
pub kind: OperandKind,
|
||||||
|
|
||||||
|
/// Member name in InstructionDate variant.
|
||||||
|
pub member: &'static str,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Every instruction opcode has a corresponding instruction format which
|
||||||
|
/// determines the number of operands and their kinds. Instruction formats are
|
||||||
|
/// identified structurally, i.e., the format of an instruction is derived from
|
||||||
|
/// the kinds of operands used in its declaration.
|
||||||
|
///
|
||||||
|
/// The instruction format stores two separate lists of operands: Immediates
|
||||||
|
/// and values. Immediate operands (including entity references) are
|
||||||
|
/// represented as explicit members in the `InstructionData` variants. The
|
||||||
|
/// value operands are stored differently, depending on how many there are.
|
||||||
|
/// Beyond a certain point, instruction formats switch to an external value
|
||||||
|
/// list for storing value arguments. Value lists can hold an arbitrary number
|
||||||
|
/// of values.
|
||||||
|
///
|
||||||
|
/// All instruction formats must be predefined in the meta shared/formats module.
|
||||||
|
///
|
||||||
|
/// :param kinds: List of `OperandKind` objects describing the operands.
|
||||||
|
/// :param name: Instruction format name in CamelCase. This is used as a Rust
|
||||||
|
/// variant name in both the `InstructionData` and `InstructionFormat`
|
||||||
|
/// enums.
|
||||||
|
/// :param typevar_operand: Index of the value input operand that is used to
|
||||||
|
/// infer the controlling type variable. By default, this is `0`, the first
|
||||||
|
/// `value` operand. The index is relative to the values only, ignoring
|
||||||
|
/// immediate operands.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct InstructionFormat {
|
||||||
|
pub name: &'static str,
|
||||||
|
pub num_value_operands: usize,
|
||||||
|
pub has_value_list: bool,
|
||||||
|
pub imm_fields: Vec<FormatField>,
|
||||||
|
pub typevar_operand: Option<usize>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for InstructionFormat {
|
||||||
|
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||||
|
let args = self
|
||||||
|
.imm_fields
|
||||||
|
.iter()
|
||||||
|
.map(|field| format!("{}: {}", field.member, field.kind.name))
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join(", ");
|
||||||
|
fmt.write_fmt(format_args!(
|
||||||
|
"{}(imms=({}), vals={})",
|
||||||
|
self.name, args, self.num_value_operands
|
||||||
|
))?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct InstructionFormatBuilder {
|
||||||
|
name: &'static str,
|
||||||
|
num_value_operands: usize,
|
||||||
|
has_value_list: bool,
|
||||||
|
imm_fields: Vec<FormatField>,
|
||||||
|
typevar_operand: Option<usize>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ImmParameter {
|
||||||
|
kind: OperandKind,
|
||||||
|
member: &'static str,
|
||||||
|
}
|
||||||
|
impl Into<ImmParameter> for (&'static str, &OperandKind) {
|
||||||
|
fn into(self) -> ImmParameter {
|
||||||
|
ImmParameter {
|
||||||
|
kind: self.1.clone(),
|
||||||
|
member: self.0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Into<ImmParameter> for &OperandKind {
|
||||||
|
fn into(self) -> ImmParameter {
|
||||||
|
ImmParameter {
|
||||||
|
kind: self.clone(),
|
||||||
|
member: self.default_member.unwrap(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl InstructionFormatBuilder {
|
||||||
|
pub fn new(name: &'static str) -> Self {
|
||||||
|
Self {
|
||||||
|
name,
|
||||||
|
num_value_operands: 0,
|
||||||
|
has_value_list: false,
|
||||||
|
imm_fields: Vec::new(),
|
||||||
|
typevar_operand: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn value(mut self) -> Self {
|
||||||
|
self.num_value_operands += 1;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn varargs(mut self) -> Self {
|
||||||
|
self.has_value_list = true;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn imm(mut self, param: impl Into<ImmParameter>) -> Self {
|
||||||
|
let imm_param = param.into();
|
||||||
|
let field = FormatField {
|
||||||
|
immnum: self.imm_fields.len(),
|
||||||
|
kind: imm_param.kind,
|
||||||
|
member: imm_param.member,
|
||||||
|
};
|
||||||
|
self.imm_fields.push(field);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn typevar_operand(mut self, operand_index: usize) -> Self {
|
||||||
|
assert!(self.typevar_operand.is_none());
|
||||||
|
assert!(self.has_value_list || operand_index < self.num_value_operands);
|
||||||
|
self.typevar_operand = Some(operand_index);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn finish(self) -> InstructionFormat {
|
||||||
|
let typevar_operand = if self.typevar_operand.is_some() {
|
||||||
|
self.typevar_operand
|
||||||
|
} else if self.has_value_list || self.num_value_operands > 0 {
|
||||||
|
// Default to the first value operand, if there's one.
|
||||||
|
Some(0)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
InstructionFormat {
|
||||||
|
name: self.name,
|
||||||
|
num_value_operands: self.num_value_operands,
|
||||||
|
has_value_list: self.has_value_list,
|
||||||
|
imm_fields: self.imm_fields,
|
||||||
|
typevar_operand,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||||
|
pub struct InstructionFormatIndex(u32);
|
||||||
|
entity_impl!(InstructionFormatIndex);
|
||||||
|
|
||||||
|
pub struct FormatRegistry {
|
||||||
|
/// Map (immediate kinds names, number of values, has varargs) to an instruction format index
|
||||||
|
/// in the actual map.
|
||||||
|
sig_to_index: HashMap<(Vec<String>, usize, bool), InstructionFormatIndex>,
|
||||||
|
map: PrimaryMap<InstructionFormatIndex, InstructionFormat>,
|
||||||
|
name_set: HashSet<&'static str>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FormatRegistry {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
sig_to_index: HashMap::new(),
|
||||||
|
map: PrimaryMap::new(),
|
||||||
|
name_set: HashSet::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Find an existing instruction format that matches the given lists of instruction inputs and
|
||||||
|
/// outputs.
|
||||||
|
pub fn lookup(&self, operands_in: &Vec<Operand>) -> InstructionFormatIndex {
|
||||||
|
let mut imm_keys = Vec::new();
|
||||||
|
let mut num_values = 0;
|
||||||
|
let mut has_varargs = false;
|
||||||
|
|
||||||
|
for operand in operands_in.iter() {
|
||||||
|
if operand.is_value() {
|
||||||
|
num_values += 1;
|
||||||
|
}
|
||||||
|
has_varargs = has_varargs || operand.is_varargs();
|
||||||
|
if let Some(imm_key) = operand.kind.imm_key() {
|
||||||
|
imm_keys.push(imm_key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let sig = (imm_keys, num_values, has_varargs);
|
||||||
|
*self
|
||||||
|
.sig_to_index
|
||||||
|
.get(&sig)
|
||||||
|
.expect("unknown InstructionFormat; please define it in shared/formats.rs first")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get(&self, index: InstructionFormatIndex) -> &InstructionFormat {
|
||||||
|
self.map.get(index).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn insert(&mut self, inst_format: InstructionFormatBuilder) {
|
||||||
|
let name = &inst_format.name;
|
||||||
|
if !self.name_set.insert(name) {
|
||||||
|
panic!(
|
||||||
|
"Trying to add an InstructionFormat named {}, but it already exists!",
|
||||||
|
name
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let format = inst_format.finish();
|
||||||
|
|
||||||
|
// Compute key.
|
||||||
|
let imm_keys = format
|
||||||
|
.imm_fields
|
||||||
|
.iter()
|
||||||
|
.map(|field| field.kind.imm_key().unwrap())
|
||||||
|
.collect();
|
||||||
|
let key = (imm_keys, format.num_value_operands, format.has_value_list);
|
||||||
|
|
||||||
|
let index = self.map.push(format);
|
||||||
|
if let Some(already_inserted) = self.sig_to_index.insert(key, index) {
|
||||||
|
panic!(
|
||||||
|
"duplicate InstructionFormat: trying to insert '{}' while '{}' already has the same structure.",
|
||||||
|
self.map.get(index).unwrap().name,
|
||||||
|
self.map.get(already_inserted).unwrap().name
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn iter(&self) -> slice::Iter<InstructionFormat> {
|
||||||
|
self.map.values()
|
||||||
|
}
|
||||||
|
}
|
||||||
458
third_party/rust/cranelift-codegen-meta/src/cdsl/inst.rs
vendored
Normal file
458
third_party/rust/cranelift-codegen-meta/src/cdsl/inst.rs
vendored
Normal file
|
|
@ -0,0 +1,458 @@
|
||||||
|
use crate::cdsl::camel_case;
|
||||||
|
use crate::cdsl::formats::{FormatRegistry, InstructionFormat, InstructionFormatIndex};
|
||||||
|
use crate::cdsl::operands::Operand;
|
||||||
|
use crate::cdsl::type_inference::Constraint;
|
||||||
|
use crate::cdsl::typevar::TypeVar;
|
||||||
|
|
||||||
|
use std::fmt;
|
||||||
|
use std::slice;
|
||||||
|
|
||||||
|
/// Every instruction must belong to exactly one instruction group. A given
|
||||||
|
/// target architecture can support instructions from multiple groups, and it
|
||||||
|
/// does not necessarily support all instructions in a group.
|
||||||
|
pub struct InstructionGroup {
|
||||||
|
_name: &'static str,
|
||||||
|
_doc: &'static str,
|
||||||
|
instructions: Vec<Instruction>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl InstructionGroup {
|
||||||
|
pub fn new(name: &'static str, doc: &'static str) -> Self {
|
||||||
|
Self {
|
||||||
|
_name: name,
|
||||||
|
_doc: doc,
|
||||||
|
instructions: Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push(&mut self, inst: Instruction) {
|
||||||
|
self.instructions.push(inst);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn iter(&self) -> slice::Iter<Instruction> {
|
||||||
|
self.instructions.iter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct PolymorphicInfo {
|
||||||
|
pub use_typevar_operand: bool,
|
||||||
|
pub ctrl_typevar: TypeVar,
|
||||||
|
pub other_typevars: Vec<TypeVar>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Instruction {
|
||||||
|
/// Instruction mnemonic, also becomes opcode name.
|
||||||
|
pub name: &'static str,
|
||||||
|
pub camel_name: String,
|
||||||
|
|
||||||
|
/// Documentation string.
|
||||||
|
doc: &'static str,
|
||||||
|
|
||||||
|
/// Input operands. This can be a mix of SSA value operands and other operand kinds.
|
||||||
|
pub operands_in: Vec<Operand>,
|
||||||
|
/// Output operands. The output operands must be SSA values or `variable_args`.
|
||||||
|
pub operands_out: Vec<Operand>,
|
||||||
|
/// Instruction-specific TypeConstraints.
|
||||||
|
_constraints: Vec<Constraint>,
|
||||||
|
|
||||||
|
/// Instruction format, automatically derived from the input operands.
|
||||||
|
pub format: InstructionFormatIndex,
|
||||||
|
|
||||||
|
/// One of the input or output operands is a free type variable. None if the instruction is not
|
||||||
|
/// polymorphic, set otherwise.
|
||||||
|
pub polymorphic_info: Option<PolymorphicInfo>,
|
||||||
|
|
||||||
|
pub value_opnums: Vec<usize>,
|
||||||
|
pub value_results: Vec<usize>,
|
||||||
|
pub imm_opnums: Vec<usize>,
|
||||||
|
|
||||||
|
/// True for instructions that terminate the EBB.
|
||||||
|
pub is_terminator: bool,
|
||||||
|
/// True for all branch or jump instructions.
|
||||||
|
pub is_branch: bool,
|
||||||
|
/// True for all indirect branch or jump instructions.',
|
||||||
|
pub is_indirect_branch: bool,
|
||||||
|
/// Is this a call instruction?
|
||||||
|
pub is_call: bool,
|
||||||
|
/// Is this a return instruction?
|
||||||
|
pub is_return: bool,
|
||||||
|
/// Is this a ghost instruction?
|
||||||
|
pub is_ghost: bool,
|
||||||
|
/// Can this instruction read from memory?
|
||||||
|
pub can_load: bool,
|
||||||
|
/// Can this instruction write to memory?
|
||||||
|
pub can_store: bool,
|
||||||
|
/// Can this instruction cause a trap?
|
||||||
|
pub can_trap: bool,
|
||||||
|
/// Does this instruction have other side effects besides can_* flags?
|
||||||
|
pub other_side_effects: bool,
|
||||||
|
/// Does this instruction write to CPU flags?
|
||||||
|
pub writes_cpu_flags: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Instruction {
|
||||||
|
pub fn snake_name(&self) -> &'static str {
|
||||||
|
if self.name == "return" {
|
||||||
|
"return_"
|
||||||
|
} else {
|
||||||
|
self.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn doc_comment_first_line(&self) -> &'static str {
|
||||||
|
for line in self.doc.split("\n") {
|
||||||
|
let stripped = line.trim();
|
||||||
|
if stripped.len() > 0 {
|
||||||
|
return stripped;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for Instruction {
|
||||||
|
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||||
|
if self.operands_out.len() > 0 {
|
||||||
|
let operands_out = self
|
||||||
|
.operands_out
|
||||||
|
.iter()
|
||||||
|
.map(|op| op.name)
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join(", ");
|
||||||
|
fmt.write_str(&operands_out)?;
|
||||||
|
fmt.write_str(" = ")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.write_str(self.name)?;
|
||||||
|
|
||||||
|
if self.operands_in.len() > 0 {
|
||||||
|
let operands_in = self
|
||||||
|
.operands_in
|
||||||
|
.iter()
|
||||||
|
.map(|op| op.name)
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join(", ");
|
||||||
|
fmt.write_str(" ")?;
|
||||||
|
fmt.write_str(&operands_in)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct InstructionBuilder {
|
||||||
|
name: &'static str,
|
||||||
|
doc: &'static str,
|
||||||
|
operands_in: Option<Vec<Operand>>,
|
||||||
|
operands_out: Option<Vec<Operand>>,
|
||||||
|
constraints: Option<Vec<Constraint>>,
|
||||||
|
|
||||||
|
// See Instruction comments for the meaning of these fields.
|
||||||
|
is_terminator: bool,
|
||||||
|
is_branch: bool,
|
||||||
|
is_indirect_branch: bool,
|
||||||
|
is_call: bool,
|
||||||
|
is_return: bool,
|
||||||
|
is_ghost: bool,
|
||||||
|
can_load: bool,
|
||||||
|
can_store: bool,
|
||||||
|
can_trap: bool,
|
||||||
|
other_side_effects: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl InstructionBuilder {
|
||||||
|
pub fn new(name: &'static str, doc: &'static str) -> Self {
|
||||||
|
Self {
|
||||||
|
name,
|
||||||
|
doc,
|
||||||
|
operands_in: None,
|
||||||
|
operands_out: None,
|
||||||
|
constraints: None,
|
||||||
|
|
||||||
|
is_terminator: false,
|
||||||
|
is_branch: false,
|
||||||
|
is_indirect_branch: false,
|
||||||
|
is_call: false,
|
||||||
|
is_return: false,
|
||||||
|
is_ghost: false,
|
||||||
|
can_load: false,
|
||||||
|
can_store: false,
|
||||||
|
can_trap: false,
|
||||||
|
other_side_effects: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn operands_in(mut self, operands: Vec<&Operand>) -> Self {
|
||||||
|
assert!(self.operands_in.is_none());
|
||||||
|
self.operands_in = Some(operands.iter().map(|x| (*x).clone()).collect());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn operands_out(mut self, operands: Vec<&Operand>) -> Self {
|
||||||
|
assert!(self.operands_out.is_none());
|
||||||
|
self.operands_out = Some(operands.iter().map(|x| (*x).clone()).collect());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn constraints(mut self, constraints: Vec<Constraint>) -> Self {
|
||||||
|
assert!(self.constraints.is_none());
|
||||||
|
self.constraints = Some(constraints);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_terminator(mut self, val: bool) -> Self {
|
||||||
|
self.is_terminator = val;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn is_branch(mut self, val: bool) -> Self {
|
||||||
|
self.is_branch = val;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn is_indirect_branch(mut self, val: bool) -> Self {
|
||||||
|
self.is_indirect_branch = val;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn is_call(mut self, val: bool) -> Self {
|
||||||
|
self.is_call = val;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn is_return(mut self, val: bool) -> Self {
|
||||||
|
self.is_return = val;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn is_ghost(mut self, val: bool) -> Self {
|
||||||
|
self.is_ghost = val;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn can_load(mut self, val: bool) -> Self {
|
||||||
|
self.can_load = val;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn can_store(mut self, val: bool) -> Self {
|
||||||
|
self.can_store = val;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn can_trap(mut self, val: bool) -> Self {
|
||||||
|
self.can_trap = val;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn other_side_effects(mut self, val: bool) -> Self {
|
||||||
|
self.other_side_effects = val;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn finish(self, format_registry: &FormatRegistry) -> Instruction {
|
||||||
|
let operands_in = self.operands_in.unwrap_or_else(Vec::new);
|
||||||
|
let operands_out = self.operands_out.unwrap_or_else(Vec::new);
|
||||||
|
|
||||||
|
let format_index = format_registry.lookup(&operands_in);
|
||||||
|
|
||||||
|
let mut value_opnums = Vec::new();
|
||||||
|
let mut imm_opnums = Vec::new();
|
||||||
|
for (i, op) in operands_in.iter().enumerate() {
|
||||||
|
if op.is_value() {
|
||||||
|
value_opnums.push(i);
|
||||||
|
} else if op.is_immediate() {
|
||||||
|
imm_opnums.push(i);
|
||||||
|
} else {
|
||||||
|
assert!(op.is_varargs());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut value_results = Vec::new();
|
||||||
|
for (i, op) in operands_out.iter().enumerate() {
|
||||||
|
if op.is_value() {
|
||||||
|
value_results.push(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let format = format_registry.get(format_index);
|
||||||
|
let polymorphic_info =
|
||||||
|
verify_polymorphic(&operands_in, &operands_out, &format, &value_opnums);
|
||||||
|
|
||||||
|
// Infer from output operands whether an instruciton clobbers CPU flags or not.
|
||||||
|
let writes_cpu_flags = operands_out.iter().any(|op| op.is_cpu_flags());
|
||||||
|
|
||||||
|
Instruction {
|
||||||
|
name: self.name,
|
||||||
|
camel_name: camel_case(self.name),
|
||||||
|
doc: self.doc,
|
||||||
|
operands_in,
|
||||||
|
operands_out,
|
||||||
|
_constraints: self.constraints.unwrap_or_else(Vec::new),
|
||||||
|
format: format_index,
|
||||||
|
polymorphic_info,
|
||||||
|
value_opnums,
|
||||||
|
value_results,
|
||||||
|
imm_opnums,
|
||||||
|
is_terminator: self.is_terminator,
|
||||||
|
is_branch: self.is_branch,
|
||||||
|
is_indirect_branch: self.is_indirect_branch,
|
||||||
|
is_call: self.is_call,
|
||||||
|
is_return: self.is_return,
|
||||||
|
is_ghost: self.is_ghost,
|
||||||
|
can_load: self.can_load,
|
||||||
|
can_store: self.can_store,
|
||||||
|
can_trap: self.can_trap,
|
||||||
|
other_side_effects: self.other_side_effects,
|
||||||
|
writes_cpu_flags,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check if this instruction is polymorphic, and verify its use of type variables.
|
||||||
|
fn verify_polymorphic(
|
||||||
|
operands_in: &Vec<Operand>,
|
||||||
|
operands_out: &Vec<Operand>,
|
||||||
|
format: &InstructionFormat,
|
||||||
|
value_opnums: &Vec<usize>,
|
||||||
|
) -> Option<PolymorphicInfo> {
|
||||||
|
// The instruction is polymorphic if it has one free input or output operand.
|
||||||
|
let is_polymorphic = operands_in
|
||||||
|
.iter()
|
||||||
|
.any(|op| op.is_value() && op.type_var().unwrap().free_typevar().is_some())
|
||||||
|
|| operands_out
|
||||||
|
.iter()
|
||||||
|
.any(|op| op.is_value() && op.type_var().unwrap().free_typevar().is_some());
|
||||||
|
|
||||||
|
if !is_polymorphic {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify the use of type variables.
|
||||||
|
let mut use_typevar_operand = false;
|
||||||
|
let mut ctrl_typevar = None;
|
||||||
|
let mut other_typevars = None;
|
||||||
|
let mut maybe_error_message = None;
|
||||||
|
|
||||||
|
let tv_op = format.typevar_operand;
|
||||||
|
if let Some(tv_op) = tv_op {
|
||||||
|
if tv_op < value_opnums.len() {
|
||||||
|
let op_num = value_opnums[tv_op];
|
||||||
|
let tv = operands_in[op_num].type_var().unwrap();
|
||||||
|
let free_typevar = tv.free_typevar();
|
||||||
|
if (free_typevar.is_some() && tv == &free_typevar.unwrap())
|
||||||
|
|| !tv.singleton_type().is_none()
|
||||||
|
{
|
||||||
|
match verify_ctrl_typevar(tv, &value_opnums, &operands_in, &operands_out) {
|
||||||
|
Ok(typevars) => {
|
||||||
|
other_typevars = Some(typevars);
|
||||||
|
ctrl_typevar = Some(tv.clone());
|
||||||
|
use_typevar_operand = true;
|
||||||
|
}
|
||||||
|
Err(error_message) => {
|
||||||
|
maybe_error_message = Some(error_message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if !use_typevar_operand {
|
||||||
|
if operands_out.len() == 0 {
|
||||||
|
match maybe_error_message {
|
||||||
|
Some(msg) => panic!(msg),
|
||||||
|
None => panic!("typevar_operand must be a free type variable"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let tv = operands_out[0].type_var().unwrap();
|
||||||
|
let free_typevar = tv.free_typevar();
|
||||||
|
if free_typevar.is_some() && tv != &free_typevar.unwrap() {
|
||||||
|
panic!("first result must be a free type variable");
|
||||||
|
}
|
||||||
|
|
||||||
|
other_typevars =
|
||||||
|
Some(verify_ctrl_typevar(tv, &value_opnums, &operands_in, &operands_out).unwrap());
|
||||||
|
ctrl_typevar = Some(tv.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
// rustc is not capable to determine this statically, so enforce it with options.
|
||||||
|
assert!(ctrl_typevar.is_some());
|
||||||
|
assert!(other_typevars.is_some());
|
||||||
|
|
||||||
|
Some(PolymorphicInfo {
|
||||||
|
use_typevar_operand,
|
||||||
|
ctrl_typevar: ctrl_typevar.unwrap(),
|
||||||
|
other_typevars: other_typevars.unwrap(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Verify that the use of TypeVars is consistent with `ctrl_typevar` as the controlling type
|
||||||
|
/// variable.
|
||||||
|
///
|
||||||
|
/// All polymorhic inputs must either be derived from `ctrl_typevar` or be independent free type
|
||||||
|
/// variables only used once.
|
||||||
|
///
|
||||||
|
/// All polymorphic results must be derived from `ctrl_typevar`.
|
||||||
|
///
|
||||||
|
/// Return a vector of other type variables used, or panics.
|
||||||
|
fn verify_ctrl_typevar(
|
||||||
|
ctrl_typevar: &TypeVar,
|
||||||
|
value_opnums: &Vec<usize>,
|
||||||
|
operands_in: &Vec<Operand>,
|
||||||
|
operands_out: &Vec<Operand>,
|
||||||
|
) -> Result<Vec<TypeVar>, String> {
|
||||||
|
let mut other_typevars = Vec::new();
|
||||||
|
|
||||||
|
// Check value inputs.
|
||||||
|
for &op_num in value_opnums {
|
||||||
|
let typ = operands_in[op_num].type_var();
|
||||||
|
|
||||||
|
let tv = if let Some(typ) = typ {
|
||||||
|
typ.free_typevar()
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
// Non-polymorphic or derived from ctrl_typevar is OK.
|
||||||
|
let tv = match tv {
|
||||||
|
Some(tv) => {
|
||||||
|
if &tv == ctrl_typevar {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
tv
|
||||||
|
}
|
||||||
|
None => continue,
|
||||||
|
};
|
||||||
|
|
||||||
|
// No other derived typevars allowed.
|
||||||
|
if typ.is_some() && typ.unwrap() != &tv {
|
||||||
|
return Err(format!(
|
||||||
|
"{:?}: type variable {} must be derived from {:?}",
|
||||||
|
operands_in[op_num],
|
||||||
|
typ.unwrap().name,
|
||||||
|
ctrl_typevar
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Other free type variables can only be used once each.
|
||||||
|
for other_tv in &other_typevars {
|
||||||
|
if &tv == other_tv {
|
||||||
|
return Err(format!(
|
||||||
|
"type variable {} can't be used more than once",
|
||||||
|
tv.name
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
other_typevars.push(tv);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check outputs.
|
||||||
|
for result in operands_out {
|
||||||
|
if !result.is_value() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let typ = result.type_var().unwrap();
|
||||||
|
let tv = typ.free_typevar();
|
||||||
|
|
||||||
|
// Non-polymorphic or derived form ctrl_typevar is OK.
|
||||||
|
if tv.is_none() || &tv.unwrap() == ctrl_typevar {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Err("type variable in output not derived from ctrl_typevar".into());
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(other_typevars)
|
||||||
|
}
|
||||||
|
|
@ -1,16 +1,24 @@
|
||||||
use super::regs::IsaRegs;
|
use crate::cdsl::inst::InstructionGroup;
|
||||||
use super::settings::SettingGroup;
|
use crate::cdsl::regs::IsaRegs;
|
||||||
|
use crate::cdsl::settings::SettingGroup;
|
||||||
|
|
||||||
pub struct TargetIsa {
|
pub struct TargetIsa {
|
||||||
pub name: &'static str,
|
pub name: &'static str,
|
||||||
|
pub instructions: InstructionGroup,
|
||||||
pub settings: SettingGroup,
|
pub settings: SettingGroup,
|
||||||
pub regs: IsaRegs,
|
pub regs: IsaRegs,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TargetIsa {
|
impl TargetIsa {
|
||||||
pub fn new(name: &'static str, settings: SettingGroup, regs: IsaRegs) -> Self {
|
pub fn new(
|
||||||
|
name: &'static str,
|
||||||
|
instructions: InstructionGroup,
|
||||||
|
settings: SettingGroup,
|
||||||
|
regs: IsaRegs,
|
||||||
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
name,
|
name,
|
||||||
|
instructions,
|
||||||
settings,
|
settings,
|
||||||
regs,
|
regs,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,15 @@
|
||||||
//! This module defines the classes that are used to define Cranelift
|
//! This module defines the classes that are used to define Cranelift
|
||||||
//! instructions and other entities.
|
//! instructions and other entities.
|
||||||
|
|
||||||
|
pub mod formats;
|
||||||
|
pub mod inst;
|
||||||
pub mod isa;
|
pub mod isa;
|
||||||
|
pub mod operands;
|
||||||
pub mod regs;
|
pub mod regs;
|
||||||
pub mod settings;
|
pub mod settings;
|
||||||
|
pub mod type_inference;
|
||||||
pub mod types;
|
pub mod types;
|
||||||
|
pub mod typevar;
|
||||||
|
|
||||||
/// A macro that converts boolean settings into predicates to look more natural.
|
/// A macro that converts boolean settings into predicates to look more natural.
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
|
|
|
||||||
285
third_party/rust/cranelift-codegen-meta/src/cdsl/operands.rs
vendored
Normal file
285
third_party/rust/cranelift-codegen-meta/src/cdsl/operands.rs
vendored
Normal file
|
|
@ -0,0 +1,285 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use crate::cdsl::camel_case;
|
||||||
|
use crate::cdsl::typevar::TypeVar;
|
||||||
|
|
||||||
|
/// An instruction operand can be an *immediate*, an *SSA value*, or an *entity reference*. The
|
||||||
|
/// type of the operand is one of:
|
||||||
|
///
|
||||||
|
/// 1. A `ValueType` instance indicates an SSA value operand with a concrete type.
|
||||||
|
///
|
||||||
|
/// 2. A `TypeVar` instance indicates an SSA value operand, and the instruction is polymorphic over
|
||||||
|
/// the possible concrete types that the type variable can assume.
|
||||||
|
///
|
||||||
|
/// 3. An `ImmediateKind` instance indicates an immediate operand whose value is encoded in the
|
||||||
|
/// instruction itself rather than being passed as an SSA value.
|
||||||
|
///
|
||||||
|
/// 4. An `EntityRefKind` instance indicates an operand that references another entity in the
|
||||||
|
/// function, typically something declared in the function preamble.
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct Operand {
|
||||||
|
pub name: &'static str,
|
||||||
|
pub doc: Option<String>,
|
||||||
|
pub kind: OperandKind,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Operand {
|
||||||
|
pub fn is_value(&self) -> bool {
|
||||||
|
match self.kind.fields {
|
||||||
|
OperandKindFields::TypeVar(_) => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn type_var(&self) -> Option<&TypeVar> {
|
||||||
|
match &self.kind.fields {
|
||||||
|
OperandKindFields::TypeVar(typevar) => Some(typevar),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_varargs(&self) -> bool {
|
||||||
|
match self.kind.fields {
|
||||||
|
OperandKindFields::VariableArgs => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns true if the operand has an immediate kind or is an EntityRef.
|
||||||
|
// TODO inherited name from the python, rename to is_immediate_or_entityref later.
|
||||||
|
pub fn is_immediate(&self) -> bool {
|
||||||
|
match self.kind.fields {
|
||||||
|
OperandKindFields::ImmEnum(_)
|
||||||
|
| OperandKindFields::ImmValue
|
||||||
|
| OperandKindFields::EntityRef => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns true if the operand has an immediate kind.
|
||||||
|
pub fn is_pure_immediate(&self) -> bool {
|
||||||
|
match self.kind.fields {
|
||||||
|
OperandKindFields::ImmEnum(_) | OperandKindFields::ImmValue => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_cpu_flags(&self) -> bool {
|
||||||
|
match &self.kind.fields {
|
||||||
|
OperandKindFields::TypeVar(type_var)
|
||||||
|
if type_var.name == "iflags" || type_var.name == "fflags" =>
|
||||||
|
{
|
||||||
|
true
|
||||||
|
}
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct OperandBuilder {
|
||||||
|
name: &'static str,
|
||||||
|
doc: Option<String>,
|
||||||
|
kind: OperandKind,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OperandBuilder {
|
||||||
|
pub fn new(name: &'static str, kind: OperandKind) -> Self {
|
||||||
|
Self {
|
||||||
|
name,
|
||||||
|
doc: None,
|
||||||
|
kind,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn doc(mut self, doc: impl Into<String>) -> Self {
|
||||||
|
assert!(self.doc.is_none());
|
||||||
|
self.doc = Some(doc.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn finish(self) -> Operand {
|
||||||
|
let doc = match self.doc {
|
||||||
|
Some(doc) => Some(doc),
|
||||||
|
None => match &self.kind.fields {
|
||||||
|
OperandKindFields::TypeVar(tvar) => Some(tvar.doc.clone()),
|
||||||
|
_ => self.kind.doc.clone(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
Operand {
|
||||||
|
name: self.name,
|
||||||
|
doc,
|
||||||
|
kind: self.kind,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type EnumValues = HashMap<&'static str, &'static str>;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum OperandKindFields {
|
||||||
|
EntityRef,
|
||||||
|
VariableArgs,
|
||||||
|
ImmValue,
|
||||||
|
ImmEnum(EnumValues),
|
||||||
|
TypeVar(TypeVar),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct OperandKind {
|
||||||
|
pub name: &'static str,
|
||||||
|
|
||||||
|
doc: Option<String>,
|
||||||
|
|
||||||
|
pub default_member: Option<&'static str>,
|
||||||
|
|
||||||
|
/// The camel-cased name of an operand kind is also the Rust type used to represent it.
|
||||||
|
pub rust_type: String,
|
||||||
|
|
||||||
|
fields: OperandKindFields,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OperandKind {
|
||||||
|
pub fn imm_key(&self) -> Option<String> {
|
||||||
|
match self.fields {
|
||||||
|
OperandKindFields::ImmEnum(_)
|
||||||
|
| OperandKindFields::ImmValue
|
||||||
|
| OperandKindFields::EntityRef => Some(self.name.to_string()),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn type_var(&self) -> TypeVar {
|
||||||
|
match &self.fields {
|
||||||
|
OperandKindFields::TypeVar(tvar) => tvar.clone(),
|
||||||
|
_ => panic!("not a typevar"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct OperandKindBuilder {
|
||||||
|
name: &'static str,
|
||||||
|
|
||||||
|
doc: Option<String>,
|
||||||
|
|
||||||
|
default_member: Option<&'static str>,
|
||||||
|
|
||||||
|
/// The camel-cased name of an operand kind is also the Rust type used to represent it.
|
||||||
|
rust_type: Option<String>,
|
||||||
|
|
||||||
|
fields: OperandKindFields,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OperandKindBuilder {
|
||||||
|
pub fn new(name: &'static str, fields: OperandKindFields) -> Self {
|
||||||
|
Self {
|
||||||
|
name,
|
||||||
|
doc: None,
|
||||||
|
default_member: None,
|
||||||
|
rust_type: None,
|
||||||
|
fields,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_imm(name: &'static str) -> Self {
|
||||||
|
Self {
|
||||||
|
name,
|
||||||
|
doc: None,
|
||||||
|
default_member: None,
|
||||||
|
rust_type: None,
|
||||||
|
fields: OperandKindFields::ImmValue,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_enum(name: &'static str, values: EnumValues) -> Self {
|
||||||
|
Self {
|
||||||
|
name,
|
||||||
|
doc: None,
|
||||||
|
default_member: None,
|
||||||
|
rust_type: None,
|
||||||
|
fields: OperandKindFields::ImmEnum(values),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn doc(mut self, doc: &'static str) -> Self {
|
||||||
|
assert!(self.doc.is_none());
|
||||||
|
self.doc = Some(doc.to_string());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn default_member(mut self, default_member: &'static str) -> Self {
|
||||||
|
assert!(self.default_member.is_none());
|
||||||
|
self.default_member = Some(default_member);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn rust_type(mut self, rust_type: &'static str) -> Self {
|
||||||
|
assert!(self.rust_type.is_none());
|
||||||
|
self.rust_type = Some(rust_type.to_string());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn finish(self) -> OperandKind {
|
||||||
|
let default_member = match self.default_member {
|
||||||
|
Some(default_member) => Some(default_member),
|
||||||
|
None => match &self.fields {
|
||||||
|
OperandKindFields::ImmEnum(_) | OperandKindFields::ImmValue => Some("imm"),
|
||||||
|
OperandKindFields::TypeVar(_) | OperandKindFields::EntityRef => Some(self.name),
|
||||||
|
OperandKindFields::VariableArgs => None,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let rust_type = match self.rust_type {
|
||||||
|
Some(rust_type) => rust_type.to_string(),
|
||||||
|
None => match &self.fields {
|
||||||
|
OperandKindFields::ImmEnum(_) | OperandKindFields::ImmValue => {
|
||||||
|
format!("ir::immediates::{}", camel_case(self.name))
|
||||||
|
}
|
||||||
|
OperandKindFields::VariableArgs => "&[Value]".to_string(),
|
||||||
|
OperandKindFields::TypeVar(_) | OperandKindFields::EntityRef => {
|
||||||
|
format!("ir::{}", camel_case(self.name))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let doc = match self.doc {
|
||||||
|
Some(doc) => Some(doc),
|
||||||
|
None => match &self.fields {
|
||||||
|
OperandKindFields::TypeVar(type_var) => Some(type_var.doc.clone()),
|
||||||
|
OperandKindFields::ImmEnum(_)
|
||||||
|
| OperandKindFields::ImmValue
|
||||||
|
| OperandKindFields::EntityRef
|
||||||
|
| OperandKindFields::VariableArgs => None,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
OperandKind {
|
||||||
|
name: self.name,
|
||||||
|
doc,
|
||||||
|
default_member,
|
||||||
|
rust_type,
|
||||||
|
fields: self.fields,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<OperandKind> for &TypeVar {
|
||||||
|
fn into(self) -> OperandKind {
|
||||||
|
OperandKindBuilder::new("value", OperandKindFields::TypeVar(self.into())).finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Into<OperandKind> for &OperandKind {
|
||||||
|
fn into(self) -> OperandKind {
|
||||||
|
self.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Helper to create an operand in definitions files.
|
||||||
|
pub fn create_operand(name: &'static str, kind: impl Into<OperandKind>) -> Operand {
|
||||||
|
OperandBuilder::new(name, kind.into()).finish()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Helper to create an operand with a documentation in definitions files.
|
||||||
|
pub fn create_operand_doc(
|
||||||
|
name: &'static str,
|
||||||
|
kind: impl Into<OperandKind>,
|
||||||
|
doc: &'static str,
|
||||||
|
) -> Operand {
|
||||||
|
OperandBuilder::new(name, kind.into()).doc(doc).finish()
|
||||||
|
}
|
||||||
5
third_party/rust/cranelift-codegen-meta/src/cdsl/type_inference.rs
vendored
Normal file
5
third_party/rust/cranelift-codegen-meta/src/cdsl/type_inference.rs
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
use crate::cdsl::typevar::TypeVar;
|
||||||
|
|
||||||
|
pub enum Constraint {
|
||||||
|
WiderOrEq(TypeVar, TypeVar),
|
||||||
|
}
|
||||||
|
|
@ -21,13 +21,13 @@ static LANE_BASE: u8 = 0x70;
|
||||||
// Rust name prefix used for the `rust_name` method.
|
// Rust name prefix used for the `rust_name` method.
|
||||||
static _RUST_NAME_PREFIX: &'static str = "ir::types::";
|
static _RUST_NAME_PREFIX: &'static str = "ir::types::";
|
||||||
|
|
||||||
// ValueType variants (i8, i32, ...) are provided in `base::types.rs`.
|
// ValueType variants (i8, i32, ...) are provided in `shared::types.rs`.
|
||||||
|
|
||||||
/// A concrete SSA value type.
|
/// A concrete SSA value type.
|
||||||
///
|
///
|
||||||
/// All SSA values have a type that is described by an instance of `ValueType`
|
/// All SSA values have a type that is described by an instance of `ValueType`
|
||||||
/// or one of its subclasses.
|
/// or one of its subclasses.
|
||||||
#[derive(Debug)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub enum ValueType {
|
pub enum ValueType {
|
||||||
BV(BVType),
|
BV(BVType),
|
||||||
Lane(LaneType),
|
Lane(LaneType),
|
||||||
|
|
@ -90,7 +90,7 @@ impl ValueType {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the name of this type for generated Rust source files.
|
/// Return the name of this type for generated Rust source files.
|
||||||
pub fn _rust_name(&self) -> String {
|
pub fn rust_name(&self) -> String {
|
||||||
format!("{}{}", _RUST_NAME_PREFIX, self.to_string().to_uppercase())
|
format!("{}{}", _RUST_NAME_PREFIX, self.to_string().to_uppercase())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -147,7 +147,7 @@ impl From<VectorType> for ValueType {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A concrete scalar type that can appear as a vector lane too.
|
/// A concrete scalar type that can appear as a vector lane too.
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy, PartialEq)]
|
||||||
pub enum LaneType {
|
pub enum LaneType {
|
||||||
BoolType(shared_types::Bool),
|
BoolType(shared_types::Bool),
|
||||||
FloatType(shared_types::Float),
|
FloatType(shared_types::Float),
|
||||||
|
|
@ -205,6 +205,43 @@ impl LaneType {
|
||||||
LaneType::FloatType(shared_types::Float::F64) => 10,
|
LaneType::FloatType(shared_types::Float::F64) => 10,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn bool_from_bits(num_bits: u16) -> LaneType {
|
||||||
|
LaneType::BoolType(match num_bits {
|
||||||
|
1 => shared_types::Bool::B1,
|
||||||
|
8 => shared_types::Bool::B8,
|
||||||
|
16 => shared_types::Bool::B16,
|
||||||
|
32 => shared_types::Bool::B32,
|
||||||
|
64 => shared_types::Bool::B64,
|
||||||
|
_ => unreachable!("unxpected num bits for bool"),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn int_from_bits(num_bits: u16) -> LaneType {
|
||||||
|
LaneType::IntType(match num_bits {
|
||||||
|
8 => shared_types::Int::I8,
|
||||||
|
16 => shared_types::Int::I16,
|
||||||
|
32 => shared_types::Int::I32,
|
||||||
|
64 => shared_types::Int::I64,
|
||||||
|
_ => unreachable!("unxpected num bits for int"),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn float_from_bits(num_bits: u16) -> LaneType {
|
||||||
|
LaneType::FloatType(match num_bits {
|
||||||
|
32 => shared_types::Float::F32,
|
||||||
|
64 => shared_types::Float::F64,
|
||||||
|
_ => unreachable!("unxpected num bits for float"),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn by(&self, lanes: u16) -> ValueType {
|
||||||
|
if lanes == 1 {
|
||||||
|
(*self).into()
|
||||||
|
} else {
|
||||||
|
ValueType::Vector(VectorType::new(*self, lanes.into()))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for LaneType {
|
impl fmt::Display for LaneType {
|
||||||
|
|
@ -290,6 +327,7 @@ impl Iterator for LaneTypeIterator {
|
||||||
///
|
///
|
||||||
/// A vector type has a lane type which is an instance of `LaneType`,
|
/// A vector type has a lane type which is an instance of `LaneType`,
|
||||||
/// and a positive number of lanes.
|
/// and a positive number of lanes.
|
||||||
|
#[derive(Clone, PartialEq)]
|
||||||
pub struct VectorType {
|
pub struct VectorType {
|
||||||
base: LaneType,
|
base: LaneType,
|
||||||
lanes: u64,
|
lanes: u64,
|
||||||
|
|
@ -320,6 +358,11 @@ impl VectorType {
|
||||||
self.lanes
|
self.lanes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return the lane type.
|
||||||
|
pub fn lane_type(&self) -> LaneType {
|
||||||
|
self.base
|
||||||
|
}
|
||||||
|
|
||||||
/// Find the unique number associated with this vector type.
|
/// Find the unique number associated with this vector type.
|
||||||
///
|
///
|
||||||
/// Vector types are encoded with the lane type in the low 4 bits and
|
/// Vector types are encoded with the lane type in the low 4 bits and
|
||||||
|
|
@ -350,14 +393,15 @@ impl fmt::Debug for VectorType {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A flat bitvector type. Used for semantics description only.
|
/// A flat bitvector type. Used for semantics description only.
|
||||||
|
#[derive(Clone, PartialEq)]
|
||||||
pub struct BVType {
|
pub struct BVType {
|
||||||
bits: u64,
|
bits: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BVType {
|
impl BVType {
|
||||||
/// Initialize a new bitvector type with `n` bits.
|
/// Initialize a new bitvector type with `n` bits.
|
||||||
pub fn _new(bits: u64) -> Self {
|
pub fn new(bits: u16) -> Self {
|
||||||
Self { bits }
|
Self { bits: bits.into() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return a string containing the documentation comment for this bitvector type.
|
/// Return a string containing the documentation comment for this bitvector type.
|
||||||
|
|
@ -386,7 +430,7 @@ impl fmt::Debug for BVType {
|
||||||
/// A concrete scalar type that is neither a vector nor a lane type.
|
/// A concrete scalar type that is neither a vector nor a lane type.
|
||||||
///
|
///
|
||||||
/// Special types cannot be used to form vectors.
|
/// Special types cannot be used to form vectors.
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub enum SpecialType {
|
pub enum SpecialType {
|
||||||
Flag(shared_types::Flag),
|
Flag(shared_types::Flag),
|
||||||
}
|
}
|
||||||
|
|
|
||||||
901
third_party/rust/cranelift-codegen-meta/src/cdsl/typevar.rs
vendored
Normal file
901
third_party/rust/cranelift-codegen-meta/src/cdsl/typevar.rs
vendored
Normal file
|
|
@ -0,0 +1,901 @@
|
||||||
|
use std::collections::BTreeSet;
|
||||||
|
use std::iter::FromIterator;
|
||||||
|
use std::ops;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
use crate::cdsl::types::{BVType, LaneType, SpecialType, ValueType};
|
||||||
|
|
||||||
|
const MAX_LANES: u16 = 256;
|
||||||
|
const MAX_BITS: u16 = 64;
|
||||||
|
const MAX_BITVEC: u16 = MAX_BITS * MAX_LANES;
|
||||||
|
|
||||||
|
/// Type variables can be used in place of concrete types when defining
|
||||||
|
/// instructions. This makes the instructions *polymorphic*.
|
||||||
|
///
|
||||||
|
/// A type variable is restricted to vary over a subset of the value types.
|
||||||
|
/// This subset is specified by a set of flags that control the permitted base
|
||||||
|
/// types and whether the type variable can assume scalar or vector types, or
|
||||||
|
/// both.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct TypeVarContent {
|
||||||
|
/// Short name of type variable used in instruction descriptions.
|
||||||
|
pub name: String,
|
||||||
|
|
||||||
|
/// Documentation string.
|
||||||
|
pub doc: String,
|
||||||
|
|
||||||
|
/// Type set associated to the type variable.
|
||||||
|
/// This field must remain private; use `get_typeset()` or `get_raw_typeset()` to get the
|
||||||
|
/// information you want.
|
||||||
|
type_set: Rc<TypeSet>,
|
||||||
|
|
||||||
|
pub base: Option<TypeVarParent>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct TypeVar {
|
||||||
|
content: Rc<TypeVarContent>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TypeVar {
|
||||||
|
pub fn new(name: impl Into<String>, doc: impl Into<String>, type_set: TypeSet) -> Self {
|
||||||
|
Self {
|
||||||
|
content: Rc::new(TypeVarContent {
|
||||||
|
name: name.into(),
|
||||||
|
doc: doc.into(),
|
||||||
|
type_set: Rc::new(type_set),
|
||||||
|
base: None,
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_singleton(value_type: ValueType) -> Self {
|
||||||
|
let (name, doc) = (value_type.to_string(), value_type.doc());
|
||||||
|
let mut builder = TypeSetBuilder::new();
|
||||||
|
|
||||||
|
let (scalar_type, num_lanes) = match value_type {
|
||||||
|
ValueType::BV(bitvec_type) => {
|
||||||
|
let bits = bitvec_type.lane_bits() as RangeBound;
|
||||||
|
return TypeVar::new(name, doc, builder.bitvecs(bits..bits).finish());
|
||||||
|
}
|
||||||
|
ValueType::Special(special_type) => {
|
||||||
|
return TypeVar::new(name, doc, builder.specials(vec![special_type]).finish());
|
||||||
|
}
|
||||||
|
ValueType::Lane(lane_type) => (lane_type, 1),
|
||||||
|
ValueType::Vector(vec_type) => {
|
||||||
|
(vec_type.lane_type(), vec_type.lane_count() as RangeBound)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
builder = builder.simd_lanes(num_lanes..num_lanes);
|
||||||
|
|
||||||
|
let builder = match scalar_type {
|
||||||
|
LaneType::IntType(int_type) => {
|
||||||
|
let bits = int_type as RangeBound;
|
||||||
|
builder.ints(bits..bits)
|
||||||
|
}
|
||||||
|
LaneType::FloatType(float_type) => {
|
||||||
|
let bits = float_type as RangeBound;
|
||||||
|
builder.floats(bits..bits)
|
||||||
|
}
|
||||||
|
LaneType::BoolType(bool_type) => {
|
||||||
|
let bits = bool_type as RangeBound;
|
||||||
|
builder.bools(bits..bits)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
TypeVar::new(name, doc, builder.finish())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns this typevar's type set, maybe computing it from the parent.
|
||||||
|
fn get_typeset(&self) -> Rc<TypeSet> {
|
||||||
|
// TODO Can this be done in a non-lazy way in derived() and we can remove this function and
|
||||||
|
// the one below?
|
||||||
|
match &self.content.base {
|
||||||
|
Some(base) => Rc::new(base.type_var.get_typeset().image(base.derived_func)),
|
||||||
|
None => self.content.type_set.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns this typevar's type set, assuming this type var has no parent.
|
||||||
|
pub fn get_raw_typeset(&self) -> &TypeSet {
|
||||||
|
assert_eq!(self.content.type_set, self.get_typeset());
|
||||||
|
&*self.content.type_set
|
||||||
|
}
|
||||||
|
|
||||||
|
/// If the associated typeset has a single type return it. Otherwise return None.
|
||||||
|
pub fn singleton_type(&self) -> Option<ValueType> {
|
||||||
|
let type_set = self.get_typeset();
|
||||||
|
if type_set.size() == 1 {
|
||||||
|
Some(type_set.get_singleton())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the free type variable controlling this one.
|
||||||
|
pub fn free_typevar(&self) -> Option<TypeVar> {
|
||||||
|
match &self.content.base {
|
||||||
|
Some(base) => base.type_var.free_typevar(),
|
||||||
|
None => {
|
||||||
|
match self.singleton_type() {
|
||||||
|
// A singleton type isn't a proper free variable.
|
||||||
|
Some(_) => None,
|
||||||
|
None => Some(self.clone()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a type variable that is a function of another.
|
||||||
|
fn derived(&self, derived_func: DerivedFunc) -> TypeVar {
|
||||||
|
let ts = self.get_typeset();
|
||||||
|
|
||||||
|
// Safety checks to avoid over/underflows.
|
||||||
|
assert!(ts.specials.len() == 0, "can't derive from special types");
|
||||||
|
match derived_func {
|
||||||
|
DerivedFunc::HalfWidth => {
|
||||||
|
assert!(
|
||||||
|
ts.ints.len() == 0 || *ts.ints.iter().min().unwrap() > 8,
|
||||||
|
"can't halve all integer types"
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
ts.floats.len() == 0 || *ts.floats.iter().min().unwrap() > 32,
|
||||||
|
"can't halve all float types"
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
ts.bools.len() == 0 || *ts.bools.iter().min().unwrap() > 8,
|
||||||
|
"can't halve all boolean types"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
DerivedFunc::DoubleWidth => {
|
||||||
|
assert!(
|
||||||
|
ts.ints.len() == 0 || *ts.ints.iter().max().unwrap() < MAX_BITS,
|
||||||
|
"can't double all integer types"
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
ts.floats.len() == 0 || *ts.floats.iter().max().unwrap() < MAX_BITS,
|
||||||
|
"can't double all float types"
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
ts.bools.len() == 0 || *ts.bools.iter().max().unwrap() < MAX_BITS,
|
||||||
|
"can't double all boolean types"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
DerivedFunc::HalfVector => {
|
||||||
|
assert!(
|
||||||
|
*ts.lanes.iter().min().unwrap() > 1,
|
||||||
|
"can't halve a scalar type"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
DerivedFunc::DoubleVector => {
|
||||||
|
assert!(
|
||||||
|
*ts.lanes.iter().max().unwrap() < MAX_LANES,
|
||||||
|
"can't double 256 lanes"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
DerivedFunc::LaneOf | DerivedFunc::ToBitVec | DerivedFunc::AsBool => {
|
||||||
|
/* no particular assertions */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return TypeVar {
|
||||||
|
content: Rc::new(TypeVarContent {
|
||||||
|
name: format!("{}({})", derived_func.name(), self.name),
|
||||||
|
doc: "".into(),
|
||||||
|
type_set: ts,
|
||||||
|
base: Some(TypeVarParent {
|
||||||
|
type_var: self.clone(),
|
||||||
|
derived_func,
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn lane_of(&self) -> TypeVar {
|
||||||
|
return self.derived(DerivedFunc::LaneOf);
|
||||||
|
}
|
||||||
|
pub fn as_bool(&self) -> TypeVar {
|
||||||
|
return self.derived(DerivedFunc::AsBool);
|
||||||
|
}
|
||||||
|
pub fn half_width(&self) -> TypeVar {
|
||||||
|
return self.derived(DerivedFunc::HalfWidth);
|
||||||
|
}
|
||||||
|
pub fn double_width(&self) -> TypeVar {
|
||||||
|
return self.derived(DerivedFunc::DoubleWidth);
|
||||||
|
}
|
||||||
|
pub fn half_vector(&self) -> TypeVar {
|
||||||
|
return self.derived(DerivedFunc::HalfVector);
|
||||||
|
}
|
||||||
|
pub fn double_vector(&self) -> TypeVar {
|
||||||
|
return self.derived(DerivedFunc::DoubleVector);
|
||||||
|
}
|
||||||
|
pub fn to_bitvec(&self) -> TypeVar {
|
||||||
|
return self.derived(DerivedFunc::ToBitVec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<TypeVar> for &TypeVar {
|
||||||
|
fn into(self) -> TypeVar {
|
||||||
|
self.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Into<TypeVar> for ValueType {
|
||||||
|
fn into(self) -> TypeVar {
|
||||||
|
TypeVar::new_singleton(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq for TypeVar {
|
||||||
|
fn eq(&self, other: &TypeVar) -> bool {
|
||||||
|
match (&self.content.base, &other.content.base) {
|
||||||
|
(Some(base1), Some(base2)) => base1.type_var.eq(&base2.type_var),
|
||||||
|
(None, None) => Rc::ptr_eq(&self.content, &other.content),
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ops::Deref for TypeVar {
|
||||||
|
type Target = TypeVarContent;
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&*self.content
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
pub enum DerivedFunc {
|
||||||
|
LaneOf,
|
||||||
|
AsBool,
|
||||||
|
HalfWidth,
|
||||||
|
DoubleWidth,
|
||||||
|
HalfVector,
|
||||||
|
DoubleVector,
|
||||||
|
ToBitVec,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DerivedFunc {
|
||||||
|
pub fn name(&self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
DerivedFunc::LaneOf => "lane_of",
|
||||||
|
DerivedFunc::AsBool => "as_bool",
|
||||||
|
DerivedFunc::HalfWidth => "half_width",
|
||||||
|
DerivedFunc::DoubleWidth => "double_width",
|
||||||
|
DerivedFunc::HalfVector => "half_vector",
|
||||||
|
DerivedFunc::DoubleVector => "double_vector",
|
||||||
|
DerivedFunc::ToBitVec => "to_bitvec",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct TypeVarParent {
|
||||||
|
pub type_var: TypeVar,
|
||||||
|
pub derived_func: DerivedFunc,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A set of types.
|
||||||
|
///
|
||||||
|
/// We don't allow arbitrary subsets of types, but use a parametrized approach
|
||||||
|
/// instead.
|
||||||
|
///
|
||||||
|
/// Objects of this class can be used as dictionary keys.
|
||||||
|
///
|
||||||
|
/// Parametrized type sets are specified in terms of ranges:
|
||||||
|
/// - The permitted range of vector lanes, where 1 indicates a scalar type.
|
||||||
|
/// - The permitted range of integer types.
|
||||||
|
/// - The permitted range of floating point types, and
|
||||||
|
/// - The permitted range of boolean types.
|
||||||
|
///
|
||||||
|
/// The ranges are inclusive from smallest bit-width to largest bit-width.
|
||||||
|
///
|
||||||
|
/// Finally, a type set can contain special types (derived from `SpecialType`)
|
||||||
|
/// which can't appear as lane types.
|
||||||
|
|
||||||
|
type RangeBound = u16;
|
||||||
|
type Range = ops::Range<RangeBound>;
|
||||||
|
type NumSet = BTreeSet<RangeBound>;
|
||||||
|
|
||||||
|
macro_rules! num_set {
|
||||||
|
($($expr:expr),*) => {
|
||||||
|
NumSet::from_iter(vec![$($expr),*])
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
|
pub struct TypeSet {
|
||||||
|
pub lanes: NumSet,
|
||||||
|
pub ints: NumSet,
|
||||||
|
pub floats: NumSet,
|
||||||
|
pub bools: NumSet,
|
||||||
|
pub bitvecs: NumSet,
|
||||||
|
pub specials: Vec<SpecialType>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TypeSet {
|
||||||
|
fn new(
|
||||||
|
lanes: NumSet,
|
||||||
|
ints: NumSet,
|
||||||
|
floats: NumSet,
|
||||||
|
bools: NumSet,
|
||||||
|
bitvecs: NumSet,
|
||||||
|
specials: Vec<SpecialType>,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
lanes,
|
||||||
|
ints,
|
||||||
|
floats,
|
||||||
|
bools,
|
||||||
|
bitvecs,
|
||||||
|
specials,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the number of concrete types represented by this typeset.
|
||||||
|
fn size(&self) -> usize {
|
||||||
|
self.lanes.len()
|
||||||
|
* (self.ints.len() + self.floats.len() + self.bools.len() + self.bitvecs.len())
|
||||||
|
+ self.specials.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the image of self across the derived function func.
|
||||||
|
fn image(&self, derived_func: DerivedFunc) -> TypeSet {
|
||||||
|
match derived_func {
|
||||||
|
DerivedFunc::LaneOf => self.lane_of(),
|
||||||
|
DerivedFunc::AsBool => self.as_bool(),
|
||||||
|
DerivedFunc::HalfWidth => self.half_width(),
|
||||||
|
DerivedFunc::DoubleWidth => self.double_width(),
|
||||||
|
DerivedFunc::HalfVector => self.half_vector(),
|
||||||
|
DerivedFunc::DoubleVector => self.double_vector(),
|
||||||
|
DerivedFunc::ToBitVec => self.to_bitvec(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return a TypeSet describing the image of self across lane_of.
|
||||||
|
fn lane_of(&self) -> TypeSet {
|
||||||
|
let mut copy = self.clone();
|
||||||
|
copy.lanes = num_set![1];
|
||||||
|
copy.bitvecs = NumSet::new();
|
||||||
|
copy
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return a TypeSet describing the image of self across as_bool.
|
||||||
|
fn as_bool(&self) -> TypeSet {
|
||||||
|
let mut copy = self.clone();
|
||||||
|
copy.ints = NumSet::new();
|
||||||
|
copy.floats = NumSet::new();
|
||||||
|
copy.bitvecs = NumSet::new();
|
||||||
|
if (&self.lanes - &num_set![1]).len() > 0 {
|
||||||
|
copy.bools = &self.ints | &self.floats;
|
||||||
|
copy.bools = ©.bools | &self.bools;
|
||||||
|
}
|
||||||
|
if self.lanes.contains(&1) {
|
||||||
|
copy.bools.insert(1);
|
||||||
|
}
|
||||||
|
copy
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return a TypeSet describing the image of self across halfwidth.
|
||||||
|
fn half_width(&self) -> TypeSet {
|
||||||
|
let mut copy = self.clone();
|
||||||
|
copy.ints = NumSet::from_iter(self.ints.iter().filter(|&&x| x > 8).map(|&x| x / 2));
|
||||||
|
copy.floats = NumSet::from_iter(self.floats.iter().filter(|&&x| x > 32).map(|&x| x / 2));
|
||||||
|
copy.bools = NumSet::from_iter(self.bools.iter().filter(|&&x| x > 8).map(|&x| x / 2));
|
||||||
|
copy.bitvecs = NumSet::from_iter(self.bitvecs.iter().filter(|&&x| x > 1).map(|&x| x / 2));
|
||||||
|
copy.specials = Vec::new();
|
||||||
|
copy
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return a TypeSet describing the image of self across doublewidth.
|
||||||
|
fn double_width(&self) -> TypeSet {
|
||||||
|
let mut copy = self.clone();
|
||||||
|
copy.ints = NumSet::from_iter(self.ints.iter().filter(|&&x| x < MAX_BITS).map(|&x| x * 2));
|
||||||
|
copy.floats = NumSet::from_iter(
|
||||||
|
self.floats
|
||||||
|
.iter()
|
||||||
|
.filter(|&&x| x < MAX_BITS)
|
||||||
|
.map(|&x| x * 2),
|
||||||
|
);
|
||||||
|
copy.bools = NumSet::from_iter(
|
||||||
|
self.bools
|
||||||
|
.iter()
|
||||||
|
.filter(|&&x| x < MAX_BITS)
|
||||||
|
.map(|&x| x * 2)
|
||||||
|
.filter(legal_bool),
|
||||||
|
);
|
||||||
|
copy.bitvecs = NumSet::from_iter(
|
||||||
|
self.bitvecs
|
||||||
|
.iter()
|
||||||
|
.filter(|&&x| x < MAX_BITVEC)
|
||||||
|
.map(|&x| x * 2),
|
||||||
|
);
|
||||||
|
copy.specials = Vec::new();
|
||||||
|
copy
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return a TypeSet describing the image of self across halfvector.
|
||||||
|
fn half_vector(&self) -> TypeSet {
|
||||||
|
let mut copy = self.clone();
|
||||||
|
copy.bitvecs = NumSet::new();
|
||||||
|
copy.lanes = NumSet::from_iter(self.lanes.iter().filter(|&&x| x > 1).map(|&x| x / 2));
|
||||||
|
copy.specials = Vec::new();
|
||||||
|
copy
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return a TypeSet describing the image of self across doublevector.
|
||||||
|
fn double_vector(&self) -> TypeSet {
|
||||||
|
let mut copy = self.clone();
|
||||||
|
copy.bitvecs = NumSet::new();
|
||||||
|
copy.lanes = NumSet::from_iter(
|
||||||
|
self.lanes
|
||||||
|
.iter()
|
||||||
|
.filter(|&&x| x < MAX_LANES)
|
||||||
|
.map(|&x| x * 2),
|
||||||
|
);
|
||||||
|
copy.specials = Vec::new();
|
||||||
|
copy
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return a TypeSet describing the image of self across to_bitvec.
|
||||||
|
fn to_bitvec(&self) -> TypeSet {
|
||||||
|
assert!(self.bitvecs.is_empty());
|
||||||
|
let all_scalars = &(&self.ints | &self.floats) | &self.bools;
|
||||||
|
|
||||||
|
let mut copy = self.clone();
|
||||||
|
copy.lanes = num_set![1];
|
||||||
|
copy.ints = NumSet::new();
|
||||||
|
copy.bools = NumSet::new();
|
||||||
|
copy.floats = NumSet::new();
|
||||||
|
copy.bitvecs = self
|
||||||
|
.lanes
|
||||||
|
.iter()
|
||||||
|
.cycle()
|
||||||
|
.zip(all_scalars.iter())
|
||||||
|
.map(|(num_lanes, lane_width)| num_lanes * lane_width)
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
copy.specials = Vec::new();
|
||||||
|
copy
|
||||||
|
}
|
||||||
|
|
||||||
|
fn concrete_types(&self) -> Vec<ValueType> {
|
||||||
|
let mut ret = Vec::new();
|
||||||
|
for &num_lanes in &self.lanes {
|
||||||
|
for &bits in &self.ints {
|
||||||
|
ret.push(LaneType::int_from_bits(bits).by(num_lanes));
|
||||||
|
}
|
||||||
|
for &bits in &self.floats {
|
||||||
|
ret.push(LaneType::float_from_bits(bits).by(num_lanes));
|
||||||
|
}
|
||||||
|
for &bits in &self.bools {
|
||||||
|
ret.push(LaneType::bool_from_bits(bits).by(num_lanes));
|
||||||
|
}
|
||||||
|
for &bits in &self.bitvecs {
|
||||||
|
assert_eq!(num_lanes, 1);
|
||||||
|
ret.push(BVType::new(bits).into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for &special in &self.specials {
|
||||||
|
ret.push(special.into());
|
||||||
|
}
|
||||||
|
ret
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the singleton type represented by self. Can only call on typesets containing 1 type.
|
||||||
|
fn get_singleton(&self) -> ValueType {
|
||||||
|
let mut types = self.concrete_types();
|
||||||
|
assert_eq!(types.len(), 1);
|
||||||
|
return types.remove(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct TypeSetBuilder {
|
||||||
|
ints: Interval,
|
||||||
|
floats: Interval,
|
||||||
|
bools: Interval,
|
||||||
|
bitvecs: Interval,
|
||||||
|
includes_scalars: bool,
|
||||||
|
simd_lanes: Interval,
|
||||||
|
specials: Vec<SpecialType>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TypeSetBuilder {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
ints: Interval::None,
|
||||||
|
floats: Interval::None,
|
||||||
|
bools: Interval::None,
|
||||||
|
bitvecs: Interval::None,
|
||||||
|
includes_scalars: true,
|
||||||
|
simd_lanes: Interval::None,
|
||||||
|
specials: Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn ints(mut self, interval: impl Into<Interval>) -> Self {
|
||||||
|
assert!(self.ints == Interval::None);
|
||||||
|
self.ints = interval.into();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn floats(mut self, interval: impl Into<Interval>) -> Self {
|
||||||
|
assert!(self.floats == Interval::None);
|
||||||
|
self.floats = interval.into();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn bools(mut self, interval: impl Into<Interval>) -> Self {
|
||||||
|
assert!(self.bools == Interval::None);
|
||||||
|
self.bools = interval.into();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn includes_scalars(mut self, includes_scalars: bool) -> Self {
|
||||||
|
self.includes_scalars = includes_scalars;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn simd_lanes(mut self, interval: impl Into<Interval>) -> Self {
|
||||||
|
assert!(self.simd_lanes == Interval::None);
|
||||||
|
self.simd_lanes = interval.into();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn bitvecs(mut self, interval: impl Into<Interval>) -> Self {
|
||||||
|
assert!(self.bitvecs == Interval::None);
|
||||||
|
self.bitvecs = interval.into();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn specials(mut self, specials: Vec<SpecialType>) -> Self {
|
||||||
|
assert!(self.specials.is_empty());
|
||||||
|
self.specials = specials;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn finish(self) -> TypeSet {
|
||||||
|
let min_lanes = if self.includes_scalars { 1 } else { 2 };
|
||||||
|
;
|
||||||
|
let bools = range_to_set(self.bools.to_range(1..MAX_BITS, None))
|
||||||
|
.into_iter()
|
||||||
|
.filter(legal_bool)
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
TypeSet::new(
|
||||||
|
range_to_set(self.simd_lanes.to_range(min_lanes..MAX_LANES, Some(1))),
|
||||||
|
range_to_set(self.ints.to_range(8..MAX_BITS, None)),
|
||||||
|
range_to_set(self.floats.to_range(32..64, None)),
|
||||||
|
bools,
|
||||||
|
range_to_set(self.bitvecs.to_range(1..MAX_BITVEC, None)),
|
||||||
|
self.specials,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq)]
|
||||||
|
pub enum Interval {
|
||||||
|
None,
|
||||||
|
All,
|
||||||
|
Range(Range),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Interval {
|
||||||
|
fn to_range(&self, full_range: Range, default: Option<RangeBound>) -> Option<Range> {
|
||||||
|
match self {
|
||||||
|
Interval::None => {
|
||||||
|
if let Some(default_val) = default {
|
||||||
|
Some(default_val..default_val)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Interval::All => Some(full_range),
|
||||||
|
|
||||||
|
Interval::Range(range) => {
|
||||||
|
let (low, high) = (range.start, range.end);
|
||||||
|
assert!(low.is_power_of_two());
|
||||||
|
assert!(high.is_power_of_two());
|
||||||
|
assert!(low <= high);
|
||||||
|
assert!(low >= full_range.start);
|
||||||
|
assert!(high <= full_range.end);
|
||||||
|
Some(low..high)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<Interval> for Range {
|
||||||
|
fn into(self) -> Interval {
|
||||||
|
Interval::Range(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn legal_bool(bits: &RangeBound) -> bool {
|
||||||
|
// Only allow legal bit widths for bool types.
|
||||||
|
*bits == 1 || (*bits >= 8 && *bits <= MAX_BITS && bits.is_power_of_two())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generates a set with all the powers of two included in the range.
|
||||||
|
fn range_to_set(range: Option<Range>) -> NumSet {
|
||||||
|
let mut set = NumSet::new();
|
||||||
|
|
||||||
|
let (low, high) = match range {
|
||||||
|
Some(range) => (range.start, range.end),
|
||||||
|
None => return set,
|
||||||
|
};
|
||||||
|
|
||||||
|
assert!(low.is_power_of_two());
|
||||||
|
assert!(high.is_power_of_two());
|
||||||
|
assert!(low <= high);
|
||||||
|
|
||||||
|
for i in low.trailing_zeros()..high.trailing_zeros() + 1 {
|
||||||
|
assert!(1 << i <= RangeBound::max_value());
|
||||||
|
set.insert(1 << i);
|
||||||
|
}
|
||||||
|
set
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_typevar_builder() {
|
||||||
|
let type_set = TypeSetBuilder::new().ints(Interval::All).finish();
|
||||||
|
assert_eq!(type_set.lanes, num_set![1]);
|
||||||
|
assert!(type_set.floats.is_empty());
|
||||||
|
assert_eq!(type_set.ints, num_set![8, 16, 32, 64]);
|
||||||
|
assert!(type_set.bools.is_empty());
|
||||||
|
assert!(type_set.bitvecs.is_empty());
|
||||||
|
assert!(type_set.specials.is_empty());
|
||||||
|
|
||||||
|
let type_set = TypeSetBuilder::new().bools(Interval::All).finish();
|
||||||
|
assert_eq!(type_set.lanes, num_set![1]);
|
||||||
|
assert!(type_set.floats.is_empty());
|
||||||
|
assert!(type_set.ints.is_empty());
|
||||||
|
assert_eq!(type_set.bools, num_set![1, 8, 16, 32, 64]);
|
||||||
|
assert!(type_set.bitvecs.is_empty());
|
||||||
|
assert!(type_set.specials.is_empty());
|
||||||
|
|
||||||
|
let type_set = TypeSetBuilder::new().floats(Interval::All).finish();
|
||||||
|
assert_eq!(type_set.lanes, num_set![1]);
|
||||||
|
assert_eq!(type_set.floats, num_set![32, 64]);
|
||||||
|
assert!(type_set.ints.is_empty());
|
||||||
|
assert!(type_set.bools.is_empty());
|
||||||
|
assert!(type_set.bitvecs.is_empty());
|
||||||
|
assert!(type_set.specials.is_empty());
|
||||||
|
|
||||||
|
let type_set = TypeSetBuilder::new()
|
||||||
|
.floats(Interval::All)
|
||||||
|
.simd_lanes(Interval::All)
|
||||||
|
.includes_scalars(false)
|
||||||
|
.finish();
|
||||||
|
assert_eq!(type_set.lanes, num_set![2, 4, 8, 16, 32, 64, 128, 256]);
|
||||||
|
assert_eq!(type_set.floats, num_set![32, 64]);
|
||||||
|
assert!(type_set.ints.is_empty());
|
||||||
|
assert!(type_set.bools.is_empty());
|
||||||
|
assert!(type_set.bitvecs.is_empty());
|
||||||
|
assert!(type_set.specials.is_empty());
|
||||||
|
|
||||||
|
let type_set = TypeSetBuilder::new()
|
||||||
|
.floats(Interval::All)
|
||||||
|
.simd_lanes(Interval::All)
|
||||||
|
.includes_scalars(true)
|
||||||
|
.finish();
|
||||||
|
assert_eq!(type_set.lanes, num_set![1, 2, 4, 8, 16, 32, 64, 128, 256]);
|
||||||
|
assert_eq!(type_set.floats, num_set![32, 64]);
|
||||||
|
assert!(type_set.ints.is_empty());
|
||||||
|
assert!(type_set.bools.is_empty());
|
||||||
|
assert!(type_set.bitvecs.is_empty());
|
||||||
|
assert!(type_set.specials.is_empty());
|
||||||
|
|
||||||
|
let type_set = TypeSetBuilder::new().ints(16..64).finish();
|
||||||
|
assert_eq!(type_set.lanes, num_set![1]);
|
||||||
|
assert_eq!(type_set.ints, num_set![16, 32, 64]);
|
||||||
|
assert!(type_set.floats.is_empty());
|
||||||
|
assert!(type_set.bools.is_empty());
|
||||||
|
assert!(type_set.bitvecs.is_empty());
|
||||||
|
assert!(type_set.specials.is_empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic]
|
||||||
|
fn test_typevar_builder_too_high_bound_panic() {
|
||||||
|
TypeSetBuilder::new().ints(16..2 * MAX_BITS).finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic]
|
||||||
|
fn test_typevar_builder_inverted_bounds_panic() {
|
||||||
|
TypeSetBuilder::new().ints(32..16).finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_as_bool() {
|
||||||
|
let a = TypeSetBuilder::new()
|
||||||
|
.simd_lanes(2..8)
|
||||||
|
.ints(8..8)
|
||||||
|
.floats(32..32)
|
||||||
|
.finish();
|
||||||
|
assert_eq!(
|
||||||
|
a.lane_of(),
|
||||||
|
TypeSetBuilder::new().ints(8..8).floats(32..32).finish()
|
||||||
|
);
|
||||||
|
|
||||||
|
// Test as_bool with disjoint intervals.
|
||||||
|
let mut a_as_bool = TypeSetBuilder::new().simd_lanes(2..8).finish();
|
||||||
|
a_as_bool.bools = num_set![8, 32];
|
||||||
|
assert_eq!(a.as_bool(), a_as_bool);
|
||||||
|
|
||||||
|
let b = TypeSetBuilder::new()
|
||||||
|
.simd_lanes(1..8)
|
||||||
|
.ints(8..8)
|
||||||
|
.floats(32..32)
|
||||||
|
.finish();
|
||||||
|
let mut b_as_bool = TypeSetBuilder::new().simd_lanes(1..8).finish();
|
||||||
|
b_as_bool.bools = num_set![1, 8, 32];
|
||||||
|
assert_eq!(b.as_bool(), b_as_bool);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_forward_images() {
|
||||||
|
let empty_set = TypeSetBuilder::new().finish();
|
||||||
|
|
||||||
|
// Half vector.
|
||||||
|
assert_eq!(
|
||||||
|
TypeSetBuilder::new()
|
||||||
|
.simd_lanes(1..32)
|
||||||
|
.finish()
|
||||||
|
.half_vector(),
|
||||||
|
TypeSetBuilder::new().simd_lanes(1..16).finish()
|
||||||
|
);
|
||||||
|
|
||||||
|
// Double vector.
|
||||||
|
assert_eq!(
|
||||||
|
TypeSetBuilder::new()
|
||||||
|
.simd_lanes(1..32)
|
||||||
|
.finish()
|
||||||
|
.double_vector(),
|
||||||
|
TypeSetBuilder::new().simd_lanes(2..64).finish()
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
TypeSetBuilder::new()
|
||||||
|
.simd_lanes(128..256)
|
||||||
|
.finish()
|
||||||
|
.double_vector(),
|
||||||
|
TypeSetBuilder::new().simd_lanes(256..256).finish()
|
||||||
|
);
|
||||||
|
|
||||||
|
// Half width.
|
||||||
|
assert_eq!(
|
||||||
|
TypeSetBuilder::new().ints(8..32).finish().half_width(),
|
||||||
|
TypeSetBuilder::new().ints(8..16).finish()
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
TypeSetBuilder::new().floats(32..32).finish().half_width(),
|
||||||
|
empty_set
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
TypeSetBuilder::new().floats(32..64).finish().half_width(),
|
||||||
|
TypeSetBuilder::new().floats(32..32).finish()
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
TypeSetBuilder::new().bools(1..8).finish().half_width(),
|
||||||
|
empty_set
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
TypeSetBuilder::new().bools(1..32).finish().half_width(),
|
||||||
|
TypeSetBuilder::new().bools(8..16).finish()
|
||||||
|
);
|
||||||
|
|
||||||
|
// Double width.
|
||||||
|
assert_eq!(
|
||||||
|
TypeSetBuilder::new().ints(8..32).finish().double_width(),
|
||||||
|
TypeSetBuilder::new().ints(16..64).finish()
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
TypeSetBuilder::new().ints(32..64).finish().double_width(),
|
||||||
|
TypeSetBuilder::new().ints(64..64).finish()
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
TypeSetBuilder::new().floats(32..32).finish().double_width(),
|
||||||
|
TypeSetBuilder::new().floats(64..64).finish()
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
TypeSetBuilder::new().floats(32..64).finish().double_width(),
|
||||||
|
TypeSetBuilder::new().floats(64..64).finish()
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
TypeSetBuilder::new().bools(1..16).finish().double_width(),
|
||||||
|
TypeSetBuilder::new().bools(16..32).finish()
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
TypeSetBuilder::new().bools(32..64).finish().double_width(),
|
||||||
|
TypeSetBuilder::new().bools(64..64).finish()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic]
|
||||||
|
fn test_typeset_singleton_panic_nonsingleton_types() {
|
||||||
|
TypeSetBuilder::new()
|
||||||
|
.ints(8..8)
|
||||||
|
.floats(32..32)
|
||||||
|
.finish()
|
||||||
|
.get_singleton();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic]
|
||||||
|
fn test_typeset_singleton_panic_nonsingleton_lanes() {
|
||||||
|
TypeSetBuilder::new()
|
||||||
|
.simd_lanes(1..2)
|
||||||
|
.floats(32..32)
|
||||||
|
.finish()
|
||||||
|
.get_singleton();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_typeset_singleton() {
|
||||||
|
use crate::shared::types as shared_types;
|
||||||
|
assert_eq!(
|
||||||
|
TypeSetBuilder::new().ints(16..16).finish().get_singleton(),
|
||||||
|
ValueType::Lane(shared_types::Int::I16.into())
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
TypeSetBuilder::new()
|
||||||
|
.floats(64..64)
|
||||||
|
.finish()
|
||||||
|
.get_singleton(),
|
||||||
|
ValueType::Lane(shared_types::Float::F64.into())
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
TypeSetBuilder::new().bools(1..1).finish().get_singleton(),
|
||||||
|
ValueType::Lane(shared_types::Bool::B1.into())
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
TypeSetBuilder::new()
|
||||||
|
.simd_lanes(4..4)
|
||||||
|
.ints(32..32)
|
||||||
|
.finish()
|
||||||
|
.get_singleton(),
|
||||||
|
LaneType::from(shared_types::Int::I32).by(4)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_typevar_functions() {
|
||||||
|
let x = TypeVar::new(
|
||||||
|
"x",
|
||||||
|
"i16 and up",
|
||||||
|
TypeSetBuilder::new().ints(16..64).finish(),
|
||||||
|
);
|
||||||
|
assert_eq!(x.half_width().name, "half_width(x)");
|
||||||
|
assert_eq!(
|
||||||
|
x.half_width().double_width().name,
|
||||||
|
"double_width(half_width(x))"
|
||||||
|
);
|
||||||
|
|
||||||
|
let x = TypeVar::new("x", "up to i32", TypeSetBuilder::new().ints(8..32).finish());
|
||||||
|
assert_eq!(x.double_width().name, "double_width(x)");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_typevar_singleton() {
|
||||||
|
use crate::cdsl::types::VectorType;
|
||||||
|
use crate::shared::types as shared_types;
|
||||||
|
|
||||||
|
// Test i32.
|
||||||
|
let typevar =
|
||||||
|
TypeVar::new_singleton(ValueType::Lane(LaneType::IntType(shared_types::Int::I32)));
|
||||||
|
assert_eq!(typevar.name, "i32");
|
||||||
|
assert_eq!(typevar.type_set.ints, num_set![32]);
|
||||||
|
assert!(typevar.type_set.floats.is_empty());
|
||||||
|
assert!(typevar.type_set.bools.is_empty());
|
||||||
|
assert!(typevar.type_set.bitvecs.is_empty());
|
||||||
|
assert!(typevar.type_set.specials.is_empty());
|
||||||
|
assert_eq!(typevar.type_set.lanes, num_set![1]);
|
||||||
|
|
||||||
|
// Test f32x4.
|
||||||
|
let typevar = TypeVar::new_singleton(ValueType::Vector(VectorType::new(
|
||||||
|
LaneType::FloatType(shared_types::Float::F32),
|
||||||
|
4,
|
||||||
|
)));
|
||||||
|
assert_eq!(typevar.name, "f32x4");
|
||||||
|
assert!(typevar.type_set.ints.is_empty());
|
||||||
|
assert_eq!(typevar.type_set.floats, num_set![32]);
|
||||||
|
assert_eq!(typevar.type_set.lanes, num_set![4]);
|
||||||
|
assert!(typevar.type_set.bools.is_empty());
|
||||||
|
assert!(typevar.type_set.bitvecs.is_empty());
|
||||||
|
assert!(typevar.type_set.specials.is_empty());
|
||||||
|
}
|
||||||
|
|
@ -132,9 +132,9 @@ fn gen_isa(isa: &TargetIsa, fmt: &mut Formatter) {
|
||||||
fmtln!(fmt, "}");
|
fmtln!(fmt, "}");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate(isa: &TargetIsa, base_filename: &str, out_dir: &str) -> Result<(), error::Error> {
|
pub fn generate(isa: &TargetIsa, filename: &str, out_dir: &str) -> Result<(), error::Error> {
|
||||||
let mut fmt = Formatter::new();
|
let mut fmt = Formatter::new();
|
||||||
gen_isa(&isa, &mut fmt);
|
gen_isa(&isa, &mut fmt);
|
||||||
fmt.update_file(format!("{}-{}.rs", base_filename, isa.name), out_dir)?;
|
fmt.update_file(filename, out_dir)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,14 @@
|
||||||
use crate::cdsl::camel_case;
|
use crate::cdsl::camel_case;
|
||||||
use crate::cdsl::isa::TargetIsa;
|
|
||||||
use crate::cdsl::settings::{
|
use crate::cdsl::settings::{
|
||||||
BoolSetting, Predicate, Preset, Setting, SettingGroup, SpecificSetting,
|
BoolSetting, Predicate, Preset, Setting, SettingGroup, SpecificSetting,
|
||||||
};
|
};
|
||||||
use crate::constant_hash::{generate_table, simple_hash};
|
use crate::constant_hash::{generate_table, simple_hash};
|
||||||
use crate::error;
|
use crate::error;
|
||||||
use crate::shared;
|
|
||||||
use crate::srcgen::{Formatter, Match};
|
use crate::srcgen::{Formatter, Match};
|
||||||
use crate::unique_table::UniqueTable;
|
use crate::unique_table::UniqueSeqTable;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
enum ParentGroup {
|
pub enum ParentGroup {
|
||||||
None,
|
None,
|
||||||
Shared,
|
Shared,
|
||||||
}
|
}
|
||||||
|
|
@ -152,13 +150,9 @@ fn gen_getter(setting: &Setting, fmt: &mut Formatter) {
|
||||||
fmt.indent(|fmt| {
|
fmt.indent(|fmt| {
|
||||||
let mut m = Match::new(format!("self.bytes[{}]", setting.byte_offset));
|
let mut m = Match::new(format!("self.bytes[{}]", setting.byte_offset));
|
||||||
for (i, v) in values.iter().enumerate() {
|
for (i, v) in values.iter().enumerate() {
|
||||||
m.arm(
|
m.arm_no_fields(format!("{}", i), format!("{}::{}", ty, camel_case(v)));
|
||||||
format!("{}", i),
|
|
||||||
vec![],
|
|
||||||
format!("{}::{}", ty, camel_case(v)),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
m.arm("_", vec![], "panic!(\"Invalid enum value\")");
|
m.arm_no_fields("_", "panic!(\"Invalid enum value\")");
|
||||||
fmt.add_match(m);
|
fmt.add_match(m);
|
||||||
});
|
});
|
||||||
fmtln!(fmt, "}");
|
fmtln!(fmt, "}");
|
||||||
|
|
@ -191,12 +185,12 @@ fn gen_getters(group: &SettingGroup, fmt: &mut Formatter) {
|
||||||
fmt.doc_comment("Get a view of the boolean predicates.");
|
fmt.doc_comment("Get a view of the boolean predicates.");
|
||||||
fmtln!(
|
fmtln!(
|
||||||
fmt,
|
fmt,
|
||||||
"pub fn predicate_view(&self) -> ::settings::PredicateView {"
|
"pub fn predicate_view(&self) -> crate::settings::PredicateView {"
|
||||||
);
|
);
|
||||||
fmt.indent(|fmt| {
|
fmt.indent(|fmt| {
|
||||||
fmtln!(
|
fmtln!(
|
||||||
fmt,
|
fmt,
|
||||||
"::settings::PredicateView::new(&self.bytes[{}..])",
|
"crate::settings::PredicateView::new(&self.bytes[{}..])",
|
||||||
group.bool_start_byte_offset
|
group.bool_start_byte_offset
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
@ -242,7 +236,7 @@ impl<'a> SettingOrPreset<'a> {
|
||||||
|
|
||||||
/// Emits DESCRIPTORS, ENUMERATORS, HASH_TABLE and PRESETS.
|
/// Emits DESCRIPTORS, ENUMERATORS, HASH_TABLE and PRESETS.
|
||||||
fn gen_descriptors(group: &SettingGroup, fmt: &mut Formatter) {
|
fn gen_descriptors(group: &SettingGroup, fmt: &mut Formatter) {
|
||||||
let mut enum_table: UniqueTable<&'static str> = UniqueTable::new();
|
let mut enum_table = UniqueSeqTable::new();
|
||||||
|
|
||||||
let mut descriptor_index_map: HashMap<SettingOrPreset, usize> = HashMap::new();
|
let mut descriptor_index_map: HashMap<SettingOrPreset, usize> = HashMap::new();
|
||||||
|
|
||||||
|
|
@ -445,17 +439,14 @@ fn gen_group(group: &SettingGroup, parent: ParentGroup, fmt: &mut Formatter) {
|
||||||
gen_display(group, fmt);
|
gen_display(group, fmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate_common(filename: &str, out_dir: &str) -> Result<SettingGroup, error::Error> {
|
pub fn generate(
|
||||||
let settings = shared::settings::generate();
|
settings: &SettingGroup,
|
||||||
|
parent_group: ParentGroup,
|
||||||
|
filename: &str,
|
||||||
|
out_dir: &str,
|
||||||
|
) -> Result<(), error::Error> {
|
||||||
let mut fmt = Formatter::new();
|
let mut fmt = Formatter::new();
|
||||||
gen_group(&settings, ParentGroup::None, &mut fmt);
|
gen_group(&settings, parent_group, &mut fmt);
|
||||||
fmt.update_file(filename, out_dir)?;
|
fmt.update_file(filename, out_dir)?;
|
||||||
Ok(settings)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn generate(isa: &TargetIsa, prefix: &str, out_dir: &str) -> Result<(), error::Error> {
|
|
||||||
let mut fmt = Formatter::new();
|
|
||||||
gen_group(&isa.settings, ParentGroup::Shared, &mut fmt);
|
|
||||||
fmt.update_file(format!("{}-{}.rs", prefix, isa.name), out_dir)?;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
|
use crate::cdsl::inst::InstructionGroup;
|
||||||
use crate::cdsl::isa::TargetIsa;
|
use crate::cdsl::isa::TargetIsa;
|
||||||
use crate::cdsl::regs::{IsaRegs, IsaRegsBuilder, RegBankBuilder, RegClassBuilder};
|
use crate::cdsl::regs::{IsaRegs, IsaRegsBuilder, RegBankBuilder, RegClassBuilder};
|
||||||
use crate::cdsl::settings::{SettingGroup, SettingGroupBuilder};
|
use crate::cdsl::settings::{SettingGroup, SettingGroupBuilder};
|
||||||
|
use crate::shared::Definitions as SharedDefinitions;
|
||||||
|
|
||||||
fn define_settings(_shared: &SettingGroup) -> SettingGroup {
|
fn define_settings(_shared: &SettingGroup) -> SettingGroup {
|
||||||
let setting = SettingGroupBuilder::new("arm32");
|
let setting = SettingGroupBuilder::new("arm32");
|
||||||
|
|
@ -44,8 +46,11 @@ fn define_regs() -> IsaRegs {
|
||||||
regs.finish()
|
regs.finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn define(shared_settings: &SettingGroup) -> TargetIsa {
|
pub fn define(shared_defs: &mut SharedDefinitions) -> TargetIsa {
|
||||||
let settings = define_settings(shared_settings);
|
let settings = define_settings(&shared_defs.settings);
|
||||||
let regs = define_regs();
|
let regs = define_regs();
|
||||||
TargetIsa::new("arm32", settings, regs)
|
|
||||||
|
let inst_group = InstructionGroup::new("arm32", "arm32 specific instruction set");
|
||||||
|
|
||||||
|
TargetIsa::new("arm32", inst_group, settings, regs)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
|
use crate::cdsl::inst::InstructionGroup;
|
||||||
use crate::cdsl::isa::TargetIsa;
|
use crate::cdsl::isa::TargetIsa;
|
||||||
use crate::cdsl::regs::{IsaRegs, IsaRegsBuilder, RegBankBuilder, RegClassBuilder};
|
use crate::cdsl::regs::{IsaRegs, IsaRegsBuilder, RegBankBuilder, RegClassBuilder};
|
||||||
use crate::cdsl::settings::{SettingGroup, SettingGroupBuilder};
|
use crate::cdsl::settings::{SettingGroup, SettingGroupBuilder};
|
||||||
|
use crate::shared::Definitions as SharedDefinitions;
|
||||||
|
|
||||||
fn define_settings(_shared: &SettingGroup) -> SettingGroup {
|
fn define_settings(_shared: &SettingGroup) -> SettingGroup {
|
||||||
let setting = SettingGroupBuilder::new("arm64");
|
let setting = SettingGroupBuilder::new("arm64");
|
||||||
|
|
@ -40,8 +42,11 @@ fn define_registers() -> IsaRegs {
|
||||||
regs.finish()
|
regs.finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn define(shared_settings: &SettingGroup) -> TargetIsa {
|
pub fn define(shared_defs: &mut SharedDefinitions) -> TargetIsa {
|
||||||
let settings = define_settings(shared_settings);
|
let settings = define_settings(&shared_defs.settings);
|
||||||
let regs = define_registers();
|
let regs = define_registers();
|
||||||
TargetIsa::new("arm64", settings, regs)
|
|
||||||
|
let inst_group = InstructionGroup::new("arm64", "arm64 specific instruction set");
|
||||||
|
|
||||||
|
TargetIsa::new("arm64", inst_group, settings, regs)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::cdsl::isa::TargetIsa;
|
use crate::cdsl::isa::TargetIsa;
|
||||||
use crate::cdsl::settings::SettingGroup;
|
use crate::shared::Definitions as SharedDefinitions;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
mod arm32;
|
mod arm32;
|
||||||
|
|
@ -55,13 +55,13 @@ impl fmt::Display for Isa {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn define(isas: &Vec<Isa>, shared_settings: &SettingGroup) -> Vec<TargetIsa> {
|
pub fn define(isas: &Vec<Isa>, shared_defs: &mut SharedDefinitions) -> Vec<TargetIsa> {
|
||||||
isas.iter()
|
isas.iter()
|
||||||
.map(|isa| match isa {
|
.map(|isa| match isa {
|
||||||
Isa::Riscv => riscv::define(shared_settings),
|
Isa::Riscv => riscv::define(shared_defs),
|
||||||
Isa::X86 => x86::define(shared_settings),
|
Isa::X86 => x86::define(shared_defs),
|
||||||
Isa::Arm32 => arm32::define(shared_settings),
|
Isa::Arm32 => arm32::define(shared_defs),
|
||||||
Isa::Arm64 => arm64::define(shared_settings),
|
Isa::Arm64 => arm64::define(shared_defs),
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
|
use crate::cdsl::inst::InstructionGroup;
|
||||||
use crate::cdsl::isa::TargetIsa;
|
use crate::cdsl::isa::TargetIsa;
|
||||||
use crate::cdsl::regs::{IsaRegs, IsaRegsBuilder, RegBankBuilder, RegClassBuilder};
|
use crate::cdsl::regs::{IsaRegs, IsaRegsBuilder, RegBankBuilder, RegClassBuilder};
|
||||||
use crate::cdsl::settings::{PredicateNode, SettingGroup, SettingGroupBuilder};
|
use crate::cdsl::settings::{PredicateNode, SettingGroup, SettingGroupBuilder};
|
||||||
|
use crate::shared::Definitions as SharedDefinitions;
|
||||||
|
|
||||||
fn define_settings(shared: &SettingGroup) -> SettingGroup {
|
fn define_settings(shared: &SettingGroup) -> SettingGroup {
|
||||||
let mut setting = SettingGroupBuilder::new("riscv");
|
let mut setting = SettingGroupBuilder::new("riscv");
|
||||||
|
|
@ -76,8 +78,11 @@ fn define_registers() -> IsaRegs {
|
||||||
regs.finish()
|
regs.finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn define(shared_settings: &SettingGroup) -> TargetIsa {
|
pub fn define(shared_defs: &mut SharedDefinitions) -> TargetIsa {
|
||||||
let settings = define_settings(shared_settings);
|
let settings = define_settings(&shared_defs.settings);
|
||||||
let regs = define_registers();
|
let regs = define_registers();
|
||||||
TargetIsa::new("riscv", settings, regs)
|
|
||||||
|
let inst_group = InstructionGroup::new("riscv", "riscv specific instruction set");
|
||||||
|
|
||||||
|
TargetIsa::new("riscv", inst_group, settings, regs)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
254
third_party/rust/cranelift-codegen-meta/src/isa/x86/instructions.rs
vendored
Normal file
254
third_party/rust/cranelift-codegen-meta/src/isa/x86/instructions.rs
vendored
Normal file
|
|
@ -0,0 +1,254 @@
|
||||||
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
|
use crate::cdsl::formats::FormatRegistry;
|
||||||
|
use crate::cdsl::inst::{InstructionBuilder as Inst, InstructionGroup};
|
||||||
|
use crate::cdsl::operands::{create_operand as operand, create_operand_doc as operand_doc};
|
||||||
|
use crate::cdsl::types::ValueType;
|
||||||
|
use crate::cdsl::typevar::{Interval, TypeSetBuilder, TypeVar};
|
||||||
|
use crate::shared::types;
|
||||||
|
|
||||||
|
pub fn define(format_registry: &FormatRegistry) -> InstructionGroup {
|
||||||
|
let mut ig = InstructionGroup::new("x86", "x86 specific instruction set");
|
||||||
|
|
||||||
|
let iflags: &TypeVar = &ValueType::Special(types::Flag::IFlags.into()).into();
|
||||||
|
|
||||||
|
let iWord = &TypeVar::new(
|
||||||
|
"iWord",
|
||||||
|
"A scalar integer machine word",
|
||||||
|
TypeSetBuilder::new().ints(32..64).finish(),
|
||||||
|
);
|
||||||
|
let nlo = &operand_doc("nlo", iWord, "Low part of numerator");
|
||||||
|
let nhi = &operand_doc("nhi", iWord, "High part of numerator");
|
||||||
|
let d = &operand_doc("d", iWord, "Denominator");
|
||||||
|
let q = &operand_doc("q", iWord, "Quotient");
|
||||||
|
let r = &operand_doc("r", iWord, "Remainder");
|
||||||
|
|
||||||
|
ig.push(
|
||||||
|
Inst::new(
|
||||||
|
"x86_udivmodx",
|
||||||
|
r#"
|
||||||
|
Extended unsigned division.
|
||||||
|
|
||||||
|
Concatenate the bits in `nhi` and `nlo` to form the numerator.
|
||||||
|
Interpret the bits as an unsigned number and divide by the unsigned
|
||||||
|
denominator `d`. Trap when `d` is zero or if the quotient is larger
|
||||||
|
than the range of the output.
|
||||||
|
|
||||||
|
Return both quotient and remainder.
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.operands_in(vec![nlo, nhi, d])
|
||||||
|
.operands_out(vec![q, r])
|
||||||
|
.can_trap(true)
|
||||||
|
.finish(format_registry),
|
||||||
|
);
|
||||||
|
|
||||||
|
ig.push(
|
||||||
|
Inst::new(
|
||||||
|
"x86_sdivmodx",
|
||||||
|
r#"
|
||||||
|
Extended signed division.
|
||||||
|
|
||||||
|
Concatenate the bits in `nhi` and `nlo` to form the numerator.
|
||||||
|
Interpret the bits as a signed number and divide by the signed
|
||||||
|
denominator `d`. Trap when `d` is zero or if the quotient is outside
|
||||||
|
the range of the output.
|
||||||
|
|
||||||
|
Return both quotient and remainder.
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.operands_in(vec![nlo, nhi, d])
|
||||||
|
.operands_out(vec![q, r])
|
||||||
|
.can_trap(true)
|
||||||
|
.finish(format_registry),
|
||||||
|
);
|
||||||
|
|
||||||
|
let argL = &operand("argL", iWord);
|
||||||
|
let argR = &operand("argR", iWord);
|
||||||
|
let resLo = &operand("resLo", iWord);
|
||||||
|
let resHi = &operand("resHi", iWord);
|
||||||
|
|
||||||
|
ig.push(
|
||||||
|
Inst::new(
|
||||||
|
"x86_umulx",
|
||||||
|
r#"
|
||||||
|
Unsigned integer multiplication, producing a double-length result.
|
||||||
|
|
||||||
|
Polymorphic over all scalar integer types, but does not support vector
|
||||||
|
types.
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.operands_in(vec![argL, argR])
|
||||||
|
.operands_out(vec![resLo, resHi])
|
||||||
|
.finish(format_registry),
|
||||||
|
);
|
||||||
|
|
||||||
|
ig.push(
|
||||||
|
Inst::new(
|
||||||
|
"x86_smulx",
|
||||||
|
r#"
|
||||||
|
Signed integer multiplication, producing a double-length result.
|
||||||
|
|
||||||
|
Polymorphic over all scalar integer types, but does not support vector
|
||||||
|
types.
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.operands_in(vec![argL, argR])
|
||||||
|
.operands_out(vec![resLo, resHi])
|
||||||
|
.finish(format_registry),
|
||||||
|
);
|
||||||
|
|
||||||
|
let Float = &TypeVar::new(
|
||||||
|
"Float",
|
||||||
|
"A scalar or vector floating point number",
|
||||||
|
TypeSetBuilder::new()
|
||||||
|
.floats(Interval::All)
|
||||||
|
.simd_lanes(Interval::All)
|
||||||
|
.finish(),
|
||||||
|
);
|
||||||
|
let IntTo = &TypeVar::new(
|
||||||
|
"IntTo",
|
||||||
|
"An integer type with the same number of lanes",
|
||||||
|
TypeSetBuilder::new()
|
||||||
|
.ints(32..64)
|
||||||
|
.simd_lanes(Interval::All)
|
||||||
|
.finish(),
|
||||||
|
);
|
||||||
|
let x = &operand("x", Float);
|
||||||
|
let a = &operand("a", IntTo);
|
||||||
|
|
||||||
|
ig.push(
|
||||||
|
Inst::new(
|
||||||
|
"x86_cvtt2si",
|
||||||
|
r#"
|
||||||
|
Convert with truncation floating point to signed integer.
|
||||||
|
|
||||||
|
The source floating point operand is converted to a signed integer by
|
||||||
|
rounding towards zero. If the result can't be represented in the output
|
||||||
|
type, returns the smallest signed value the output type can represent.
|
||||||
|
|
||||||
|
This instruction does not trap.
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.operands_in(vec![x])
|
||||||
|
.operands_out(vec![a])
|
||||||
|
.finish(format_registry),
|
||||||
|
);
|
||||||
|
|
||||||
|
let x = &operand("x", Float);
|
||||||
|
let a = &operand("a", Float);
|
||||||
|
let y = &operand("y", Float);
|
||||||
|
|
||||||
|
ig.push(
|
||||||
|
Inst::new(
|
||||||
|
"x86_fmin",
|
||||||
|
r#"
|
||||||
|
Floating point minimum with x86 semantics.
|
||||||
|
|
||||||
|
This is equivalent to the C ternary operator `x < y ? x : y` which
|
||||||
|
differs from :inst:`fmin` when either operand is NaN or when comparing
|
||||||
|
+0.0 to -0.0.
|
||||||
|
|
||||||
|
When the two operands don't compare as LT, `y` is returned unchanged,
|
||||||
|
even if it is a signalling NaN.
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.operands_in(vec![x, y])
|
||||||
|
.operands_out(vec![a])
|
||||||
|
.finish(format_registry),
|
||||||
|
);
|
||||||
|
|
||||||
|
ig.push(
|
||||||
|
Inst::new(
|
||||||
|
"x86_fmax",
|
||||||
|
r#"
|
||||||
|
Floating point maximum with x86 semantics.
|
||||||
|
|
||||||
|
This is equivalent to the C ternary operator `x > y ? x : y` which
|
||||||
|
differs from :inst:`fmax` when either operand is NaN or when comparing
|
||||||
|
+0.0 to -0.0.
|
||||||
|
|
||||||
|
When the two operands don't compare as GT, `y` is returned unchanged,
|
||||||
|
even if it is a signalling NaN.
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.operands_in(vec![x, y])
|
||||||
|
.operands_out(vec![a])
|
||||||
|
.finish(format_registry),
|
||||||
|
);
|
||||||
|
|
||||||
|
let x = &operand("x", iWord);
|
||||||
|
|
||||||
|
ig.push(
|
||||||
|
Inst::new(
|
||||||
|
"x86_push",
|
||||||
|
r#"
|
||||||
|
Pushes a value onto the stack.
|
||||||
|
|
||||||
|
Decrements the stack pointer and stores the specified value on to the top.
|
||||||
|
|
||||||
|
This is polymorphic in i32 and i64. However, it is only implemented for i64
|
||||||
|
in 64-bit mode, and only for i32 in 32-bit mode.
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.operands_in(vec![x])
|
||||||
|
.other_side_effects(true)
|
||||||
|
.can_store(true)
|
||||||
|
.finish(format_registry),
|
||||||
|
);
|
||||||
|
|
||||||
|
ig.push(
|
||||||
|
Inst::new(
|
||||||
|
"x86_pop",
|
||||||
|
r#"
|
||||||
|
Pops a value from the stack.
|
||||||
|
|
||||||
|
Loads a value from the top of the stack and then increments the stack
|
||||||
|
pointer.
|
||||||
|
|
||||||
|
This is polymorphic in i32 and i64. However, it is only implemented for i64
|
||||||
|
in 64-bit mode, and only for i32 in 32-bit mode.
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.operands_out(vec![x])
|
||||||
|
.other_side_effects(true)
|
||||||
|
.can_load(true)
|
||||||
|
.finish(format_registry),
|
||||||
|
);
|
||||||
|
|
||||||
|
let y = &operand("y", iWord);
|
||||||
|
let rflags = &operand("rflags", iflags);
|
||||||
|
|
||||||
|
ig.push(
|
||||||
|
Inst::new(
|
||||||
|
"x86_bsr",
|
||||||
|
r#"
|
||||||
|
Bit Scan Reverse -- returns the bit-index of the most significant 1
|
||||||
|
in the word. Result is undefined if the argument is zero. However, it
|
||||||
|
sets the Z flag depending on the argument, so it is at least easy to
|
||||||
|
detect and handle that case.
|
||||||
|
|
||||||
|
This is polymorphic in i32 and i64. It is implemented for both i64 and
|
||||||
|
i32 in 64-bit mode, and only for i32 in 32-bit mode.
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.operands_in(vec![x])
|
||||||
|
.operands_out(vec![y, rflags])
|
||||||
|
.finish(format_registry),
|
||||||
|
);
|
||||||
|
|
||||||
|
ig.push(
|
||||||
|
Inst::new(
|
||||||
|
"x86_bsf",
|
||||||
|
r#"
|
||||||
|
Bit Scan Forwards -- returns the bit-index of the least significant 1
|
||||||
|
in the word. Is otherwise identical to 'bsr', just above.
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.operands_in(vec![x])
|
||||||
|
.operands_out(vec![y, rflags])
|
||||||
|
.finish(format_registry),
|
||||||
|
);
|
||||||
|
|
||||||
|
ig
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,11 @@
|
||||||
|
mod instructions;
|
||||||
|
|
||||||
use crate::cdsl::isa::TargetIsa;
|
use crate::cdsl::isa::TargetIsa;
|
||||||
use crate::cdsl::regs::{IsaRegs, IsaRegsBuilder, RegBankBuilder, RegClassBuilder};
|
use crate::cdsl::regs::{IsaRegs, IsaRegsBuilder, RegBankBuilder, RegClassBuilder};
|
||||||
use crate::cdsl::settings::{PredicateNode, SettingGroup, SettingGroupBuilder};
|
use crate::cdsl::settings::{PredicateNode, SettingGroup, SettingGroupBuilder};
|
||||||
|
|
||||||
|
use crate::shared::Definitions as SharedDefinitions;
|
||||||
|
|
||||||
fn define_settings(_shared: &SettingGroup) -> SettingGroup {
|
fn define_settings(_shared: &SettingGroup) -> SettingGroup {
|
||||||
let mut settings = SettingGroupBuilder::new("x86");
|
let mut settings = SettingGroupBuilder::new("x86");
|
||||||
|
|
||||||
|
|
@ -109,8 +113,11 @@ fn define_registers() -> IsaRegs {
|
||||||
regs.finish()
|
regs.finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn define(shared_settings: &SettingGroup) -> TargetIsa {
|
pub fn define(shared_defs: &mut SharedDefinitions) -> TargetIsa {
|
||||||
let settings = define_settings(shared_settings);
|
let settings = define_settings(&shared_defs.settings);
|
||||||
let regs = define_registers();
|
let regs = define_registers();
|
||||||
TargetIsa::new("x86", settings, regs)
|
|
||||||
|
let inst_group = instructions::define(&shared_defs.format_registry);
|
||||||
|
|
||||||
|
TargetIsa::new("x86", inst_group, settings, regs)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,16 +20,27 @@ pub fn isa_from_arch(arch: &str) -> Result<isa::Isa, String> {
|
||||||
/// Generates all the Rust source files used in Cranelift from the meta-language.
|
/// Generates all the Rust source files used in Cranelift from the meta-language.
|
||||||
pub fn generate(isas: &Vec<isa::Isa>, out_dir: &str) -> Result<(), error::Error> {
|
pub fn generate(isas: &Vec<isa::Isa>, out_dir: &str) -> Result<(), error::Error> {
|
||||||
// Common definitions.
|
// Common definitions.
|
||||||
let shared_settings = gen_settings::generate_common("new_settings.rs", &out_dir)?;
|
let mut shared_defs = shared::define();
|
||||||
|
|
||||||
|
gen_settings::generate(
|
||||||
|
&shared_defs.settings,
|
||||||
|
gen_settings::ParentGroup::None,
|
||||||
|
"new_settings.rs",
|
||||||
|
&out_dir,
|
||||||
|
)?;
|
||||||
gen_types::generate("types.rs", &out_dir)?;
|
gen_types::generate("types.rs", &out_dir)?;
|
||||||
|
|
||||||
// Per ISA definitions.
|
// Per ISA definitions.
|
||||||
let isas = isa::define(isas, &shared_settings);
|
let isas = isa::define(isas, &mut shared_defs);
|
||||||
|
|
||||||
for isa in isas {
|
for isa in isas {
|
||||||
gen_registers::generate(&isa, "registers", &out_dir)?;
|
gen_registers::generate(&isa, &format!("registers-{}.rs", isa.name), &out_dir)?;
|
||||||
gen_settings::generate(&isa, "new_settings", &out_dir)?;
|
gen_settings::generate(
|
||||||
|
&isa.settings,
|
||||||
|
gen_settings::ParentGroup::Shared,
|
||||||
|
&format!("new_settings-{}", isa.name),
|
||||||
|
&out_dir,
|
||||||
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
||||||
65
third_party/rust/cranelift-codegen-meta/src/shared/entities.rs
vendored
Normal file
65
third_party/rust/cranelift-codegen-meta/src/shared/entities.rs
vendored
Normal file
|
|
@ -0,0 +1,65 @@
|
||||||
|
use crate::cdsl::operands::{OperandKind, OperandKindBuilder as Builder, OperandKindFields};
|
||||||
|
|
||||||
|
/// Small helper to initialize an OperandBuilder with the right kind, for a given name and doc.
|
||||||
|
fn create(name: &'static str, doc: &'static str) -> Builder {
|
||||||
|
Builder::new(name, OperandKindFields::EntityRef).doc(doc)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn define() -> Vec<OperandKind> {
|
||||||
|
let mut kinds = Vec::new();
|
||||||
|
|
||||||
|
// A reference to an extended basic block in the same function.
|
||||||
|
// This is primarliy used in control flow instructions.
|
||||||
|
let ebb = create("ebb", "An extended basic block in the same function.")
|
||||||
|
.default_member("destination")
|
||||||
|
.finish();
|
||||||
|
kinds.push(ebb);
|
||||||
|
|
||||||
|
// A reference to a stack slot declared in the function preamble.
|
||||||
|
let stack_slot = create("stack_slot", "A stack slot").finish();
|
||||||
|
kinds.push(stack_slot);
|
||||||
|
|
||||||
|
// A reference to a global value.
|
||||||
|
let global_value = create("global_value", "A global value.").finish();
|
||||||
|
kinds.push(global_value);
|
||||||
|
|
||||||
|
// A reference to a function signature declared in the function preamble.
|
||||||
|
// This is used to provide the call signature in a call_indirect instruction.
|
||||||
|
let sig_ref = create("sig_ref", "A function signature.").finish();
|
||||||
|
kinds.push(sig_ref);
|
||||||
|
|
||||||
|
// A reference to an external function declared in the function preamble.
|
||||||
|
// This is used to provide the callee and signature in a call instruction.
|
||||||
|
let func_ref = create("func_ref", "An external function.").finish();
|
||||||
|
kinds.push(func_ref);
|
||||||
|
|
||||||
|
// A reference to a jump table declared in the function preamble.
|
||||||
|
let jump_table = create("jump_table", "A jump table.")
|
||||||
|
.default_member("table")
|
||||||
|
.finish();
|
||||||
|
kinds.push(jump_table);
|
||||||
|
|
||||||
|
// A reference to a heap declared in the function preamble.
|
||||||
|
let heap = create("heap", "A heap.").finish();
|
||||||
|
kinds.push(heap);
|
||||||
|
|
||||||
|
// A reference to a table declared in the function preamble.
|
||||||
|
let table = create("table", "A table.").finish();
|
||||||
|
kinds.push(table);
|
||||||
|
|
||||||
|
// A variable-sized list of value operands. Use for Ebb and function call arguments.
|
||||||
|
let varargs = Builder::new("variable_args", OperandKindFields::VariableArgs)
|
||||||
|
.doc(
|
||||||
|
r#"
|
||||||
|
A variable size list of `value` operands.
|
||||||
|
|
||||||
|
Use this to represent arguments passed to a function call, arguments
|
||||||
|
passed to an extended basic block, or a variable number of results
|
||||||
|
returned from an instruction.
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.finish();
|
||||||
|
kinds.push(varargs);
|
||||||
|
|
||||||
|
return kinds;
|
||||||
|
}
|
||||||
184
third_party/rust/cranelift-codegen-meta/src/shared/formats.rs
vendored
Normal file
184
third_party/rust/cranelift-codegen-meta/src/shared/formats.rs
vendored
Normal file
|
|
@ -0,0 +1,184 @@
|
||||||
|
use crate::cdsl::formats::{FormatRegistry, InstructionFormatBuilder as Builder};
|
||||||
|
use crate::shared::OperandKinds;
|
||||||
|
|
||||||
|
pub fn define(immediates: &OperandKinds, entities: &OperandKinds) -> FormatRegistry {
|
||||||
|
// Shorthands for immediates.
|
||||||
|
let uimm8 = immediates.by_name("uimm8");
|
||||||
|
let uimm32 = immediates.by_name("uimm32");
|
||||||
|
let imm64 = immediates.by_name("imm64");
|
||||||
|
let ieee32 = immediates.by_name("ieee32");
|
||||||
|
let ieee64 = immediates.by_name("ieee64");
|
||||||
|
let boolean = immediates.by_name("boolean");
|
||||||
|
let intcc = immediates.by_name("intcc");
|
||||||
|
let floatcc = immediates.by_name("floatcc");
|
||||||
|
let memflags = immediates.by_name("memflags");
|
||||||
|
let offset32 = immediates.by_name("offset32");
|
||||||
|
let trapcode = immediates.by_name("trapcode");
|
||||||
|
let regunit = immediates.by_name("regunit");
|
||||||
|
|
||||||
|
// Shorthands for entities.
|
||||||
|
let global_value = entities.by_name("global_value");
|
||||||
|
let ebb = entities.by_name("ebb");
|
||||||
|
let jump_table = entities.by_name("jump_table");
|
||||||
|
let func_ref = entities.by_name("func_ref");
|
||||||
|
let sig_ref = entities.by_name("sig_ref");
|
||||||
|
let stack_slot = entities.by_name("stack_slot");
|
||||||
|
let heap = entities.by_name("heap");
|
||||||
|
let table = entities.by_name("table");
|
||||||
|
|
||||||
|
let mut registry = FormatRegistry::new();
|
||||||
|
|
||||||
|
registry.insert(Builder::new("Unary").value());
|
||||||
|
registry.insert(Builder::new("UnaryImm").imm(imm64));
|
||||||
|
registry.insert(Builder::new("UnaryIeee32").imm(ieee32));
|
||||||
|
registry.insert(Builder::new("UnaryIeee64").imm(ieee64));
|
||||||
|
registry.insert(Builder::new("UnaryBool").imm(boolean));
|
||||||
|
registry.insert(Builder::new("UnaryGlobalValue").imm(global_value));
|
||||||
|
|
||||||
|
registry.insert(Builder::new("Binary").value().value());
|
||||||
|
registry.insert(Builder::new("BinaryImm").value().imm(imm64));
|
||||||
|
|
||||||
|
// The select instructions are controlled by the second VALUE operand.
|
||||||
|
// The first VALUE operand is the controlling flag which has a derived type.
|
||||||
|
// The fma instruction has the same constraint on all inputs.
|
||||||
|
registry.insert(
|
||||||
|
Builder::new("Ternary")
|
||||||
|
.value()
|
||||||
|
.value()
|
||||||
|
.value()
|
||||||
|
.typevar_operand(1),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Catch-all for instructions with many outputs and inputs and no immediate
|
||||||
|
// operands.
|
||||||
|
registry.insert(Builder::new("MultiAry").varargs());
|
||||||
|
|
||||||
|
registry.insert(Builder::new("NullAry"));
|
||||||
|
|
||||||
|
registry.insert(
|
||||||
|
Builder::new("InsertLane")
|
||||||
|
.value()
|
||||||
|
.imm(("lane", uimm8))
|
||||||
|
.value(),
|
||||||
|
);
|
||||||
|
registry.insert(Builder::new("ExtractLane").value().imm(("lane", uimm8)));
|
||||||
|
|
||||||
|
registry.insert(Builder::new("IntCompare").imm(intcc).value().value());
|
||||||
|
registry.insert(Builder::new("IntCompareImm").imm(intcc).value().imm(imm64));
|
||||||
|
registry.insert(Builder::new("IntCond").imm(intcc).value());
|
||||||
|
|
||||||
|
registry.insert(Builder::new("FloatCompare").imm(floatcc).value().value());
|
||||||
|
registry.insert(Builder::new("FloatCond").imm(floatcc).value());;
|
||||||
|
|
||||||
|
registry.insert(Builder::new("IntSelect").imm(intcc).value().value().value());
|
||||||
|
|
||||||
|
registry.insert(Builder::new("Jump").imm(ebb).varargs());
|
||||||
|
registry.insert(Builder::new("Branch").value().imm(ebb).varargs());
|
||||||
|
registry.insert(
|
||||||
|
Builder::new("BranchInt")
|
||||||
|
.imm(intcc)
|
||||||
|
.value()
|
||||||
|
.imm(ebb)
|
||||||
|
.varargs(),
|
||||||
|
);
|
||||||
|
registry.insert(
|
||||||
|
Builder::new("BranchFloat")
|
||||||
|
.imm(floatcc)
|
||||||
|
.value()
|
||||||
|
.imm(ebb)
|
||||||
|
.varargs(),
|
||||||
|
);
|
||||||
|
registry.insert(
|
||||||
|
Builder::new("BranchIcmp")
|
||||||
|
.imm(intcc)
|
||||||
|
.value()
|
||||||
|
.value()
|
||||||
|
.imm(ebb)
|
||||||
|
.varargs(),
|
||||||
|
);
|
||||||
|
registry.insert(Builder::new("BranchTable").value().imm(ebb).imm(jump_table));
|
||||||
|
registry.insert(
|
||||||
|
Builder::new("BranchTableEntry")
|
||||||
|
.value()
|
||||||
|
.value()
|
||||||
|
.imm(uimm8)
|
||||||
|
.imm(jump_table),
|
||||||
|
);
|
||||||
|
registry.insert(Builder::new("BranchTableBase").imm(jump_table));
|
||||||
|
registry.insert(Builder::new("IndirectJump").value().imm(jump_table));
|
||||||
|
|
||||||
|
registry.insert(Builder::new("Call").imm(func_ref).varargs());
|
||||||
|
registry.insert(Builder::new("CallIndirect").imm(sig_ref).value().varargs());
|
||||||
|
registry.insert(Builder::new("FuncAddr").imm(func_ref));
|
||||||
|
|
||||||
|
registry.insert(Builder::new("Load").imm(memflags).value().imm(offset32));
|
||||||
|
registry.insert(
|
||||||
|
Builder::new("LoadComplex")
|
||||||
|
.imm(memflags)
|
||||||
|
.varargs()
|
||||||
|
.imm(offset32),
|
||||||
|
);
|
||||||
|
registry.insert(
|
||||||
|
Builder::new("Store")
|
||||||
|
.imm(memflags)
|
||||||
|
.value()
|
||||||
|
.value()
|
||||||
|
.imm(offset32),
|
||||||
|
);
|
||||||
|
registry.insert(
|
||||||
|
Builder::new("StoreComplex")
|
||||||
|
.imm(memflags)
|
||||||
|
.value()
|
||||||
|
.varargs()
|
||||||
|
.imm(offset32),
|
||||||
|
);
|
||||||
|
registry.insert(Builder::new("StackLoad").imm(stack_slot).imm(offset32));
|
||||||
|
registry.insert(
|
||||||
|
Builder::new("StackStore")
|
||||||
|
.value()
|
||||||
|
.imm(stack_slot)
|
||||||
|
.imm(offset32),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Accessing a WebAssembly heap.
|
||||||
|
registry.insert(Builder::new("HeapAddr").imm(heap).value().imm(uimm32));
|
||||||
|
|
||||||
|
// Accessing a WebAssembly table.
|
||||||
|
registry.insert(Builder::new("TableAddr").imm(table).value().imm(offset32));
|
||||||
|
|
||||||
|
registry.insert(
|
||||||
|
Builder::new("RegMove")
|
||||||
|
.value()
|
||||||
|
.imm(("src", regunit))
|
||||||
|
.imm(("dst", regunit)),
|
||||||
|
);
|
||||||
|
registry.insert(
|
||||||
|
Builder::new("CopySpecial")
|
||||||
|
.imm(("src", regunit))
|
||||||
|
.imm(("dst", regunit)),
|
||||||
|
);
|
||||||
|
registry.insert(
|
||||||
|
Builder::new("RegSpill")
|
||||||
|
.value()
|
||||||
|
.imm(("src", regunit))
|
||||||
|
.imm(("dst", stack_slot)),
|
||||||
|
);
|
||||||
|
registry.insert(
|
||||||
|
Builder::new("RegFill")
|
||||||
|
.value()
|
||||||
|
.imm(("src", stack_slot))
|
||||||
|
.imm(("dst", regunit)),
|
||||||
|
);
|
||||||
|
|
||||||
|
registry.insert(Builder::new("Trap").imm(trapcode));
|
||||||
|
registry.insert(Builder::new("CondTrap").value().imm(trapcode));
|
||||||
|
registry.insert(Builder::new("IntCondTrap").imm(intcc).value().imm(trapcode));
|
||||||
|
registry.insert(
|
||||||
|
Builder::new("FloatCondTrap")
|
||||||
|
.imm(floatcc)
|
||||||
|
.value()
|
||||||
|
.imm(trapcode),
|
||||||
|
);
|
||||||
|
|
||||||
|
registry
|
||||||
|
}
|
||||||
145
third_party/rust/cranelift-codegen-meta/src/shared/immediates.rs
vendored
Normal file
145
third_party/rust/cranelift-codegen-meta/src/shared/immediates.rs
vendored
Normal file
|
|
@ -0,0 +1,145 @@
|
||||||
|
use crate::cdsl::operands::{OperandKind, OperandKindBuilder as Builder};
|
||||||
|
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
pub fn define() -> Vec<OperandKind> {
|
||||||
|
let mut kinds = Vec::new();
|
||||||
|
|
||||||
|
// A 64-bit immediate integer operand.
|
||||||
|
//
|
||||||
|
// This type of immediate integer can interact with SSA values with any
|
||||||
|
// IntType type.
|
||||||
|
let imm64 = Builder::new_imm("imm64")
|
||||||
|
.doc("A 64-bit immediate integer.")
|
||||||
|
.finish();
|
||||||
|
kinds.push(imm64);
|
||||||
|
|
||||||
|
// An unsigned 8-bit immediate integer operand.
|
||||||
|
//
|
||||||
|
// This small operand is used to indicate lane indexes in SIMD vectors and
|
||||||
|
// immediate bit counts on shift instructions.
|
||||||
|
let uimm8 = Builder::new_imm("uimm8")
|
||||||
|
.doc("An 8-bit immediate unsigned integer.")
|
||||||
|
.finish();
|
||||||
|
kinds.push(uimm8);
|
||||||
|
|
||||||
|
// An unsigned 32-bit immediate integer operand.
|
||||||
|
let uimm32 = Builder::new_imm("uimm32")
|
||||||
|
.doc("A 32-bit immediate unsigned integer.")
|
||||||
|
.finish();
|
||||||
|
kinds.push(uimm32);
|
||||||
|
|
||||||
|
// A 32-bit immediate signed offset.
|
||||||
|
//
|
||||||
|
// This is used to represent an immediate address offset in load/store
|
||||||
|
// instructions.
|
||||||
|
let offset32 = Builder::new_imm("offset32")
|
||||||
|
.doc("A 32-bit immediate signed offset.")
|
||||||
|
.default_member("offset")
|
||||||
|
.finish();
|
||||||
|
kinds.push(offset32);
|
||||||
|
|
||||||
|
// A 32-bit immediate floating point operand.
|
||||||
|
//
|
||||||
|
// IEEE 754-2008 binary32 interchange format.
|
||||||
|
let ieee32 = Builder::new_imm("ieee32")
|
||||||
|
.doc("A 32-bit immediate floating point number.")
|
||||||
|
.finish();
|
||||||
|
kinds.push(ieee32);
|
||||||
|
|
||||||
|
// A 64-bit immediate floating point operand.
|
||||||
|
//
|
||||||
|
// IEEE 754-2008 binary64 interchange format.
|
||||||
|
let ieee64 = Builder::new_imm("ieee64")
|
||||||
|
.doc("A 64-bit immediate floating point number.")
|
||||||
|
.finish();
|
||||||
|
kinds.push(ieee64);
|
||||||
|
|
||||||
|
// An immediate boolean operand.
|
||||||
|
//
|
||||||
|
// This type of immediate boolean can interact with SSA values with any
|
||||||
|
// BoolType type.
|
||||||
|
let boolean = Builder::new_imm("boolean")
|
||||||
|
.doc("An immediate boolean.")
|
||||||
|
.rust_type("bool")
|
||||||
|
.finish();
|
||||||
|
kinds.push(boolean);
|
||||||
|
|
||||||
|
// A condition code for comparing integer values.
|
||||||
|
// This enumerated operand kind is used for the `icmp` instruction and corresponds to the
|
||||||
|
// condcodes::IntCC` Rust type.
|
||||||
|
let mut intcc_values = HashMap::new();
|
||||||
|
intcc_values.insert("eq", "Equal");
|
||||||
|
intcc_values.insert("ne", "NotEqual");
|
||||||
|
intcc_values.insert("sge", "UnsignedGreaterThanOrEqual");
|
||||||
|
intcc_values.insert("sgt", "UnsignedGreaterThan");
|
||||||
|
intcc_values.insert("sle", "UnsignedLessThanOrEqual");
|
||||||
|
intcc_values.insert("slt", "UnsignedLessThan");
|
||||||
|
intcc_values.insert("uge", "UnsignedGreaterThanOrEqual");
|
||||||
|
intcc_values.insert("ugt", "UnsignedGreaterThan");
|
||||||
|
intcc_values.insert("ule", "UnsignedLessThanOrEqual");
|
||||||
|
intcc_values.insert("ult", "UnsignedLessThan");
|
||||||
|
let intcc = Builder::new_enum("intcc", intcc_values)
|
||||||
|
.doc("An integer comparison condition code.")
|
||||||
|
.default_member("cond")
|
||||||
|
.rust_type("ir::condcodes::IntCC")
|
||||||
|
.finish();
|
||||||
|
kinds.push(intcc);
|
||||||
|
|
||||||
|
// A condition code for comparing floating point values. This enumerated operand kind is used
|
||||||
|
// for the `fcmp` instruction and corresponds to the `condcodes::FloatCC` Rust type.
|
||||||
|
let mut floatcc_values = HashMap::new();
|
||||||
|
floatcc_values.insert("ord", "Ordered");
|
||||||
|
floatcc_values.insert("uno", "Unordered");
|
||||||
|
floatcc_values.insert("eq", "Equal");
|
||||||
|
floatcc_values.insert("ne", "NotEqual");
|
||||||
|
floatcc_values.insert("one", "OrderedNotEqual");
|
||||||
|
floatcc_values.insert("ueq", "UnorderedOrEqual");
|
||||||
|
floatcc_values.insert("lt", "LessThan");
|
||||||
|
floatcc_values.insert("le", "LessThanOrEqual");
|
||||||
|
floatcc_values.insert("gt", "GreaterThan");
|
||||||
|
floatcc_values.insert("ge", "GreaterThanOrEqual");
|
||||||
|
floatcc_values.insert("ult", "UnorderedOrLessThan");
|
||||||
|
floatcc_values.insert("ule", "UnorderedOrLessThanOrEqual");
|
||||||
|
floatcc_values.insert("ugt", "UnorderedOrGreaterThan");
|
||||||
|
floatcc_values.insert("uge", "UnorderedOrGreaterThanOrEqual");
|
||||||
|
let floatcc = Builder::new_enum("floatcc", floatcc_values)
|
||||||
|
.doc("A floating point comparison condition code")
|
||||||
|
.default_member("cond")
|
||||||
|
.rust_type("ir::condcodes::FloatCC")
|
||||||
|
.finish();
|
||||||
|
kinds.push(floatcc);
|
||||||
|
|
||||||
|
// Flags for memory operations like :clif:inst:`load` and :clif:inst:`store`.
|
||||||
|
let memflags = Builder::new_imm("memflags")
|
||||||
|
.doc("Memory operation flags")
|
||||||
|
.default_member("flags")
|
||||||
|
.rust_type("ir::MemFlags")
|
||||||
|
.finish();
|
||||||
|
kinds.push(memflags);
|
||||||
|
|
||||||
|
// A register unit in the current target ISA.
|
||||||
|
let regunit = Builder::new_imm("regunit")
|
||||||
|
.doc("A register unit in the target ISA")
|
||||||
|
.rust_type("isa::RegUnit")
|
||||||
|
.finish();
|
||||||
|
kinds.push(regunit);
|
||||||
|
|
||||||
|
// A trap code indicating the reason for trapping.
|
||||||
|
//
|
||||||
|
// The Rust enum type also has a `User(u16)` variant for user-provided trap
|
||||||
|
// codes.
|
||||||
|
let mut trapcode_values = HashMap::new();
|
||||||
|
trapcode_values.insert("stk_ovf", "StackOverflow");
|
||||||
|
trapcode_values.insert("heap_oob", "HeapOutOfBounds");
|
||||||
|
trapcode_values.insert("int_ovf", "IntegerOverflow");
|
||||||
|
trapcode_values.insert("int_divz", "IntegerDivisionByZero");
|
||||||
|
let trapcode = Builder::new_enum("trapcode", trapcode_values)
|
||||||
|
.doc("A trap reason code.")
|
||||||
|
.default_member("code")
|
||||||
|
.rust_type("ir::TrapCode")
|
||||||
|
.finish();
|
||||||
|
kinds.push(trapcode);
|
||||||
|
|
||||||
|
return kinds;
|
||||||
|
}
|
||||||
3185
third_party/rust/cranelift-codegen-meta/src/shared/instructions.rs
vendored
Normal file
3185
third_party/rust/cranelift-codegen-meta/src/shared/instructions.rs
vendored
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -1,4 +1,59 @@
|
||||||
//! Shared definitions for the Cranelift intermediate language.
|
//! Shared definitions for the Cranelift intermediate language.
|
||||||
|
|
||||||
|
pub mod entities;
|
||||||
|
pub mod formats;
|
||||||
|
pub mod immediates;
|
||||||
|
pub mod instructions;
|
||||||
pub mod settings;
|
pub mod settings;
|
||||||
pub mod types;
|
pub mod types;
|
||||||
|
|
||||||
|
use crate::cdsl::formats::FormatRegistry;
|
||||||
|
use crate::cdsl::inst::InstructionGroup;
|
||||||
|
use crate::cdsl::operands::OperandKind;
|
||||||
|
use crate::cdsl::settings::SettingGroup;
|
||||||
|
|
||||||
|
pub struct Definitions {
|
||||||
|
pub settings: SettingGroup,
|
||||||
|
pub instructions: InstructionGroup,
|
||||||
|
pub operand_kinds: OperandKinds,
|
||||||
|
pub format_registry: FormatRegistry,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct OperandKinds(Vec<OperandKind>);
|
||||||
|
|
||||||
|
impl OperandKinds {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self(Vec::new())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn by_name(&self, name: &'static str) -> &OperandKind {
|
||||||
|
self.0
|
||||||
|
.iter()
|
||||||
|
.find(|op| op.name == name)
|
||||||
|
.expect(&format!("unknown Operand name: {}", name))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push(&mut self, operand_kind: OperandKind) {
|
||||||
|
assert!(
|
||||||
|
self.0
|
||||||
|
.iter()
|
||||||
|
.find(|existing| existing.name == operand_kind.name)
|
||||||
|
.is_none(),
|
||||||
|
"trying to insert operand kind '{}' for the second time",
|
||||||
|
operand_kind.name
|
||||||
|
);
|
||||||
|
self.0.push(operand_kind);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn define() -> Definitions {
|
||||||
|
let immediates = OperandKinds(immediates::define());
|
||||||
|
let entities = OperandKinds(entities::define());
|
||||||
|
let format_registry = formats::define(&immediates, &entities);
|
||||||
|
Definitions {
|
||||||
|
settings: settings::define(),
|
||||||
|
instructions: instructions::define(&format_registry, &immediates, &entities),
|
||||||
|
operand_kinds: immediates,
|
||||||
|
format_registry,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::cdsl::settings::{SettingGroup, SettingGroupBuilder};
|
use crate::cdsl::settings::{SettingGroup, SettingGroupBuilder};
|
||||||
|
|
||||||
pub fn generate() -> SettingGroup {
|
pub fn define() -> SettingGroup {
|
||||||
let mut settings = SettingGroupBuilder::new("shared");
|
let mut settings = SettingGroupBuilder::new("shared");
|
||||||
|
|
||||||
settings.add_enum(
|
settings.add_enum(
|
||||||
|
|
|
||||||
|
|
@ -113,7 +113,7 @@ impl Iterator for FloatIterator {
|
||||||
/// A type representing CPU flags.
|
/// A type representing CPU flags.
|
||||||
///
|
///
|
||||||
/// Flags can't be stored in memory.
|
/// Flags can't be stored in memory.
|
||||||
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
|
||||||
pub enum Flag {
|
pub enum Flag {
|
||||||
/// CPU flags from an integer comparison.
|
/// CPU flags from an integer comparison.
|
||||||
IFlags,
|
IFlags,
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,14 @@ macro_rules! fmtln {
|
||||||
($fmt:ident, $arg:expr) => {
|
($fmt:ident, $arg:expr) => {
|
||||||
$fmt.line($arg);
|
$fmt.line($arg);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
($_:tt, $($args:expr),+) => {
|
||||||
|
compile_error!("This macro requires at least two arguments: the Formatter instance and a format string.");
|
||||||
|
};
|
||||||
|
|
||||||
|
($_:tt) => {
|
||||||
|
compile_error!("This macro requires at least two arguments: the Formatter instance and a format string.");
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Formatter {
|
pub struct Formatter {
|
||||||
|
|
@ -84,6 +92,11 @@ impl Formatter {
|
||||||
self.lines.push(indented_line);
|
self.lines.push(indented_line);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Pushes an empty line.
|
||||||
|
pub fn empty_line(&mut self) {
|
||||||
|
self.lines.push("\n".to_string());
|
||||||
|
}
|
||||||
|
|
||||||
/// Emit a line outdented one level.
|
/// Emit a line outdented one level.
|
||||||
pub fn _outdented_line(&mut self, s: &str) {
|
pub fn _outdented_line(&mut self, s: &str) {
|
||||||
let new_line = format!("{}{}", self._get_outdent(), s);
|
let new_line = format!("{}{}", self._get_outdent(), s);
|
||||||
|
|
@ -112,7 +125,7 @@ impl Formatter {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add one or more lines after stripping common indentation.
|
/// Add one or more lines after stripping common indentation.
|
||||||
pub fn _multi_line(&mut self, s: &str) {
|
pub fn multi_line(&mut self, s: &str) {
|
||||||
parse_multiline(s).into_iter().for_each(|l| self.line(&l));
|
parse_multiline(s).into_iter().for_each(|l| self.line(&l));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -141,7 +154,7 @@ impl Formatter {
|
||||||
self.indent(|fmt| {
|
self.indent(|fmt| {
|
||||||
for (&(ref fields, ref body), ref names) in m.arms.iter() {
|
for (&(ref fields, ref body), ref names) in m.arms.iter() {
|
||||||
// name { fields } | name { fields } => { body }
|
// name { fields } | name { fields } => { body }
|
||||||
let conditions: Vec<String> = names
|
let conditions = names
|
||||||
.iter()
|
.iter()
|
||||||
.map(|name| {
|
.map(|name| {
|
||||||
if fields.len() > 0 {
|
if fields.len() > 0 {
|
||||||
|
|
@ -150,9 +163,20 @@ impl Formatter {
|
||||||
name.clone()
|
name.clone()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect();
|
.collect::<Vec<_>>()
|
||||||
let lhs = conditions.join(" | ");
|
.join(" |\n")
|
||||||
fmtln!(fmt, "{} => {{", lhs);
|
+ " => {";
|
||||||
|
|
||||||
|
fmt.multi_line(&conditions);
|
||||||
|
fmt.indent(|fmt| {
|
||||||
|
fmt.line(body);
|
||||||
|
});
|
||||||
|
fmt.line("}");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure to include the catch all clause last.
|
||||||
|
if let Some(body) = m.catch_all {
|
||||||
|
fmt.line("_ => {");
|
||||||
fmt.indent(|fmt| {
|
fmt.indent(|fmt| {
|
||||||
fmt.line(body);
|
fmt.line(body);
|
||||||
});
|
});
|
||||||
|
|
@ -239,27 +263,57 @@ fn parse_multiline(s: &str) -> Vec<String> {
|
||||||
pub struct Match {
|
pub struct Match {
|
||||||
expr: String,
|
expr: String,
|
||||||
arms: BTreeMap<(Vec<String>, String), BTreeSet<String>>,
|
arms: BTreeMap<(Vec<String>, String), BTreeSet<String>>,
|
||||||
|
/// The clause for the placeholder pattern _.
|
||||||
|
catch_all: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Match {
|
impl Match {
|
||||||
/// Create a new match statement on `expr`.
|
/// Create a new match statement on `expr`.
|
||||||
pub fn new<T: Into<String>>(expr: T) -> Self {
|
pub fn new(expr: impl Into<String>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
expr: expr.into(),
|
expr: expr.into(),
|
||||||
arms: BTreeMap::new(),
|
arms: BTreeMap::new(),
|
||||||
|
catch_all: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add an arm to the Match statement.
|
fn set_catch_all(&mut self, clause: String) {
|
||||||
pub fn arm<T: Into<String>>(&mut self, name: T, fields: Vec<T>, body: T) {
|
assert!(self.catch_all.is_none());
|
||||||
// let key = (fields, body);
|
self.catch_all = Some(clause);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add an arm that reads fields to the Match statement.
|
||||||
|
pub fn arm<T: Into<String>, S: Into<String>>(&mut self, name: T, fields: Vec<S>, body: T) {
|
||||||
|
let name = name.into();
|
||||||
|
assert!(
|
||||||
|
name != "_",
|
||||||
|
"catch all clause can't extract fields, use arm_no_fields instead."
|
||||||
|
);
|
||||||
|
|
||||||
let body = body.into();
|
let body = body.into();
|
||||||
let fields = fields.into_iter().map(|x| x.into()).collect();
|
let fields = fields.into_iter().map(|x| x.into()).collect();
|
||||||
let match_arm = self
|
let match_arm = self
|
||||||
.arms
|
.arms
|
||||||
.entry((fields, body))
|
.entry((fields, body))
|
||||||
.or_insert_with(BTreeSet::new);
|
.or_insert_with(BTreeSet::new);
|
||||||
match_arm.insert(name.into());
|
match_arm.insert(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Adds an arm that doesn't read anythings from the fields to the Match statement.
|
||||||
|
pub fn arm_no_fields(&mut self, name: impl Into<String>, body: impl Into<String>) {
|
||||||
|
let body = body.into();
|
||||||
|
|
||||||
|
let name = name.into();
|
||||||
|
if name == "_" {
|
||||||
|
self.set_catch_all(body);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let match_arm = self
|
||||||
|
.arms
|
||||||
|
.entry((Vec::new(), body))
|
||||||
|
.or_insert_with(BTreeSet::new);
|
||||||
|
match_arm.insert(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -296,7 +350,8 @@ match x {
|
||||||
Green { a, b } => {
|
Green { a, b } => {
|
||||||
different body
|
different body
|
||||||
}
|
}
|
||||||
Orange { a, b } | Yellow { a, b } => {
|
Orange { a, b } |
|
||||||
|
Yellow { a, b } => {
|
||||||
some body
|
some body
|
||||||
}
|
}
|
||||||
Blue { x, y } => {
|
Blue { x, y } => {
|
||||||
|
|
@ -308,6 +363,36 @@ match x {
|
||||||
assert_eq!(fmt.lines, expected_lines);
|
assert_eq!(fmt.lines, expected_lines);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn match_with_catchall_order() {
|
||||||
|
// The catchall placeholder must be placed after other clauses.
|
||||||
|
let mut m = Match::new("x");
|
||||||
|
m.arm("Orange", vec!["a", "b"], "some body");
|
||||||
|
m.arm("Green", vec!["a", "b"], "different body");
|
||||||
|
m.arm_no_fields("_", "unreachable!()");
|
||||||
|
assert_eq!(m.arms.len(), 2); // catchall is not counted
|
||||||
|
|
||||||
|
let mut fmt = Formatter::new();
|
||||||
|
fmt.add_match(m);
|
||||||
|
|
||||||
|
let expected_lines = from_raw_string(
|
||||||
|
r#"
|
||||||
|
match x {
|
||||||
|
Green { a, b } => {
|
||||||
|
different body
|
||||||
|
}
|
||||||
|
Orange { a, b } => {
|
||||||
|
some body
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
assert_eq!(fmt.lines, expected_lines);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_multiline_works() {
|
fn parse_multiline_works() {
|
||||||
let input = "\n hello\n world\n";
|
let input = "\n hello\n world\n";
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,76 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::hash::Hash;
|
||||||
use std::slice;
|
use std::slice;
|
||||||
|
|
||||||
|
/// Collect items into the `table` list, removing duplicates.
|
||||||
|
pub struct UniqueTable<'entries, T: Eq + Hash> {
|
||||||
|
table: Vec<&'entries T>,
|
||||||
|
map: HashMap<&'entries T, usize>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'entries, T: Eq + Hash> UniqueTable<'entries, T> {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
table: Vec::new(),
|
||||||
|
map: HashMap::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add(&mut self, entry: &'entries T) -> usize {
|
||||||
|
match self.map.get(&entry) {
|
||||||
|
None => {
|
||||||
|
let i = self.table.len();
|
||||||
|
self.table.push(entry);
|
||||||
|
self.map.insert(entry, i);
|
||||||
|
i
|
||||||
|
}
|
||||||
|
Some(&i) => i,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn len(&self) -> usize {
|
||||||
|
self.table.len()
|
||||||
|
}
|
||||||
|
pub fn iter(&self) -> slice::Iter<&'entries T> {
|
||||||
|
self.table.iter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A table of sequences which tries to avoid common subsequences.
|
/// A table of sequences which tries to avoid common subsequences.
|
||||||
pub struct UniqueTable<T: PartialEq + Clone> {
|
pub struct UniqueSeqTable<T: PartialEq + Clone> {
|
||||||
table: Vec<T>,
|
table: Vec<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: PartialEq + Clone> UniqueTable<T> {
|
impl<T: PartialEq + Clone> UniqueSeqTable<T> {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self { table: Vec::new() }
|
Self { table: Vec::new() }
|
||||||
}
|
}
|
||||||
pub fn add(&mut self, values: &Vec<T>) -> usize {
|
pub fn add(&mut self, values: &Vec<T>) -> usize {
|
||||||
|
if values.len() == 0 {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
if let Some(offset) = find_subsequence(values, &self.table) {
|
if let Some(offset) = find_subsequence(values, &self.table) {
|
||||||
offset
|
offset
|
||||||
} else {
|
} else {
|
||||||
let offset = self.table.len();
|
let table_len = self.table.len();
|
||||||
self.table.extend((*values).clone());
|
|
||||||
offset
|
// Try to put in common the last elements of the table if they're a prefix of the new
|
||||||
|
// sequence.
|
||||||
|
//
|
||||||
|
// We know there wasn't a full match, so the best prefix we can hope to find contains
|
||||||
|
// all the values but the last one.
|
||||||
|
let mut start_from = usize::min(table_len, values.len() - 1);
|
||||||
|
while start_from != 0 {
|
||||||
|
// Loop invariant: start_from <= table_len, so table_len - start_from >= 0.
|
||||||
|
if values[0..start_from] == self.table[table_len - start_from..table_len] {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
start_from -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.table
|
||||||
|
.extend(values[start_from..values.len()].iter().cloned());
|
||||||
|
table_len - start_from
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn len(&self) -> usize {
|
pub fn len(&self) -> usize {
|
||||||
|
|
@ -35,17 +90,10 @@ fn find_subsequence<T: PartialEq>(sub: &Vec<T>, whole: &Vec<T>) -> Option<usize>
|
||||||
if whole.len() < sub.len() {
|
if whole.len() < sub.len() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let max = whole.len() + 1 - sub.len();
|
let max = whole.len() - sub.len();
|
||||||
for i in 0..max {
|
for i in 0..max + 1 {
|
||||||
let mut found: Option<usize> = Some(i);
|
if whole[i..i + sub.len()] == sub[..] {
|
||||||
for j in 0..sub.len() {
|
return Some(i);
|
||||||
if sub[j] != whole[i + j] {
|
|
||||||
found = None;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if found.is_some() {
|
|
||||||
return found;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return None;
|
return None;
|
||||||
|
|
@ -66,3 +114,24 @@ fn test_find_subsequence() {
|
||||||
Some(1)
|
Some(1)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_optimal_add() {
|
||||||
|
let mut seq_table = UniqueSeqTable::new();
|
||||||
|
// [0, 1, 2, 3]
|
||||||
|
assert_eq!(seq_table.add(&vec![0, 1, 2, 3]), 0);
|
||||||
|
assert_eq!(seq_table.add(&vec![0, 1, 2, 3]), 0);
|
||||||
|
assert_eq!(seq_table.add(&vec![1, 2, 3]), 1);
|
||||||
|
assert_eq!(seq_table.add(&vec![2, 3]), 2);
|
||||||
|
assert_eq!(seq_table.len(), 4);
|
||||||
|
// [0, 1, 2, 3, 4]
|
||||||
|
assert_eq!(seq_table.add(&vec![2, 3, 4]), 2);
|
||||||
|
assert_eq!(seq_table.len(), 5);
|
||||||
|
// [0, 1, 2, 3, 4, 6, 5, 7]
|
||||||
|
assert_eq!(seq_table.add(&vec![4, 6, 5, 7]), 4);
|
||||||
|
assert_eq!(seq_table.len(), 8);
|
||||||
|
// [0, 1, 2, 3, 4, 6, 5, 7, 8, 2, 3, 4]
|
||||||
|
assert_eq!(seq_table.add(&vec![8, 2, 3, 4]), 8);
|
||||||
|
assert_eq!(seq_table.add(&vec![8]), 8);
|
||||||
|
assert_eq!(seq_table.len(), 12);
|
||||||
|
}
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
105
third_party/rust/cranelift-codegen/Cargo.toml
vendored
105
third_party/rust/cranelift-codegen/Cargo.toml
vendored
|
|
@ -1,70 +1,63 @@
|
||||||
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
|
|
||||||
#
|
|
||||||
# When uploading crates to the registry Cargo will automatically
|
|
||||||
# "normalize" Cargo.toml files for maximal compatibility
|
|
||||||
# with all versions of Cargo and also rewrite `path` dependencies
|
|
||||||
# to registry (e.g. crates.io) dependencies
|
|
||||||
#
|
|
||||||
# If you believe there's an error in this file please file an
|
|
||||||
# issue against the rust-lang/cargo repository. If you're
|
|
||||||
# editing this file be aware that the upstream Cargo.toml
|
|
||||||
# will likely look very different (and much more reasonable)
|
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
edition = "2018"
|
|
||||||
name = "cranelift-codegen"
|
|
||||||
version = "0.29.0"
|
|
||||||
authors = ["The Cranelift Project Developers"]
|
authors = ["The Cranelift Project Developers"]
|
||||||
build = "build.rs"
|
name = "cranelift-codegen"
|
||||||
|
version = "0.30.0"
|
||||||
description = "Low-level code generator library"
|
description = "Low-level code generator library"
|
||||||
|
license = "Apache-2.0 WITH LLVM-exception"
|
||||||
documentation = "https://cranelift.readthedocs.io/"
|
documentation = "https://cranelift.readthedocs.io/"
|
||||||
|
repository = "https://github.com/CraneStation/cranelift"
|
||||||
|
categories = ["no-std"]
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
keywords = ["compile", "compiler", "jit"]
|
keywords = ["compile", "compiler", "jit"]
|
||||||
categories = ["no-std"]
|
build = "build.rs"
|
||||||
license = "Apache-2.0 WITH LLVM-exception"
|
edition = "2018"
|
||||||
repository = "https://github.com/CraneStation/cranelift"
|
|
||||||
[dependencies.cranelift-bforest]
|
|
||||||
version = "0.29.0"
|
|
||||||
default-features = false
|
|
||||||
|
|
||||||
[dependencies.cranelift-entity]
|
[dependencies]
|
||||||
version = "0.29.0"
|
cranelift-entity = { path = "../cranelift-entity", version = "0.30.0", default-features = false }
|
||||||
default-features = false
|
cranelift-bforest = { path = "../cranelift-bforest", version = "0.30.0", default-features = false }
|
||||||
|
failure = { version = "0.1.1", default-features = false, features = ["derive"] }
|
||||||
|
failure_derive = { version = "0.1.1", default-features = false }
|
||||||
|
hashmap_core = { version = "0.1.9", optional = true }
|
||||||
|
target-lexicon = { version = "0.4.0", default-features = false }
|
||||||
|
log = { version = "0.4.6", default-features = false }
|
||||||
|
# It is a goal of the cranelift-codegen crate to have minimal external dependencies.
|
||||||
|
# Please don't add any unless they are essential to the task of creating binary
|
||||||
|
# machine code. Integration tests that need external dependencies can be
|
||||||
|
# accomodated in `tests`.
|
||||||
|
|
||||||
[dependencies.failure]
|
[build-dependencies]
|
||||||
version = "0.1.1"
|
cranelift-codegen-meta = { path = "meta", version = "0.30.0", default-features = false }
|
||||||
features = ["derive"]
|
|
||||||
default-features = false
|
|
||||||
|
|
||||||
[dependencies.failure_derive]
|
|
||||||
version = "0.1.1"
|
|
||||||
default-features = false
|
|
||||||
|
|
||||||
[dependencies.hashmap_core]
|
|
||||||
version = "0.1.9"
|
|
||||||
optional = true
|
|
||||||
|
|
||||||
[dependencies.log]
|
|
||||||
version = "0.4.6"
|
|
||||||
default-features = false
|
|
||||||
|
|
||||||
[dependencies.target-lexicon]
|
|
||||||
version = "0.2.0"
|
|
||||||
default-features = false
|
|
||||||
[build-dependencies.cranelift-codegen-meta]
|
|
||||||
version = "0.29.0"
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
default = ["std", "x86", "arm32", "arm64", "riscv"]
|
||||||
|
|
||||||
|
# The "std" feature enables use of libstd. The "core" feature enables use
|
||||||
|
# of some minimal std-like replacement libraries. At least one of these two
|
||||||
|
# features need to be enabled.
|
||||||
|
std = [
|
||||||
|
"cranelift-entity/std",
|
||||||
|
"cranelift-bforest/std",
|
||||||
|
"target-lexicon/std",
|
||||||
|
"cranelift-codegen-meta/std"
|
||||||
|
]
|
||||||
|
|
||||||
|
# The "core" features enables use of "hashmap_core" since core doesn't have
|
||||||
|
# a HashMap implementation, and a workaround for Cargo #4866.
|
||||||
|
core = [
|
||||||
|
"hashmap_core",
|
||||||
|
"cranelift-codegen-meta/core"
|
||||||
|
]
|
||||||
|
|
||||||
|
# This enables some additional functions useful for writing tests, but which
|
||||||
|
# can significantly increase the size of the library.
|
||||||
|
testing_hooks = []
|
||||||
|
|
||||||
|
# ISA targets for which we should build.
|
||||||
|
x86 = []
|
||||||
arm32 = []
|
arm32 = []
|
||||||
arm64 = []
|
arm64 = []
|
||||||
core = ["hashmap_core"]
|
|
||||||
default = ["std", "x86", "arm32", "arm64", "riscv"]
|
|
||||||
riscv = []
|
riscv = []
|
||||||
std = ["cranelift-entity/std", "cranelift-bforest/std", "target-lexicon/std"]
|
|
||||||
testing_hooks = []
|
|
||||||
x86 = []
|
|
||||||
[badges.maintenance]
|
|
||||||
status = "experimental"
|
|
||||||
|
|
||||||
[badges.travis-ci]
|
[badges]
|
||||||
repository = "CraneStation/cranelift"
|
maintenance = { status = "experimental" }
|
||||||
|
travis-ci = { repository = "CraneStation/cranelift" }
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ stack_slot = EntityRefKind('stack_slot', 'A stack slot.')
|
||||||
#: A reference to a global value.
|
#: A reference to a global value.
|
||||||
global_value = EntityRefKind('global_value', 'A global value.')
|
global_value = EntityRefKind('global_value', 'A global value.')
|
||||||
|
|
||||||
#: A reference to a function sugnature declared in the function preamble.
|
#: A reference to a function signature declared in the function preamble.
|
||||||
#: This is used to provide the call signature in a call_indirect instruction.
|
#: This is used to provide the call signature in a call_indirect instruction.
|
||||||
sig_ref = EntityRefKind('sig_ref', 'A function signature.')
|
sig_ref = EntityRefKind('sig_ref', 'A function signature.')
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -252,7 +252,7 @@ class Instruction(object):
|
||||||
for opnum in self.value_opnums:
|
for opnum in self.value_opnums:
|
||||||
typ = self.ins[opnum].typevar
|
typ = self.ins[opnum].typevar
|
||||||
tv = typ.free_typevar()
|
tv = typ.free_typevar()
|
||||||
# Non-polymorphic or derived form ctrl_typevar is OK.
|
# Non-polymorphic or derived from ctrl_typevar is OK.
|
||||||
if tv is None or tv is ctrl_typevar:
|
if tv is None or tv is ctrl_typevar:
|
||||||
continue
|
continue
|
||||||
# No other derived typevars allowed.
|
# No other derived typevars allowed.
|
||||||
|
|
|
||||||
|
|
@ -364,7 +364,7 @@ def gen_opcodes(groups, fmt):
|
||||||
# We explicitly set the discriminant of the first variant to 1, which
|
# We explicitly set the discriminant of the first variant to 1, which
|
||||||
# allows us to take advantage of the NonZero optimization, meaning that
|
# allows us to take advantage of the NonZero optimization, meaning that
|
||||||
# wrapping enums can use the 0 discriminant instead of increasing the size
|
# wrapping enums can use the 0 discriminant instead of increasing the size
|
||||||
# if the whole type, and so SIZEOF(Option<Opcode>>) == SIZEOF(Opcode)
|
# of the whole type, and so SIZEOF(Option<Opcode>>) == SIZEOF(Opcode)
|
||||||
is_first_opcode = True
|
is_first_opcode = True
|
||||||
with fmt.indented('pub enum Opcode {', '}'):
|
with fmt.indented('pub enum Opcode {', '}'):
|
||||||
for g in groups:
|
for g in groups:
|
||||||
|
|
|
||||||
|
|
@ -631,7 +631,7 @@ X86_64.enc(base.uextend.i32.i16, *r.urm_noflags(0x0f, 0xb7))
|
||||||
|
|
||||||
# movzbq, encoded as movzbl because it's equivalent and shorter
|
# movzbq, encoded as movzbl because it's equivalent and shorter
|
||||||
X86_64.enc(base.uextend.i64.i8, *r.urm_noflags.rex(0x0f, 0xb6))
|
X86_64.enc(base.uextend.i64.i8, *r.urm_noflags.rex(0x0f, 0xb6))
|
||||||
X86_64.enc(base.uextend.i64.i8, *r.urm_noflags(0x0f, 0xb6))
|
X86_64.enc(base.uextend.i64.i8, *r.urm_noflags_abcd(0x0f, 0xb6))
|
||||||
|
|
||||||
# movzwq, encoded as movzwl because it's equivalent and shorter
|
# movzwq, encoded as movzwl because it's equivalent and shorter
|
||||||
X86_64.enc(base.uextend.i64.i16, *r.urm_noflags.rex(0x0f, 0xb7))
|
X86_64.enc(base.uextend.i64.i16, *r.urm_noflags.rex(0x0f, 0xb7))
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,7 @@ pub fn relax_branches(func: &mut Function, isa: &TargetIsa) -> CodegenResult<Cod
|
||||||
divert.clear();
|
divert.clear();
|
||||||
cur.func.offsets[ebb] = offset;
|
cur.func.offsets[ebb] = offset;
|
||||||
while let Some(inst) = cur.next_inst() {
|
while let Some(inst) = cur.next_inst() {
|
||||||
|
divert.apply(&cur.func.dfg[inst]);
|
||||||
let enc = cur.func.encodings[inst];
|
let enc = cur.func.encodings[inst];
|
||||||
offset += encinfo.byte_size(enc, inst, &divert, &cur.func);
|
offset += encinfo.byte_size(enc, inst, &divert, &cur.func);
|
||||||
}
|
}
|
||||||
|
|
@ -81,10 +82,6 @@ pub fn relax_branches(func: &mut Function, isa: &TargetIsa) -> CodegenResult<Cod
|
||||||
|
|
||||||
// Record the offset for `ebb` and make sure we iterate until offsets are stable.
|
// Record the offset for `ebb` and make sure we iterate until offsets are stable.
|
||||||
if cur.func.offsets[ebb] != offset {
|
if cur.func.offsets[ebb] != offset {
|
||||||
debug_assert!(
|
|
||||||
cur.func.offsets[ebb] < offset,
|
|
||||||
"Code shrinking during relaxation"
|
|
||||||
);
|
|
||||||
cur.func.offsets[ebb] = offset;
|
cur.func.offsets[ebb] = offset;
|
||||||
go_again = true;
|
go_again = true;
|
||||||
}
|
}
|
||||||
|
|
@ -173,12 +170,12 @@ fn relax_branch(
|
||||||
dest_offset
|
dest_offset
|
||||||
);
|
);
|
||||||
|
|
||||||
// Pick the first encoding that can handle the branch range.
|
// Pick the smallest encoding that can handle the branch range.
|
||||||
let dfg = &cur.func.dfg;
|
let dfg = &cur.func.dfg;
|
||||||
let ctrl_type = dfg.ctrl_typevar(inst);
|
let ctrl_type = dfg.ctrl_typevar(inst);
|
||||||
if let Some(enc) = isa
|
if let Some(enc) = isa
|
||||||
.legal_encodings(cur.func, &dfg[inst], ctrl_type)
|
.legal_encodings(cur.func, &dfg[inst], ctrl_type)
|
||||||
.find(|&enc| {
|
.filter(|&enc| {
|
||||||
let range = encinfo.branch_range(enc).expect("Branch with no range");
|
let range = encinfo.branch_range(enc).expect("Branch with no range");
|
||||||
if !range.contains(offset, dest_offset) {
|
if !range.contains(offset, dest_offset) {
|
||||||
debug!(" trying [{}]: out of range", encinfo.display(enc));
|
debug!(" trying [{}]: out of range", encinfo.display(enc));
|
||||||
|
|
@ -198,7 +195,9 @@ fn relax_branch(
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
.min_by_key(|&enc| encinfo.byte_size(enc, inst, &divert, &cur.func))
|
||||||
{
|
{
|
||||||
|
debug_assert!(enc != cur.func.encodings[inst]);
|
||||||
cur.func.encodings[inst] = enc;
|
cur.func.encodings[inst] = enc;
|
||||||
return encinfo.byte_size(enc, inst, &divert, &cur.func);
|
return encinfo.byte_size(enc, inst, &divert, &cur.func);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -91,18 +91,21 @@ impl Context {
|
||||||
///
|
///
|
||||||
/// This function calls `compile` and `emit_to_memory`, taking care to resize `mem` as
|
/// This function calls `compile` and `emit_to_memory`, taking care to resize `mem` as
|
||||||
/// needed, so it provides a safe interface.
|
/// needed, so it provides a safe interface.
|
||||||
|
///
|
||||||
|
/// Returns the size of the function's code and the size of the read-only data.
|
||||||
pub fn compile_and_emit(
|
pub fn compile_and_emit(
|
||||||
&mut self,
|
&mut self,
|
||||||
isa: &TargetIsa,
|
isa: &TargetIsa,
|
||||||
mem: &mut Vec<u8>,
|
mem: &mut Vec<u8>,
|
||||||
relocs: &mut RelocSink,
|
relocs: &mut RelocSink,
|
||||||
traps: &mut TrapSink,
|
traps: &mut TrapSink,
|
||||||
) -> CodegenResult<()> {
|
) -> CodegenResult<(CodeOffset, CodeOffset)> {
|
||||||
let code_size = self.compile(isa)?;
|
let total_size = self.compile(isa)?;
|
||||||
let old_len = mem.len();
|
let old_len = mem.len();
|
||||||
mem.resize(old_len + code_size as usize, 0);
|
mem.resize(old_len + total_size as usize, 0);
|
||||||
|
let code_size =
|
||||||
unsafe { self.emit_to_memory(isa, mem.as_mut_ptr().add(old_len), relocs, traps) };
|
unsafe { self.emit_to_memory(isa, mem.as_mut_ptr().add(old_len), relocs, traps) };
|
||||||
Ok(())
|
Ok((code_size, total_size - code_size))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Compile the function.
|
/// Compile the function.
|
||||||
|
|
@ -111,7 +114,7 @@ impl Context {
|
||||||
/// represented by `isa`. This does not include the final step of emitting machine code into a
|
/// represented by `isa`. This does not include the final step of emitting machine code into a
|
||||||
/// code sink.
|
/// code sink.
|
||||||
///
|
///
|
||||||
/// Returns the size of the function's code.
|
/// Returns the size of the function's code and read-only data.
|
||||||
pub fn compile(&mut self, isa: &TargetIsa) -> CodegenResult<CodeOffset> {
|
pub fn compile(&mut self, isa: &TargetIsa) -> CodegenResult<CodeOffset> {
|
||||||
let _tt = timing::compile();
|
let _tt = timing::compile();
|
||||||
self.verify_if(isa)?;
|
self.verify_if(isa)?;
|
||||||
|
|
@ -155,15 +158,19 @@ impl Context {
|
||||||
///
|
///
|
||||||
/// This function is unsafe since it does not perform bounds checking on the memory buffer,
|
/// This function is unsafe since it does not perform bounds checking on the memory buffer,
|
||||||
/// and it can't guarantee that the `mem` pointer is valid.
|
/// and it can't guarantee that the `mem` pointer is valid.
|
||||||
|
///
|
||||||
|
/// Returns the size of the function's code.
|
||||||
pub unsafe fn emit_to_memory(
|
pub unsafe fn emit_to_memory(
|
||||||
&self,
|
&self,
|
||||||
isa: &TargetIsa,
|
isa: &TargetIsa,
|
||||||
mem: *mut u8,
|
mem: *mut u8,
|
||||||
relocs: &mut RelocSink,
|
relocs: &mut RelocSink,
|
||||||
traps: &mut TrapSink,
|
traps: &mut TrapSink,
|
||||||
) {
|
) -> CodeOffset {
|
||||||
let _tt = timing::binemit();
|
let _tt = timing::binemit();
|
||||||
isa.emit_function_to_memory(&self.func, &mut MemoryCodeSink::new(mem, relocs, traps));
|
let mut sink = MemoryCodeSink::new(mem, relocs, traps);
|
||||||
|
isa.emit_function_to_memory(&self.func, &mut sink);
|
||||||
|
sink.code_size as CodeOffset
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Run the verifier on the function.
|
/// Run the verifier on the function.
|
||||||
|
|
|
||||||
|
|
@ -246,7 +246,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_magicU32() {
|
fn test_magic_u32() {
|
||||||
assert_eq!(magic_u32(2u32), make_mu32(0x80000000u32, false, 0));
|
assert_eq!(magic_u32(2u32), make_mu32(0x80000000u32, false, 0));
|
||||||
assert_eq!(magic_u32(3u32), make_mu32(0xaaaaaaabu32, false, 1));
|
assert_eq!(magic_u32(3u32), make_mu32(0xaaaaaaabu32, false, 1));
|
||||||
assert_eq!(magic_u32(4u32), make_mu32(0x40000000u32, false, 0));
|
assert_eq!(magic_u32(4u32), make_mu32(0x40000000u32, false, 0));
|
||||||
|
|
@ -279,8 +279,9 @@ mod tests {
|
||||||
make_mu32(0x80000001u32, false, 31)
|
make_mu32(0x80000001u32, false, 31)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_magicU64() {
|
fn test_magic_u64() {
|
||||||
assert_eq!(magic_u64(2u64), make_mu64(0x8000000000000000u64, false, 0));
|
assert_eq!(magic_u64(2u64), make_mu64(0x8000000000000000u64, false, 0));
|
||||||
assert_eq!(magic_u64(3u64), make_mu64(0xaaaaaaaaaaaaaaabu64, false, 1));
|
assert_eq!(magic_u64(3u64), make_mu64(0xaaaaaaaaaaaaaaabu64, false, 1));
|
||||||
assert_eq!(magic_u64(4u64), make_mu64(0x4000000000000000u64, false, 0));
|
assert_eq!(magic_u64(4u64), make_mu64(0x4000000000000000u64, false, 0));
|
||||||
|
|
@ -346,8 +347,9 @@ mod tests {
|
||||||
make_mu64(0x8000000000000001u64, false, 63)
|
make_mu64(0x8000000000000001u64, false, 63)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_magicS32() {
|
fn test_magic_s32() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
magic_s32(-0x80000000i32),
|
magic_s32(-0x80000000i32),
|
||||||
make_ms32(0x7fffffffu32 as i32, 30)
|
make_ms32(0x7fffffffu32 as i32, 30)
|
||||||
|
|
@ -390,8 +392,9 @@ mod tests {
|
||||||
make_ms32(0x40000001u32 as i32, 29)
|
make_ms32(0x40000001u32 as i32, 29)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_magicS64() {
|
fn test_magic_s64() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
magic_s64(-0x8000000000000000i64),
|
magic_s64(-0x8000000000000000i64),
|
||||||
make_ms64(0x7fffffffffffffffu64 as i64, 62)
|
make_ms64(0x7fffffffffffffffu64 as i64, 62)
|
||||||
|
|
@ -515,6 +518,7 @@ mod tests {
|
||||||
make_ms64(0x4000000000000001u64 as i64, 61)
|
make_ms64(0x4000000000000001u64 as i64, 61)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_magic_generators_dont_panic() {
|
fn test_magic_generators_dont_panic() {
|
||||||
// The point of this is to check that the magic number generators
|
// The point of this is to check that the magic number generators
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,88 @@
|
||||||
//! ARM ABI implementation.
|
//! ARM ABI implementation.
|
||||||
|
//! This is from the RISC-V target and will need to be updated for ARM32.
|
||||||
|
|
||||||
use super::registers::{D, GPR, Q, S};
|
use super::registers::{D, GPR, Q, S};
|
||||||
use crate::ir;
|
use crate::abi::{legalize_args, ArgAction, ArgAssigner, ValueConversion};
|
||||||
|
use crate::ir::{self, AbiParam, ArgumentExtension, ArgumentLoc, Type};
|
||||||
use crate::isa::RegClass;
|
use crate::isa::RegClass;
|
||||||
use crate::regalloc::RegisterSet;
|
use crate::regalloc::RegisterSet;
|
||||||
use crate::settings as shared_settings;
|
use core::i32;
|
||||||
|
use target_lexicon::Triple;
|
||||||
|
|
||||||
|
struct Args {
|
||||||
|
pointer_bits: u8,
|
||||||
|
pointer_bytes: u8,
|
||||||
|
pointer_type: Type,
|
||||||
|
regs: u32,
|
||||||
|
reg_limit: u32,
|
||||||
|
offset: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Args {
|
||||||
|
fn new(bits: u8) -> Self {
|
||||||
|
Self {
|
||||||
|
pointer_bits: bits,
|
||||||
|
pointer_bytes: bits / 8,
|
||||||
|
pointer_type: Type::int(u16::from(bits)).unwrap(),
|
||||||
|
regs: 0,
|
||||||
|
reg_limit: 8,
|
||||||
|
offset: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ArgAssigner for Args {
|
||||||
|
fn assign(&mut self, arg: &AbiParam) -> ArgAction {
|
||||||
|
fn align(value: u32, to: u32) -> u32 {
|
||||||
|
(value + to - 1) & !(to - 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
let ty = arg.value_type;
|
||||||
|
|
||||||
|
// Check for a legal type.
|
||||||
|
// SIMD instructions are currently no implemented, so break down vectors
|
||||||
|
if ty.is_vector() {
|
||||||
|
return ValueConversion::VectorSplit.into();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Large integers and booleans are broken down to fit in a register.
|
||||||
|
if !ty.is_float() && ty.bits() > u16::from(self.pointer_bits) {
|
||||||
|
// Align registers and stack to a multiple of two pointers.
|
||||||
|
self.regs = align(self.regs, 2);
|
||||||
|
self.offset = align(self.offset, 2 * u32::from(self.pointer_bytes));
|
||||||
|
return ValueConversion::IntSplit.into();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Small integers are extended to the size of a pointer register.
|
||||||
|
if ty.is_int() && ty.bits() < u16::from(self.pointer_bits) {
|
||||||
|
match arg.extension {
|
||||||
|
ArgumentExtension::None => {}
|
||||||
|
ArgumentExtension::Uext => return ValueConversion::Uext(self.pointer_type).into(),
|
||||||
|
ArgumentExtension::Sext => return ValueConversion::Sext(self.pointer_type).into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.regs < self.reg_limit {
|
||||||
|
// Assign to a register.
|
||||||
|
let reg = GPR.unit(10 + self.regs as usize);
|
||||||
|
self.regs += 1;
|
||||||
|
ArgumentLoc::Reg(reg).into()
|
||||||
|
} else {
|
||||||
|
// Assign a stack location.
|
||||||
|
let loc = ArgumentLoc::Stack(self.offset as i32);
|
||||||
|
self.offset += u32::from(self.pointer_bytes);
|
||||||
|
debug_assert!(self.offset <= i32::MAX as u32);
|
||||||
|
loc.into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Legalize `sig`.
|
/// Legalize `sig`.
|
||||||
pub fn legalize_signature(
|
pub fn legalize_signature(sig: &mut ir::Signature, triple: &Triple, _current: bool) {
|
||||||
_sig: &mut ir::Signature,
|
let bits = triple.pointer_width().unwrap().bits();
|
||||||
_flags: &shared_settings::Flags,
|
|
||||||
_current: bool,
|
let mut args = Args::new(bits);
|
||||||
) {
|
legalize_args(&mut sig.params, &mut args);
|
||||||
unimplemented!()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get register class for a type appearing in a legalized signature.
|
/// Get register class for a type appearing in a legalized signature.
|
||||||
|
|
|
||||||
|
|
@ -102,7 +102,7 @@ impl TargetIsa for Isa {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn legalize_signature(&self, sig: &mut ir::Signature, current: bool) {
|
fn legalize_signature(&self, sig: &mut ir::Signature, current: bool) {
|
||||||
abi::legalize_signature(sig, &self.shared_flags, current)
|
abi::legalize_signature(sig, &self.triple, current)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn regclass_for_abi_type(&self, ty: ir::Type) -> RegClass {
|
fn regclass_for_abi_type(&self, ty: ir::Type) -> RegClass {
|
||||||
|
|
|
||||||
|
|
@ -161,13 +161,14 @@ pub fn legalize_signature(sig: &mut ir::Signature, triple: &Triple, _current: bo
|
||||||
|
|
||||||
legalize_args(&mut sig.params, &mut args);
|
legalize_args(&mut sig.params, &mut args);
|
||||||
|
|
||||||
let regs = if sig.call_conv == CallConv::WindowsFastcall {
|
let (regs, fpr_limit) = if sig.call_conv == CallConv::WindowsFastcall {
|
||||||
&RET_GPRS_WIN_FASTCALL_X64[..]
|
// windows-x64 calling convention only uses XMM0 or RAX for return values
|
||||||
|
(&RET_GPRS_WIN_FASTCALL_X64[..], 1)
|
||||||
} else {
|
} else {
|
||||||
&RET_GPRS[..]
|
(&RET_GPRS[..], 2)
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut rets = Args::new(bits, regs, 2, sig.call_conv);
|
let mut rets = Args::new(bits, regs, fpr_limit, sig.call_conv);
|
||||||
legalize_args(&mut sig.returns, &mut rets);
|
legalize_args(&mut sig.returns, &mut rets);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
20
third_party/rust/cranelift-codegen/src/licm.rs
vendored
20
third_party/rust/cranelift-codegen/src/licm.rs
vendored
|
|
@ -5,7 +5,9 @@ use crate::dominator_tree::DominatorTree;
|
||||||
use crate::entity::{EntityList, ListPool};
|
use crate::entity::{EntityList, ListPool};
|
||||||
use crate::flowgraph::{BasicBlock, ControlFlowGraph};
|
use crate::flowgraph::{BasicBlock, ControlFlowGraph};
|
||||||
use crate::fx::FxHashSet;
|
use crate::fx::FxHashSet;
|
||||||
use crate::ir::{DataFlowGraph, Ebb, Function, Inst, InstBuilder, Layout, Opcode, Type, Value};
|
use crate::ir::{
|
||||||
|
DataFlowGraph, Ebb, Function, Inst, InstBuilder, InstructionData, Layout, Opcode, Type, Value,
|
||||||
|
};
|
||||||
use crate::isa::TargetIsa;
|
use crate::isa::TargetIsa;
|
||||||
use crate::loop_analysis::{Loop, LoopAnalysis};
|
use crate::loop_analysis::{Loop, LoopAnalysis};
|
||||||
use crate::timing;
|
use crate::timing;
|
||||||
|
|
@ -145,8 +147,7 @@ fn change_branch_jump_destination(inst: Inst, new_ebb: Ebb, func: &mut Function)
|
||||||
|
|
||||||
/// Test whether the given opcode is unsafe to even consider for LICM.
|
/// Test whether the given opcode is unsafe to even consider for LICM.
|
||||||
fn trivially_unsafe_for_licm(opcode: Opcode) -> bool {
|
fn trivially_unsafe_for_licm(opcode: Opcode) -> bool {
|
||||||
opcode.can_load()
|
opcode.can_store()
|
||||||
|| opcode.can_store()
|
|
||||||
|| opcode.is_call()
|
|| opcode.is_call()
|
||||||
|| opcode.is_branch()
|
|| opcode.is_branch()
|
||||||
|| opcode.is_terminator()
|
|| opcode.is_terminator()
|
||||||
|
|
@ -156,12 +157,25 @@ fn trivially_unsafe_for_licm(opcode: Opcode) -> bool {
|
||||||
|| opcode.writes_cpu_flags()
|
|| opcode.writes_cpu_flags()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_unsafe_load(inst_data: &InstructionData) -> bool {
|
||||||
|
match *inst_data {
|
||||||
|
InstructionData::Load { flags, .. } | InstructionData::LoadComplex { flags, .. } => {
|
||||||
|
!flags.readonly() || !flags.notrap()
|
||||||
|
}
|
||||||
|
_ => inst_data.opcode().can_load(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Test whether the given instruction is loop-invariant.
|
/// Test whether the given instruction is loop-invariant.
|
||||||
fn is_loop_invariant(inst: Inst, dfg: &DataFlowGraph, loop_values: &FxHashSet<Value>) -> bool {
|
fn is_loop_invariant(inst: Inst, dfg: &DataFlowGraph, loop_values: &FxHashSet<Value>) -> bool {
|
||||||
if trivially_unsafe_for_licm(dfg[inst].opcode()) {
|
if trivially_unsafe_for_licm(dfg[inst].opcode()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if is_unsafe_load(&dfg[inst]) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
let inst_args = dfg.inst_args(inst);
|
let inst_args = dfg.inst_args(inst);
|
||||||
for arg in inst_args {
|
for arg in inst_args {
|
||||||
let arg = dfg.resolve_aliases(*arg);
|
let arg = dfg.resolve_aliases(*arg);
|
||||||
|
|
|
||||||
|
|
@ -128,6 +128,7 @@ fn optimize_cpu_flags(
|
||||||
// We found a compare+branch pattern. Transform it to use flags.
|
// We found a compare+branch pattern. Transform it to use flags.
|
||||||
let args = info.args.as_slice(&pos.func.dfg.value_lists)[1..].to_vec();
|
let args = info.args.as_slice(&pos.func.dfg.value_lists)[1..].to_vec();
|
||||||
pos.goto_inst(info.cmp_inst);
|
pos.goto_inst(info.cmp_inst);
|
||||||
|
pos.use_srcloc(info.cmp_inst);
|
||||||
match info.kind {
|
match info.kind {
|
||||||
CmpBrKind::Icmp { mut cond, arg } => {
|
CmpBrKind::Icmp { mut cond, arg } => {
|
||||||
let flags = pos.ins().ifcmp(info.cmp_arg, arg);
|
let flags = pos.ins().ifcmp(info.cmp_arg, arg);
|
||||||
|
|
|
||||||
|
|
@ -292,6 +292,9 @@ impl<'a> Context<'a> {
|
||||||
|
|
||||||
// Insert a copy instruction at the top of `ebb`.
|
// Insert a copy instruction at the top of `ebb`.
|
||||||
let mut pos = EncCursor::new(self.func, self.isa).at_first_inst(ebb);
|
let mut pos = EncCursor::new(self.func, self.isa).at_first_inst(ebb);
|
||||||
|
if let Some(inst) = pos.current_inst() {
|
||||||
|
pos.use_srcloc(inst);
|
||||||
|
}
|
||||||
pos.ins().with_result(param).copy(new_val);
|
pos.ins().with_result(param).copy(new_val);
|
||||||
let inst = pos.built_inst();
|
let inst = pos.built_inst();
|
||||||
self.liveness.move_def_locally(param, inst);
|
self.liveness.move_def_locally(param, inst);
|
||||||
|
|
@ -347,6 +350,7 @@ impl<'a> Context<'a> {
|
||||||
pred_val: Value,
|
pred_val: Value,
|
||||||
) -> Value {
|
) -> Value {
|
||||||
let mut pos = EncCursor::new(self.func, self.isa).at_inst(pred_inst);
|
let mut pos = EncCursor::new(self.func, self.isa).at_inst(pred_inst);
|
||||||
|
pos.use_srcloc(pred_inst);
|
||||||
let copy = pos.ins().copy(pred_val);
|
let copy = pos.ins().copy(pred_val);
|
||||||
let inst = pos.built_inst();
|
let inst = pos.built_inst();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -420,6 +420,7 @@ impl<'a> Context<'a> {
|
||||||
// secondary `opidx` key makes it possible to use an unstable (non-allocating) sort.
|
// secondary `opidx` key makes it possible to use an unstable (non-allocating) sort.
|
||||||
self.reg_uses.sort_unstable_by_key(|u| (u.value, u.opidx));
|
self.reg_uses.sort_unstable_by_key(|u| (u.value, u.opidx));
|
||||||
|
|
||||||
|
self.cur.use_srcloc(inst);
|
||||||
for i in 0..self.reg_uses.len() {
|
for i in 0..self.reg_uses.len() {
|
||||||
let ru = self.reg_uses[i];
|
let ru = self.reg_uses[i];
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -176,7 +176,7 @@ mod details {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Information about passes in a single thread.
|
// Information about passes in a single thread.
|
||||||
thread_local! {
|
thread_local! {
|
||||||
static CURRENT_PASS: Cell<Pass> = Cell::new(Pass::None);
|
static CURRENT_PASS: Cell<Pass> = Cell::new(Pass::None);
|
||||||
static PASS_TIME: RefCell<PassTimes> = RefCell::new(Default::default());
|
static PASS_TIME: RefCell<PassTimes> = RefCell::new(Default::default());
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
{"files":{"Cargo.toml":"bdfb55271249705ca4f66080d59757b97af8872bcd0080c858780d472d6094bc","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"96ceffbfd88fb06e3b41aa4d3087cffbbf8441d04eba7ab09662a72ab600a321","src/boxed_slice.rs":"687428ee0442013c0d5962dd78d0964830233bc4cb19aa530d30da0f1dc437a9","src/iter.rs":"4a4d3309fe9aad14fd7702f02459f4277b4ddb50dba700e58dcc75665ffebfb3","src/keys.rs":"b8c2fba26dee15bf3d1880bb2b41e8d66fe1428d242ee6d9fd30ee94bbd0407d","src/lib.rs":"139fc0eeed2e8cde2b82b8b7402e8c7cd079a9fbbf1ec692622e5ad0c10d9faf","src/list.rs":"fc3decc81bcef92e106aae53e586a0ef21d70916fa53a48f7b813c5da44b8dc2","src/map.rs":"f35031459aca446734726c132c0a571482f1ec2ca8221b352d2e18c74950e977","src/packed_option.rs":"9d47f5b8302ee685c096817e376144e363507d1c77ef562d3ae4dbddae568195","src/primary.rs":"e95e4b2ed36413d80c4c0dcfc19dcf8a9f52e34467aaec196c774fd639747028","src/set.rs":"ec0ff7a9ee674c90ff9d06ea1fd4ab05039369146c2d259f476c6f612417933f","src/sparse.rs":"cf345a81d69a5dddaed4778b6aaaf06c70da2c1fd4cd21e366ed6ca5906ffdab"},"package":"4e124e09cb7dc85fbe2162420aebbe8e9e3b8f9210901be7867416c5beec8226"}
|
{"files":{"Cargo.toml":"48e037bea5be27018e3f98bfba7ca7b0af1322c2083c69a137ab3320cd64b9fb","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"96ceffbfd88fb06e3b41aa4d3087cffbbf8441d04eba7ab09662a72ab600a321","src/boxed_slice.rs":"687428ee0442013c0d5962dd78d0964830233bc4cb19aa530d30da0f1dc437a9","src/iter.rs":"4a4d3309fe9aad14fd7702f02459f4277b4ddb50dba700e58dcc75665ffebfb3","src/keys.rs":"b8c2fba26dee15bf3d1880bb2b41e8d66fe1428d242ee6d9fd30ee94bbd0407d","src/lib.rs":"139fc0eeed2e8cde2b82b8b7402e8c7cd079a9fbbf1ec692622e5ad0c10d9faf","src/list.rs":"fc3decc81bcef92e106aae53e586a0ef21d70916fa53a48f7b813c5da44b8dc2","src/map.rs":"f35031459aca446734726c132c0a571482f1ec2ca8221b352d2e18c74950e977","src/packed_option.rs":"9d47f5b8302ee685c096817e376144e363507d1c77ef562d3ae4dbddae568195","src/primary.rs":"e95e4b2ed36413d80c4c0dcfc19dcf8a9f52e34467aaec196c774fd639747028","src/set.rs":"ec0ff7a9ee674c90ff9d06ea1fd4ab05039369146c2d259f476c6f612417933f","src/sparse.rs":"cf345a81d69a5dddaed4778b6aaaf06c70da2c1fd4cd21e366ed6ca5906ffdab"},"package":null}
|
||||||
33
third_party/rust/cranelift-entity/Cargo.toml
vendored
33
third_party/rust/cranelift-entity/Cargo.toml
vendored
|
|
@ -1,34 +1,21 @@
|
||||||
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
|
|
||||||
#
|
|
||||||
# When uploading crates to the registry Cargo will automatically
|
|
||||||
# "normalize" Cargo.toml files for maximal compatibility
|
|
||||||
# with all versions of Cargo and also rewrite `path` dependencies
|
|
||||||
# to registry (e.g. crates.io) dependencies
|
|
||||||
#
|
|
||||||
# If you believe there's an error in this file please file an
|
|
||||||
# issue against the rust-lang/cargo repository. If you're
|
|
||||||
# editing this file be aware that the upstream Cargo.toml
|
|
||||||
# will likely look very different (and much more reasonable)
|
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
edition = "2018"
|
|
||||||
name = "cranelift-entity"
|
|
||||||
version = "0.29.0"
|
|
||||||
authors = ["The Cranelift Project Developers"]
|
authors = ["The Cranelift Project Developers"]
|
||||||
|
name = "cranelift-entity"
|
||||||
|
version = "0.30.0"
|
||||||
description = "Data structures using entity references as mapping keys"
|
description = "Data structures using entity references as mapping keys"
|
||||||
|
license = "Apache-2.0 WITH LLVM-exception"
|
||||||
documentation = "https://cranelift.readthedocs.io/"
|
documentation = "https://cranelift.readthedocs.io/"
|
||||||
|
repository = "https://github.com/CraneStation/cranelift"
|
||||||
|
categories = ["no-std"]
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
keywords = ["entity", "set", "map"]
|
keywords = ["entity", "set", "map"]
|
||||||
categories = ["no-std"]
|
edition = "2018"
|
||||||
license = "Apache-2.0 WITH LLVM-exception"
|
|
||||||
repository = "https://github.com/CraneStation/cranelift"
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
core = []
|
|
||||||
default = ["std"]
|
default = ["std"]
|
||||||
std = []
|
std = []
|
||||||
[badges.maintenance]
|
core = []
|
||||||
status = "experimental"
|
|
||||||
|
|
||||||
[badges.travis-ci]
|
[badges]
|
||||||
repository = "CraneStation/cranelift"
|
maintenance = { status = "experimental" }
|
||||||
|
travis-ci = { repository = "CraneStation/cranelift" }
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
{"files":{"Cargo.toml":"b5d70a2290241ca933b8bc6530f92f784c508d34448f86516ce3ddbdd62c1ba7","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"dea43e8044284df50f8b8772e9b48ba8b109b45c74111ff73619775d57ad8d67","src/frontend.rs":"f3ad024e4895eddf83c8fe19c93ae37709a6bf27db2e1beef153fd742d99defa","src/lib.rs":"1cc2e7aaffa45bccea9e59fcc9d9c5d295a9f7adacd6bd55933834e20e969aef","src/ssa.rs":"88cb07071943f3e72a91c91afb58960689b4d9c56352b3bb7cd5d69288066190","src/switch.rs":"1afa11f037c91d6c87f8c6b88cddddc5f22c2b6ee9d0f05382ed05d0c4f29135","src/variable.rs":"f082efaa4b2d3c5eb48f6344149408074e1e15cb581f7a63f549313c7a1037be"},"package":"2833c6e1a93c524ce0c2ab31266cdc84d38c906349f79f19378a5e5995727b23"}
|
{"files":{"Cargo.toml":"c92f07d9959d10331c6b4770a4db12f706927a18897dfed45472abcd6e58190e","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"dea43e8044284df50f8b8772e9b48ba8b109b45c74111ff73619775d57ad8d67","src/frontend.rs":"f3ad024e4895eddf83c8fe19c93ae37709a6bf27db2e1beef153fd742d99defa","src/lib.rs":"1cc2e7aaffa45bccea9e59fcc9d9c5d295a9f7adacd6bd55933834e20e969aef","src/ssa.rs":"88cb07071943f3e72a91c91afb58960689b4d9c56352b3bb7cd5d69288066190","src/switch.rs":"b8f337966b540254feb5f979b4a146f5ef69ae199864da6332c9d7513ff3ec8b","src/variable.rs":"f082efaa4b2d3c5eb48f6344149408074e1e15cb581f7a63f549313c7a1037be"},"package":null}
|
||||||
52
third_party/rust/cranelift-frontend/Cargo.toml
vendored
52
third_party/rust/cranelift-frontend/Cargo.toml
vendored
|
|
@ -1,48 +1,26 @@
|
||||||
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
|
|
||||||
#
|
|
||||||
# When uploading crates to the registry Cargo will automatically
|
|
||||||
# "normalize" Cargo.toml files for maximal compatibility
|
|
||||||
# with all versions of Cargo and also rewrite `path` dependencies
|
|
||||||
# to registry (e.g. crates.io) dependencies
|
|
||||||
#
|
|
||||||
# If you believe there's an error in this file please file an
|
|
||||||
# issue against the rust-lang/cargo repository. If you're
|
|
||||||
# editing this file be aware that the upstream Cargo.toml
|
|
||||||
# will likely look very different (and much more reasonable)
|
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
edition = "2018"
|
|
||||||
name = "cranelift-frontend"
|
|
||||||
version = "0.29.0"
|
|
||||||
authors = ["The Cranelift Project Developers"]
|
authors = ["The Cranelift Project Developers"]
|
||||||
|
name = "cranelift-frontend"
|
||||||
|
version = "0.30.0"
|
||||||
description = "Cranelift IR builder helper"
|
description = "Cranelift IR builder helper"
|
||||||
documentation = "https://cranelift.readthedocs.io/"
|
|
||||||
readme = "README.md"
|
|
||||||
categories = ["no-std"]
|
|
||||||
license = "Apache-2.0 WITH LLVM-exception"
|
license = "Apache-2.0 WITH LLVM-exception"
|
||||||
|
documentation = "https://cranelift.readthedocs.io/"
|
||||||
|
categories = ["no-std"]
|
||||||
repository = "https://github.com/CraneStation/cranelift"
|
repository = "https://github.com/CraneStation/cranelift"
|
||||||
[dependencies.cranelift-codegen]
|
readme = "README.md"
|
||||||
version = "0.29.0"
|
edition = "2018"
|
||||||
default-features = false
|
|
||||||
|
|
||||||
[dependencies.hashmap_core]
|
[dependencies]
|
||||||
version = "0.1.9"
|
cranelift-codegen = { path = "../cranelift-codegen", version = "0.30.0", default-features = false }
|
||||||
optional = true
|
target-lexicon = { version = "0.4.0", default-features = false }
|
||||||
|
log = { version = "0.4.6", default-features = false }
|
||||||
[dependencies.log]
|
hashmap_core = { version = "0.1.9", optional = true }
|
||||||
version = "0.4.6"
|
|
||||||
default-features = false
|
|
||||||
|
|
||||||
[dependencies.target-lexicon]
|
|
||||||
version = "0.2.0"
|
|
||||||
default-features = false
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
core = ["hashmap_core", "cranelift-codegen/core"]
|
|
||||||
default = ["std"]
|
default = ["std"]
|
||||||
std = ["cranelift-codegen/std"]
|
std = ["cranelift-codegen/std"]
|
||||||
[badges.maintenance]
|
core = ["hashmap_core", "cranelift-codegen/core"]
|
||||||
status = "experimental"
|
|
||||||
|
|
||||||
[badges.travis-ci]
|
[badges]
|
||||||
repository = "CraneStation/cranelift"
|
maintenance = { status = "experimental" }
|
||||||
|
travis-ci = { repository = "CraneStation/cranelift" }
|
||||||
|
|
|
||||||
131
third_party/rust/cranelift-frontend/src/switch.rs
vendored
131
third_party/rust/cranelift-frontend/src/switch.rs
vendored
|
|
@ -9,6 +9,36 @@ type EntryIndex = u64;
|
||||||
|
|
||||||
/// Unlike with `br_table`, `Switch` cases may be sparse or non-0-based.
|
/// Unlike with `br_table`, `Switch` cases may be sparse or non-0-based.
|
||||||
/// They emit efficient code using branches, jump tables, or a combination of both.
|
/// They emit efficient code using branches, jump tables, or a combination of both.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use cranelift_codegen::ir::types::*;
|
||||||
|
/// # use cranelift_codegen::ir::{ExternalName, Function, Signature, InstBuilder};
|
||||||
|
/// # use cranelift_codegen::isa::CallConv;
|
||||||
|
/// # use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext, Switch};
|
||||||
|
/// #
|
||||||
|
/// # let mut sig = Signature::new(CallConv::SystemV);
|
||||||
|
/// # let mut fn_builder_ctx = FunctionBuilderContext::new();
|
||||||
|
/// # let mut func = Function::with_name_signature(ExternalName::user(0, 0), sig);
|
||||||
|
/// # let mut builder = FunctionBuilder::new(&mut func, &mut fn_builder_ctx);
|
||||||
|
/// #
|
||||||
|
/// # let entry = builder.create_ebb();
|
||||||
|
/// # builder.switch_to_block(entry);
|
||||||
|
/// #
|
||||||
|
/// let block0 = builder.create_ebb();
|
||||||
|
/// let block1 = builder.create_ebb();
|
||||||
|
/// let block2 = builder.create_ebb();
|
||||||
|
/// let fallback = builder.create_ebb();
|
||||||
|
///
|
||||||
|
/// let val = builder.ins().iconst(I32, 1);
|
||||||
|
///
|
||||||
|
/// let mut switch = Switch::new();
|
||||||
|
/// switch.set_entry(0, block0);
|
||||||
|
/// switch.set_entry(1, block1);
|
||||||
|
/// switch.set_entry(7, block2);
|
||||||
|
/// switch.emit(&mut builder, val, fallback);
|
||||||
|
/// ```
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct Switch {
|
pub struct Switch {
|
||||||
cases: HashMap<EntryIndex, Ebb>,
|
cases: HashMap<EntryIndex, Ebb>,
|
||||||
|
|
@ -32,6 +62,14 @@ impl Switch {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Turn the `cases` `HashMap` into a list of `ContiguousCaseRange`s.
|
||||||
|
///
|
||||||
|
/// # Postconditions
|
||||||
|
///
|
||||||
|
/// * Every entry will be represented.
|
||||||
|
/// * The `ContiguousCaseRange`s will not overlap.
|
||||||
|
/// * Between two `ContiguousCaseRange`s there will be at least one entry index.
|
||||||
|
/// * No `ContiguousCaseRange`s will be empty.
|
||||||
fn collect_contiguous_case_ranges(self) -> Vec<ContiguousCaseRange> {
|
fn collect_contiguous_case_ranges(self) -> Vec<ContiguousCaseRange> {
|
||||||
debug!("build_contiguous_case_ranges before: {:#?}", self.cases);
|
debug!("build_contiguous_case_ranges before: {:#?}", self.cases);
|
||||||
let mut cases = self.cases.into_iter().collect::<Vec<(_, _)>>();
|
let mut cases = self.cases.into_iter().collect::<Vec<(_, _)>>();
|
||||||
|
|
@ -60,6 +98,7 @@ impl Switch {
|
||||||
contiguous_case_ranges
|
contiguous_case_ranges
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Binary search for the right `ContiguousCaseRange`.
|
||||||
fn build_search_tree(
|
fn build_search_tree(
|
||||||
bx: &mut FunctionBuilder,
|
bx: &mut FunctionBuilder,
|
||||||
val: Value,
|
val: Value,
|
||||||
|
|
@ -120,6 +159,7 @@ impl Switch {
|
||||||
cases_and_jt_ebbs
|
cases_and_jt_ebbs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Linear search for the right `ContiguousCaseRange`.
|
||||||
fn build_search_branches(
|
fn build_search_branches(
|
||||||
bx: &mut FunctionBuilder,
|
bx: &mut FunctionBuilder,
|
||||||
val: Value,
|
val: Value,
|
||||||
|
|
@ -128,22 +168,41 @@ impl Switch {
|
||||||
cases_and_jt_ebbs: &mut Vec<(EntryIndex, Ebb, Vec<Ebb>)>,
|
cases_and_jt_ebbs: &mut Vec<(EntryIndex, Ebb, Vec<Ebb>)>,
|
||||||
) {
|
) {
|
||||||
for ContiguousCaseRange { first_index, ebbs } in contiguous_case_ranges.into_iter().rev() {
|
for ContiguousCaseRange { first_index, ebbs } in contiguous_case_ranges.into_iter().rev() {
|
||||||
if ebbs.len() == 1 {
|
match (ebbs.len(), first_index) {
|
||||||
|
(1, 0) => {
|
||||||
|
bx.ins().brz(val, ebbs[0], &[]);
|
||||||
|
}
|
||||||
|
(1, _) => {
|
||||||
let is_good_val = bx.ins().icmp_imm(IntCC::Equal, val, first_index as i64);
|
let is_good_val = bx.ins().icmp_imm(IntCC::Equal, val, first_index as i64);
|
||||||
bx.ins().brnz(is_good_val, ebbs[0], &[]);
|
bx.ins().brnz(is_good_val, ebbs[0], &[]);
|
||||||
} else {
|
}
|
||||||
|
(_, 0) => {
|
||||||
|
// if `first_index` is 0, then `icmp_imm uge val, first_index` is trivially true
|
||||||
let jt_ebb = bx.create_ebb();
|
let jt_ebb = bx.create_ebb();
|
||||||
let is_good_val =
|
bx.ins().jump(jt_ebb, &[]);
|
||||||
bx.ins()
|
cases_and_jt_ebbs.push((first_index, jt_ebb, ebbs));
|
||||||
.icmp_imm(IntCC::UnsignedGreaterThanOrEqual, val, first_index as i64);
|
// `jump otherwise` below must not be hit, because the current block has been
|
||||||
|
// filled above. This is the last iteration anyway, as 0 is the smallest
|
||||||
|
// unsigned int, so just return here.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
(_, _) => {
|
||||||
|
let jt_ebb = bx.create_ebb();
|
||||||
|
let is_good_val = bx.ins().icmp_imm(
|
||||||
|
IntCC::UnsignedGreaterThanOrEqual,
|
||||||
|
val,
|
||||||
|
first_index as i64,
|
||||||
|
);
|
||||||
bx.ins().brnz(is_good_val, jt_ebb, &[]);
|
bx.ins().brnz(is_good_val, jt_ebb, &[]);
|
||||||
cases_and_jt_ebbs.push((first_index, jt_ebb, ebbs));
|
cases_and_jt_ebbs.push((first_index, jt_ebb, ebbs));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bx.ins().jump(otherwise, &[]);
|
bx.ins().jump(otherwise, &[]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// For every item in `cases_and_jt_ebbs` this will create a jump table in the specified ebb.
|
||||||
fn build_jump_tables(
|
fn build_jump_tables(
|
||||||
bx: &mut FunctionBuilder,
|
bx: &mut FunctionBuilder,
|
||||||
val: Value,
|
val: Value,
|
||||||
|
|
@ -158,7 +217,11 @@ impl Switch {
|
||||||
let jump_table = bx.create_jump_table(jt_data);
|
let jump_table = bx.create_jump_table(jt_data);
|
||||||
|
|
||||||
bx.switch_to_block(jt_ebb);
|
bx.switch_to_block(jt_ebb);
|
||||||
let discr = bx.ins().iadd_imm(val, (first_index as i64).wrapping_neg());
|
let discr = if first_index == 0 {
|
||||||
|
val
|
||||||
|
} else {
|
||||||
|
bx.ins().iadd_imm(val, (first_index as i64).wrapping_neg())
|
||||||
|
};
|
||||||
bx.ins().br_table(discr, otherwise, jump_table);
|
bx.ins().br_table(discr, otherwise, jump_table);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -183,9 +246,22 @@ impl Switch {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This represents a contiguous range of cases to switch on.
|
||||||
|
///
|
||||||
|
/// For example 10 => ebb1, 11 => ebb2, 12 => ebb7 will be represented as:
|
||||||
|
///
|
||||||
|
/// ```plain
|
||||||
|
/// ContiguousCaseRange {
|
||||||
|
/// first_index: 10,
|
||||||
|
/// ebbs: vec![Ebb::from_u32(1), Ebb::from_u32(2), Ebb::from_u32(7)]
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct ContiguousCaseRange {
|
struct ContiguousCaseRange {
|
||||||
|
/// The entry index of the first case. Eg. 10 when the entry indexes are 10, 11, 12 and 13.
|
||||||
first_index: EntryIndex,
|
first_index: EntryIndex,
|
||||||
|
|
||||||
|
/// The ebbs to jump to sorted in ascending order of entry index.
|
||||||
ebbs: Vec<Ebb>,
|
ebbs: Vec<Ebb>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -237,8 +313,7 @@ mod tests {
|
||||||
"ebb0:
|
"ebb0:
|
||||||
v0 = iconst.i8 0
|
v0 = iconst.i8 0
|
||||||
v1 = uextend.i32 v0
|
v1 = uextend.i32 v0
|
||||||
v2 = icmp_imm eq v1, 0
|
brz v1, ebb1
|
||||||
brnz v2, ebb1
|
|
||||||
jump ebb0"
|
jump ebb0"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -267,13 +342,10 @@ mod tests {
|
||||||
ebb0:
|
ebb0:
|
||||||
v0 = iconst.i8 0
|
v0 = iconst.i8 0
|
||||||
v1 = uextend.i32 v0
|
v1 = uextend.i32 v0
|
||||||
v2 = icmp_imm uge v1, 0
|
jump ebb3
|
||||||
brnz v2, ebb3
|
|
||||||
jump ebb0
|
|
||||||
|
|
||||||
ebb3:
|
ebb3:
|
||||||
v3 = iadd_imm.i32 v1, 0
|
br_table.i32 v1, ebb0, jt0"
|
||||||
br_table v3, ebb0, jt0"
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -287,8 +359,7 @@ ebb3:
|
||||||
v1 = uextend.i32 v0
|
v1 = uextend.i32 v0
|
||||||
v2 = icmp_imm eq v1, 2
|
v2 = icmp_imm eq v1, 2
|
||||||
brnz v2, ebb2
|
brnz v2, ebb2
|
||||||
v3 = icmp_imm eq v1, 0
|
brz v1, ebb1
|
||||||
brnz v3, ebb1
|
|
||||||
jump ebb0"
|
jump ebb0"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -318,17 +389,14 @@ ebb9:
|
||||||
ebb8:
|
ebb8:
|
||||||
v5 = icmp_imm.i32 eq v1, 5
|
v5 = icmp_imm.i32 eq v1, 5
|
||||||
brnz v5, ebb3
|
brnz v5, ebb3
|
||||||
v6 = icmp_imm.i32 uge v1, 0
|
jump ebb11
|
||||||
brnz v6, ebb11
|
|
||||||
jump ebb0
|
|
||||||
|
|
||||||
ebb11:
|
ebb11:
|
||||||
v7 = iadd_imm.i32 v1, 0
|
br_table.i32 v1, ebb0, jt0
|
||||||
br_table v7, ebb0, jt0
|
|
||||||
|
|
||||||
ebb10:
|
ebb10:
|
||||||
v8 = iadd_imm.i32 v1, -10
|
v6 = iadd_imm.i32 v1, -10
|
||||||
br_table v8, ebb0, jt1"
|
br_table v6, ebb0, jt1"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -363,4 +431,23 @@ ebb10:
|
||||||
jump ebb0"
|
jump ebb0"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn switch_optimal_codegen() {
|
||||||
|
let func = setup!(0, [-1i64 as u64, 0, 1,]);
|
||||||
|
assert_eq!(
|
||||||
|
func,
|
||||||
|
" jt0 = jump_table [ebb2, ebb3]
|
||||||
|
|
||||||
|
ebb0:
|
||||||
|
v0 = iconst.i8 0
|
||||||
|
v1 = uextend.i32 v0
|
||||||
|
v2 = icmp_imm eq v1, -1
|
||||||
|
brnz v2, ebb1
|
||||||
|
jump ebb4
|
||||||
|
|
||||||
|
ebb4:
|
||||||
|
br_table.i32 v1, ebb0, jt0"
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
{"files":{"Cargo.toml":"ed12a641047878536a2be05241a6a59b30e029584168d15fe8dff9ef4e226cf7","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"87679cdb53e8cbec3b1aa45afb2124727c1c059f8bd10363d27daf318a9f9a36","src/code_translator.rs":"00740be2943fe96d8588d15ec3b812b997f41e4bc9cd27510173889172aff8bc","src/environ/dummy.rs":"42df6db37892ea28e9a004934599d8bbcbd62db52f787486cd81a23f1a563613","src/environ/mod.rs":"617c147485038dfd797ab0ea71b4cfa9574d95d5d5b1ca362c6b7b6a462cf577","src/environ/spec.rs":"1c22dfbf956d80cbf34a6b8087dfb38b1f73a5cf010c341b673dba4286468bfe","src/func_translator.rs":"b27debdc0d17f30ecfa7a9bf4bdeea6054966507b5d398ccd4165574da4f674a","src/lib.rs":"95183fc86a20687e547d2edbd9868681005f0c3a2ca1ae1471e2ae38098f85c6","src/module_translator.rs":"ac54c24aaa3775f72ccd16d1781be648bb0e83ea83909f933d07e86ef1879213","src/sections_translator.rs":"499f6d1ca8a4151dab891d14bb901c292adea13b1daccdd6e2b104fb9f5a49a7","src/state.rs":"1b1fa08736702d062c49118fba67f0a13752b4d863c1d11abd90eeb219777a23","src/translation_utils.rs":"50b45794018e1c471694f4f60707329213c9fb4153798a879953a479213b8a56","tests/wasm_testsuite.rs":"c6eac90ebdb6b58d8247c22e04454d95943c5ab0621084b624eb20c0ce2a96a3"},"package":"e75efb45cd8d8700b4bdc225f0077bc7c615f84a5807ce001d59b4da48d85573"}
|
{"files":{"Cargo.toml":"9827446df24b295abe90539e7ccfda7c54955f1cb44e4d49c3a4e5a66bfa5fae","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"87679cdb53e8cbec3b1aa45afb2124727c1c059f8bd10363d27daf318a9f9a36","src/code_translator.rs":"96fc0bf7b2c2f0de0596724bfe72d7fbcf5db1b676721fe024f5555ddbcbb7b6","src/environ/dummy.rs":"42df6db37892ea28e9a004934599d8bbcbd62db52f787486cd81a23f1a563613","src/environ/mod.rs":"617c147485038dfd797ab0ea71b4cfa9574d95d5d5b1ca362c6b7b6a462cf577","src/environ/spec.rs":"1c22dfbf956d80cbf34a6b8087dfb38b1f73a5cf010c341b673dba4286468bfe","src/func_translator.rs":"b27debdc0d17f30ecfa7a9bf4bdeea6054966507b5d398ccd4165574da4f674a","src/lib.rs":"95183fc86a20687e547d2edbd9868681005f0c3a2ca1ae1471e2ae38098f85c6","src/module_translator.rs":"ac54c24aaa3775f72ccd16d1781be648bb0e83ea83909f933d07e86ef1879213","src/sections_translator.rs":"55290a6b5d2a71719404d4d5f08a389dbf37c053264d17f3b292a57d1bdd5b62","src/state.rs":"1b1fa08736702d062c49118fba67f0a13752b4d863c1d11abd90eeb219777a23","src/translation_utils.rs":"50b45794018e1c471694f4f60707329213c9fb4153798a879953a479213b8a56","tests/wasm_testsuite.rs":"c6eac90ebdb6b58d8247c22e04454d95943c5ab0621084b624eb20c0ce2a96a3"},"package":null}
|
||||||
83
third_party/rust/cranelift-wasm/Cargo.toml
vendored
83
third_party/rust/cranelift-wasm/Cargo.toml
vendored
|
|
@ -1,74 +1,35 @@
|
||||||
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
|
|
||||||
#
|
|
||||||
# When uploading crates to the registry Cargo will automatically
|
|
||||||
# "normalize" Cargo.toml files for maximal compatibility
|
|
||||||
# with all versions of Cargo and also rewrite `path` dependencies
|
|
||||||
# to registry (e.g. crates.io) dependencies
|
|
||||||
#
|
|
||||||
# If you believe there's an error in this file please file an
|
|
||||||
# issue against the rust-lang/cargo repository. If you're
|
|
||||||
# editing this file be aware that the upstream Cargo.toml
|
|
||||||
# will likely look very different (and much more reasonable)
|
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
edition = "2018"
|
|
||||||
name = "cranelift-wasm"
|
name = "cranelift-wasm"
|
||||||
version = "0.29.0"
|
version = "0.30.0"
|
||||||
authors = ["The Cranelift Project Developers"]
|
authors = ["The Cranelift Project Developers"]
|
||||||
description = "Translator from WebAssembly to Cranelift IR"
|
description = "Translator from WebAssembly to Cranelift IR"
|
||||||
|
repository = "https://github.com/CraneStation/cranelift"
|
||||||
|
license = "Apache-2.0 WITH LLVM-exception"
|
||||||
|
categories = ["no-std", "wasm"]
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
keywords = ["webassembly", "wasm"]
|
keywords = ["webassembly", "wasm"]
|
||||||
categories = ["no-std", "wasm"]
|
edition = "2018"
|
||||||
license = "Apache-2.0 WITH LLVM-exception"
|
|
||||||
repository = "https://github.com/CraneStation/cranelift"
|
|
||||||
[dependencies.cast]
|
|
||||||
version = "0.2.2"
|
|
||||||
default-features = false
|
|
||||||
|
|
||||||
[dependencies.cranelift-codegen]
|
[dependencies]
|
||||||
version = "0.29.0"
|
wasmparser = { version = "0.29.2", default-features = false }
|
||||||
default-features = false
|
cranelift-codegen = { path = "../cranelift-codegen", version = "0.30.0", default-features = false }
|
||||||
|
cranelift-entity = { path = "../cranelift-entity", version = "0.30.0", default-features = false }
|
||||||
|
cranelift-frontend = { path = "../cranelift-frontend", version = "0.30.0", default-features = false }
|
||||||
|
hashmap_core = { version = "0.1.9", optional = true }
|
||||||
|
failure = { version = "0.1.1", default-features = false, features = ["derive"] }
|
||||||
|
failure_derive = { version = "0.1.1", default-features = false }
|
||||||
|
log = { version = "0.4.6", default-features = false }
|
||||||
|
cast = { version = "0.2.2", default-features = false }
|
||||||
|
|
||||||
[dependencies.cranelift-entity]
|
[dev-dependencies]
|
||||||
version = "0.29.0"
|
wabt = "0.7.0"
|
||||||
default-features = false
|
target-lexicon = "0.4.0"
|
||||||
|
|
||||||
[dependencies.cranelift-frontend]
|
|
||||||
version = "0.29.0"
|
|
||||||
default-features = false
|
|
||||||
|
|
||||||
[dependencies.failure]
|
|
||||||
version = "0.1.1"
|
|
||||||
features = ["derive"]
|
|
||||||
default-features = false
|
|
||||||
|
|
||||||
[dependencies.failure_derive]
|
|
||||||
version = "0.1.1"
|
|
||||||
default-features = false
|
|
||||||
|
|
||||||
[dependencies.hashmap_core]
|
|
||||||
version = "0.1.9"
|
|
||||||
optional = true
|
|
||||||
|
|
||||||
[dependencies.log]
|
|
||||||
version = "0.4.6"
|
|
||||||
default-features = false
|
|
||||||
|
|
||||||
[dependencies.wasmparser]
|
|
||||||
version = "0.23.0"
|
|
||||||
default-features = false
|
|
||||||
[dev-dependencies.target-lexicon]
|
|
||||||
version = "0.2.0"
|
|
||||||
|
|
||||||
[dev-dependencies.wabt]
|
|
||||||
version = "0.7.0"
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
core = ["hashmap_core", "cranelift-codegen/core", "cranelift-frontend/core", "wasmparser/core"]
|
|
||||||
default = ["std"]
|
default = ["std"]
|
||||||
std = ["cranelift-codegen/std", "cranelift-frontend/std", "wasmparser/std"]
|
std = ["cranelift-codegen/std", "cranelift-frontend/std", "wasmparser/std"]
|
||||||
[badges.maintenance]
|
core = ["hashmap_core", "cranelift-codegen/core", "cranelift-frontend/core", "wasmparser/core"]
|
||||||
status = "experimental"
|
|
||||||
|
|
||||||
[badges.travis-ci]
|
[badges]
|
||||||
repository = "CraneStation/cranelift"
|
maintenance = { status = "experimental" }
|
||||||
|
travis-ci = { repository = "CraneStation/cranelift" }
|
||||||
|
|
|
||||||
|
|
@ -886,6 +886,161 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
|
||||||
Operator::RefNull | Operator::RefIsNull { .. } => {
|
Operator::RefNull | Operator::RefIsNull { .. } => {
|
||||||
return Err(WasmError::Unsupported("proposed reference-type operators"));
|
return Err(WasmError::Unsupported("proposed reference-type operators"));
|
||||||
}
|
}
|
||||||
|
Operator::MemoryInit { .. }
|
||||||
|
| Operator::DataDrop { .. }
|
||||||
|
| Operator::MemoryCopy
|
||||||
|
| Operator::MemoryFill
|
||||||
|
| Operator::TableInit { .. }
|
||||||
|
| Operator::ElemDrop { .. }
|
||||||
|
| Operator::TableCopy
|
||||||
|
| Operator::TableGet { .. }
|
||||||
|
| Operator::TableSet { .. }
|
||||||
|
| Operator::TableGrow { .. }
|
||||||
|
| Operator::TableSize { .. } => {
|
||||||
|
return Err(WasmError::Unsupported("proposed bulk memory operators"));
|
||||||
|
}
|
||||||
|
Operator::V128Load { .. }
|
||||||
|
| Operator::V128Store { .. }
|
||||||
|
| Operator::V128Const { .. }
|
||||||
|
| Operator::V8x16Shuffle { .. }
|
||||||
|
| Operator::I8x16Splat
|
||||||
|
| Operator::I8x16ExtractLaneS { .. }
|
||||||
|
| Operator::I8x16ExtractLaneU { .. }
|
||||||
|
| Operator::I8x16ReplaceLane { .. }
|
||||||
|
| Operator::I16x8Splat
|
||||||
|
| Operator::I16x8ExtractLaneS { .. }
|
||||||
|
| Operator::I16x8ExtractLaneU { .. }
|
||||||
|
| Operator::I16x8ReplaceLane { .. }
|
||||||
|
| Operator::I32x4Splat
|
||||||
|
| Operator::I32x4ExtractLane { .. }
|
||||||
|
| Operator::I32x4ReplaceLane { .. }
|
||||||
|
| Operator::I64x2Splat
|
||||||
|
| Operator::I64x2ExtractLane { .. }
|
||||||
|
| Operator::I64x2ReplaceLane { .. }
|
||||||
|
| Operator::F32x4Splat
|
||||||
|
| Operator::F32x4ExtractLane { .. }
|
||||||
|
| Operator::F32x4ReplaceLane { .. }
|
||||||
|
| Operator::F64x2Splat
|
||||||
|
| Operator::F64x2ExtractLane { .. }
|
||||||
|
| Operator::F64x2ReplaceLane { .. }
|
||||||
|
| Operator::I8x16Eq
|
||||||
|
| Operator::I8x16Ne
|
||||||
|
| Operator::I8x16LtS
|
||||||
|
| Operator::I8x16LtU
|
||||||
|
| Operator::I8x16GtS
|
||||||
|
| Operator::I8x16GtU
|
||||||
|
| Operator::I8x16LeS
|
||||||
|
| Operator::I8x16LeU
|
||||||
|
| Operator::I8x16GeS
|
||||||
|
| Operator::I8x16GeU
|
||||||
|
| Operator::I16x8Eq
|
||||||
|
| Operator::I16x8Ne
|
||||||
|
| Operator::I16x8LtS
|
||||||
|
| Operator::I16x8LtU
|
||||||
|
| Operator::I16x8GtS
|
||||||
|
| Operator::I16x8GtU
|
||||||
|
| Operator::I16x8LeS
|
||||||
|
| Operator::I16x8LeU
|
||||||
|
| Operator::I16x8GeS
|
||||||
|
| Operator::I16x8GeU
|
||||||
|
| Operator::I32x4Eq
|
||||||
|
| Operator::I32x4Ne
|
||||||
|
| Operator::I32x4LtS
|
||||||
|
| Operator::I32x4LtU
|
||||||
|
| Operator::I32x4GtS
|
||||||
|
| Operator::I32x4GtU
|
||||||
|
| Operator::I32x4LeS
|
||||||
|
| Operator::I32x4LeU
|
||||||
|
| Operator::I32x4GeS
|
||||||
|
| Operator::I32x4GeU
|
||||||
|
| Operator::F32x4Eq
|
||||||
|
| Operator::F32x4Ne
|
||||||
|
| Operator::F32x4Lt
|
||||||
|
| Operator::F32x4Gt
|
||||||
|
| Operator::F32x4Le
|
||||||
|
| Operator::F32x4Ge
|
||||||
|
| Operator::F64x2Eq
|
||||||
|
| Operator::F64x2Ne
|
||||||
|
| Operator::F64x2Lt
|
||||||
|
| Operator::F64x2Gt
|
||||||
|
| Operator::F64x2Le
|
||||||
|
| Operator::F64x2Ge
|
||||||
|
| Operator::V128Not
|
||||||
|
| Operator::V128And
|
||||||
|
| Operator::V128Or
|
||||||
|
| Operator::V128Xor
|
||||||
|
| Operator::V128Bitselect
|
||||||
|
| Operator::I8x16Neg
|
||||||
|
| Operator::I8x16AnyTrue
|
||||||
|
| Operator::I8x16AllTrue
|
||||||
|
| Operator::I8x16Shl
|
||||||
|
| Operator::I8x16ShrS
|
||||||
|
| Operator::I8x16ShrU
|
||||||
|
| Operator::I8x16Add
|
||||||
|
| Operator::I8x16AddSaturateS
|
||||||
|
| Operator::I8x16AddSaturateU
|
||||||
|
| Operator::I8x16Sub
|
||||||
|
| Operator::I8x16SubSaturateS
|
||||||
|
| Operator::I8x16SubSaturateU
|
||||||
|
| Operator::I8x16Mul
|
||||||
|
| Operator::I16x8Neg
|
||||||
|
| Operator::I16x8AnyTrue
|
||||||
|
| Operator::I16x8AllTrue
|
||||||
|
| Operator::I16x8Shl
|
||||||
|
| Operator::I16x8ShrS
|
||||||
|
| Operator::I16x8ShrU
|
||||||
|
| Operator::I16x8Add
|
||||||
|
| Operator::I16x8AddSaturateS
|
||||||
|
| Operator::I16x8AddSaturateU
|
||||||
|
| Operator::I16x8Sub
|
||||||
|
| Operator::I16x8SubSaturateS
|
||||||
|
| Operator::I16x8SubSaturateU
|
||||||
|
| Operator::I16x8Mul
|
||||||
|
| Operator::I32x4Neg
|
||||||
|
| Operator::I32x4AnyTrue
|
||||||
|
| Operator::I32x4AllTrue
|
||||||
|
| Operator::I32x4Shl
|
||||||
|
| Operator::I32x4ShrS
|
||||||
|
| Operator::I32x4ShrU
|
||||||
|
| Operator::I32x4Add
|
||||||
|
| Operator::I32x4Sub
|
||||||
|
| Operator::I32x4Mul
|
||||||
|
| Operator::I64x2Neg
|
||||||
|
| Operator::I64x2AnyTrue
|
||||||
|
| Operator::I64x2AllTrue
|
||||||
|
| Operator::I64x2Shl
|
||||||
|
| Operator::I64x2ShrS
|
||||||
|
| Operator::I64x2ShrU
|
||||||
|
| Operator::I64x2Add
|
||||||
|
| Operator::I64x2Sub
|
||||||
|
| Operator::F32x4Abs
|
||||||
|
| Operator::F32x4Neg
|
||||||
|
| Operator::F32x4Sqrt
|
||||||
|
| Operator::F32x4Add
|
||||||
|
| Operator::F32x4Sub
|
||||||
|
| Operator::F32x4Mul
|
||||||
|
| Operator::F32x4Div
|
||||||
|
| Operator::F32x4Min
|
||||||
|
| Operator::F32x4Max
|
||||||
|
| Operator::F64x2Abs
|
||||||
|
| Operator::F64x2Neg
|
||||||
|
| Operator::F64x2Sqrt
|
||||||
|
| Operator::F64x2Add
|
||||||
|
| Operator::F64x2Sub
|
||||||
|
| Operator::F64x2Mul
|
||||||
|
| Operator::F64x2Div
|
||||||
|
| Operator::F64x2Min
|
||||||
|
| Operator::F64x2Max
|
||||||
|
| Operator::I32x4TruncSF32x4Sat
|
||||||
|
| Operator::I32x4TruncUF32x4Sat
|
||||||
|
| Operator::I64x2TruncSF64x2Sat
|
||||||
|
| Operator::I64x2TruncUF64x2Sat
|
||||||
|
| Operator::F32x4ConvertSI32x4
|
||||||
|
| Operator::F32x4ConvertUI32x4
|
||||||
|
| Operator::F64x2ConvertSI64x2
|
||||||
|
| Operator::F64x2ConvertUI64x2 => {
|
||||||
|
return Err(WasmError::Unsupported("proposed SIMD operators"));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,15 +12,15 @@ use crate::translation_utils::{
|
||||||
type_to_type, FuncIndex, Global, GlobalIndex, GlobalInit, Memory, MemoryIndex, SignatureIndex,
|
type_to_type, FuncIndex, Global, GlobalIndex, GlobalInit, Memory, MemoryIndex, SignatureIndex,
|
||||||
Table, TableElementType, TableIndex,
|
Table, TableElementType, TableIndex,
|
||||||
};
|
};
|
||||||
use core::str::from_utf8;
|
|
||||||
use cranelift_codegen::ir::{self, AbiParam, Signature};
|
use cranelift_codegen::ir::{self, AbiParam, Signature};
|
||||||
use cranelift_entity::EntityRef;
|
use cranelift_entity::EntityRef;
|
||||||
use std::vec::Vec;
|
use std::vec::Vec;
|
||||||
use wasmparser::{
|
use wasmparser::{
|
||||||
self, CodeSectionReader, Data, DataSectionReader, Element, ElementSectionReader, Export,
|
self, CodeSectionReader, Data, DataKind, DataSectionReader, Element, ElementKind,
|
||||||
ExportSectionReader, ExternalKind, FuncType, FunctionSectionReader, GlobalSectionReader,
|
ElementSectionReader, Export, ExportSectionReader, ExternalKind, FuncType,
|
||||||
GlobalType, ImportSectionEntryType, ImportSectionReader, MemorySectionReader, MemoryType,
|
FunctionSectionReader, GlobalSectionReader, GlobalType, ImportSectionEntryType,
|
||||||
Operator, TableSectionReader, TypeSectionReader,
|
ImportSectionReader, MemorySectionReader, MemoryType, Operator, TableSectionReader,
|
||||||
|
TypeSectionReader,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Parses the Type section of the wasm module.
|
/// Parses the Type section of the wasm module.
|
||||||
|
|
@ -65,12 +65,8 @@ pub fn parse_import_section<'data>(
|
||||||
|
|
||||||
for entry in imports {
|
for entry in imports {
|
||||||
let import = entry?;
|
let import = entry?;
|
||||||
|
let module_name = import.module;
|
||||||
// The input has already been validated, so we should be able to
|
let field_name = import.field;
|
||||||
// assume valid UTF-8 and use `from_utf8_unchecked` if performance
|
|
||||||
// becomes a concern here.
|
|
||||||
let module_name = from_utf8(import.module).unwrap();
|
|
||||||
let field_name = from_utf8(import.field).unwrap();
|
|
||||||
|
|
||||||
match import.ty {
|
match import.ty {
|
||||||
ImportSectionEntryType::Function(sig) => {
|
ImportSectionEntryType::Function(sig) => {
|
||||||
|
|
@ -232,13 +228,12 @@ pub fn parse_export_section<'data>(
|
||||||
// The input has already been validated, so we should be able to
|
// The input has already been validated, so we should be able to
|
||||||
// assume valid UTF-8 and use `from_utf8_unchecked` if performance
|
// assume valid UTF-8 and use `from_utf8_unchecked` if performance
|
||||||
// becomes a concern here.
|
// becomes a concern here.
|
||||||
let name = from_utf8(field).unwrap();
|
|
||||||
let index = index as usize;
|
let index = index as usize;
|
||||||
match *kind {
|
match *kind {
|
||||||
ExternalKind::Function => environ.declare_func_export(FuncIndex::new(index), name),
|
ExternalKind::Function => environ.declare_func_export(FuncIndex::new(index), field),
|
||||||
ExternalKind::Table => environ.declare_table_export(TableIndex::new(index), name),
|
ExternalKind::Table => environ.declare_table_export(TableIndex::new(index), field),
|
||||||
ExternalKind::Memory => environ.declare_memory_export(MemoryIndex::new(index), name),
|
ExternalKind::Memory => environ.declare_memory_export(MemoryIndex::new(index), field),
|
||||||
ExternalKind::Global => environ.declare_global_export(GlobalIndex::new(index), name),
|
ExternalKind::Global => environ.declare_global_export(GlobalIndex::new(index), field),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -260,15 +255,18 @@ pub fn parse_element_section<'data>(
|
||||||
environ.reserve_table_elements(elements.get_count());
|
environ.reserve_table_elements(elements.get_count());
|
||||||
|
|
||||||
for entry in elements {
|
for entry in elements {
|
||||||
let Element {
|
let Element { kind, items } = entry?;
|
||||||
|
if let ElementKind::Active {
|
||||||
table_index,
|
table_index,
|
||||||
init_expr,
|
init_expr,
|
||||||
items,
|
} = kind
|
||||||
} = entry?;
|
{
|
||||||
let mut init_expr_reader = init_expr.get_binary_reader();
|
let mut init_expr_reader = init_expr.get_binary_reader();
|
||||||
let (base, offset) = match init_expr_reader.read_operator()? {
|
let (base, offset) = match init_expr_reader.read_operator()? {
|
||||||
Operator::I32Const { value } => (None, value as u32 as usize),
|
Operator::I32Const { value } => (None, value as u32 as usize),
|
||||||
Operator::GetGlobal { global_index } => (Some(GlobalIndex::from_u32(global_index)), 0),
|
Operator::GetGlobal { global_index } => {
|
||||||
|
(Some(GlobalIndex::from_u32(global_index)), 0)
|
||||||
|
}
|
||||||
ref s => panic!("unsupported init expr in element section: {:?}", s),
|
ref s => panic!("unsupported init expr in element section: {:?}", s),
|
||||||
};
|
};
|
||||||
let items_reader = items.get_items_reader()?;
|
let items_reader = items.get_items_reader()?;
|
||||||
|
|
@ -283,6 +281,9 @@ pub fn parse_element_section<'data>(
|
||||||
offset,
|
offset,
|
||||||
elems.into_boxed_slice(),
|
elems.into_boxed_slice(),
|
||||||
)
|
)
|
||||||
|
} else {
|
||||||
|
panic!("unsupported passive elements section");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
@ -309,15 +310,18 @@ pub fn parse_data_section<'data>(
|
||||||
environ.reserve_data_initializers(data.get_count());
|
environ.reserve_data_initializers(data.get_count());
|
||||||
|
|
||||||
for entry in data {
|
for entry in data {
|
||||||
let Data {
|
let Data { kind, data } = entry?;
|
||||||
|
if let DataKind::Active {
|
||||||
memory_index,
|
memory_index,
|
||||||
init_expr,
|
init_expr,
|
||||||
data,
|
} = kind
|
||||||
} = entry?;
|
{
|
||||||
let mut init_expr_reader = init_expr.get_binary_reader();
|
let mut init_expr_reader = init_expr.get_binary_reader();
|
||||||
let (base, offset) = match init_expr_reader.read_operator()? {
|
let (base, offset) = match init_expr_reader.read_operator()? {
|
||||||
Operator::I32Const { value } => (None, value as u32 as usize),
|
Operator::I32Const { value } => (None, value as u32 as usize),
|
||||||
Operator::GetGlobal { global_index } => (Some(GlobalIndex::from_u32(global_index)), 0),
|
Operator::GetGlobal { global_index } => {
|
||||||
|
(Some(GlobalIndex::from_u32(global_index)), 0)
|
||||||
|
}
|
||||||
ref s => panic!("unsupported init expr in data section: {:?}", s),
|
ref s => panic!("unsupported init expr in data section: {:?}", s),
|
||||||
};
|
};
|
||||||
environ.declare_data_initialization(
|
environ.declare_data_initialization(
|
||||||
|
|
@ -326,6 +330,9 @@ pub fn parse_data_section<'data>(
|
||||||
offset,
|
offset,
|
||||||
data,
|
data,
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
panic!("unsupported passive data section");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
{"files":{".rustfmt.toml":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".travis.yml":"e7a5518637394467f13cb084fa7fa75783007815b17ba22d4dee567965d418bb","Cargo.toml":"5dbb0ad2824e20f91e80cc7b3ab2f9f241e8dbeb214c821e65a9add3b3f49045","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"89f73d9404c960632bef4cfde9709862dbb510081180318e0be7bf12d18e9da7","build.rs":"c349b503b884c79aef182ba27eeffa51ca439a511d8c6adefa2ed56f80a4530c","examples/misc.rs":"2e7f27fc7b7479b9cf96bdf81b402a6ef4bec71f8ef6f4f39588745b85cb2d3d","src/host.rs":"c4a0aa3364662eb2c585a69c8872d3e380f1b8537b51def6ca582b301993ce0a","src/lib.rs":"72a94fcc6b7f5dd6692cda84974b3ffb50b6c5eb9e2ebed91c6635d102202ced","src/parse_error.rs":"38c0cb21171741faa1c69c931be6a97be658b01de07bcb69aae84e5319b03920","src/targets.rs":"4f6585736061118e61c857908b8f7c539a48641c7233f7cfc856e9c94e4ffa34","src/triple.rs":"d3cdd3be7b18f04511ae59c6156983e4300bc57a3671282c74b2c7e81e699d75"},"package":null}
|
{"files":{"Cargo.toml":"615784e9f863ec4eeb00066ba899ab2fd8cf6619abcc35411f47ed29745b88ad","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"89f73d9404c960632bef4cfde9709862dbb510081180318e0be7bf12d18e9da7","build.rs":"800c0d76136d72e2894a7a3eb603ce02fc4da5d96c46b970edf6f909b999741e","examples/misc.rs":"49a579845450b7b020ed5c97dca142fc548725893cbc82f6f750ee0caab2beca","src/host.rs":"fb543df4f362e9119a58523563e453110f4e3a426f0995911d0ca386657cf1d9","src/lib.rs":"69b1b9e21c0b6e447fd53991a60e7ab20f814c2ab5faa7870e3423bf588c658f","src/parse_error.rs":"9f6897c0f0b5b666ce5e7ff1f3e3001964397d3e5f933884036b14f52b612363","src/targets.rs":"ebd909b42ad8fcec6486170076f3b6454365377b2e23dbed56cf007c761ff490","src/triple.rs":"aba17839dd6895927d3d75fd5b83698df8be6d3ea64d7c0235c62acf12645a33"},"package":"1b0ab4982b8945c35cc1c46a83a9094c414f6828a099ce5dcaa8ee2b04642dcb"}
|
||||||
31
third_party/rust/target-lexicon/.travis.yml
vendored
31
third_party/rust/target-lexicon/.travis.yml
vendored
|
|
@ -1,31 +0,0 @@
|
||||||
language: rust
|
|
||||||
rust:
|
|
||||||
- stable
|
|
||||||
- beta
|
|
||||||
- nightly
|
|
||||||
matrix:
|
|
||||||
allow_failures:
|
|
||||||
- rust: beta
|
|
||||||
- rust: nightly
|
|
||||||
dist: trusty
|
|
||||||
sudo: false
|
|
||||||
before_script:
|
|
||||||
# If an old version of rustfmt from cargo is already installed, uninstall
|
|
||||||
# it, since it can prevent the installation of the new version from rustup.
|
|
||||||
- cargo uninstall rustfmt || true
|
|
||||||
- cargo install --list
|
|
||||||
# If we're testing beta or nightly, we still need to install the stable
|
|
||||||
# toolchain so that we can run the stable version of rustfmt.
|
|
||||||
- rustup toolchain install stable
|
|
||||||
# Install the stable version of rustfmt.
|
|
||||||
- rustup component add --toolchain=stable rustfmt-preview
|
|
||||||
- rustup component list --toolchain=stable
|
|
||||||
- rustup show
|
|
||||||
- rustfmt +stable --version || echo fail
|
|
||||||
# Sometimes the component isn't actually ready after being installed, and
|
|
||||||
# rustup update makes it ready.
|
|
||||||
- rustup update
|
|
||||||
- rustfmt +stable --version
|
|
||||||
script: cargo test
|
|
||||||
cache:
|
|
||||||
cargo: true
|
|
||||||
37
third_party/rust/target-lexicon/Cargo.toml
vendored
37
third_party/rust/target-lexicon/Cargo.toml
vendored
|
|
@ -1,6 +1,19 @@
|
||||||
|
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
|
||||||
|
#
|
||||||
|
# When uploading crates to the registry Cargo will automatically
|
||||||
|
# "normalize" Cargo.toml files for maximal compatibility
|
||||||
|
# with all versions of Cargo and also rewrite `path` dependencies
|
||||||
|
# to registry (e.g. crates.io) dependencies
|
||||||
|
#
|
||||||
|
# If you believe there's an error in this file please file an
|
||||||
|
# issue against the rust-lang/cargo repository. If you're
|
||||||
|
# editing this file be aware that the upstream Cargo.toml
|
||||||
|
# will likely look very different (and much more reasonable)
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
|
edition = "2018"
|
||||||
name = "target-lexicon"
|
name = "target-lexicon"
|
||||||
version = "0.2.0"
|
version = "0.4.0"
|
||||||
authors = ["Dan Gohman <sunfish@mozilla.com>"]
|
authors = ["Dan Gohman <sunfish@mozilla.com>"]
|
||||||
description = "Targeting utilities for compilers and related tools"
|
description = "Targeting utilities for compilers and related tools"
|
||||||
documentation = "https://docs.rs/target-lexicon/"
|
documentation = "https://docs.rs/target-lexicon/"
|
||||||
|
|
@ -9,18 +22,22 @@ keywords = ["target", "host", "triple", "compiler", "jit"]
|
||||||
categories = ["no-std"]
|
categories = ["no-std"]
|
||||||
license = "Apache-2.0 WITH LLVM-exception"
|
license = "Apache-2.0 WITH LLVM-exception"
|
||||||
repository = "https://github.com/CraneStation/target-lexicon"
|
repository = "https://github.com/CraneStation/target-lexicon"
|
||||||
|
[dependencies.failure]
|
||||||
|
version = "0.1.3"
|
||||||
|
features = ["derive"]
|
||||||
|
default-features = false
|
||||||
|
|
||||||
[dependencies]
|
[dependencies.failure_derive]
|
||||||
failure = { version = "0.1.3", default-features = false, features = ["derive"] }
|
version = "0.1.3"
|
||||||
failure_derive = { version = "0.1.3", default-features = false }
|
default-features = false
|
||||||
|
[build-dependencies.serde_json]
|
||||||
[build-dependencies]
|
version = "1.0"
|
||||||
serde_json = "1.0"
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["std"]
|
default = ["std"]
|
||||||
std = []
|
std = []
|
||||||
|
[badges.maintenance]
|
||||||
|
status = "passively-maintained"
|
||||||
|
|
||||||
[badges]
|
[badges.travis-ci]
|
||||||
maintenance = { status = "passively-maintained" }
|
repository = "CraneStation/target-lexicon"
|
||||||
travis-ci = { repository = "CraneStation/target-lexicon" }
|
|
||||||
|
|
|
||||||
2
third_party/rust/target-lexicon/build.rs
vendored
2
third_party/rust/target-lexicon/build.rs
vendored
|
|
@ -36,7 +36,7 @@ mod parse_error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
use triple::{Endianness, PointerWidth, Triple};
|
use self::triple::{Endianness, PointerWidth, Triple};
|
||||||
|
|
||||||
/// Assuming `target` is a path to a custom target json config file, open it
|
/// Assuming `target` is a path to a custom target json config file, open it
|
||||||
/// and build a `Triple` using its contents.
|
/// and build a `Triple` using its contents.
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
extern crate target_lexicon;
|
extern crate target_lexicon;
|
||||||
|
|
||||||
use std::str::FromStr;
|
use core::str::FromStr;
|
||||||
use target_lexicon::{Triple, HOST};
|
use target_lexicon::{Triple, HOST};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
|
||||||
2
third_party/rust/target-lexicon/src/host.rs
vendored
2
third_party/rust/target-lexicon/src/host.rs
vendored
|
|
@ -1,4 +1,4 @@
|
||||||
use {Architecture, BinaryFormat, Environment, OperatingSystem, Triple, Vendor};
|
use crate::{Architecture, BinaryFormat, Environment, OperatingSystem, Triple, Vendor};
|
||||||
|
|
||||||
// Include the implementations of the `HOST` object containing information
|
// Include the implementations of the `HOST` object containing information
|
||||||
// about the current host.
|
// about the current host.
|
||||||
|
|
|
||||||
21
third_party/rust/target-lexicon/src/lib.rs
vendored
21
third_party/rust/target-lexicon/src/lib.rs
vendored
|
|
@ -15,29 +15,24 @@
|
||||||
use_self
|
use_self
|
||||||
)
|
)
|
||||||
)]
|
)]
|
||||||
#![cfg_attr(not(feature = "std"), no_std)]
|
#![no_std]
|
||||||
#![cfg_attr(not(feature = "std"), feature(alloc))]
|
#![cfg_attr(not(feature = "std"), feature(alloc))]
|
||||||
|
|
||||||
#[cfg(not(feature = "std"))]
|
#[cfg(not(feature = "std"))]
|
||||||
extern crate alloc;
|
extern crate alloc as std;
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
extern crate std;
|
||||||
|
|
||||||
extern crate failure;
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate failure_derive;
|
extern crate failure_derive;
|
||||||
|
|
||||||
#[cfg(not(feature = "std"))]
|
|
||||||
mod std {
|
|
||||||
pub use alloc::{borrow, string};
|
|
||||||
pub use core::*;
|
|
||||||
}
|
|
||||||
|
|
||||||
mod host;
|
mod host;
|
||||||
mod parse_error;
|
mod parse_error;
|
||||||
mod targets;
|
mod targets;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod triple;
|
mod triple;
|
||||||
|
|
||||||
pub use host::HOST;
|
pub use self::host::HOST;
|
||||||
pub use parse_error::ParseError;
|
pub use self::parse_error::ParseError;
|
||||||
pub use targets::{Architecture, BinaryFormat, Environment, OperatingSystem, Vendor};
|
pub use self::targets::{Architecture, BinaryFormat, Environment, OperatingSystem, Vendor};
|
||||||
pub use triple::{CallingConvention, Endianness, PointerWidth, Triple};
|
pub use self::triple::{CallingConvention, Endianness, PointerWidth, Triple};
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,4 @@ pub enum ParseError {
|
||||||
UnrecognizedBinaryFormat(String),
|
UnrecognizedBinaryFormat(String),
|
||||||
#[fail(display = "Unrecognized field: {}", _0)]
|
#[fail(display = "Unrecognized field: {}", _0)]
|
||||||
UnrecognizedField(String),
|
UnrecognizedField(String),
|
||||||
#[fail(display = "\"none\" requires an explicit binary format")]
|
|
||||||
NoneWithoutBinaryFormat,
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
172
third_party/rust/target-lexicon/src/targets.rs
vendored
172
third_party/rust/target-lexicon/src/targets.rs
vendored
|
|
@ -1,8 +1,8 @@
|
||||||
// This file defines all the identifier enums and target-aware logic.
|
// This file defines all the identifier enums and target-aware logic.
|
||||||
|
|
||||||
use std::fmt;
|
use crate::triple::{Endianness, PointerWidth, Triple};
|
||||||
use std::str::FromStr;
|
use core::fmt;
|
||||||
use triple::{Endianness, PointerWidth, Triple};
|
use core::str::FromStr;
|
||||||
|
|
||||||
/// The "architecture" field, which in some cases also specifies a specific
|
/// The "architecture" field, which in some cases also specifies a specific
|
||||||
/// subarchitecture.
|
/// subarchitecture.
|
||||||
|
|
@ -12,9 +12,12 @@ pub enum Architecture {
|
||||||
Unknown,
|
Unknown,
|
||||||
Aarch64,
|
Aarch64,
|
||||||
Arm,
|
Arm,
|
||||||
|
Armebv7r,
|
||||||
Armv4t,
|
Armv4t,
|
||||||
Armv5te,
|
Armv5te,
|
||||||
|
Armv6,
|
||||||
Armv7,
|
Armv7,
|
||||||
|
Armv7r,
|
||||||
Armv7s,
|
Armv7s,
|
||||||
Asmjs,
|
Asmjs,
|
||||||
I386,
|
I386,
|
||||||
|
|
@ -29,15 +32,20 @@ pub enum Architecture {
|
||||||
Powerpc64,
|
Powerpc64,
|
||||||
Powerpc64le,
|
Powerpc64le,
|
||||||
Riscv32,
|
Riscv32,
|
||||||
|
Riscv32imac,
|
||||||
|
Riscv32imc,
|
||||||
Riscv64,
|
Riscv64,
|
||||||
S390x,
|
S390x,
|
||||||
Sparc,
|
Sparc,
|
||||||
Sparc64,
|
Sparc64,
|
||||||
Sparcv9,
|
Sparcv9,
|
||||||
Thumbv6m,
|
Thumbv6m,
|
||||||
|
Thumbv7a,
|
||||||
Thumbv7em,
|
Thumbv7em,
|
||||||
Thumbv7m,
|
Thumbv7m,
|
||||||
Thumbv7neon,
|
Thumbv7neon,
|
||||||
|
Thumbv8mBase,
|
||||||
|
Thumbv8mMain,
|
||||||
Wasm32,
|
Wasm32,
|
||||||
X86_64,
|
X86_64,
|
||||||
}
|
}
|
||||||
|
|
@ -50,6 +58,7 @@ pub enum Vendor {
|
||||||
Unknown,
|
Unknown,
|
||||||
Apple,
|
Apple,
|
||||||
Experimental,
|
Experimental,
|
||||||
|
Fortanix,
|
||||||
Pc,
|
Pc,
|
||||||
Rumprun,
|
Rumprun,
|
||||||
Sun,
|
Sun,
|
||||||
|
|
@ -69,14 +78,17 @@ pub enum OperatingSystem {
|
||||||
Freebsd,
|
Freebsd,
|
||||||
Fuchsia,
|
Fuchsia,
|
||||||
Haiku,
|
Haiku,
|
||||||
|
Hermit,
|
||||||
Ios,
|
Ios,
|
||||||
L4re,
|
L4re,
|
||||||
Linux,
|
Linux,
|
||||||
Nebulet,
|
Nebulet,
|
||||||
Netbsd,
|
Netbsd,
|
||||||
|
None_,
|
||||||
Openbsd,
|
Openbsd,
|
||||||
Redox,
|
Redox,
|
||||||
Solaris,
|
Solaris,
|
||||||
|
Uefi,
|
||||||
Windows,
|
Windows,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -102,6 +114,7 @@ pub enum Environment {
|
||||||
Musleabihf,
|
Musleabihf,
|
||||||
Msvc,
|
Msvc,
|
||||||
Uclibc,
|
Uclibc,
|
||||||
|
Sgx,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The "binary format" field, which is usually omitted, and the binary format
|
/// The "binary format" field, which is usually omitted, and the binary format
|
||||||
|
|
@ -125,7 +138,9 @@ impl Architecture {
|
||||||
| Architecture::Arm
|
| Architecture::Arm
|
||||||
| Architecture::Armv4t
|
| Architecture::Armv4t
|
||||||
| Architecture::Armv5te
|
| Architecture::Armv5te
|
||||||
|
| Architecture::Armv6
|
||||||
| Architecture::Armv7
|
| Architecture::Armv7
|
||||||
|
| Architecture::Armv7r
|
||||||
| Architecture::Armv7s
|
| Architecture::Armv7s
|
||||||
| Architecture::Asmjs
|
| Architecture::Asmjs
|
||||||
| Architecture::I386
|
| Architecture::I386
|
||||||
|
|
@ -136,14 +151,20 @@ impl Architecture {
|
||||||
| Architecture::Msp430
|
| Architecture::Msp430
|
||||||
| Architecture::Powerpc64le
|
| Architecture::Powerpc64le
|
||||||
| Architecture::Riscv32
|
| Architecture::Riscv32
|
||||||
|
| Architecture::Riscv32imac
|
||||||
|
| Architecture::Riscv32imc
|
||||||
| Architecture::Riscv64
|
| Architecture::Riscv64
|
||||||
| Architecture::Thumbv6m
|
| Architecture::Thumbv6m
|
||||||
|
| Architecture::Thumbv7a
|
||||||
| Architecture::Thumbv7em
|
| Architecture::Thumbv7em
|
||||||
| Architecture::Thumbv7m
|
| Architecture::Thumbv7m
|
||||||
| Architecture::Thumbv7neon
|
| Architecture::Thumbv7neon
|
||||||
|
| Architecture::Thumbv8mBase
|
||||||
|
| Architecture::Thumbv8mMain
|
||||||
| Architecture::Wasm32
|
| Architecture::Wasm32
|
||||||
| Architecture::X86_64 => Ok(Endianness::Little),
|
| Architecture::X86_64 => Ok(Endianness::Little),
|
||||||
Architecture::Mips
|
Architecture::Armebv7r
|
||||||
|
| Architecture::Mips
|
||||||
| Architecture::Mips64
|
| Architecture::Mips64
|
||||||
| Architecture::Powerpc
|
| Architecture::Powerpc
|
||||||
| Architecture::Powerpc64
|
| Architecture::Powerpc64
|
||||||
|
|
@ -160,9 +181,12 @@ impl Architecture {
|
||||||
Architecture::Unknown => Err(()),
|
Architecture::Unknown => Err(()),
|
||||||
Architecture::Msp430 => Ok(PointerWidth::U16),
|
Architecture::Msp430 => Ok(PointerWidth::U16),
|
||||||
Architecture::Arm
|
Architecture::Arm
|
||||||
|
| Architecture::Armebv7r
|
||||||
| Architecture::Armv4t
|
| Architecture::Armv4t
|
||||||
| Architecture::Armv5te
|
| Architecture::Armv5te
|
||||||
|
| Architecture::Armv6
|
||||||
| Architecture::Armv7
|
| Architecture::Armv7
|
||||||
|
| Architecture::Armv7r
|
||||||
| Architecture::Armv7s
|
| Architecture::Armv7s
|
||||||
| Architecture::Asmjs
|
| Architecture::Asmjs
|
||||||
| Architecture::I386
|
| Architecture::I386
|
||||||
|
|
@ -170,11 +194,16 @@ impl Architecture {
|
||||||
| Architecture::I686
|
| Architecture::I686
|
||||||
| Architecture::Mipsel
|
| Architecture::Mipsel
|
||||||
| Architecture::Riscv32
|
| Architecture::Riscv32
|
||||||
|
| Architecture::Riscv32imac
|
||||||
|
| Architecture::Riscv32imc
|
||||||
| Architecture::Sparc
|
| Architecture::Sparc
|
||||||
| Architecture::Thumbv6m
|
| Architecture::Thumbv6m
|
||||||
|
| Architecture::Thumbv7a
|
||||||
| Architecture::Thumbv7em
|
| Architecture::Thumbv7em
|
||||||
| Architecture::Thumbv7m
|
| Architecture::Thumbv7m
|
||||||
| Architecture::Thumbv7neon
|
| Architecture::Thumbv7neon
|
||||||
|
| Architecture::Thumbv8mBase
|
||||||
|
| Architecture::Thumbv8mMain
|
||||||
| Architecture::Wasm32
|
| Architecture::Wasm32
|
||||||
| Architecture::Mips
|
| Architecture::Mips
|
||||||
| Architecture::Powerpc => Ok(PointerWidth::U32),
|
| Architecture::Powerpc => Ok(PointerWidth::U32),
|
||||||
|
|
@ -196,6 +225,7 @@ impl Architecture {
|
||||||
/// `binary_format` field.
|
/// `binary_format` field.
|
||||||
pub fn default_binary_format(triple: &Triple) -> BinaryFormat {
|
pub fn default_binary_format(triple: &Triple) -> BinaryFormat {
|
||||||
match triple.operating_system {
|
match triple.operating_system {
|
||||||
|
OperatingSystem::None_ => BinaryFormat::Unknown,
|
||||||
OperatingSystem::Darwin | OperatingSystem::Ios => BinaryFormat::Macho,
|
OperatingSystem::Darwin | OperatingSystem::Ios => BinaryFormat::Macho,
|
||||||
OperatingSystem::Windows => BinaryFormat::Coff,
|
OperatingSystem::Windows => BinaryFormat::Coff,
|
||||||
OperatingSystem::Nebulet | OperatingSystem::Emscripten | OperatingSystem::Unknown => {
|
OperatingSystem::Nebulet | OperatingSystem::Emscripten | OperatingSystem::Unknown => {
|
||||||
|
|
@ -214,9 +244,12 @@ impl fmt::Display for Architecture {
|
||||||
Architecture::Unknown => "unknown",
|
Architecture::Unknown => "unknown",
|
||||||
Architecture::Aarch64 => "aarch64",
|
Architecture::Aarch64 => "aarch64",
|
||||||
Architecture::Arm => "arm",
|
Architecture::Arm => "arm",
|
||||||
|
Architecture::Armebv7r => "armebv7r",
|
||||||
Architecture::Armv4t => "armv4t",
|
Architecture::Armv4t => "armv4t",
|
||||||
Architecture::Armv5te => "armv5te",
|
Architecture::Armv5te => "armv5te",
|
||||||
|
Architecture::Armv6 => "armv6",
|
||||||
Architecture::Armv7 => "armv7",
|
Architecture::Armv7 => "armv7",
|
||||||
|
Architecture::Armv7r => "armv7r",
|
||||||
Architecture::Armv7s => "armv7s",
|
Architecture::Armv7s => "armv7s",
|
||||||
Architecture::Asmjs => "asmjs",
|
Architecture::Asmjs => "asmjs",
|
||||||
Architecture::I386 => "i386",
|
Architecture::I386 => "i386",
|
||||||
|
|
@ -231,15 +264,20 @@ impl fmt::Display for Architecture {
|
||||||
Architecture::Powerpc64 => "powerpc64",
|
Architecture::Powerpc64 => "powerpc64",
|
||||||
Architecture::Powerpc64le => "powerpc64le",
|
Architecture::Powerpc64le => "powerpc64le",
|
||||||
Architecture::Riscv32 => "riscv32",
|
Architecture::Riscv32 => "riscv32",
|
||||||
|
Architecture::Riscv32imac => "riscv32imac",
|
||||||
|
Architecture::Riscv32imc => "riscv32imc",
|
||||||
Architecture::Riscv64 => "riscv64",
|
Architecture::Riscv64 => "riscv64",
|
||||||
Architecture::S390x => "s390x",
|
Architecture::S390x => "s390x",
|
||||||
Architecture::Sparc => "sparc",
|
Architecture::Sparc => "sparc",
|
||||||
Architecture::Sparc64 => "sparc64",
|
Architecture::Sparc64 => "sparc64",
|
||||||
Architecture::Sparcv9 => "sparcv9",
|
Architecture::Sparcv9 => "sparcv9",
|
||||||
Architecture::Thumbv6m => "thumbv6m",
|
Architecture::Thumbv6m => "thumbv6m",
|
||||||
|
Architecture::Thumbv7a => "thumbv7a",
|
||||||
Architecture::Thumbv7em => "thumbv7em",
|
Architecture::Thumbv7em => "thumbv7em",
|
||||||
Architecture::Thumbv7m => "thumbv7m",
|
Architecture::Thumbv7m => "thumbv7m",
|
||||||
Architecture::Thumbv7neon => "thumbv7neon",
|
Architecture::Thumbv7neon => "thumbv7neon",
|
||||||
|
Architecture::Thumbv8mBase => "thumbv8m.base",
|
||||||
|
Architecture::Thumbv8mMain => "thumbv8m.main",
|
||||||
Architecture::Wasm32 => "wasm32",
|
Architecture::Wasm32 => "wasm32",
|
||||||
Architecture::X86_64 => "x86_64",
|
Architecture::X86_64 => "x86_64",
|
||||||
};
|
};
|
||||||
|
|
@ -255,9 +293,12 @@ impl FromStr for Architecture {
|
||||||
"unknown" => Architecture::Unknown,
|
"unknown" => Architecture::Unknown,
|
||||||
"aarch64" => Architecture::Aarch64,
|
"aarch64" => Architecture::Aarch64,
|
||||||
"arm" => Architecture::Arm,
|
"arm" => Architecture::Arm,
|
||||||
|
"armebv7r" => Architecture::Armebv7r,
|
||||||
"armv4t" => Architecture::Armv4t,
|
"armv4t" => Architecture::Armv4t,
|
||||||
"armv5te" => Architecture::Armv5te,
|
"armv5te" => Architecture::Armv5te,
|
||||||
|
"armv6" => Architecture::Armv6,
|
||||||
"armv7" => Architecture::Armv7,
|
"armv7" => Architecture::Armv7,
|
||||||
|
"armv7r" => Architecture::Armv7r,
|
||||||
"armv7s" => Architecture::Armv7s,
|
"armv7s" => Architecture::Armv7s,
|
||||||
"asmjs" => Architecture::Asmjs,
|
"asmjs" => Architecture::Asmjs,
|
||||||
"i386" => Architecture::I386,
|
"i386" => Architecture::I386,
|
||||||
|
|
@ -272,15 +313,20 @@ impl FromStr for Architecture {
|
||||||
"powerpc64" => Architecture::Powerpc64,
|
"powerpc64" => Architecture::Powerpc64,
|
||||||
"powerpc64le" => Architecture::Powerpc64le,
|
"powerpc64le" => Architecture::Powerpc64le,
|
||||||
"riscv32" => Architecture::Riscv32,
|
"riscv32" => Architecture::Riscv32,
|
||||||
|
"riscv32imac" => Architecture::Riscv32imac,
|
||||||
|
"riscv32imc" => Architecture::Riscv32imc,
|
||||||
"riscv64" => Architecture::Riscv64,
|
"riscv64" => Architecture::Riscv64,
|
||||||
"s390x" => Architecture::S390x,
|
"s390x" => Architecture::S390x,
|
||||||
"sparc" => Architecture::Sparc,
|
"sparc" => Architecture::Sparc,
|
||||||
"sparc64" => Architecture::Sparc64,
|
"sparc64" => Architecture::Sparc64,
|
||||||
"sparcv9" => Architecture::Sparcv9,
|
"sparcv9" => Architecture::Sparcv9,
|
||||||
"thumbv6m" => Architecture::Thumbv6m,
|
"thumbv6m" => Architecture::Thumbv6m,
|
||||||
|
"thumbv7a" => Architecture::Thumbv7a,
|
||||||
"thumbv7em" => Architecture::Thumbv7em,
|
"thumbv7em" => Architecture::Thumbv7em,
|
||||||
"thumbv7m" => Architecture::Thumbv7m,
|
"thumbv7m" => Architecture::Thumbv7m,
|
||||||
"thumbv7neon" => Architecture::Thumbv7neon,
|
"thumbv7neon" => Architecture::Thumbv7neon,
|
||||||
|
"thumbv8m.base" => Architecture::Thumbv8mBase,
|
||||||
|
"thumbv8m.main" => Architecture::Thumbv8mMain,
|
||||||
"wasm32" => Architecture::Wasm32,
|
"wasm32" => Architecture::Wasm32,
|
||||||
"x86_64" => Architecture::X86_64,
|
"x86_64" => Architecture::X86_64,
|
||||||
_ => return Err(()),
|
_ => return Err(()),
|
||||||
|
|
@ -294,6 +340,7 @@ impl fmt::Display for Vendor {
|
||||||
Vendor::Unknown => "unknown",
|
Vendor::Unknown => "unknown",
|
||||||
Vendor::Apple => "apple",
|
Vendor::Apple => "apple",
|
||||||
Vendor::Experimental => "experimental",
|
Vendor::Experimental => "experimental",
|
||||||
|
Vendor::Fortanix => "fortanix",
|
||||||
Vendor::Pc => "pc",
|
Vendor::Pc => "pc",
|
||||||
Vendor::Rumprun => "rumprun",
|
Vendor::Rumprun => "rumprun",
|
||||||
Vendor::Sun => "sun",
|
Vendor::Sun => "sun",
|
||||||
|
|
@ -310,6 +357,7 @@ impl FromStr for Vendor {
|
||||||
"unknown" => Vendor::Unknown,
|
"unknown" => Vendor::Unknown,
|
||||||
"apple" => Vendor::Apple,
|
"apple" => Vendor::Apple,
|
||||||
"experimental" => Vendor::Experimental,
|
"experimental" => Vendor::Experimental,
|
||||||
|
"fortanix" => Vendor::Fortanix,
|
||||||
"pc" => Vendor::Pc,
|
"pc" => Vendor::Pc,
|
||||||
"rumprun" => Vendor::Rumprun,
|
"rumprun" => Vendor::Rumprun,
|
||||||
"sun" => Vendor::Sun,
|
"sun" => Vendor::Sun,
|
||||||
|
|
@ -330,14 +378,17 @@ impl fmt::Display for OperatingSystem {
|
||||||
OperatingSystem::Freebsd => "freebsd",
|
OperatingSystem::Freebsd => "freebsd",
|
||||||
OperatingSystem::Fuchsia => "fuchsia",
|
OperatingSystem::Fuchsia => "fuchsia",
|
||||||
OperatingSystem::Haiku => "haiku",
|
OperatingSystem::Haiku => "haiku",
|
||||||
|
OperatingSystem::Hermit => "hermit",
|
||||||
OperatingSystem::Ios => "ios",
|
OperatingSystem::Ios => "ios",
|
||||||
OperatingSystem::L4re => "l4re",
|
OperatingSystem::L4re => "l4re",
|
||||||
OperatingSystem::Linux => "linux",
|
OperatingSystem::Linux => "linux",
|
||||||
OperatingSystem::Nebulet => "nebulet",
|
OperatingSystem::Nebulet => "nebulet",
|
||||||
OperatingSystem::Netbsd => "netbsd",
|
OperatingSystem::Netbsd => "netbsd",
|
||||||
|
OperatingSystem::None_ => "none",
|
||||||
OperatingSystem::Openbsd => "openbsd",
|
OperatingSystem::Openbsd => "openbsd",
|
||||||
OperatingSystem::Redox => "redox",
|
OperatingSystem::Redox => "redox",
|
||||||
OperatingSystem::Solaris => "solaris",
|
OperatingSystem::Solaris => "solaris",
|
||||||
|
OperatingSystem::Uefi => "uefi",
|
||||||
OperatingSystem::Windows => "windows",
|
OperatingSystem::Windows => "windows",
|
||||||
};
|
};
|
||||||
f.write_str(s)
|
f.write_str(s)
|
||||||
|
|
@ -358,14 +409,17 @@ impl FromStr for OperatingSystem {
|
||||||
"freebsd" => OperatingSystem::Freebsd,
|
"freebsd" => OperatingSystem::Freebsd,
|
||||||
"fuchsia" => OperatingSystem::Fuchsia,
|
"fuchsia" => OperatingSystem::Fuchsia,
|
||||||
"haiku" => OperatingSystem::Haiku,
|
"haiku" => OperatingSystem::Haiku,
|
||||||
|
"hermit" => OperatingSystem::Hermit,
|
||||||
"ios" => OperatingSystem::Ios,
|
"ios" => OperatingSystem::Ios,
|
||||||
"l4re" => OperatingSystem::L4re,
|
"l4re" => OperatingSystem::L4re,
|
||||||
"linux" => OperatingSystem::Linux,
|
"linux" => OperatingSystem::Linux,
|
||||||
"nebulet" => OperatingSystem::Nebulet,
|
"nebulet" => OperatingSystem::Nebulet,
|
||||||
"netbsd" => OperatingSystem::Netbsd,
|
"netbsd" => OperatingSystem::Netbsd,
|
||||||
|
"none" => OperatingSystem::None_,
|
||||||
"openbsd" => OperatingSystem::Openbsd,
|
"openbsd" => OperatingSystem::Openbsd,
|
||||||
"redox" => OperatingSystem::Redox,
|
"redox" => OperatingSystem::Redox,
|
||||||
"solaris" => OperatingSystem::Solaris,
|
"solaris" => OperatingSystem::Solaris,
|
||||||
|
"uefi" => OperatingSystem::Uefi,
|
||||||
"windows" => OperatingSystem::Windows,
|
"windows" => OperatingSystem::Windows,
|
||||||
_ => return Err(()),
|
_ => return Err(()),
|
||||||
})
|
})
|
||||||
|
|
@ -391,6 +445,7 @@ impl fmt::Display for Environment {
|
||||||
Environment::Musleabihf => "musleabihf",
|
Environment::Musleabihf => "musleabihf",
|
||||||
Environment::Msvc => "msvc",
|
Environment::Msvc => "msvc",
|
||||||
Environment::Uclibc => "uclibc",
|
Environment::Uclibc => "uclibc",
|
||||||
|
Environment::Sgx => "sgx",
|
||||||
};
|
};
|
||||||
f.write_str(s)
|
f.write_str(s)
|
||||||
}
|
}
|
||||||
|
|
@ -417,6 +472,7 @@ impl FromStr for Environment {
|
||||||
"musleabihf" => Environment::Musleabihf,
|
"musleabihf" => Environment::Musleabihf,
|
||||||
"msvc" => Environment::Msvc,
|
"msvc" => Environment::Msvc,
|
||||||
"uclibc" => Environment::Uclibc,
|
"uclibc" => Environment::Uclibc,
|
||||||
|
"sgx" => Environment::Sgx,
|
||||||
_ => return Err(()),
|
_ => return Err(()),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -461,72 +517,19 @@ mod tests {
|
||||||
// "rustup target list" and "rustc --print target-list".
|
// "rustup target list" and "rustc --print target-list".
|
||||||
let targets = [
|
let targets = [
|
||||||
"aarch64-apple-ios",
|
"aarch64-apple-ios",
|
||||||
|
"aarch64-fuchsia",
|
||||||
"aarch64-linux-android",
|
"aarch64-linux-android",
|
||||||
"aarch64-unknown-fuchsia",
|
"aarch64-pc-windows-msvc",
|
||||||
"aarch64-unknown-linux-gnu",
|
|
||||||
"aarch64-unknown-linux-musl",
|
|
||||||
"arm-linux-androideabi",
|
|
||||||
"arm-unknown-linux-gnueabi",
|
|
||||||
"arm-unknown-linux-gnueabihf",
|
|
||||||
"arm-unknown-linux-musleabi",
|
|
||||||
"arm-unknown-linux-musleabihf",
|
|
||||||
"armv5te-unknown-linux-gnueabi",
|
|
||||||
"armv7-apple-ios",
|
|
||||||
"armv7-linux-androideabi",
|
|
||||||
"armv7-unknown-linux-gnueabihf",
|
|
||||||
"armv7-unknown-linux-musleabihf",
|
|
||||||
"armv7s-apple-ios",
|
|
||||||
"asmjs-unknown-emscripten",
|
|
||||||
"i386-apple-ios",
|
|
||||||
"i586-pc-windows-msvc",
|
|
||||||
"i586-unknown-linux-gnu",
|
|
||||||
"i586-unknown-linux-musl",
|
|
||||||
"i686-apple-darwin",
|
|
||||||
"i686-linux-android",
|
|
||||||
"i686-pc-windows-gnu",
|
|
||||||
"i686-pc-windows-msvc",
|
|
||||||
"i686-unknown-freebsd",
|
|
||||||
"i686-unknown-linux-gnu",
|
|
||||||
"i686-unknown-linux-musl",
|
|
||||||
"mips-unknown-linux-gnu",
|
|
||||||
"mips-unknown-linux-musl",
|
|
||||||
"mips64-unknown-linux-gnuabi64",
|
|
||||||
"mips64el-unknown-linux-gnuabi64",
|
|
||||||
"mipsel-unknown-linux-gnu",
|
|
||||||
"mipsel-unknown-linux-musl",
|
|
||||||
"powerpc-unknown-linux-gnu",
|
|
||||||
"powerpc64-unknown-linux-gnu",
|
|
||||||
"powerpc64le-unknown-linux-gnu",
|
|
||||||
"s390x-unknown-linux-gnu",
|
|
||||||
"sparc64-unknown-linux-gnu",
|
|
||||||
"sparcv9-sun-solaris",
|
|
||||||
"thumbv6m-none-eabi",
|
|
||||||
"thumbv7em-none-eabi",
|
|
||||||
"thumbv7em-none-eabihf",
|
|
||||||
"thumbv7m-none-eabi",
|
|
||||||
"wasm32-unknown-emscripten",
|
|
||||||
"wasm32-unknown-unknown",
|
|
||||||
"x86_64-apple-darwin",
|
|
||||||
"x86_64-apple-ios",
|
|
||||||
"x86_64-linux-android",
|
|
||||||
"x86_64-pc-windows-gnu",
|
|
||||||
"x86_64-pc-windows-msvc",
|
|
||||||
"x86_64-rumprun-netbsd",
|
|
||||||
"x86_64-sun-solaris",
|
|
||||||
"x86_64-unknown-cloudabi",
|
|
||||||
"x86_64-unknown-freebsd",
|
|
||||||
"x86_64-unknown-fuchsia",
|
|
||||||
"x86_64-unknown-linux-gnu",
|
|
||||||
"x86_64-unknown-linux-gnux32",
|
|
||||||
"x86_64-unknown-linux-musl",
|
|
||||||
"x86_64-unknown-netbsd",
|
|
||||||
"x86_64-unknown-redox",
|
|
||||||
"aarch64-linux-android",
|
|
||||||
"aarch64-unknown-cloudabi",
|
"aarch64-unknown-cloudabi",
|
||||||
"aarch64-unknown-freebsd",
|
"aarch64-unknown-freebsd",
|
||||||
"aarch64-unknown-fuchsia",
|
"aarch64-unknown-hermit",
|
||||||
"aarch64-unknown-linux-gnu",
|
"aarch64-unknown-linux-gnu",
|
||||||
"aarch64-unknown-linux-musl",
|
"aarch64-unknown-linux-musl",
|
||||||
|
"aarch64-unknown-netbsd",
|
||||||
|
"aarch64-unknown-none",
|
||||||
|
"aarch64-unknown-openbsd",
|
||||||
|
"armebv7r-none-eabi",
|
||||||
|
"armebv7r-none-eabihf",
|
||||||
"arm-linux-androideabi",
|
"arm-linux-androideabi",
|
||||||
"arm-unknown-linux-gnueabi",
|
"arm-unknown-linux-gnueabi",
|
||||||
"arm-unknown-linux-gnueabihf",
|
"arm-unknown-linux-gnueabihf",
|
||||||
|
|
@ -534,11 +537,19 @@ mod tests {
|
||||||
"arm-unknown-linux-musleabihf",
|
"arm-unknown-linux-musleabihf",
|
||||||
"armv4t-unknown-linux-gnueabi",
|
"armv4t-unknown-linux-gnueabi",
|
||||||
"armv5te-unknown-linux-gnueabi",
|
"armv5te-unknown-linux-gnueabi",
|
||||||
|
"armv5te-unknown-linux-musleabi",
|
||||||
|
"armv6-unknown-netbsd-eabihf",
|
||||||
|
"armv7-apple-ios",
|
||||||
"armv7-linux-androideabi",
|
"armv7-linux-androideabi",
|
||||||
|
"armv7r-none-eabi",
|
||||||
|
"armv7r-none-eabihf",
|
||||||
|
"armv7s-apple-ios",
|
||||||
"armv7-unknown-cloudabi-eabihf",
|
"armv7-unknown-cloudabi-eabihf",
|
||||||
"armv7-unknown-linux-gnueabihf",
|
"armv7-unknown-linux-gnueabihf",
|
||||||
"armv7-unknown-linux-musleabihf",
|
"armv7-unknown-linux-musleabihf",
|
||||||
|
"armv7-unknown-netbsd-eabihf",
|
||||||
"asmjs-unknown-emscripten",
|
"asmjs-unknown-emscripten",
|
||||||
|
"i386-apple-ios",
|
||||||
"i586-pc-windows-msvc",
|
"i586-pc-windows-msvc",
|
||||||
"i586-unknown-linux-gnu",
|
"i586-unknown-linux-gnu",
|
||||||
"i586-unknown-linux-musl",
|
"i586-unknown-linux-musl",
|
||||||
|
|
@ -554,33 +565,47 @@ mod tests {
|
||||||
"i686-unknown-linux-musl",
|
"i686-unknown-linux-musl",
|
||||||
"i686-unknown-netbsd",
|
"i686-unknown-netbsd",
|
||||||
"i686-unknown-openbsd",
|
"i686-unknown-openbsd",
|
||||||
"mips-unknown-linux-gnu",
|
|
||||||
"mips-unknown-linux-musl",
|
|
||||||
"mips-unknown-linux-uclibc",
|
|
||||||
"mips64-unknown-linux-gnuabi64",
|
|
||||||
"mips64el-unknown-linux-gnuabi64",
|
"mips64el-unknown-linux-gnuabi64",
|
||||||
|
"mips64-unknown-linux-gnuabi64",
|
||||||
"mipsel-unknown-linux-gnu",
|
"mipsel-unknown-linux-gnu",
|
||||||
"mipsel-unknown-linux-musl",
|
"mipsel-unknown-linux-musl",
|
||||||
"mipsel-unknown-linux-uclibc",
|
"mipsel-unknown-linux-uclibc",
|
||||||
|
"mips-unknown-linux-gnu",
|
||||||
|
"mips-unknown-linux-musl",
|
||||||
|
"mips-unknown-linux-uclibc",
|
||||||
"msp430-none-elf",
|
"msp430-none-elf",
|
||||||
|
"powerpc64le-unknown-linux-gnu",
|
||||||
|
"powerpc64le-unknown-linux-musl",
|
||||||
|
"powerpc64-unknown-linux-gnu",
|
||||||
|
"powerpc64-unknown-linux-musl",
|
||||||
"powerpc-unknown-linux-gnu",
|
"powerpc-unknown-linux-gnu",
|
||||||
"powerpc-unknown-linux-gnuspe",
|
"powerpc-unknown-linux-gnuspe",
|
||||||
|
"powerpc-unknown-linux-musl",
|
||||||
"powerpc-unknown-netbsd",
|
"powerpc-unknown-netbsd",
|
||||||
"powerpc64-unknown-linux-gnu",
|
"riscv32imac-unknown-none-elf",
|
||||||
"powerpc64le-unknown-linux-gnu",
|
"riscv32imc-unknown-none-elf",
|
||||||
"s390x-unknown-linux-gnu",
|
"s390x-unknown-linux-gnu",
|
||||||
"sparc-unknown-linux-gnu",
|
|
||||||
"sparc64-unknown-linux-gnu",
|
"sparc64-unknown-linux-gnu",
|
||||||
"sparc64-unknown-netbsd",
|
"sparc64-unknown-netbsd",
|
||||||
|
"sparc-unknown-linux-gnu",
|
||||||
"sparcv9-sun-solaris",
|
"sparcv9-sun-solaris",
|
||||||
"thumbv6m-none-eabi",
|
"thumbv6m-none-eabi",
|
||||||
|
"thumbv7a-pc-windows-msvc",
|
||||||
"thumbv7em-none-eabi",
|
"thumbv7em-none-eabi",
|
||||||
"thumbv7em-none-eabihf",
|
"thumbv7em-none-eabihf",
|
||||||
"thumbv7m-none-eabi",
|
"thumbv7m-none-eabi",
|
||||||
|
"thumbv7neon-linux-androideabi",
|
||||||
|
"thumbv7neon-unknown-linux-gnueabihf",
|
||||||
|
"thumbv8m.base-none-eabi",
|
||||||
|
"thumbv8m.main-none-eabi",
|
||||||
|
"thumbv8m.main-none-eabihf",
|
||||||
"wasm32-experimental-emscripten",
|
"wasm32-experimental-emscripten",
|
||||||
"wasm32-unknown-emscripten",
|
"wasm32-unknown-emscripten",
|
||||||
"wasm32-unknown-unknown",
|
"wasm32-unknown-unknown",
|
||||||
"x86_64-apple-darwin",
|
"x86_64-apple-darwin",
|
||||||
|
"x86_64-apple-ios",
|
||||||
|
"x86_64-fortanix-unknown-sgx",
|
||||||
|
"x86_64-fuchsia",
|
||||||
"x86_64-linux-android",
|
"x86_64-linux-android",
|
||||||
"x86_64-pc-windows-gnu",
|
"x86_64-pc-windows-gnu",
|
||||||
"x86_64-pc-windows-msvc",
|
"x86_64-pc-windows-msvc",
|
||||||
|
|
@ -590,8 +615,8 @@ mod tests {
|
||||||
"x86_64-unknown-cloudabi",
|
"x86_64-unknown-cloudabi",
|
||||||
"x86_64-unknown-dragonfly",
|
"x86_64-unknown-dragonfly",
|
||||||
"x86_64-unknown-freebsd",
|
"x86_64-unknown-freebsd",
|
||||||
"x86_64-unknown-fuchsia",
|
|
||||||
"x86_64-unknown-haiku",
|
"x86_64-unknown-haiku",
|
||||||
|
"x86_64-unknown-hermit",
|
||||||
"x86_64-unknown-l4re-uclibc",
|
"x86_64-unknown-l4re-uclibc",
|
||||||
"x86_64-unknown-linux-gnu",
|
"x86_64-unknown-linux-gnu",
|
||||||
"x86_64-unknown-linux-gnux32",
|
"x86_64-unknown-linux-gnux32",
|
||||||
|
|
@ -599,6 +624,7 @@ mod tests {
|
||||||
"x86_64-unknown-netbsd",
|
"x86_64-unknown-netbsd",
|
||||||
"x86_64-unknown-openbsd",
|
"x86_64-unknown-openbsd",
|
||||||
"x86_64-unknown-redox",
|
"x86_64-unknown-redox",
|
||||||
|
"x86_64-unknown-uefi",
|
||||||
];
|
];
|
||||||
|
|
||||||
for target in targets.iter() {
|
for target in targets.iter() {
|
||||||
|
|
|
||||||
46
third_party/rust/target-lexicon/src/triple.rs
vendored
46
third_party/rust/target-lexicon/src/triple.rs
vendored
|
|
@ -1,12 +1,12 @@
|
||||||
// This file defines the `Triple` type and support code shared by all targets.
|
// This file defines the `Triple` type and support code shared by all targets.
|
||||||
|
|
||||||
use parse_error::ParseError;
|
use crate::parse_error::ParseError;
|
||||||
use std::borrow::ToOwned;
|
use crate::targets::{
|
||||||
use std::fmt;
|
|
||||||
use std::str::FromStr;
|
|
||||||
use targets::{
|
|
||||||
default_binary_format, Architecture, BinaryFormat, Environment, OperatingSystem, Vendor,
|
default_binary_format, Architecture, BinaryFormat, Environment, OperatingSystem, Vendor,
|
||||||
};
|
};
|
||||||
|
use core::fmt;
|
||||||
|
use core::str::FromStr;
|
||||||
|
use std::borrow::ToOwned;
|
||||||
|
|
||||||
/// The target memory endianness.
|
/// The target memory endianness.
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
|
|
@ -155,17 +155,24 @@ impl fmt::Display for Triple {
|
||||||
|
|
||||||
write!(f, "{}", self.architecture)?;
|
write!(f, "{}", self.architecture)?;
|
||||||
if self.vendor == Vendor::Unknown
|
if self.vendor == Vendor::Unknown
|
||||||
&& self.operating_system == OperatingSystem::Unknown
|
&& ((self.operating_system == OperatingSystem::Linux
|
||||||
&& (self.environment != Environment::Unknown
|
|
||||||
|| self.binary_format != implied_binary_format)
|
|
||||||
{
|
|
||||||
// "none" is special-case shorthand for unknown vendor and unknown operating system.
|
|
||||||
f.write_str("-none")?;
|
|
||||||
} else if self.operating_system == OperatingSystem::Linux
|
|
||||||
&& (self.environment == Environment::Android
|
&& (self.environment == Environment::Android
|
||||||
|| self.environment == Environment::Androideabi)
|
|| self.environment == Environment::Androideabi))
|
||||||
|
|| self.operating_system == OperatingSystem::Fuchsia
|
||||||
|
|| (self.operating_system == OperatingSystem::None_
|
||||||
|
&& (self.architecture == Architecture::Armebv7r
|
||||||
|
|| self.architecture == Architecture::Armv7r
|
||||||
|
|| self.architecture == Architecture::Thumbv6m
|
||||||
|
|| self.architecture == Architecture::Thumbv7em
|
||||||
|
|| self.architecture == Architecture::Thumbv7m
|
||||||
|
|| self.architecture == Architecture::Thumbv8mBase
|
||||||
|
|| self.architecture == Architecture::Thumbv8mMain
|
||||||
|
|| self.architecture == Architecture::Msp430)))
|
||||||
{
|
{
|
||||||
// As a special case, omit the vendor for Android targets.
|
// As a special case, omit the vendor for Android, Fuchsia, and sometimes
|
||||||
|
// None_, depending on the hardware architecture. This logic is entirely
|
||||||
|
// ad-hoc, and is just sufficient to handle the current set of recognized
|
||||||
|
// triples.
|
||||||
write!(f, "-{}", self.operating_system)?;
|
write!(f, "-{}", self.operating_system)?;
|
||||||
} else {
|
} else {
|
||||||
write!(f, "-{}-{}", self.vendor, self.operating_system)?;
|
write!(f, "-{}-{}", self.vendor, self.operating_system)?;
|
||||||
|
|
@ -203,16 +210,7 @@ impl FromStr for Triple {
|
||||||
let mut has_vendor = false;
|
let mut has_vendor = false;
|
||||||
let mut has_operating_system = false;
|
let mut has_operating_system = false;
|
||||||
if let Some(s) = current_part {
|
if let Some(s) = current_part {
|
||||||
// "none" is special-case shorthand for unknown vendor and unknown operating system.
|
if let Ok(vendor) = Vendor::from_str(s) {
|
||||||
if s == "none" {
|
|
||||||
has_operating_system = true;
|
|
||||||
has_vendor = true;
|
|
||||||
current_part = parts.next();
|
|
||||||
// "none" requires an explicit environment or binary format.
|
|
||||||
if current_part.is_none() {
|
|
||||||
return Err(ParseError::NoneWithoutBinaryFormat);
|
|
||||||
}
|
|
||||||
} else if let Ok(vendor) = Vendor::from_str(s) {
|
|
||||||
has_vendor = true;
|
has_vendor = true;
|
||||||
result.vendor = vendor;
|
result.vendor = vendor;
|
||||||
current_part = parts.next();
|
current_part = parts.next();
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
{"files":{"Cargo.toml":"7f3766bd0ddca19ad961a1da2ebcc50de261b42a0ab5b386c0a6b3704ea8d46b","LICENSE":"a6c48161a09acc75a0e25503bab66a731eb5fba5392ed4bb4743e4ba5085327a","README.md":"13ea373a411dfa7371cd994736289bb000db51957da92315fecbcc9fe7dcab92","examples/dump.rs":"b0a4fbc3dd85df85f5eca39861b09f89716c55ff97657e7a32cf6fdee7a88e60","examples/simple.rs":"9726621cd8314ed3c7e293913b06847208ff98e43e1b4d5c79708a7b71c7a768","format-all.sh":"6b02a40629ef3d2c0b9671222582a6217d526317a41262ae06c7a95de53bcbeb","src/binary_reader.rs":"d6b0dd34c2a97babae84d1758df75515de372c5228450267141ebbad402c8acd","src/lib.rs":"c19b1965080115dfd5c256398f87f90cd0c35220eb6c9c71ae4e96a71bb38e2f","src/limits.rs":"2cf22e266c2828d68bb521485b8bd604a2ecb7a023204d7874b3da5837ec44f9","src/parser.rs":"8f29497795ef8b93134680ff9cb38dbb4f0520ceba270c1d6cee22694362b270","src/primitives.rs":"32d3662d7473bc770bcb14a2878ce9d21a00635d928ee142ae4bdbfbb741b159","src/readers/code_section.rs":"d71a798dce497838c8d6b3aa9744a2cae818b7aff99d45a31a4accb892985fd1","src/readers/data_section.rs":"74e751ea3cecbe29eb6d6b1b0119f859a5aec1a3240c4a71c381e7409378fa45","src/readers/element_section.rs":"b8f2e367b08f0a7097a9eece6a27e7170c175a13c007b7c4cb3517fa81250ff4","src/readers/export_section.rs":"dc11c96c4955cf18d1fdd50c2a6dddabd915c0ee8fc998e12130b534c9c2b621","src/readers/function_section.rs":"57c0479ba8d7f61908ed74e86cbc26553fdd6d2d952f032ce29385a39f82efd3","src/readers/global_section.rs":"5fa18bed0fffadcc2dbdcbaedbe4e4398992fd1ce9e611b0319333a7681082ac","src/readers/import_section.rs":"4dc8ec40c237c30b951bb31a7150a5159430e01d62c91d58ef4922bec65b0f6a","src/readers/init_expr.rs":"7020c80013dad4518a5f969c3ab4d624b46d778f03e632871cf343964f63441c","src/readers/linking_section.rs":"9df71f3ee5356f0d273c099212213353080001e261ca697caddf6b847fb5af09","src/readers/memory_section.rs":"83212f86cfc40d18fb392e9234c880afdf443f4af38a727ba346f9c740ef8718","src/readers/mod.rs":"9de31285cded591651108f16b9463cee7289536c722dbcf49a33847047a82bd1","src/readers/module.rs":"31329dabf177f29b40fa53fa44b19ab545c47bae8bc1e29ef995f413f572e303","src/readers/name_section.rs":"e61633a3a43f4626f15cd85d53f66a5e2bab0f016658ca792b0c94574f84b57c","src/readers/operators.rs":"da43ee8afcb0c1d6e7f1e19e8a10143101f0c598b1e533a394c7397f43881a82","src/readers/reloc_section.rs":"0ef818a8b83a4542c4c29c23642436a92d3e7c37bc0248e817ed5a9d65ec38ce","src/readers/section_reader.rs":"3d2260449fa0455d710ba6d97810372ec36cba70722c10dd236c3a18ca0eb56f","src/readers/sourcemappingurl_section.rs":"742602c2537ba3ed50f830b1929fe2d19bb68ea04ddb59f77dc47109e84f262a","src/readers/start_section.rs":"3eeae00e1aa0fcb2e0d93b7b0eaac30a60d3f1431c71c589cd3f73adb363d532","src/readers/table_section.rs":"e564876825a7b31df2b5dc850279b523e26dc50a08da935cc8d635a49e809951","src/readers/type_section.rs":"2fa33a7b793f3bfa01c259b5dbc38633b7343931886ab41f0cb96dd78db3bf6e","src/tests.rs":"ef8247ba96a17505dbd08d0d9c4caee8f3c7510523680f00f147d5ff1512b744","src/validator.rs":"ad7e73c8677513598264b2f48e0cf3fefbd36b451b0c76ea6609f906884cf467","test-all.sh":"ff894f4e5e34389ad6ef697bd4ade28a2483dd456eabba8b757945546568f4c9","test-no_std.sh":"f8bc939b378fe618b7ec6297152708e7c8740858eb94e5756464934a38796b8c"},"package":"b5e01c420bc7d36e778bd242e1167b079562ba8b34087122cc9057187026d060"}
|
{"files":{"Cargo.toml":"6f05ad46e7a84c8ae06ee90f29bb874acb68074a88aa31838554b9f9c07cd405","LICENSE":"a6c48161a09acc75a0e25503bab66a731eb5fba5392ed4bb4743e4ba5085327a","README.md":"13ea373a411dfa7371cd994736289bb000db51957da92315fecbcc9fe7dcab92","examples/dump.rs":"fdebf1af451d06691d011ba7220f3f9a483b2c54a851f06b610aaa5fcb3832df","examples/simple.rs":"c79ae542913e72cfcd03711543d173b2e8f62783e6c206459953bdb94dbb8c0c","format-all.sh":"6b02a40629ef3d2c0b9671222582a6217d526317a41262ae06c7a95de53bcbeb","src/binary_reader.rs":"e8d58f2ab57123955c680e9c9e790aec8e8a36732a77349bcdbadd7d8faf1c7d","src/lib.rs":"2fae91a32fe51183d5f9d4aab48665a0e617d6127a2031d6aaf4aa257e76dca1","src/limits.rs":"2cf22e266c2828d68bb521485b8bd604a2ecb7a023204d7874b3da5837ec44f9","src/parser.rs":"40624c94c125446b0c6106e7590b35c58df2a6ceafc85a72bb013eef2018eb58","src/primitives.rs":"4627647982376ea8519f931f09108d04c7080cf6b2a4b2d85e559ba7cfb6ad70","src/readers/code_section.rs":"2034c399b76428ac993c22f551f3c541b132d8b4ccc74e34f0043e25534d107b","src/readers/data_count_section.rs":"27ef37517b6beac21245008b14b5416b851c52d0af8e2ae85c1456674e1c9a9e","src/readers/data_section.rs":"e7e2a539d2d3049d4a8f68df9ea2f21d97e7061657bbd91845e1df3e9c1f2ebc","src/readers/element_section.rs":"e31e1d819c0b10acf58b8975238554245defe36db1c3206683b056c52978fb21","src/readers/export_section.rs":"7c74f7a11406a95c162f6ad4f77aafd0b1eee309f33b69f06bea12b23925e143","src/readers/function_section.rs":"57c0479ba8d7f61908ed74e86cbc26553fdd6d2d952f032ce29385a39f82efd3","src/readers/global_section.rs":"5fa18bed0fffadcc2dbdcbaedbe4e4398992fd1ce9e611b0319333a7681082ac","src/readers/import_section.rs":"1db4bf7290d04783d5cf526050d025b15a1daaf2bd97fca1a92ecb873d48f641","src/readers/init_expr.rs":"7020c80013dad4518a5f969c3ab4d624b46d778f03e632871cf343964f63441c","src/readers/linking_section.rs":"9df71f3ee5356f0d273c099212213353080001e261ca697caddf6b847fb5af09","src/readers/memory_section.rs":"83212f86cfc40d18fb392e9234c880afdf443f4af38a727ba346f9c740ef8718","src/readers/mod.rs":"13822fff4190b72f6ae14e29635d2c148a38ee972e148eb99a4688b0309bc2c9","src/readers/module.rs":"66473e7077b3d77ed01ed58d2796c8de7afdb2b90f2b0669c06fa90ca1b3434e","src/readers/name_section.rs":"297f57393d5fef745ec265438108aa6eb7ed2762c03c3beb539493612442f3da","src/readers/operators.rs":"da43ee8afcb0c1d6e7f1e19e8a10143101f0c598b1e533a394c7397f43881a82","src/readers/producers_section.rs":"674f402fc4545c94487f827153871b37adab44ed5eff4070a436eb18e514023a","src/readers/reloc_section.rs":"0ef818a8b83a4542c4c29c23642436a92d3e7c37bc0248e817ed5a9d65ec38ce","src/readers/section_reader.rs":"3d2260449fa0455d710ba6d97810372ec36cba70722c10dd236c3a18ca0eb56f","src/readers/sourcemappingurl_section.rs":"ababe84d51e4817ad19f827aa2b5239578e7f202e5ec06dd688b618885138434","src/readers/start_section.rs":"3eeae00e1aa0fcb2e0d93b7b0eaac30a60d3f1431c71c589cd3f73adb363d532","src/readers/table_section.rs":"e564876825a7b31df2b5dc850279b523e26dc50a08da935cc8d635a49e809951","src/readers/type_section.rs":"2fa33a7b793f3bfa01c259b5dbc38633b7343931886ab41f0cb96dd78db3bf6e","src/tests.rs":"ca486d82ffaa31370534d7d1475c0603f0e9d4888d3d07287b9d5458e6d11156","src/validator.rs":"ec0d1368f3b7833ff6d6178db50e3ffc6b2878d1d6ddab37728fdf21e8256896","test-all.sh":"ff894f4e5e34389ad6ef697bd4ade28a2483dd456eabba8b757945546568f4c9","test-no_std.sh":"f8bc939b378fe618b7ec6297152708e7c8740858eb94e5756464934a38796b8c"},"package":"981a8797cf89762e0233ec45fae731cb79a4dfaee12d9f0fe6cee01e4ac58d00"}
|
||||||
2
third_party/rust/wasmparser/Cargo.toml
vendored
2
third_party/rust/wasmparser/Cargo.toml
vendored
|
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "wasmparser"
|
name = "wasmparser"
|
||||||
version = "0.23.0"
|
version = "0.29.2"
|
||||||
authors = ["Yury Delendik <ydelendik@mozilla.com>"]
|
authors = ["Yury Delendik <ydelendik@mozilla.com>"]
|
||||||
exclude = ["fuzz/**/*", "tests/**/*"]
|
exclude = ["fuzz/**/*", "tests/**/*"]
|
||||||
description = "A simple event-driven library for parsing WebAssembly binary files.\n"
|
description = "A simple event-driven library for parsing WebAssembly binary files.\n"
|
||||||
|
|
|
||||||
12
third_party/rust/wasmparser/examples/dump.rs
vendored
12
third_party/rust/wasmparser/examples/dump.rs
vendored
|
|
@ -9,10 +9,6 @@ use wasmparser::Parser;
|
||||||
use wasmparser::ParserState;
|
use wasmparser::ParserState;
|
||||||
use wasmparser::WasmDecoder;
|
use wasmparser::WasmDecoder;
|
||||||
|
|
||||||
fn get_name(bytes: &[u8]) -> &str {
|
|
||||||
str::from_utf8(bytes).ok().unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let args = env::args().collect::<Vec<_>>();
|
let args = env::args().collect::<Vec<_>>();
|
||||||
if args.len() != 2 {
|
if args.len() != 2 {
|
||||||
|
|
@ -32,9 +28,7 @@ fn main() {
|
||||||
} => {
|
} => {
|
||||||
println!(
|
println!(
|
||||||
"ExportSectionEntry {{ field: \"{}\", kind: {:?}, index: {} }}",
|
"ExportSectionEntry {{ field: \"{}\", kind: {:?}, index: {} }}",
|
||||||
get_name(field),
|
field, kind, index
|
||||||
kind,
|
|
||||||
index
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ParserState::ImportSectionEntry {
|
ParserState::ImportSectionEntry {
|
||||||
|
|
@ -44,9 +38,7 @@ fn main() {
|
||||||
} => {
|
} => {
|
||||||
println!(
|
println!(
|
||||||
"ImportSectionEntry {{ module: \"{}\", field: \"{}\", ty: {:?} }}",
|
"ImportSectionEntry {{ module: \"{}\", field: \"{}\", ty: {:?} }}",
|
||||||
get_name(module),
|
module, field, ty
|
||||||
get_name(field),
|
|
||||||
ty
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ParserState::EndWasm => break,
|
ParserState::EndWasm => break,
|
||||||
|
|
|
||||||
|
|
@ -9,10 +9,6 @@ use wasmparser::Parser;
|
||||||
use wasmparser::ParserState;
|
use wasmparser::ParserState;
|
||||||
use wasmparser::WasmDecoder;
|
use wasmparser::WasmDecoder;
|
||||||
|
|
||||||
fn get_name(bytes: &[u8]) -> &str {
|
|
||||||
str::from_utf8(bytes).ok().unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let args = env::args().collect::<Vec<_>>();
|
let args = env::args().collect::<Vec<_>>();
|
||||||
if args.len() != 2 {
|
if args.len() != 2 {
|
||||||
|
|
@ -31,10 +27,10 @@ fn main() {
|
||||||
ParserState::ExportSectionEntry {
|
ParserState::ExportSectionEntry {
|
||||||
field, ref kind, ..
|
field, ref kind, ..
|
||||||
} => {
|
} => {
|
||||||
println!(" Export {} {:?}", get_name(field), kind);
|
println!(" Export {} {:?}", field, kind);
|
||||||
}
|
}
|
||||||
ParserState::ImportSectionEntry { module, field, .. } => {
|
ParserState::ImportSectionEntry { module, field, .. } => {
|
||||||
println!(" Import {}::{}", get_name(module), get_name(field))
|
println!(" Import {}::{}", module, field)
|
||||||
}
|
}
|
||||||
ParserState::EndWasm => break,
|
ParserState::EndWasm => break,
|
||||||
ParserState::Error(err) => panic!("Error: {:?}", err),
|
ParserState::Error(err) => panic!("Error: {:?}", err),
|
||||||
|
|
|
||||||
362
third_party/rust/wasmparser/src/binary_reader.rs
vendored
362
third_party/rust/wasmparser/src/binary_reader.rs
vendored
|
|
@ -14,6 +14,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use std::boxed::Box;
|
use std::boxed::Box;
|
||||||
|
use std::str;
|
||||||
use std::vec::Vec;
|
use std::vec::Vec;
|
||||||
|
|
||||||
use limits::{
|
use limits::{
|
||||||
|
|
@ -24,35 +25,17 @@ use limits::{
|
||||||
use primitives::{
|
use primitives::{
|
||||||
BinaryReaderError, BrTable, CustomSectionKind, ExternalKind, FuncType, GlobalType, Ieee32,
|
BinaryReaderError, BrTable, CustomSectionKind, ExternalKind, FuncType, GlobalType, Ieee32,
|
||||||
Ieee64, LinkingType, MemoryImmediate, MemoryType, NameType, Operator, RelocType,
|
Ieee64, LinkingType, MemoryImmediate, MemoryType, NameType, Operator, RelocType,
|
||||||
ResizableLimits, Result, SectionCode, TableType, Type,
|
ResizableLimits, Result, SIMDLineIndex, SectionCode, TableType, Type, V128,
|
||||||
};
|
};
|
||||||
|
|
||||||
const MAX_WASM_BR_TABLE_SIZE: usize = MAX_WASM_FUNCTION_SIZE;
|
const MAX_WASM_BR_TABLE_SIZE: usize = MAX_WASM_FUNCTION_SIZE;
|
||||||
|
|
||||||
fn is_name(name: &[u8], expected: &'static str) -> bool {
|
fn is_name(name: &str, expected: &'static str) -> bool {
|
||||||
if name.len() != expected.len() {
|
name == expected
|
||||||
return false;
|
|
||||||
}
|
|
||||||
let expected_bytes = expected.as_bytes();
|
|
||||||
for i in 0..name.len() {
|
|
||||||
if name[i] != expected_bytes[i] {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_name_prefix(name: &[u8], prefix: &'static str) -> bool {
|
fn is_name_prefix(name: &str, prefix: &'static str) -> bool {
|
||||||
if name.len() < prefix.len() {
|
name.starts_with(prefix)
|
||||||
return false;
|
|
||||||
}
|
|
||||||
let expected_bytes = prefix.as_bytes();
|
|
||||||
for i in 0..expected_bytes.len() {
|
|
||||||
if name[i] != expected_bytes[i] {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const WASM_MAGIC_NUMBER: u32 = 0x6d736100;
|
const WASM_MAGIC_NUMBER: u32 = 0x6d736100;
|
||||||
|
|
@ -123,6 +106,13 @@ impl<'a> BinaryReader<'a> {
|
||||||
self.original_offset + self.position
|
self.original_offset + self.position
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn range(&self) -> Range {
|
||||||
|
Range {
|
||||||
|
start: self.original_offset,
|
||||||
|
end: self.original_offset + self.buffer.len(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn ensure_has_byte(&self) -> Result<()> {
|
fn ensure_has_byte(&self) -> Result<()> {
|
||||||
if self.position < self.buffer.len() {
|
if self.position < self.buffer.len() {
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -185,6 +175,7 @@ impl<'a> BinaryReader<'a> {
|
||||||
-0x02 => Ok(Type::I64),
|
-0x02 => Ok(Type::I64),
|
||||||
-0x03 => Ok(Type::F32),
|
-0x03 => Ok(Type::F32),
|
||||||
-0x04 => Ok(Type::F64),
|
-0x04 => Ok(Type::F64),
|
||||||
|
-0x05 => Ok(Type::V128),
|
||||||
-0x10 => Ok(Type::AnyFunc),
|
-0x10 => Ok(Type::AnyFunc),
|
||||||
-0x11 => Ok(Type::AnyRef),
|
-0x11 => Ok(Type::AnyRef),
|
||||||
-0x20 => Ok(Type::Func),
|
-0x20 => Ok(Type::Func),
|
||||||
|
|
@ -332,6 +323,8 @@ impl<'a> BinaryReader<'a> {
|
||||||
let name = self.read_string()?;
|
let name = self.read_string()?;
|
||||||
let kind = if is_name(name, "name") {
|
let kind = if is_name(name, "name") {
|
||||||
CustomSectionKind::Name
|
CustomSectionKind::Name
|
||||||
|
} else if is_name(name, "producers") {
|
||||||
|
CustomSectionKind::Producers
|
||||||
} else if is_name(name, "sourceMappingURL") {
|
} else if is_name(name, "sourceMappingURL") {
|
||||||
CustomSectionKind::SourceMappingURL
|
CustomSectionKind::SourceMappingURL
|
||||||
} else if is_name_prefix(name, "reloc.") {
|
} else if is_name_prefix(name, "reloc.") {
|
||||||
|
|
@ -354,6 +347,7 @@ impl<'a> BinaryReader<'a> {
|
||||||
9 => Ok(SectionCode::Element),
|
9 => Ok(SectionCode::Element),
|
||||||
10 => Ok(SectionCode::Code),
|
10 => Ok(SectionCode::Code),
|
||||||
11 => Ok(SectionCode::Data),
|
11 => Ok(SectionCode::Data),
|
||||||
|
12 => Ok(SectionCode::DataCount),
|
||||||
_ => Err(BinaryReaderError {
|
_ => Err(BinaryReaderError {
|
||||||
message: "Invalid section code",
|
message: "Invalid section code",
|
||||||
offset,
|
offset,
|
||||||
|
|
@ -376,6 +370,7 @@ impl<'a> BinaryReader<'a> {
|
||||||
self.skip_var_32()?;
|
self.skip_var_32()?;
|
||||||
Ok(BrTable {
|
Ok(BrTable {
|
||||||
buffer: &self.buffer[start..self.position],
|
buffer: &self.buffer[start..self.position],
|
||||||
|
cnt: targets_len as usize,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -558,7 +553,7 @@ impl<'a> BinaryReader<'a> {
|
||||||
Ok(Ieee64(value))
|
Ok(Ieee64(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_string(&mut self) -> Result<&'a [u8]> {
|
pub fn read_string(&mut self) -> Result<&'a str> {
|
||||||
let len = self.read_var_u32()? as usize;
|
let len = self.read_var_u32()? as usize;
|
||||||
if len > MAX_WASM_STRING_SIZE {
|
if len > MAX_WASM_STRING_SIZE {
|
||||||
return Err(BinaryReaderError {
|
return Err(BinaryReaderError {
|
||||||
|
|
@ -566,7 +561,11 @@ impl<'a> BinaryReader<'a> {
|
||||||
offset: self.original_position() - 1,
|
offset: self.original_position() - 1,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
self.read_bytes(len)
|
let bytes = self.read_bytes(len)?;
|
||||||
|
str::from_utf8(bytes).map_err(|_| BinaryReaderError {
|
||||||
|
message: "non-utf8 string",
|
||||||
|
offset: self.original_position() - 1,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_memarg_of_align(&mut self, align: u32) -> Result<MemoryImmediate> {
|
fn read_memarg_of_align(&mut self, align: u32) -> Result<MemoryImmediate> {
|
||||||
|
|
@ -786,7 +785,7 @@ impl<'a> BinaryReader<'a> {
|
||||||
return Err(BinaryReaderError {
|
return Err(BinaryReaderError {
|
||||||
message: "Unknown 0xFE opcode",
|
message: "Unknown 0xFE opcode",
|
||||||
offset: self.original_position() - 1,
|
offset: self.original_position() - 1,
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -822,7 +821,7 @@ impl<'a> BinaryReader<'a> {
|
||||||
},
|
},
|
||||||
0x11 => Operator::CallIndirect {
|
0x11 => Operator::CallIndirect {
|
||||||
index: self.read_var_u32()?,
|
index: self.read_var_u32()?,
|
||||||
table_index: self.read_var_u1()?,
|
table_index: self.read_var_u32()?,
|
||||||
},
|
},
|
||||||
0x1a => Operator::Drop,
|
0x1a => Operator::Drop,
|
||||||
0x1b => Operator::Select,
|
0x1b => Operator::Select,
|
||||||
|
|
@ -841,6 +840,12 @@ impl<'a> BinaryReader<'a> {
|
||||||
0x24 => Operator::SetGlobal {
|
0x24 => Operator::SetGlobal {
|
||||||
global_index: self.read_var_u32()?,
|
global_index: self.read_var_u32()?,
|
||||||
},
|
},
|
||||||
|
0x25 => Operator::TableGet {
|
||||||
|
table: self.read_var_u32()?,
|
||||||
|
},
|
||||||
|
0x26 => Operator::TableSet {
|
||||||
|
table: self.read_var_u32()?,
|
||||||
|
},
|
||||||
0x28 => Operator::I32Load {
|
0x28 => Operator::I32Load {
|
||||||
memarg: self.read_memarg()?,
|
memarg: self.read_memarg()?,
|
||||||
},
|
},
|
||||||
|
|
@ -1062,14 +1067,14 @@ impl<'a> BinaryReader<'a> {
|
||||||
0xd1 => Operator::RefIsNull,
|
0xd1 => Operator::RefIsNull,
|
||||||
|
|
||||||
0xfc => self.read_0xfc_operator()?,
|
0xfc => self.read_0xfc_operator()?,
|
||||||
|
0xfd => self.read_0xfd_operator()?,
|
||||||
0xfe => self.read_0xfe_operator()?,
|
0xfe => self.read_0xfe_operator()?,
|
||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
return Err(BinaryReaderError {
|
return Err(BinaryReaderError {
|
||||||
message: "Unknown opcode",
|
message: "Unknown opcode",
|
||||||
offset: self.original_position() - 1,
|
offset: self.original_position() - 1,
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -1086,12 +1091,305 @@ impl<'a> BinaryReader<'a> {
|
||||||
0x06 => Operator::I64TruncSSatF64,
|
0x06 => Operator::I64TruncSSatF64,
|
||||||
0x07 => Operator::I64TruncUSatF64,
|
0x07 => Operator::I64TruncUSatF64,
|
||||||
|
|
||||||
|
0x08 => {
|
||||||
|
let segment = self.read_var_u32()?;
|
||||||
|
let mem = self.read_u8()?;
|
||||||
|
if mem != 0 {
|
||||||
|
return Err(BinaryReaderError {
|
||||||
|
message: "reserved byte must be zero",
|
||||||
|
offset: self.original_position() - 1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Operator::MemoryInit { segment }
|
||||||
|
}
|
||||||
|
0x09 => {
|
||||||
|
let segment = self.read_var_u32()?;
|
||||||
|
Operator::DataDrop { segment }
|
||||||
|
}
|
||||||
|
0x0a => {
|
||||||
|
let src = self.read_u8()?;
|
||||||
|
if src != 0 {
|
||||||
|
return Err(BinaryReaderError {
|
||||||
|
message: "reserved byte must be zero",
|
||||||
|
offset: self.original_position() - 1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let dst = self.read_u8()?;
|
||||||
|
if dst != 0 {
|
||||||
|
return Err(BinaryReaderError {
|
||||||
|
message: "reserved byte must be zero",
|
||||||
|
offset: self.original_position() - 1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Operator::MemoryCopy
|
||||||
|
}
|
||||||
|
0x0b => {
|
||||||
|
let mem = self.read_u8()?;
|
||||||
|
if mem != 0 {
|
||||||
|
return Err(BinaryReaderError {
|
||||||
|
message: "reserved byte must be zero",
|
||||||
|
offset: self.original_position() - 1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Operator::MemoryFill
|
||||||
|
}
|
||||||
|
0x0c => {
|
||||||
|
let segment = self.read_var_u32()?;
|
||||||
|
let table = self.read_u8()?;
|
||||||
|
if table != 0 {
|
||||||
|
return Err(BinaryReaderError {
|
||||||
|
message: "reserved byte must be zero",
|
||||||
|
offset: self.original_position() - 1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Operator::TableInit { segment }
|
||||||
|
}
|
||||||
|
0x0d => {
|
||||||
|
let segment = self.read_var_u32()?;
|
||||||
|
Operator::ElemDrop { segment }
|
||||||
|
}
|
||||||
|
0x0e => {
|
||||||
|
let src = self.read_u8()?;
|
||||||
|
if src != 0 {
|
||||||
|
return Err(BinaryReaderError {
|
||||||
|
message: "reserved byte must be zero",
|
||||||
|
offset: self.original_position() - 1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let dst = self.read_u8()?;
|
||||||
|
if dst != 0 {
|
||||||
|
return Err(BinaryReaderError {
|
||||||
|
message: "reserved byte must be zero",
|
||||||
|
offset: self.original_position() - 1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Operator::TableCopy
|
||||||
|
}
|
||||||
|
|
||||||
|
0x0f => {
|
||||||
|
let table = self.read_var_u32()?;
|
||||||
|
Operator::TableGrow { table }
|
||||||
|
}
|
||||||
|
0x10 => {
|
||||||
|
let table = self.read_var_u32()?;
|
||||||
|
Operator::TableSize { table }
|
||||||
|
}
|
||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
return Err(BinaryReaderError {
|
return Err(BinaryReaderError {
|
||||||
message: "Unknown 0xfc opcode",
|
message: "Unknown 0xfc opcode",
|
||||||
offset: self.original_position() - 1,
|
offset: self.original_position() - 1,
|
||||||
|
});
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn read_line_index(&mut self, max: u32) -> Result<SIMDLineIndex> {
|
||||||
|
let index = self.read_u8()?;
|
||||||
|
if index >= max {
|
||||||
|
return Err(BinaryReaderError {
|
||||||
|
message: "line index out of range",
|
||||||
|
offset: self.original_position() - 1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Ok(index as SIMDLineIndex)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_v128(&mut self) -> Result<V128> {
|
||||||
|
let mut bytes = [0; 16];
|
||||||
|
bytes.clone_from_slice(self.read_bytes(16)?);
|
||||||
|
Ok(V128(bytes))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_0xfd_operator(&mut self) -> Result<Operator<'a>> {
|
||||||
|
let code = self.read_u8()? as u8;
|
||||||
|
Ok(match code {
|
||||||
|
0x00 => Operator::V128Load {
|
||||||
|
memarg: self.read_memarg()?,
|
||||||
|
},
|
||||||
|
0x01 => Operator::V128Store {
|
||||||
|
memarg: self.read_memarg()?,
|
||||||
|
},
|
||||||
|
0x02 => Operator::V128Const {
|
||||||
|
value: self.read_v128()?,
|
||||||
|
},
|
||||||
|
0x03 => {
|
||||||
|
let mut lines = [0 as SIMDLineIndex; 16];
|
||||||
|
for i in 0..16 {
|
||||||
|
lines[i] = self.read_line_index(32)?
|
||||||
|
}
|
||||||
|
Operator::V8x16Shuffle { lines }
|
||||||
|
}
|
||||||
|
0x04 => Operator::I8x16Splat,
|
||||||
|
0x05 => Operator::I8x16ExtractLaneS {
|
||||||
|
line: self.read_line_index(16)?,
|
||||||
|
},
|
||||||
|
0x06 => Operator::I8x16ExtractLaneU {
|
||||||
|
line: self.read_line_index(16)?,
|
||||||
|
},
|
||||||
|
0x07 => Operator::I8x16ReplaceLane {
|
||||||
|
line: self.read_line_index(16)?,
|
||||||
|
},
|
||||||
|
0x08 => Operator::I16x8Splat,
|
||||||
|
0x09 => Operator::I16x8ExtractLaneS {
|
||||||
|
line: self.read_line_index(8)?,
|
||||||
|
},
|
||||||
|
0x0a => Operator::I16x8ExtractLaneU {
|
||||||
|
line: self.read_line_index(8)?,
|
||||||
|
},
|
||||||
|
0x0b => Operator::I16x8ReplaceLane {
|
||||||
|
line: self.read_line_index(8)?,
|
||||||
|
},
|
||||||
|
0x0c => Operator::I32x4Splat,
|
||||||
|
0x0d => Operator::I32x4ExtractLane {
|
||||||
|
line: self.read_line_index(4)?,
|
||||||
|
},
|
||||||
|
0x0e => Operator::I32x4ReplaceLane {
|
||||||
|
line: self.read_line_index(4)?,
|
||||||
|
},
|
||||||
|
0x0f => Operator::I64x2Splat,
|
||||||
|
0x10 => Operator::I64x2ExtractLane {
|
||||||
|
line: self.read_line_index(2)?,
|
||||||
|
},
|
||||||
|
0x11 => Operator::I64x2ReplaceLane {
|
||||||
|
line: self.read_line_index(2)?,
|
||||||
|
},
|
||||||
|
0x12 => Operator::F32x4Splat,
|
||||||
|
0x13 => Operator::F32x4ExtractLane {
|
||||||
|
line: self.read_line_index(4)?,
|
||||||
|
},
|
||||||
|
0x14 => Operator::F32x4ReplaceLane {
|
||||||
|
line: self.read_line_index(4)?,
|
||||||
|
},
|
||||||
|
0x15 => Operator::F64x2Splat,
|
||||||
|
0x16 => Operator::F64x2ExtractLane {
|
||||||
|
line: self.read_line_index(2)?,
|
||||||
|
},
|
||||||
|
0x17 => Operator::F64x2ReplaceLane {
|
||||||
|
line: self.read_line_index(2)?,
|
||||||
|
},
|
||||||
|
0x18 => Operator::I8x16Eq,
|
||||||
|
0x19 => Operator::I8x16Ne,
|
||||||
|
0x1a => Operator::I8x16LtS,
|
||||||
|
0x1b => Operator::I8x16LtU,
|
||||||
|
0x1c => Operator::I8x16GtS,
|
||||||
|
0x1d => Operator::I8x16GtU,
|
||||||
|
0x1e => Operator::I8x16LeS,
|
||||||
|
0x1f => Operator::I8x16LeU,
|
||||||
|
0x20 => Operator::I8x16GeS,
|
||||||
|
0x21 => Operator::I8x16GeU,
|
||||||
|
0x22 => Operator::I16x8Eq,
|
||||||
|
0x23 => Operator::I16x8Ne,
|
||||||
|
0x24 => Operator::I16x8LtS,
|
||||||
|
0x25 => Operator::I16x8LtU,
|
||||||
|
0x26 => Operator::I16x8GtS,
|
||||||
|
0x27 => Operator::I16x8GtU,
|
||||||
|
0x28 => Operator::I16x8LeS,
|
||||||
|
0x29 => Operator::I16x8LeU,
|
||||||
|
0x2a => Operator::I16x8GeS,
|
||||||
|
0x2b => Operator::I16x8GeU,
|
||||||
|
0x2c => Operator::I32x4Eq,
|
||||||
|
0x2d => Operator::I32x4Ne,
|
||||||
|
0x2e => Operator::I32x4LtS,
|
||||||
|
0x2f => Operator::I32x4LtU,
|
||||||
|
0x30 => Operator::I32x4GtS,
|
||||||
|
0x31 => Operator::I32x4GtU,
|
||||||
|
0x32 => Operator::I32x4LeS,
|
||||||
|
0x33 => Operator::I32x4LeU,
|
||||||
|
0x34 => Operator::I32x4GeS,
|
||||||
|
0x35 => Operator::I32x4GeU,
|
||||||
|
0x40 => Operator::F32x4Eq,
|
||||||
|
0x41 => Operator::F32x4Ne,
|
||||||
|
0x42 => Operator::F32x4Lt,
|
||||||
|
0x43 => Operator::F32x4Gt,
|
||||||
|
0x44 => Operator::F32x4Le,
|
||||||
|
0x45 => Operator::F32x4Ge,
|
||||||
|
0x46 => Operator::F64x2Eq,
|
||||||
|
0x47 => Operator::F64x2Ne,
|
||||||
|
0x48 => Operator::F64x2Lt,
|
||||||
|
0x49 => Operator::F64x2Gt,
|
||||||
|
0x4a => Operator::F64x2Le,
|
||||||
|
0x4b => Operator::F64x2Ge,
|
||||||
|
0x4c => Operator::V128Not,
|
||||||
|
0x4d => Operator::V128And,
|
||||||
|
0x4e => Operator::V128Or,
|
||||||
|
0x4f => Operator::V128Xor,
|
||||||
|
0x50 => Operator::V128Bitselect,
|
||||||
|
0x51 => Operator::I8x16Neg,
|
||||||
|
0x52 => Operator::I8x16AnyTrue,
|
||||||
|
0x53 => Operator::I8x16AllTrue,
|
||||||
|
0x54 => Operator::I8x16Shl,
|
||||||
|
0x55 => Operator::I8x16ShrS,
|
||||||
|
0x56 => Operator::I8x16ShrU,
|
||||||
|
0x57 => Operator::I8x16Add,
|
||||||
|
0x58 => Operator::I8x16AddSaturateS,
|
||||||
|
0x59 => Operator::I8x16AddSaturateU,
|
||||||
|
0x5a => Operator::I8x16Sub,
|
||||||
|
0x5b => Operator::I8x16SubSaturateS,
|
||||||
|
0x5c => Operator::I8x16SubSaturateU,
|
||||||
|
0x5d => Operator::I8x16Mul,
|
||||||
|
0x62 => Operator::I16x8Neg,
|
||||||
|
0x63 => Operator::I16x8AnyTrue,
|
||||||
|
0x64 => Operator::I16x8AllTrue,
|
||||||
|
0x65 => Operator::I16x8Shl,
|
||||||
|
0x66 => Operator::I16x8ShrS,
|
||||||
|
0x67 => Operator::I16x8ShrU,
|
||||||
|
0x68 => Operator::I16x8Add,
|
||||||
|
0x69 => Operator::I16x8AddSaturateS,
|
||||||
|
0x6a => Operator::I16x8AddSaturateU,
|
||||||
|
0x6b => Operator::I16x8Sub,
|
||||||
|
0x6c => Operator::I16x8SubSaturateS,
|
||||||
|
0x6d => Operator::I16x8SubSaturateU,
|
||||||
|
0x6e => Operator::I16x8Mul,
|
||||||
|
0x73 => Operator::I32x4Neg,
|
||||||
|
0x74 => Operator::I32x4AnyTrue,
|
||||||
|
0x75 => Operator::I32x4AllTrue,
|
||||||
|
0x76 => Operator::I32x4Shl,
|
||||||
|
0x77 => Operator::I32x4ShrS,
|
||||||
|
0x78 => Operator::I32x4ShrU,
|
||||||
|
0x79 => Operator::I32x4Add,
|
||||||
|
0x7c => Operator::I32x4Sub,
|
||||||
|
0x7f => Operator::I32x4Mul,
|
||||||
|
0x84 => Operator::I64x2Neg,
|
||||||
|
0x85 => Operator::I64x2AnyTrue,
|
||||||
|
0x86 => Operator::I64x2AllTrue,
|
||||||
|
0x87 => Operator::I64x2Shl,
|
||||||
|
0x88 => Operator::I64x2ShrS,
|
||||||
|
0x89 => Operator::I64x2ShrU,
|
||||||
|
0x8a => Operator::I64x2Add,
|
||||||
|
0x8d => Operator::I64x2Sub,
|
||||||
|
0x95 => Operator::F32x4Abs,
|
||||||
|
0x96 => Operator::F32x4Neg,
|
||||||
|
0x97 => Operator::F32x4Sqrt,
|
||||||
|
0x9a => Operator::F32x4Add,
|
||||||
|
0x9b => Operator::F32x4Sub,
|
||||||
|
0x9c => Operator::F32x4Mul,
|
||||||
|
0x9d => Operator::F32x4Div,
|
||||||
|
0x9e => Operator::F32x4Min,
|
||||||
|
0x9f => Operator::F32x4Max,
|
||||||
|
0xa0 => Operator::F64x2Abs,
|
||||||
|
0xa1 => Operator::F64x2Neg,
|
||||||
|
0xa2 => Operator::F64x2Sqrt,
|
||||||
|
0xa5 => Operator::F64x2Add,
|
||||||
|
0xa6 => Operator::F64x2Sub,
|
||||||
|
0xa7 => Operator::F64x2Mul,
|
||||||
|
0xa8 => Operator::F64x2Div,
|
||||||
|
0xa9 => Operator::F64x2Min,
|
||||||
|
0xaa => Operator::F64x2Max,
|
||||||
|
0xab => Operator::I32x4TruncSF32x4Sat,
|
||||||
|
0xac => Operator::I32x4TruncUF32x4Sat,
|
||||||
|
0xad => Operator::I64x2TruncSF64x2Sat,
|
||||||
|
0xae => Operator::I64x2TruncUF64x2Sat,
|
||||||
|
0xaf => Operator::F32x4ConvertSI32x4,
|
||||||
|
0xb0 => Operator::F32x4ConvertUI32x4,
|
||||||
|
0xb1 => Operator::F64x2ConvertSI64x2,
|
||||||
|
0xb2 => Operator::F64x2ConvertUI64x2,
|
||||||
|
_ => {
|
||||||
|
return Err(BinaryReaderError {
|
||||||
|
message: "Unknown 0xfd opcode",
|
||||||
|
offset: self.original_position() - 1,
|
||||||
|
});
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1181,6 +1479,12 @@ impl<'a> BinaryReader<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> BrTable<'a> {
|
impl<'a> BrTable<'a> {
|
||||||
|
/// Returns the number of `br_table` entries, not including the default
|
||||||
|
/// label
|
||||||
|
pub fn len(&self) -> usize {
|
||||||
|
self.cnt
|
||||||
|
}
|
||||||
|
|
||||||
/// Reads br_table entries.
|
/// Reads br_table entries.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
|
|
|
||||||
6
third_party/rust/wasmparser/src/lib.rs
vendored
6
third_party/rust/wasmparser/src/lib.rs
vendored
|
|
@ -66,6 +66,7 @@ pub use primitives::Result;
|
||||||
pub use primitives::SectionCode;
|
pub use primitives::SectionCode;
|
||||||
pub use primitives::TableType;
|
pub use primitives::TableType;
|
||||||
pub use primitives::Type;
|
pub use primitives::Type;
|
||||||
|
pub use primitives::V128;
|
||||||
|
|
||||||
pub use validator::validate;
|
pub use validator::validate;
|
||||||
pub use validator::OperatorValidatorConfig;
|
pub use validator::OperatorValidatorConfig;
|
||||||
|
|
@ -76,10 +77,12 @@ pub use validator::WasmModuleResources;
|
||||||
|
|
||||||
pub use readers::CodeSectionReader;
|
pub use readers::CodeSectionReader;
|
||||||
pub use readers::Data;
|
pub use readers::Data;
|
||||||
|
pub use readers::DataKind;
|
||||||
pub use readers::DataSectionReader;
|
pub use readers::DataSectionReader;
|
||||||
pub use readers::Element;
|
pub use readers::Element;
|
||||||
pub use readers::ElementItems;
|
pub use readers::ElementItems;
|
||||||
pub use readers::ElementItemsReader;
|
pub use readers::ElementItemsReader;
|
||||||
|
pub use readers::ElementKind;
|
||||||
pub use readers::ElementSectionReader;
|
pub use readers::ElementSectionReader;
|
||||||
pub use readers::Export;
|
pub use readers::Export;
|
||||||
pub use readers::ExportSectionReader;
|
pub use readers::ExportSectionReader;
|
||||||
|
|
@ -98,6 +101,9 @@ pub use readers::Name;
|
||||||
pub use readers::NameSectionReader;
|
pub use readers::NameSectionReader;
|
||||||
pub use readers::NamingReader;
|
pub use readers::NamingReader;
|
||||||
pub use readers::OperatorsReader;
|
pub use readers::OperatorsReader;
|
||||||
|
pub use readers::ProducersField;
|
||||||
|
pub use readers::ProducersFieldValue;
|
||||||
|
pub use readers::ProducersSectionReader;
|
||||||
pub use readers::Reloc;
|
pub use readers::Reloc;
|
||||||
pub use readers::RelocSectionReader;
|
pub use readers::RelocSectionReader;
|
||||||
pub use readers::Section;
|
pub use readers::Section;
|
||||||
|
|
|
||||||
100
third_party/rust/wasmparser/src/parser.rs
vendored
100
third_party/rust/wasmparser/src/parser.rs
vendored
|
|
@ -28,11 +28,11 @@ use primitives::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use readers::{
|
use readers::{
|
||||||
CodeSectionReader, Data, DataSectionReader, Element, ElementItems, ElementSectionReader,
|
CodeSectionReader, Data, DataKind, DataSectionReader, Element, ElementItems, ElementKind,
|
||||||
Export, ExportSectionReader, FunctionBody, FunctionSectionReader, Global, GlobalSectionReader,
|
ElementSectionReader, Export, ExportSectionReader, FunctionBody, FunctionSectionReader, Global,
|
||||||
Import, ImportSectionReader, LinkingSectionReader, MemorySectionReader, ModuleReader, Name,
|
GlobalSectionReader, Import, ImportSectionReader, LinkingSectionReader, MemorySectionReader,
|
||||||
NameSectionReader, NamingReader, OperatorsReader, Reloc, RelocSectionReader, Section,
|
ModuleReader, Name, NameSectionReader, NamingReader, OperatorsReader, Reloc,
|
||||||
SectionReader, TableSectionReader, TypeSectionReader,
|
RelocSectionReader, Section, SectionReader, TableSectionReader, TypeSectionReader,
|
||||||
};
|
};
|
||||||
|
|
||||||
use binary_reader::{BinaryReader, Range};
|
use binary_reader::{BinaryReader, Range};
|
||||||
|
|
@ -47,7 +47,7 @@ pub struct LocalName<'a> {
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum NameEntry<'a> {
|
pub enum NameEntry<'a> {
|
||||||
Module(&'a [u8]),
|
Module(&'a str),
|
||||||
Function(Box<[Naming<'a>]>),
|
Function(Box<[Naming<'a>]>),
|
||||||
Local(Box<[LocalName<'a>]>),
|
Local(Box<[LocalName<'a>]>),
|
||||||
}
|
}
|
||||||
|
|
@ -86,20 +86,21 @@ pub enum ParserState<'a> {
|
||||||
|
|
||||||
TypeSectionEntry(FuncType),
|
TypeSectionEntry(FuncType),
|
||||||
ImportSectionEntry {
|
ImportSectionEntry {
|
||||||
module: &'a [u8],
|
module: &'a str,
|
||||||
field: &'a [u8],
|
field: &'a str,
|
||||||
ty: ImportSectionEntryType,
|
ty: ImportSectionEntryType,
|
||||||
},
|
},
|
||||||
FunctionSectionEntry(u32),
|
FunctionSectionEntry(u32),
|
||||||
TableSectionEntry(TableType),
|
TableSectionEntry(TableType),
|
||||||
MemorySectionEntry(MemoryType),
|
MemorySectionEntry(MemoryType),
|
||||||
ExportSectionEntry {
|
ExportSectionEntry {
|
||||||
field: &'a [u8],
|
field: &'a str,
|
||||||
kind: ExternalKind,
|
kind: ExternalKind,
|
||||||
index: u32,
|
index: u32,
|
||||||
},
|
},
|
||||||
NameSectionEntry(NameEntry<'a>),
|
NameSectionEntry(NameEntry<'a>),
|
||||||
StartSectionEntry(u32),
|
StartSectionEntry(u32),
|
||||||
|
DataCountSectionEntry(u32),
|
||||||
|
|
||||||
BeginInitExpressionBody,
|
BeginInitExpressionBody,
|
||||||
InitExpressionOperator(Operator<'a>),
|
InitExpressionOperator(Operator<'a>),
|
||||||
|
|
@ -115,11 +116,13 @@ pub enum ParserState<'a> {
|
||||||
EndFunctionBody,
|
EndFunctionBody,
|
||||||
SkippingFunctionBody,
|
SkippingFunctionBody,
|
||||||
|
|
||||||
BeginElementSectionEntry(u32),
|
BeginPassiveElementSectionEntry(Type),
|
||||||
|
BeginActiveElementSectionEntry(u32),
|
||||||
ElementSectionEntryBody(Box<[u32]>),
|
ElementSectionEntryBody(Box<[u32]>),
|
||||||
EndElementSectionEntry,
|
EndElementSectionEntry,
|
||||||
|
|
||||||
BeginDataSectionEntry(u32),
|
BeginPassiveDataSectionEntry,
|
||||||
|
BeginActiveDataSectionEntry(u32),
|
||||||
EndDataSectionEntry,
|
EndDataSectionEntry,
|
||||||
BeginDataSectionEntryBody(u32),
|
BeginDataSectionEntryBody(u32),
|
||||||
DataSectionEntryBodyChunk(&'a [u8]),
|
DataSectionEntryBodyChunk(&'a [u8]),
|
||||||
|
|
@ -132,7 +135,7 @@ pub enum ParserState<'a> {
|
||||||
RelocSectionEntry(RelocEntry),
|
RelocSectionEntry(RelocEntry),
|
||||||
LinkingSectionEntry(LinkingType),
|
LinkingSectionEntry(LinkingType),
|
||||||
|
|
||||||
SourceMappingURL(&'a [u8]),
|
SourceMappingURL(&'a str),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
|
@ -269,33 +272,33 @@ impl<'a> Parser<'a> {
|
||||||
ParserSectionReader::CodeSectionReader(ref reader) => return reader.original_position(),
|
ParserSectionReader::CodeSectionReader(ref reader) => return reader.original_position(),
|
||||||
ParserSectionReader::DataSectionReader(ref reader) => return reader.original_position(),
|
ParserSectionReader::DataSectionReader(ref reader) => return reader.original_position(),
|
||||||
ParserSectionReader::ElementSectionReader(ref reader) => {
|
ParserSectionReader::ElementSectionReader(ref reader) => {
|
||||||
return reader.original_position()
|
return reader.original_position();
|
||||||
}
|
}
|
||||||
ParserSectionReader::ExportSectionReader(ref reader) => {
|
ParserSectionReader::ExportSectionReader(ref reader) => {
|
||||||
return reader.original_position()
|
return reader.original_position();
|
||||||
}
|
}
|
||||||
ParserSectionReader::FunctionSectionReader(ref reader) => {
|
ParserSectionReader::FunctionSectionReader(ref reader) => {
|
||||||
return reader.original_position()
|
return reader.original_position();
|
||||||
}
|
}
|
||||||
ParserSectionReader::GlobalSectionReader(ref reader) => {
|
ParserSectionReader::GlobalSectionReader(ref reader) => {
|
||||||
return reader.original_position()
|
return reader.original_position();
|
||||||
}
|
}
|
||||||
ParserSectionReader::ImportSectionReader(ref reader) => {
|
ParserSectionReader::ImportSectionReader(ref reader) => {
|
||||||
return reader.original_position()
|
return reader.original_position();
|
||||||
}
|
}
|
||||||
ParserSectionReader::MemorySectionReader(ref reader) => {
|
ParserSectionReader::MemorySectionReader(ref reader) => {
|
||||||
return reader.original_position()
|
return reader.original_position();
|
||||||
}
|
}
|
||||||
ParserSectionReader::TableSectionReader(ref reader) => {
|
ParserSectionReader::TableSectionReader(ref reader) => {
|
||||||
return reader.original_position()
|
return reader.original_position();
|
||||||
}
|
}
|
||||||
ParserSectionReader::TypeSectionReader(ref reader) => return reader.original_position(),
|
ParserSectionReader::TypeSectionReader(ref reader) => return reader.original_position(),
|
||||||
ParserSectionReader::NameSectionReader(ref reader) => return reader.original_position(),
|
ParserSectionReader::NameSectionReader(ref reader) => return reader.original_position(),
|
||||||
ParserSectionReader::LinkingSectionReader(ref reader) => {
|
ParserSectionReader::LinkingSectionReader(ref reader) => {
|
||||||
return reader.original_position()
|
return reader.original_position();
|
||||||
}
|
}
|
||||||
ParserSectionReader::RelocSectionReader(ref reader) => {
|
ParserSectionReader::RelocSectionReader(ref reader) => {
|
||||||
return reader.original_position()
|
return reader.original_position();
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
};
|
};
|
||||||
|
|
@ -317,7 +320,7 @@ impl<'a> Parser<'a> {
|
||||||
fn read_section_header(&mut self) -> Result<()> {
|
fn read_section_header(&mut self) -> Result<()> {
|
||||||
let section = self.module_reader.as_mut().expect("module reader").read()?;
|
let section = self.module_reader.as_mut().expect("module reader").read()?;
|
||||||
let code = section.code;
|
let code = section.code;
|
||||||
let range = section.get_range();
|
let range = section.range();
|
||||||
self.current_section = Some(section);
|
self.current_section = Some(section);
|
||||||
self.state = ParserState::BeginSection { code, range };
|
self.state = ParserState::BeginSection { code, range };
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -408,13 +411,19 @@ impl<'a> Parser<'a> {
|
||||||
if self.section_entries_left == 0 {
|
if self.section_entries_left == 0 {
|
||||||
return self.check_section_end();
|
return self.check_section_end();
|
||||||
}
|
}
|
||||||
let Element {
|
let Element { kind, items } = section_reader!(self, ElementSectionReader).read()?;
|
||||||
|
match kind {
|
||||||
|
ElementKind::Passive(ty) => {
|
||||||
|
self.state = ParserState::BeginPassiveElementSectionEntry(ty);
|
||||||
|
}
|
||||||
|
ElementKind::Active {
|
||||||
table_index,
|
table_index,
|
||||||
init_expr,
|
init_expr,
|
||||||
items,
|
} => {
|
||||||
} = section_reader!(self, ElementSectionReader).read()?;
|
self.state = ParserState::BeginActiveElementSectionEntry(table_index);
|
||||||
self.state = ParserState::BeginElementSectionEntry(table_index);
|
|
||||||
self.operators_reader = Some(init_expr.get_operators_reader());
|
self.operators_reader = Some(init_expr.get_operators_reader());
|
||||||
|
}
|
||||||
|
}
|
||||||
self.element_items = Some(items);
|
self.element_items = Some(items);
|
||||||
self.section_entries_left -= 1;
|
self.section_entries_left -= 1;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -447,7 +456,7 @@ impl<'a> Parser<'a> {
|
||||||
return self.check_section_end();
|
return self.check_section_end();
|
||||||
}
|
}
|
||||||
let function_body = section_reader!(self, CodeSectionReader).read()?;
|
let function_body = section_reader!(self, CodeSectionReader).read()?;
|
||||||
let range = function_body.get_range();
|
let range = function_body.range();
|
||||||
self.state = ParserState::BeginFunctionBody { range };
|
self.state = ParserState::BeginFunctionBody { range };
|
||||||
self.current_function_body = Some(function_body);
|
self.current_function_body = Some(function_body);
|
||||||
self.section_entries_left -= 1;
|
self.section_entries_left -= 1;
|
||||||
|
|
@ -529,13 +538,19 @@ impl<'a> Parser<'a> {
|
||||||
if self.section_entries_left == 0 {
|
if self.section_entries_left == 0 {
|
||||||
return self.check_section_end();
|
return self.check_section_end();
|
||||||
}
|
}
|
||||||
let Data {
|
let Data { kind, data } = section_reader!(self, DataSectionReader).read()?;
|
||||||
|
match kind {
|
||||||
|
DataKind::Passive => {
|
||||||
|
self.state = ParserState::BeginPassiveDataSectionEntry;
|
||||||
|
}
|
||||||
|
DataKind::Active {
|
||||||
memory_index,
|
memory_index,
|
||||||
init_expr,
|
init_expr,
|
||||||
data,
|
} => {
|
||||||
} = section_reader!(self, DataSectionReader).read()?;
|
self.state = ParserState::BeginActiveDataSectionEntry(memory_index);
|
||||||
self.state = ParserState::BeginDataSectionEntry(memory_index);
|
|
||||||
self.operators_reader = Some(init_expr.get_operators_reader());
|
self.operators_reader = Some(init_expr.get_operators_reader());
|
||||||
|
}
|
||||||
|
}
|
||||||
self.current_data_segment = Some(data);
|
self.current_data_segment = Some(data);
|
||||||
self.section_entries_left -= 1;
|
self.section_entries_left -= 1;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -731,6 +746,17 @@ impl<'a> Parser<'a> {
|
||||||
.get_start_section_content()?;
|
.get_start_section_content()?;
|
||||||
self.state = ParserState::StartSectionEntry(func_index);
|
self.state = ParserState::StartSectionEntry(func_index);
|
||||||
}
|
}
|
||||||
|
ParserState::BeginSection {
|
||||||
|
code: SectionCode::DataCount,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
let func_index = self
|
||||||
|
.current_section
|
||||||
|
.as_ref()
|
||||||
|
.expect("section")
|
||||||
|
.get_data_count_section_content()?;
|
||||||
|
self.state = ParserState::DataCountSectionEntry(func_index);
|
||||||
|
}
|
||||||
ParserState::BeginSection {
|
ParserState::BeginSection {
|
||||||
code: SectionCode::Custom { .. },
|
code: SectionCode::Custom { .. },
|
||||||
..
|
..
|
||||||
|
|
@ -774,7 +800,8 @@ impl<'a> Parser<'a> {
|
||||||
start_section_reader!(self, LinkingSectionReader, get_linking_section_reader);
|
start_section_reader!(self, LinkingSectionReader, get_linking_section_reader);
|
||||||
self.read_linking_entry()?;
|
self.read_linking_entry()?;
|
||||||
}
|
}
|
||||||
ParserState::ReadingCustomSection(CustomSectionKind::Unknown) => {
|
ParserState::ReadingCustomSection(CustomSectionKind::Producers)
|
||||||
|
| ParserState::ReadingCustomSection(CustomSectionKind::Unknown) => {
|
||||||
self.create_custom_section_binary_reader();
|
self.create_custom_section_binary_reader();
|
||||||
self.read_section_body_bytes()?;
|
self.read_section_body_bytes()?;
|
||||||
}
|
}
|
||||||
|
|
@ -875,13 +902,17 @@ impl<'a> Parser<'a> {
|
||||||
self.read_init_expression_body(InitExpressionContinuation::GlobalSection)
|
self.read_init_expression_body(InitExpressionContinuation::GlobalSection)
|
||||||
}
|
}
|
||||||
ParserState::EndGlobalSectionEntry => self.read_global_entry()?,
|
ParserState::EndGlobalSectionEntry => self.read_global_entry()?,
|
||||||
ParserState::BeginElementSectionEntry(_) => {
|
ParserState::BeginPassiveElementSectionEntry(_) => self.read_element_entry_body()?,
|
||||||
|
ParserState::BeginActiveElementSectionEntry(_) => {
|
||||||
self.read_init_expression_body(InitExpressionContinuation::ElementSection)
|
self.read_init_expression_body(InitExpressionContinuation::ElementSection)
|
||||||
}
|
}
|
||||||
ParserState::BeginInitExpressionBody | ParserState::InitExpressionOperator(_) => {
|
ParserState::BeginInitExpressionBody | ParserState::InitExpressionOperator(_) => {
|
||||||
self.read_init_expression_operator()?
|
self.read_init_expression_operator()?
|
||||||
}
|
}
|
||||||
ParserState::BeginDataSectionEntry(_) => {
|
ParserState::BeginPassiveDataSectionEntry => {
|
||||||
|
self.read_data_entry_body()?;
|
||||||
|
}
|
||||||
|
ParserState::BeginActiveDataSectionEntry(_) => {
|
||||||
self.read_init_expression_body(InitExpressionContinuation::DataSection)
|
self.read_init_expression_body(InitExpressionContinuation::DataSection)
|
||||||
}
|
}
|
||||||
ParserState::EndInitExpressionBody => {
|
ParserState::EndInitExpressionBody => {
|
||||||
|
|
@ -917,6 +948,7 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
ParserState::EndElementSectionEntry => self.read_element_entry()?,
|
ParserState::EndElementSectionEntry => self.read_element_entry()?,
|
||||||
ParserState::StartSectionEntry(_) => self.position_to_section_end()?,
|
ParserState::StartSectionEntry(_) => self.position_to_section_end()?,
|
||||||
|
ParserState::DataCountSectionEntry(_) => self.position_to_section_end()?,
|
||||||
ParserState::NameSectionEntry(_) => self.read_name_entry()?,
|
ParserState::NameSectionEntry(_) => self.read_name_entry()?,
|
||||||
ParserState::SourceMappingURL(_) => self.position_to_section_end()?,
|
ParserState::SourceMappingURL(_) => self.position_to_section_end()?,
|
||||||
ParserState::RelocSectionHeader(_) => {
|
ParserState::RelocSectionHeader(_) => {
|
||||||
|
|
|
||||||
186
third_party/rust/wasmparser/src/primitives.rs
vendored
186
third_party/rust/wasmparser/src/primitives.rs
vendored
|
|
@ -14,6 +14,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use std::boxed::Box;
|
use std::boxed::Box;
|
||||||
|
use std::error::Error;
|
||||||
|
use std::fmt;
|
||||||
use std::result;
|
use std::result;
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
|
@ -24,10 +26,19 @@ pub struct BinaryReaderError {
|
||||||
|
|
||||||
pub type Result<T> = result::Result<T, BinaryReaderError>;
|
pub type Result<T> = result::Result<T, BinaryReaderError>;
|
||||||
|
|
||||||
|
impl Error for BinaryReaderError {}
|
||||||
|
|
||||||
|
impl fmt::Display for BinaryReaderError {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "{} (at offset {})", self.message, self.offset)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
pub enum CustomSectionKind {
|
pub enum CustomSectionKind {
|
||||||
Unknown,
|
Unknown,
|
||||||
Name,
|
Name,
|
||||||
|
Producers,
|
||||||
SourceMappingURL,
|
SourceMappingURL,
|
||||||
Reloc,
|
Reloc,
|
||||||
Linking,
|
Linking,
|
||||||
|
|
@ -39,7 +50,7 @@ pub enum CustomSectionKind {
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
pub enum SectionCode<'a> {
|
pub enum SectionCode<'a> {
|
||||||
Custom {
|
Custom {
|
||||||
name: &'a [u8],
|
name: &'a str,
|
||||||
kind: CustomSectionKind,
|
kind: CustomSectionKind,
|
||||||
},
|
},
|
||||||
Type, // Function signature declarations
|
Type, // Function signature declarations
|
||||||
|
|
@ -53,6 +64,7 @@ pub enum SectionCode<'a> {
|
||||||
Element, // Elements section
|
Element, // Elements section
|
||||||
Code, // Function bodies (code)
|
Code, // Function bodies (code)
|
||||||
Data, // Data segments
|
Data, // Data segments
|
||||||
|
DataCount, // Count of passive data segments
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Types as defined [here].
|
/// Types as defined [here].
|
||||||
|
|
@ -64,6 +76,7 @@ pub enum Type {
|
||||||
I64,
|
I64,
|
||||||
F32,
|
F32,
|
||||||
F64,
|
F64,
|
||||||
|
V128,
|
||||||
AnyFunc,
|
AnyFunc,
|
||||||
AnyRef,
|
AnyRef,
|
||||||
Func,
|
Func,
|
||||||
|
|
@ -129,7 +142,7 @@ pub struct MemoryImmediate {
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct Naming<'a> {
|
pub struct Naming<'a> {
|
||||||
pub index: u32,
|
pub index: u32,
|
||||||
pub name: &'a [u8],
|
pub name: &'a str,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
|
@ -160,6 +173,7 @@ pub enum RelocType {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct BrTable<'a> {
|
pub struct BrTable<'a> {
|
||||||
pub(crate) buffer: &'a [u8],
|
pub(crate) buffer: &'a [u8],
|
||||||
|
pub(crate) cnt: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An IEEE binary32 immediate floating point value, represented as a u32
|
/// An IEEE binary32 immediate floating point value, represented as a u32
|
||||||
|
|
@ -188,6 +202,17 @@ impl Ieee64 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
||||||
|
pub struct V128(pub(crate) [u8; 16]);
|
||||||
|
|
||||||
|
impl V128 {
|
||||||
|
pub fn bytes(&self) -> &[u8; 16] {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type SIMDLineIndex = u8;
|
||||||
|
|
||||||
/// Instructions as defined [here].
|
/// Instructions as defined [here].
|
||||||
///
|
///
|
||||||
/// [here]: https://webassembly.github.io/spec/binary/instructions.html
|
/// [here]: https://webassembly.github.io/spec/binary/instructions.html
|
||||||
|
|
@ -384,6 +409,20 @@ pub enum Operator<'a> {
|
||||||
I64TruncSSatF64,
|
I64TruncSSatF64,
|
||||||
I64TruncUSatF64,
|
I64TruncUSatF64,
|
||||||
|
|
||||||
|
// 0xFC operators
|
||||||
|
// bulk memory https://github.com/WebAssembly/bulk-memory-operations/blob/master/proposals/bulk-memory-operations/Overview.md
|
||||||
|
MemoryInit { segment: u32 },
|
||||||
|
DataDrop { segment: u32 },
|
||||||
|
MemoryCopy,
|
||||||
|
MemoryFill,
|
||||||
|
TableInit { segment: u32 },
|
||||||
|
ElemDrop { segment: u32 },
|
||||||
|
TableCopy,
|
||||||
|
TableGet { table: u32 },
|
||||||
|
TableSet { table: u32 },
|
||||||
|
TableGrow { table: u32 },
|
||||||
|
TableSize { table: u32 },
|
||||||
|
|
||||||
// 0xFE operators
|
// 0xFE operators
|
||||||
// https://github.com/WebAssembly/threads/blob/master/proposals/threads/Overview.md
|
// https://github.com/WebAssembly/threads/blob/master/proposals/threads/Overview.md
|
||||||
Wake { memarg: MemoryImmediate },
|
Wake { memarg: MemoryImmediate },
|
||||||
|
|
@ -452,4 +491,147 @@ pub enum Operator<'a> {
|
||||||
I64AtomicRmw8UCmpxchg { memarg: MemoryImmediate },
|
I64AtomicRmw8UCmpxchg { memarg: MemoryImmediate },
|
||||||
I64AtomicRmw16UCmpxchg { memarg: MemoryImmediate },
|
I64AtomicRmw16UCmpxchg { memarg: MemoryImmediate },
|
||||||
I64AtomicRmw32UCmpxchg { memarg: MemoryImmediate },
|
I64AtomicRmw32UCmpxchg { memarg: MemoryImmediate },
|
||||||
|
|
||||||
|
// 0xFD operators
|
||||||
|
// SIMD https://github.com/WebAssembly/simd/blob/master/proposals/simd/BinarySIMD.md
|
||||||
|
V128Load { memarg: MemoryImmediate },
|
||||||
|
V128Store { memarg: MemoryImmediate },
|
||||||
|
V128Const { value: V128 },
|
||||||
|
V8x16Shuffle { lines: [SIMDLineIndex; 16] },
|
||||||
|
I8x16Splat,
|
||||||
|
I8x16ExtractLaneS { line: SIMDLineIndex },
|
||||||
|
I8x16ExtractLaneU { line: SIMDLineIndex },
|
||||||
|
I8x16ReplaceLane { line: SIMDLineIndex },
|
||||||
|
I16x8Splat,
|
||||||
|
I16x8ExtractLaneS { line: SIMDLineIndex },
|
||||||
|
I16x8ExtractLaneU { line: SIMDLineIndex },
|
||||||
|
I16x8ReplaceLane { line: SIMDLineIndex },
|
||||||
|
I32x4Splat,
|
||||||
|
I32x4ExtractLane { line: SIMDLineIndex },
|
||||||
|
I32x4ReplaceLane { line: SIMDLineIndex },
|
||||||
|
I64x2Splat,
|
||||||
|
I64x2ExtractLane { line: SIMDLineIndex },
|
||||||
|
I64x2ReplaceLane { line: SIMDLineIndex },
|
||||||
|
F32x4Splat,
|
||||||
|
F32x4ExtractLane { line: SIMDLineIndex },
|
||||||
|
F32x4ReplaceLane { line: SIMDLineIndex },
|
||||||
|
F64x2Splat,
|
||||||
|
F64x2ExtractLane { line: SIMDLineIndex },
|
||||||
|
F64x2ReplaceLane { line: SIMDLineIndex },
|
||||||
|
I8x16Eq,
|
||||||
|
I8x16Ne,
|
||||||
|
I8x16LtS,
|
||||||
|
I8x16LtU,
|
||||||
|
I8x16GtS,
|
||||||
|
I8x16GtU,
|
||||||
|
I8x16LeS,
|
||||||
|
I8x16LeU,
|
||||||
|
I8x16GeS,
|
||||||
|
I8x16GeU,
|
||||||
|
I16x8Eq,
|
||||||
|
I16x8Ne,
|
||||||
|
I16x8LtS,
|
||||||
|
I16x8LtU,
|
||||||
|
I16x8GtS,
|
||||||
|
I16x8GtU,
|
||||||
|
I16x8LeS,
|
||||||
|
I16x8LeU,
|
||||||
|
I16x8GeS,
|
||||||
|
I16x8GeU,
|
||||||
|
I32x4Eq,
|
||||||
|
I32x4Ne,
|
||||||
|
I32x4LtS,
|
||||||
|
I32x4LtU,
|
||||||
|
I32x4GtS,
|
||||||
|
I32x4GtU,
|
||||||
|
I32x4LeS,
|
||||||
|
I32x4LeU,
|
||||||
|
I32x4GeS,
|
||||||
|
I32x4GeU,
|
||||||
|
F32x4Eq,
|
||||||
|
F32x4Ne,
|
||||||
|
F32x4Lt,
|
||||||
|
F32x4Gt,
|
||||||
|
F32x4Le,
|
||||||
|
F32x4Ge,
|
||||||
|
F64x2Eq,
|
||||||
|
F64x2Ne,
|
||||||
|
F64x2Lt,
|
||||||
|
F64x2Gt,
|
||||||
|
F64x2Le,
|
||||||
|
F64x2Ge,
|
||||||
|
V128Not,
|
||||||
|
V128And,
|
||||||
|
V128Or,
|
||||||
|
V128Xor,
|
||||||
|
V128Bitselect,
|
||||||
|
I8x16Neg,
|
||||||
|
I8x16AnyTrue,
|
||||||
|
I8x16AllTrue,
|
||||||
|
I8x16Shl,
|
||||||
|
I8x16ShrS,
|
||||||
|
I8x16ShrU,
|
||||||
|
I8x16Add,
|
||||||
|
I8x16AddSaturateS,
|
||||||
|
I8x16AddSaturateU,
|
||||||
|
I8x16Sub,
|
||||||
|
I8x16SubSaturateS,
|
||||||
|
I8x16SubSaturateU,
|
||||||
|
I8x16Mul,
|
||||||
|
I16x8Neg,
|
||||||
|
I16x8AnyTrue,
|
||||||
|
I16x8AllTrue,
|
||||||
|
I16x8Shl,
|
||||||
|
I16x8ShrS,
|
||||||
|
I16x8ShrU,
|
||||||
|
I16x8Add,
|
||||||
|
I16x8AddSaturateS,
|
||||||
|
I16x8AddSaturateU,
|
||||||
|
I16x8Sub,
|
||||||
|
I16x8SubSaturateS,
|
||||||
|
I16x8SubSaturateU,
|
||||||
|
I16x8Mul,
|
||||||
|
I32x4Neg,
|
||||||
|
I32x4AnyTrue,
|
||||||
|
I32x4AllTrue,
|
||||||
|
I32x4Shl,
|
||||||
|
I32x4ShrS,
|
||||||
|
I32x4ShrU,
|
||||||
|
I32x4Add,
|
||||||
|
I32x4Sub,
|
||||||
|
I32x4Mul,
|
||||||
|
I64x2Neg,
|
||||||
|
I64x2AnyTrue,
|
||||||
|
I64x2AllTrue,
|
||||||
|
I64x2Shl,
|
||||||
|
I64x2ShrS,
|
||||||
|
I64x2ShrU,
|
||||||
|
I64x2Add,
|
||||||
|
I64x2Sub,
|
||||||
|
F32x4Abs,
|
||||||
|
F32x4Neg,
|
||||||
|
F32x4Sqrt,
|
||||||
|
F32x4Add,
|
||||||
|
F32x4Sub,
|
||||||
|
F32x4Mul,
|
||||||
|
F32x4Div,
|
||||||
|
F32x4Min,
|
||||||
|
F32x4Max,
|
||||||
|
F64x2Abs,
|
||||||
|
F64x2Neg,
|
||||||
|
F64x2Sqrt,
|
||||||
|
F64x2Add,
|
||||||
|
F64x2Sub,
|
||||||
|
F64x2Mul,
|
||||||
|
F64x2Div,
|
||||||
|
F64x2Min,
|
||||||
|
F64x2Max,
|
||||||
|
I32x4TruncSF32x4Sat,
|
||||||
|
I32x4TruncUF32x4Sat,
|
||||||
|
I64x2TruncSF64x2Sat,
|
||||||
|
I64x2TruncUF64x2Sat,
|
||||||
|
F32x4ConvertSI32x4,
|
||||||
|
F32x4ConvertUI32x4,
|
||||||
|
F64x2ConvertSI64x2,
|
||||||
|
F64x2ConvertUI64x2,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@ impl<'a> FunctionBody<'a> {
|
||||||
Ok(OperatorsReader::new(&self.data[pos..], self.offset + pos))
|
Ok(OperatorsReader::new(&self.data[pos..], self.offset + pos))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn get_range(&self) -> Range {
|
pub fn range(&self) -> Range {
|
||||||
Range {
|
Range {
|
||||||
start: self.offset,
|
start: self.offset,
|
||||||
end: self.offset + self.data.len(),
|
end: self.offset + self.data.len(),
|
||||||
|
|
|
||||||
28
third_party/rust/wasmparser/src/readers/data_count_section.rs
vendored
Normal file
28
third_party/rust/wasmparser/src/readers/data_count_section.rs
vendored
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
/* Copyright 2018 Mozilla Foundation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
use super::{BinaryReader, BinaryReaderError, Result};
|
||||||
|
|
||||||
|
pub(crate) fn read_data_count_section_content(data: &[u8], offset: usize) -> Result<u32> {
|
||||||
|
let mut reader = BinaryReader::new_with_offset(data, offset);
|
||||||
|
let count = reader.read_var_u32()?;
|
||||||
|
if !reader.eof() {
|
||||||
|
return Err(BinaryReaderError {
|
||||||
|
message: "Unexpected content in the data count section",
|
||||||
|
offset: offset + reader.position,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Ok(count)
|
||||||
|
}
|
||||||
|
|
@ -20,11 +20,19 @@ use super::{
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct Data<'a> {
|
pub struct Data<'a> {
|
||||||
pub memory_index: u32,
|
pub kind: DataKind<'a>,
|
||||||
pub init_expr: InitExpr<'a>,
|
|
||||||
pub data: &'a [u8],
|
pub data: &'a [u8],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
pub enum DataKind<'a> {
|
||||||
|
Passive,
|
||||||
|
Active {
|
||||||
|
memory_index: u32,
|
||||||
|
init_expr: InitExpr<'a>,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
pub struct DataSectionReader<'a> {
|
pub struct DataSectionReader<'a> {
|
||||||
reader: BinaryReader<'a>,
|
reader: BinaryReader<'a>,
|
||||||
count: u32,
|
count: u32,
|
||||||
|
|
@ -64,7 +72,7 @@ impl<'a> DataSectionReader<'a> {
|
||||||
/// # 0x05, 0x03, 0x01, 0x00, 0x02,
|
/// # 0x05, 0x03, 0x01, 0x00, 0x02,
|
||||||
/// # 0x0a, 0x05, 0x01, 0x03, 0x00, 0x01, 0x0b,
|
/// # 0x0a, 0x05, 0x01, 0x03, 0x00, 0x01, 0x0b,
|
||||||
/// # 0x0b, 0x0b, 0x01, 0x00, 0x41, 0x80, 0x08, 0x0b, 0x04, 0x00, 0x00, 0x00, 0x00];
|
/// # 0x0b, 0x0b, 0x01, 0x00, 0x41, 0x80, 0x08, 0x0b, 0x04, 0x00, 0x00, 0x00, 0x00];
|
||||||
/// use wasmparser::ModuleReader;
|
/// use wasmparser::{ModuleReader, DataKind};
|
||||||
/// let mut reader = ModuleReader::new(data).expect("module reader");
|
/// let mut reader = ModuleReader::new(data).expect("module reader");
|
||||||
/// let section = reader.read().expect("type section");
|
/// let section = reader.read().expect("type section");
|
||||||
/// let section = reader.read().expect("function section");
|
/// let section = reader.read().expect("function section");
|
||||||
|
|
@ -75,32 +83,48 @@ impl<'a> DataSectionReader<'a> {
|
||||||
/// for _ in 0..data_reader.get_count() {
|
/// for _ in 0..data_reader.get_count() {
|
||||||
/// let data = data_reader.read().expect("data");
|
/// let data = data_reader.read().expect("data");
|
||||||
/// println!("Data: {:?}", data);
|
/// println!("Data: {:?}", data);
|
||||||
/// let mut init_expr_reader = data.init_expr.get_binary_reader();
|
/// if let DataKind::Active { init_expr, .. } = data.kind {
|
||||||
|
/// let mut init_expr_reader = init_expr.get_binary_reader();
|
||||||
/// let op = init_expr_reader.read_operator().expect("op");
|
/// let op = init_expr_reader.read_operator().expect("op");
|
||||||
/// println!("Init const: {:?}", op);
|
/// println!("Init const: {:?}", op);
|
||||||
/// }
|
/// }
|
||||||
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn read<'b>(&mut self) -> Result<Data<'b>>
|
pub fn read<'b>(&mut self) -> Result<Data<'b>>
|
||||||
where
|
where
|
||||||
'a: 'b,
|
'a: 'b,
|
||||||
{
|
{
|
||||||
let memory_index = self.reader.read_var_u32()?;
|
let flags = self.reader.read_var_u32()?;
|
||||||
|
let kind = if flags == 1 {
|
||||||
|
DataKind::Passive
|
||||||
|
} else {
|
||||||
|
let memory_index = match flags {
|
||||||
|
0 => 0,
|
||||||
|
2 => self.reader.read_var_u32()?,
|
||||||
|
_ => {
|
||||||
|
return Err(BinaryReaderError {
|
||||||
|
message: "invalid flags byte in data segment",
|
||||||
|
offset: self.reader.original_position() - 1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
let init_expr = {
|
let init_expr = {
|
||||||
let expr_offset = self.reader.position;
|
let expr_offset = self.reader.position;
|
||||||
self.reader.skip_init_expr()?;
|
self.reader.skip_init_expr()?;
|
||||||
let data = &self.reader.buffer[expr_offset..self.reader.position];
|
let data = &self.reader.buffer[expr_offset..self.reader.position];
|
||||||
InitExpr::new(data, self.reader.original_offset + expr_offset)
|
InitExpr::new(data, self.reader.original_offset + expr_offset)
|
||||||
};
|
};
|
||||||
|
DataKind::Active {
|
||||||
|
memory_index,
|
||||||
|
init_expr,
|
||||||
|
}
|
||||||
|
};
|
||||||
let data_len = self.reader.read_var_u32()? as usize;
|
let data_len = self.reader.read_var_u32()? as usize;
|
||||||
let data_end = self.reader.position + data_len;
|
let data_end = self.reader.position + data_len;
|
||||||
self.verify_data_end(data_end)?;
|
self.verify_data_end(data_end)?;
|
||||||
let data = &self.reader.buffer[self.reader.position..data_end];
|
let data = &self.reader.buffer[self.reader.position..data_end];
|
||||||
self.reader.skip_to(data_end);
|
self.reader.skip_to(data_end);
|
||||||
Ok(Data {
|
Ok(Data { kind, data })
|
||||||
memory_index,
|
|
||||||
init_expr,
|
|
||||||
data,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,16 +14,25 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
BinaryReader, InitExpr, Result, SectionIteratorLimited, SectionReader, SectionWithLimitedItems,
|
BinaryReader, BinaryReaderError, InitExpr, Result, SectionIteratorLimited, SectionReader,
|
||||||
|
SectionWithLimitedItems, Type,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct Element<'a> {
|
pub struct Element<'a> {
|
||||||
pub table_index: u32,
|
pub kind: ElementKind<'a>,
|
||||||
pub init_expr: InitExpr<'a>,
|
|
||||||
pub items: ElementItems<'a>,
|
pub items: ElementItems<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
pub enum ElementKind<'a> {
|
||||||
|
Passive(Type),
|
||||||
|
Active {
|
||||||
|
table_index: u32,
|
||||||
|
init_expr: InitExpr<'a>,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct ElementItems<'a> {
|
pub struct ElementItems<'a> {
|
||||||
offset: usize,
|
offset: usize,
|
||||||
|
|
@ -129,7 +138,7 @@ impl<'a> ElementSectionReader<'a> {
|
||||||
/// # 0x05, 0x03, 0x01, 0x00, 0x02,
|
/// # 0x05, 0x03, 0x01, 0x00, 0x02,
|
||||||
/// # 0x09, 0x07, 0x01, 0x00, 0x41, 0x00, 0x0B, 0x01, 0x00,
|
/// # 0x09, 0x07, 0x01, 0x00, 0x41, 0x00, 0x0B, 0x01, 0x00,
|
||||||
/// # 0x0a, 0x05, 0x01, 0x03, 0x00, 0x01, 0x0b];
|
/// # 0x0a, 0x05, 0x01, 0x03, 0x00, 0x01, 0x0b];
|
||||||
/// use wasmparser::ModuleReader;
|
/// use wasmparser::{ModuleReader, ElementKind};
|
||||||
///use wasmparser::Result;
|
///use wasmparser::Result;
|
||||||
/// let mut reader = ModuleReader::new(data).expect("module reader");
|
/// let mut reader = ModuleReader::new(data).expect("module reader");
|
||||||
/// let section = reader.read().expect("type section");
|
/// let section = reader.read().expect("type section");
|
||||||
|
|
@ -140,9 +149,11 @@ impl<'a> ElementSectionReader<'a> {
|
||||||
/// for _ in 0..element_reader.get_count() {
|
/// for _ in 0..element_reader.get_count() {
|
||||||
/// let element = element_reader.read().expect("element");
|
/// let element = element_reader.read().expect("element");
|
||||||
/// println!("Element: {:?}", element);
|
/// println!("Element: {:?}", element);
|
||||||
/// let mut init_expr_reader = element.init_expr.get_binary_reader();
|
/// if let ElementKind::Active { init_expr, .. } = element.kind {
|
||||||
|
/// let mut init_expr_reader = init_expr.get_binary_reader();
|
||||||
/// let op = init_expr_reader.read_operator().expect("op");
|
/// let op = init_expr_reader.read_operator().expect("op");
|
||||||
/// println!("Init const: {:?}", op);
|
/// println!("Init const: {:?}", op);
|
||||||
|
/// }
|
||||||
/// let mut items_reader = element.items.get_items_reader().expect("items reader");
|
/// let mut items_reader = element.items.get_items_reader().expect("items reader");
|
||||||
/// for _ in 0..items_reader.get_count() {
|
/// for _ in 0..items_reader.get_count() {
|
||||||
/// let item = items_reader.read().expect("item");
|
/// let item = items_reader.read().expect("item");
|
||||||
|
|
@ -154,13 +165,32 @@ impl<'a> ElementSectionReader<'a> {
|
||||||
where
|
where
|
||||||
'a: 'b,
|
'a: 'b,
|
||||||
{
|
{
|
||||||
let table_index = self.reader.read_var_u32()?;
|
let flags = self.reader.read_var_u32()?;
|
||||||
|
let kind = if flags == 1 {
|
||||||
|
let ty = self.reader.read_type()?;
|
||||||
|
ElementKind::Passive(ty)
|
||||||
|
} else {
|
||||||
|
let table_index = match flags {
|
||||||
|
0 => 0,
|
||||||
|
2 => self.reader.read_var_u32()?,
|
||||||
|
_ => {
|
||||||
|
return Err(BinaryReaderError {
|
||||||
|
message: "invalid flags byte in element segment",
|
||||||
|
offset: self.reader.original_position() - 1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
let init_expr = {
|
let init_expr = {
|
||||||
let expr_offset = self.reader.position;
|
let expr_offset = self.reader.position;
|
||||||
self.reader.skip_init_expr()?;
|
self.reader.skip_init_expr()?;
|
||||||
let data = &self.reader.buffer[expr_offset..self.reader.position];
|
let data = &self.reader.buffer[expr_offset..self.reader.position];
|
||||||
InitExpr::new(data, self.reader.original_offset + expr_offset)
|
InitExpr::new(data, self.reader.original_offset + expr_offset)
|
||||||
};
|
};
|
||||||
|
ElementKind::Active {
|
||||||
|
table_index,
|
||||||
|
init_expr,
|
||||||
|
}
|
||||||
|
};
|
||||||
let data_start = self.reader.position;
|
let data_start = self.reader.position;
|
||||||
let items_count = self.reader.read_var_u32()?;
|
let items_count = self.reader.read_var_u32()?;
|
||||||
for _ in 0..items_count {
|
for _ in 0..items_count {
|
||||||
|
|
@ -171,11 +201,7 @@ impl<'a> ElementSectionReader<'a> {
|
||||||
offset: self.reader.original_offset + data_start,
|
offset: self.reader.original_offset + data_start,
|
||||||
data: &self.reader.buffer[data_start..data_end],
|
data: &self.reader.buffer[data_start..data_end],
|
||||||
};
|
};
|
||||||
Ok(Element {
|
Ok(Element { kind, items })
|
||||||
table_index,
|
|
||||||
init_expr,
|
|
||||||
items,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ use super::{
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct Export<'a> {
|
pub struct Export<'a> {
|
||||||
pub field: &'a [u8],
|
pub field: &'a str,
|
||||||
pub kind: ExternalKind,
|
pub kind: ExternalKind,
|
||||||
pub index: u32,
|
pub index: u32,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,8 +20,8 @@ use super::{
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct Import<'a> {
|
pub struct Import<'a> {
|
||||||
pub module: &'a [u8],
|
pub module: &'a str,
|
||||||
pub field: &'a [u8],
|
pub field: &'a str,
|
||||||
pub ty: ImportSectionEntryType,
|
pub ty: ImportSectionEntryType,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,11 +24,14 @@ use super::SectionHeader;
|
||||||
pub use self::code_section::CodeSectionReader;
|
pub use self::code_section::CodeSectionReader;
|
||||||
pub use self::code_section::FunctionBody;
|
pub use self::code_section::FunctionBody;
|
||||||
pub use self::code_section::LocalsReader;
|
pub use self::code_section::LocalsReader;
|
||||||
|
use self::data_count_section::read_data_count_section_content;
|
||||||
pub use self::data_section::Data;
|
pub use self::data_section::Data;
|
||||||
|
pub use self::data_section::DataKind;
|
||||||
pub use self::data_section::DataSectionReader;
|
pub use self::data_section::DataSectionReader;
|
||||||
pub use self::element_section::Element;
|
pub use self::element_section::Element;
|
||||||
pub use self::element_section::ElementItems;
|
pub use self::element_section::ElementItems;
|
||||||
pub use self::element_section::ElementItemsReader;
|
pub use self::element_section::ElementItemsReader;
|
||||||
|
pub use self::element_section::ElementKind;
|
||||||
pub use self::element_section::ElementSectionReader;
|
pub use self::element_section::ElementSectionReader;
|
||||||
pub use self::export_section::Export;
|
pub use self::export_section::Export;
|
||||||
pub use self::export_section::ExportSectionReader;
|
pub use self::export_section::ExportSectionReader;
|
||||||
|
|
@ -57,6 +60,10 @@ pub use self::name_section::Name;
|
||||||
pub use self::name_section::NameSectionReader;
|
pub use self::name_section::NameSectionReader;
|
||||||
pub use self::name_section::NamingReader;
|
pub use self::name_section::NamingReader;
|
||||||
|
|
||||||
|
pub use self::producers_section::ProducersField;
|
||||||
|
pub use self::producers_section::ProducersFieldValue;
|
||||||
|
pub use self::producers_section::ProducersSectionReader;
|
||||||
|
|
||||||
pub use self::linking_section::LinkingSectionReader;
|
pub use self::linking_section::LinkingSectionReader;
|
||||||
|
|
||||||
pub use self::reloc_section::Reloc;
|
pub use self::reloc_section::Reloc;
|
||||||
|
|
@ -67,6 +74,7 @@ use self::sourcemappingurl_section::read_sourcemappingurl_section_content;
|
||||||
pub use self::operators::OperatorsReader;
|
pub use self::operators::OperatorsReader;
|
||||||
|
|
||||||
mod code_section;
|
mod code_section;
|
||||||
|
mod data_count_section;
|
||||||
mod data_section;
|
mod data_section;
|
||||||
mod element_section;
|
mod element_section;
|
||||||
mod export_section;
|
mod export_section;
|
||||||
|
|
@ -79,6 +87,7 @@ mod memory_section;
|
||||||
mod module;
|
mod module;
|
||||||
mod name_section;
|
mod name_section;
|
||||||
mod operators;
|
mod operators;
|
||||||
|
mod producers_section;
|
||||||
mod reloc_section;
|
mod reloc_section;
|
||||||
mod section_reader;
|
mod section_reader;
|
||||||
mod sourcemappingurl_section;
|
mod sourcemappingurl_section;
|
||||||
|
|
|
||||||
|
|
@ -20,10 +20,11 @@ use super::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
read_sourcemappingurl_section_content, read_start_section_content, CodeSectionReader,
|
read_data_count_section_content, read_sourcemappingurl_section_content,
|
||||||
DataSectionReader, ElementSectionReader, ExportSectionReader, FunctionSectionReader,
|
read_start_section_content, CodeSectionReader, DataSectionReader, ElementSectionReader,
|
||||||
GlobalSectionReader, ImportSectionReader, LinkingSectionReader, MemorySectionReader,
|
ExportSectionReader, FunctionSectionReader, GlobalSectionReader, ImportSectionReader,
|
||||||
NameSectionReader, RelocSectionReader, TableSectionReader, TypeSectionReader,
|
LinkingSectionReader, MemorySectionReader, NameSectionReader, ProducersSectionReader,
|
||||||
|
RelocSectionReader, TableSectionReader, TypeSectionReader,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
@ -167,6 +168,19 @@ impl<'a> Section<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_producers_section_reader<'b>(&self) -> Result<ProducersSectionReader<'b>>
|
||||||
|
where
|
||||||
|
'a: 'b,
|
||||||
|
{
|
||||||
|
match self.code {
|
||||||
|
SectionCode::Custom {
|
||||||
|
kind: CustomSectionKind::Producers,
|
||||||
|
..
|
||||||
|
} => ProducersSectionReader::new(self.data, self.offset),
|
||||||
|
_ => panic!("Invalid state for get_producers_section_reader"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_linking_section_reader<'b>(&self) -> Result<LinkingSectionReader<'b>>
|
pub fn get_linking_section_reader<'b>(&self) -> Result<LinkingSectionReader<'b>>
|
||||||
where
|
where
|
||||||
'a: 'b,
|
'a: 'b,
|
||||||
|
|
@ -200,7 +214,14 @@ impl<'a> Section<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_sourcemappingurl_section_content<'b>(&self) -> Result<&'b [u8]>
|
pub fn get_data_count_section_content(&self) -> Result<u32> {
|
||||||
|
match self.code {
|
||||||
|
SectionCode::DataCount => read_data_count_section_content(self.data, self.offset),
|
||||||
|
_ => panic!("Invalid state for get_data_count_section_content"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_sourcemappingurl_section_content<'b>(&self) -> Result<&'b str>
|
||||||
where
|
where
|
||||||
'a: 'b,
|
'a: 'b,
|
||||||
{
|
{
|
||||||
|
|
@ -220,7 +241,7 @@ impl<'a> Section<'a> {
|
||||||
BinaryReader::new_with_offset(self.data, self.offset)
|
BinaryReader::new_with_offset(self.data, self.offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn get_range(&self) -> Range {
|
pub fn range(&self) -> Range {
|
||||||
Range {
|
Range {
|
||||||
start: self.offset,
|
start: self.offset,
|
||||||
end: self.offset + self.data.len(),
|
end: self.offset + self.data.len(),
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ pub struct ModuleName<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ModuleName<'a> {
|
impl<'a> ModuleName<'a> {
|
||||||
pub fn get_name<'b>(&self) -> Result<&'b [u8]>
|
pub fn get_name<'b>(&self) -> Result<&'b str>
|
||||||
where
|
where
|
||||||
'a: 'b,
|
'a: 'b,
|
||||||
{
|
{
|
||||||
|
|
|
||||||
192
third_party/rust/wasmparser/src/readers/producers_section.rs
vendored
Normal file
192
third_party/rust/wasmparser/src/readers/producers_section.rs
vendored
Normal file
|
|
@ -0,0 +1,192 @@
|
||||||
|
/* Copyright 2019 Mozilla Foundation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
use super::{BinaryReader, Result, SectionIteratorLimited, SectionReader, SectionWithLimitedItems};
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
pub struct ProducersFieldValue<'a> {
|
||||||
|
pub name: &'a str,
|
||||||
|
pub version: &'a str,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ProducersFieldValuesReader<'a> {
|
||||||
|
reader: BinaryReader<'a>,
|
||||||
|
count: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> ProducersFieldValuesReader<'a> {
|
||||||
|
pub fn get_count(&self) -> u32 {
|
||||||
|
self.count
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn original_position(&self) -> usize {
|
||||||
|
self.reader.original_position()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn skip(reader: &mut BinaryReader, values_count: u32) -> Result<()> {
|
||||||
|
for _ in 0..values_count {
|
||||||
|
reader.skip_string()?;
|
||||||
|
reader.skip_string()?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read<'b>(&mut self) -> Result<ProducersFieldValue<'b>>
|
||||||
|
where
|
||||||
|
'a: 'b,
|
||||||
|
{
|
||||||
|
let name = self.reader.read_string()?;
|
||||||
|
let version = self.reader.read_string()?;
|
||||||
|
Ok(ProducersFieldValue { name, version })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> IntoIterator for ProducersFieldValuesReader<'a> {
|
||||||
|
type Item = Result<ProducersFieldValue<'a>>;
|
||||||
|
type IntoIter = ProducersFieldValuesIterator<'a>;
|
||||||
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
|
let count = self.count;
|
||||||
|
ProducersFieldValuesIterator {
|
||||||
|
reader: self,
|
||||||
|
left: count,
|
||||||
|
err: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ProducersFieldValuesIterator<'a> {
|
||||||
|
reader: ProducersFieldValuesReader<'a>,
|
||||||
|
left: u32,
|
||||||
|
err: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Iterator for ProducersFieldValuesIterator<'a> {
|
||||||
|
type Item = Result<ProducersFieldValue<'a>>;
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
if self.err || self.left == 0 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let result = self.reader.read();
|
||||||
|
self.err = result.is_err();
|
||||||
|
self.left -= 1;
|
||||||
|
Some(result)
|
||||||
|
}
|
||||||
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||||
|
let count = self.reader.get_count() as usize;
|
||||||
|
(count, Some(count))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
pub struct ProducersField<'a> {
|
||||||
|
pub name: &'a str,
|
||||||
|
values_count: u32,
|
||||||
|
values_data: &'a [u8],
|
||||||
|
values_offset: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> ProducersField<'a> {
|
||||||
|
pub fn get_producer_field_values_reader<'b>(&self) -> Result<ProducersFieldValuesReader<'b>>
|
||||||
|
where
|
||||||
|
'a: 'b,
|
||||||
|
{
|
||||||
|
Ok(ProducersFieldValuesReader {
|
||||||
|
reader: BinaryReader::new_with_offset(self.values_data, self.values_offset),
|
||||||
|
count: self.values_count,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ProducersSectionReader<'a> {
|
||||||
|
reader: BinaryReader<'a>,
|
||||||
|
count: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> ProducersSectionReader<'a> {
|
||||||
|
/// Creates reader for the producers section.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
/// ```
|
||||||
|
/// # let data: &[u8] = &[0x01, 0x08, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65,
|
||||||
|
/// # 0x02, 0x03, 0x77, 0x61, 0x74, 0x01, 0x31, 0x01, 0x43, 0x03, 0x39, 0x2e, 0x30];
|
||||||
|
/// use wasmparser::{ProducersSectionReader, ProducersFieldValue, Result};
|
||||||
|
/// let mut reader = ProducersSectionReader::new(data, 0).expect("producers reader");
|
||||||
|
/// let field = reader.read().expect("producers field");
|
||||||
|
/// assert!(field.name == "language");
|
||||||
|
/// let mut values_reader = field.get_producer_field_values_reader().expect("values reader");
|
||||||
|
/// let value = values_reader.into_iter().collect::<Result<Vec<ProducersFieldValue>>>().expect("values");
|
||||||
|
/// assert!(value.len() == 2);
|
||||||
|
/// assert!(value[0].name == "wat" && value[0].version == "1");
|
||||||
|
/// assert!(value[1].name == "C" && value[1].version == "9.0");
|
||||||
|
/// ```
|
||||||
|
pub fn new(data: &'a [u8], offset: usize) -> Result<ProducersSectionReader<'a>> {
|
||||||
|
let mut reader = BinaryReader::new_with_offset(data, offset);
|
||||||
|
let count = reader.read_var_u32()?;
|
||||||
|
Ok(ProducersSectionReader { reader, count })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn original_position(&self) -> usize {
|
||||||
|
self.reader.original_position()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_count(&self) -> u32 {
|
||||||
|
self.count
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read<'b>(&mut self) -> Result<ProducersField<'b>>
|
||||||
|
where
|
||||||
|
'a: 'b,
|
||||||
|
{
|
||||||
|
let name = self.reader.read_string()?;
|
||||||
|
let values_count = self.reader.read_var_u32()?;
|
||||||
|
let values_start = self.reader.position;
|
||||||
|
ProducersFieldValuesReader::skip(&mut self.reader, values_count)?;
|
||||||
|
let values_end = self.reader.position;
|
||||||
|
Ok(ProducersField {
|
||||||
|
name,
|
||||||
|
values_count,
|
||||||
|
values_data: &self.reader.buffer[values_start..values_end],
|
||||||
|
values_offset: self.reader.original_offset + values_start,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> SectionReader for ProducersSectionReader<'a> {
|
||||||
|
type Item = ProducersField<'a>;
|
||||||
|
fn read(&mut self) -> Result<Self::Item> {
|
||||||
|
ProducersSectionReader::read(self)
|
||||||
|
}
|
||||||
|
fn eof(&self) -> bool {
|
||||||
|
self.reader.eof()
|
||||||
|
}
|
||||||
|
fn original_position(&self) -> usize {
|
||||||
|
ProducersSectionReader::original_position(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> SectionWithLimitedItems for ProducersSectionReader<'a> {
|
||||||
|
fn get_count(&self) -> u32 {
|
||||||
|
ProducersSectionReader::get_count(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> IntoIterator for ProducersSectionReader<'a> {
|
||||||
|
type Item = Result<ProducersField<'a>>;
|
||||||
|
type IntoIter = SectionIteratorLimited<ProducersSectionReader<'a>>;
|
||||||
|
|
||||||
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
|
SectionIteratorLimited::new(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -18,7 +18,7 @@ use super::{BinaryReader, BinaryReaderError, Result};
|
||||||
pub(crate) fn read_sourcemappingurl_section_content<'a>(
|
pub(crate) fn read_sourcemappingurl_section_content<'a>(
|
||||||
data: &'a [u8],
|
data: &'a [u8],
|
||||||
offset: usize,
|
offset: usize,
|
||||||
) -> Result<&'a [u8]> {
|
) -> Result<&'a str> {
|
||||||
let mut reader = BinaryReader::new_with_offset(data, offset);
|
let mut reader = BinaryReader::new_with_offset(data, offset);
|
||||||
let url = reader.read_string()?;
|
let url = reader.read_string()?;
|
||||||
if !reader.eof() {
|
if !reader.eof() {
|
||||||
|
|
|
||||||
2
third_party/rust/wasmparser/src/tests.rs
vendored
2
third_party/rust/wasmparser/src/tests.rs
vendored
|
|
@ -27,6 +27,8 @@ mod simple_tests {
|
||||||
operator_config: OperatorValidatorConfig {
|
operator_config: OperatorValidatorConfig {
|
||||||
enable_threads: true,
|
enable_threads: true,
|
||||||
enable_reference_types: true,
|
enable_reference_types: true,
|
||||||
|
enable_simd: true,
|
||||||
|
enable_bulk_memory: true,
|
||||||
},
|
},
|
||||||
mutable_global_imports: true,
|
mutable_global_imports: true,
|
||||||
});
|
});
|
||||||
|
|
|
||||||
450
third_party/rust/wasmparser/src/validator.rs
vendored
450
third_party/rust/wasmparser/src/validator.rs
vendored
|
|
@ -29,7 +29,7 @@ use binary_reader::BinaryReader;
|
||||||
|
|
||||||
use primitives::{
|
use primitives::{
|
||||||
BinaryReaderError, ExternalKind, FuncType, GlobalType, ImportSectionEntryType, MemoryImmediate,
|
BinaryReaderError, ExternalKind, FuncType, GlobalType, ImportSectionEntryType, MemoryImmediate,
|
||||||
MemoryType, Operator, ResizableLimits, Result, SectionCode, TableType, Type,
|
MemoryType, Operator, ResizableLimits, Result, SIMDLineIndex, SectionCode, TableType, Type,
|
||||||
};
|
};
|
||||||
|
|
||||||
use parser::{Parser, ParserInput, ParserState, WasmDecoder};
|
use parser::{Parser, ParserInput, ParserState, WasmDecoder};
|
||||||
|
|
@ -128,6 +128,7 @@ enum SectionOrderState {
|
||||||
Export,
|
Export,
|
||||||
Start,
|
Start,
|
||||||
Element,
|
Element,
|
||||||
|
DataCount,
|
||||||
Code,
|
Code,
|
||||||
Data,
|
Data,
|
||||||
}
|
}
|
||||||
|
|
@ -146,6 +147,7 @@ impl SectionOrderState {
|
||||||
SectionCode::Element => Some(SectionOrderState::Element),
|
SectionCode::Element => Some(SectionOrderState::Element),
|
||||||
SectionCode::Code => Some(SectionOrderState::Code),
|
SectionCode::Code => Some(SectionOrderState::Code),
|
||||||
SectionCode::Data => Some(SectionOrderState::Data),
|
SectionCode::Data => Some(SectionOrderState::Data),
|
||||||
|
SectionCode::DataCount => Some(SectionOrderState::DataCount),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -302,6 +304,8 @@ pub trait WasmModuleResources {
|
||||||
fn memories(&self) -> &[MemoryType];
|
fn memories(&self) -> &[MemoryType];
|
||||||
fn globals(&self) -> &[GlobalType];
|
fn globals(&self) -> &[GlobalType];
|
||||||
fn func_type_indices(&self) -> &[u32];
|
fn func_type_indices(&self) -> &[u32];
|
||||||
|
fn element_count(&self) -> u32;
|
||||||
|
fn data_count(&self) -> u32;
|
||||||
}
|
}
|
||||||
|
|
||||||
type OperatorValidatorResult<T> = result::Result<T, &'static str>;
|
type OperatorValidatorResult<T> = result::Result<T, &'static str>;
|
||||||
|
|
@ -310,11 +314,15 @@ type OperatorValidatorResult<T> = result::Result<T, &'static str>;
|
||||||
pub struct OperatorValidatorConfig {
|
pub struct OperatorValidatorConfig {
|
||||||
pub enable_threads: bool,
|
pub enable_threads: bool,
|
||||||
pub enable_reference_types: bool,
|
pub enable_reference_types: bool,
|
||||||
|
pub enable_simd: bool,
|
||||||
|
pub enable_bulk_memory: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
const DEFAULT_OPERATOR_VALIDATOR_CONFIG: OperatorValidatorConfig = OperatorValidatorConfig {
|
const DEFAULT_OPERATOR_VALIDATOR_CONFIG: OperatorValidatorConfig = OperatorValidatorConfig {
|
||||||
enable_threads: false,
|
enable_threads: false,
|
||||||
enable_reference_types: false,
|
enable_reference_types: false,
|
||||||
|
enable_simd: false,
|
||||||
|
enable_bulk_memory: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct OperatorValidator {
|
struct OperatorValidator {
|
||||||
|
|
@ -453,7 +461,7 @@ impl OperatorValidator {
|
||||||
}
|
}
|
||||||
let block = func_state.block_at(relative_depth as usize);
|
let block = func_state.block_at(relative_depth as usize);
|
||||||
if block.jump_to_top {
|
if block.jump_to_top {
|
||||||
if !func_state.assert_last_block_stack_len_exact(reserve_items) {
|
if !func_state.assert_block_stack_len(0, reserve_items) {
|
||||||
return Err("stack size does not match target loop type");
|
return Err("stack size does not match target loop type");
|
||||||
}
|
}
|
||||||
return Ok(());
|
return Ok(());
|
||||||
|
|
@ -549,6 +557,20 @@ impl OperatorValidator {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn check_simd_enabled(&self) -> OperatorValidatorResult<()> {
|
||||||
|
if !self.config.enable_simd {
|
||||||
|
return Err("SIMD support is not enabled");
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_bulk_memory_enabled(&self) -> OperatorValidatorResult<()> {
|
||||||
|
if !self.config.enable_bulk_memory {
|
||||||
|
return Err("bulk memory support is not enabled");
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn check_shared_memarg_wo_align(
|
fn check_shared_memarg_wo_align(
|
||||||
&self,
|
&self,
|
||||||
_: &MemoryImmediate,
|
_: &MemoryImmediate,
|
||||||
|
|
@ -558,6 +580,13 @@ impl OperatorValidator {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn check_simd_line_index(&self, index: SIMDLineIndex, max: u8) -> OperatorValidatorResult<()> {
|
||||||
|
if index >= max {
|
||||||
|
return Err("SIMD index out of bounds");
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn check_block_type(&self, ty: Type) -> OperatorValidatorResult<()> {
|
fn check_block_type(&self, ty: Type) -> OperatorValidatorResult<()> {
|
||||||
match ty {
|
match ty {
|
||||||
Type::EmptyBlockType | Type::I32 | Type::I64 | Type::F32 | Type::F64 => Ok(()),
|
Type::EmptyBlockType | Type::I32 | Type::I64 | Type::F32 | Type::F64 => Ok(()),
|
||||||
|
|
@ -1244,6 +1273,338 @@ impl OperatorValidator {
|
||||||
self.check_operands(func_state, &[Type::AnyRef])?;
|
self.check_operands(func_state, &[Type::AnyRef])?;
|
||||||
OperatorAction::ChangeFrameWithType(0, Type::I32)
|
OperatorAction::ChangeFrameWithType(0, Type::I32)
|
||||||
}
|
}
|
||||||
|
Operator::V128Load { ref memarg } => {
|
||||||
|
self.check_simd_enabled()?;
|
||||||
|
self.check_memarg(memarg, 4, resources)?;
|
||||||
|
self.check_operands_1(func_state, Type::I32)?;
|
||||||
|
OperatorAction::ChangeFrameWithType(1, Type::V128)
|
||||||
|
}
|
||||||
|
Operator::V128Store { ref memarg } => {
|
||||||
|
self.check_simd_enabled()?;
|
||||||
|
self.check_memarg(memarg, 4, resources)?;
|
||||||
|
self.check_operands_2(func_state, Type::I32, Type::V128)?;
|
||||||
|
OperatorAction::ChangeFrame(2)
|
||||||
|
}
|
||||||
|
Operator::V128Const { .. } => {
|
||||||
|
self.check_simd_enabled()?;
|
||||||
|
OperatorAction::ChangeFrameWithType(0, Type::V128)
|
||||||
|
}
|
||||||
|
Operator::V8x16Shuffle { ref lines } => {
|
||||||
|
self.check_simd_enabled()?;
|
||||||
|
self.check_operands_2(func_state, Type::V128, Type::V128)?;
|
||||||
|
for i in lines {
|
||||||
|
self.check_simd_line_index(*i, 32)?;
|
||||||
|
}
|
||||||
|
OperatorAction::ChangeFrameWithType(2, Type::V128)
|
||||||
|
}
|
||||||
|
Operator::I8x16Splat | Operator::I16x8Splat | Operator::I32x4Splat => {
|
||||||
|
self.check_simd_enabled()?;
|
||||||
|
self.check_operands_1(func_state, Type::I32)?;
|
||||||
|
OperatorAction::ChangeFrameWithType(1, Type::V128)
|
||||||
|
}
|
||||||
|
Operator::I64x2Splat => {
|
||||||
|
self.check_simd_enabled()?;
|
||||||
|
self.check_operands_1(func_state, Type::I64)?;
|
||||||
|
OperatorAction::ChangeFrameWithType(1, Type::V128)
|
||||||
|
}
|
||||||
|
Operator::F32x4Splat => {
|
||||||
|
self.check_simd_enabled()?;
|
||||||
|
self.check_operands_1(func_state, Type::F32)?;
|
||||||
|
OperatorAction::ChangeFrameWithType(1, Type::V128)
|
||||||
|
}
|
||||||
|
Operator::F64x2Splat => {
|
||||||
|
self.check_simd_enabled()?;
|
||||||
|
self.check_operands_1(func_state, Type::F64)?;
|
||||||
|
OperatorAction::ChangeFrameWithType(1, Type::V128)
|
||||||
|
}
|
||||||
|
Operator::I8x16ExtractLaneS { line } | Operator::I8x16ExtractLaneU { line } => {
|
||||||
|
self.check_simd_enabled()?;
|
||||||
|
self.check_simd_line_index(line, 16)?;
|
||||||
|
self.check_operands_1(func_state, Type::V128)?;
|
||||||
|
OperatorAction::ChangeFrameWithType(1, Type::I32)
|
||||||
|
}
|
||||||
|
Operator::I16x8ExtractLaneS { line } | Operator::I16x8ExtractLaneU { line } => {
|
||||||
|
self.check_simd_enabled()?;
|
||||||
|
self.check_simd_line_index(line, 8)?;
|
||||||
|
self.check_operands_1(func_state, Type::V128)?;
|
||||||
|
OperatorAction::ChangeFrameWithType(1, Type::I32)
|
||||||
|
}
|
||||||
|
Operator::I32x4ExtractLane { line } => {
|
||||||
|
self.check_simd_enabled()?;
|
||||||
|
self.check_simd_line_index(line, 4)?;
|
||||||
|
self.check_operands_1(func_state, Type::V128)?;
|
||||||
|
OperatorAction::ChangeFrameWithType(1, Type::I32)
|
||||||
|
}
|
||||||
|
Operator::I8x16ReplaceLane { line } => {
|
||||||
|
self.check_simd_enabled()?;
|
||||||
|
self.check_simd_line_index(line, 16)?;
|
||||||
|
self.check_operands_2(func_state, Type::V128, Type::I32)?;
|
||||||
|
OperatorAction::ChangeFrameWithType(2, Type::V128)
|
||||||
|
}
|
||||||
|
Operator::I16x8ReplaceLane { line } => {
|
||||||
|
self.check_simd_enabled()?;
|
||||||
|
self.check_simd_line_index(line, 8)?;
|
||||||
|
self.check_operands_2(func_state, Type::V128, Type::I32)?;
|
||||||
|
OperatorAction::ChangeFrameWithType(2, Type::V128)
|
||||||
|
}
|
||||||
|
Operator::I32x4ReplaceLane { line } => {
|
||||||
|
self.check_simd_enabled()?;
|
||||||
|
self.check_simd_line_index(line, 4)?;
|
||||||
|
self.check_operands_2(func_state, Type::V128, Type::I32)?;
|
||||||
|
OperatorAction::ChangeFrameWithType(2, Type::V128)
|
||||||
|
}
|
||||||
|
Operator::I64x2ExtractLane { line } => {
|
||||||
|
self.check_simd_enabled()?;
|
||||||
|
self.check_simd_line_index(line, 2)?;
|
||||||
|
self.check_operands_1(func_state, Type::V128)?;
|
||||||
|
OperatorAction::ChangeFrameWithType(1, Type::I64)
|
||||||
|
}
|
||||||
|
Operator::I64x2ReplaceLane { line } => {
|
||||||
|
self.check_simd_enabled()?;
|
||||||
|
self.check_simd_line_index(line, 2)?;
|
||||||
|
self.check_operands_2(func_state, Type::V128, Type::I64)?;
|
||||||
|
OperatorAction::ChangeFrameWithType(2, Type::V128)
|
||||||
|
}
|
||||||
|
Operator::F32x4ExtractLane { line } => {
|
||||||
|
self.check_simd_enabled()?;
|
||||||
|
self.check_simd_line_index(line, 4)?;
|
||||||
|
self.check_operands_1(func_state, Type::V128)?;
|
||||||
|
OperatorAction::ChangeFrameWithType(1, Type::F32)
|
||||||
|
}
|
||||||
|
Operator::F32x4ReplaceLane { line } => {
|
||||||
|
self.check_simd_enabled()?;
|
||||||
|
self.check_simd_line_index(line, 4)?;
|
||||||
|
self.check_operands_2(func_state, Type::V128, Type::F32)?;
|
||||||
|
OperatorAction::ChangeFrameWithType(2, Type::V128)
|
||||||
|
}
|
||||||
|
Operator::F64x2ExtractLane { line } => {
|
||||||
|
self.check_simd_enabled()?;
|
||||||
|
self.check_simd_line_index(line, 2)?;
|
||||||
|
self.check_operands_1(func_state, Type::V128)?;
|
||||||
|
OperatorAction::ChangeFrameWithType(1, Type::F64)
|
||||||
|
}
|
||||||
|
Operator::F64x2ReplaceLane { line } => {
|
||||||
|
self.check_simd_enabled()?;
|
||||||
|
self.check_simd_line_index(line, 2)?;
|
||||||
|
self.check_operands_2(func_state, Type::V128, Type::F64)?;
|
||||||
|
OperatorAction::ChangeFrameWithType(2, Type::V128)
|
||||||
|
}
|
||||||
|
Operator::I8x16Eq
|
||||||
|
| Operator::I8x16Ne
|
||||||
|
| Operator::I8x16LtS
|
||||||
|
| Operator::I8x16LtU
|
||||||
|
| Operator::I8x16GtS
|
||||||
|
| Operator::I8x16GtU
|
||||||
|
| Operator::I8x16LeS
|
||||||
|
| Operator::I8x16LeU
|
||||||
|
| Operator::I8x16GeS
|
||||||
|
| Operator::I8x16GeU
|
||||||
|
| Operator::I16x8Eq
|
||||||
|
| Operator::I16x8Ne
|
||||||
|
| Operator::I16x8LtS
|
||||||
|
| Operator::I16x8LtU
|
||||||
|
| Operator::I16x8GtS
|
||||||
|
| Operator::I16x8GtU
|
||||||
|
| Operator::I16x8LeS
|
||||||
|
| Operator::I16x8LeU
|
||||||
|
| Operator::I16x8GeS
|
||||||
|
| Operator::I16x8GeU
|
||||||
|
| Operator::I32x4Eq
|
||||||
|
| Operator::I32x4Ne
|
||||||
|
| Operator::I32x4LtS
|
||||||
|
| Operator::I32x4LtU
|
||||||
|
| Operator::I32x4GtS
|
||||||
|
| Operator::I32x4GtU
|
||||||
|
| Operator::I32x4LeS
|
||||||
|
| Operator::I32x4LeU
|
||||||
|
| Operator::I32x4GeS
|
||||||
|
| Operator::I32x4GeU
|
||||||
|
| Operator::F32x4Eq
|
||||||
|
| Operator::F32x4Ne
|
||||||
|
| Operator::F32x4Lt
|
||||||
|
| Operator::F32x4Gt
|
||||||
|
| Operator::F32x4Le
|
||||||
|
| Operator::F32x4Ge
|
||||||
|
| Operator::F64x2Eq
|
||||||
|
| Operator::F64x2Ne
|
||||||
|
| Operator::F64x2Lt
|
||||||
|
| Operator::F64x2Gt
|
||||||
|
| Operator::F64x2Le
|
||||||
|
| Operator::F64x2Ge
|
||||||
|
| Operator::V128And
|
||||||
|
| Operator::V128Or
|
||||||
|
| Operator::V128Xor
|
||||||
|
| Operator::I8x16Add
|
||||||
|
| Operator::I8x16AddSaturateS
|
||||||
|
| Operator::I8x16AddSaturateU
|
||||||
|
| Operator::I8x16Sub
|
||||||
|
| Operator::I8x16SubSaturateS
|
||||||
|
| Operator::I8x16SubSaturateU
|
||||||
|
| Operator::I8x16Mul
|
||||||
|
| Operator::I16x8Add
|
||||||
|
| Operator::I16x8AddSaturateS
|
||||||
|
| Operator::I16x8AddSaturateU
|
||||||
|
| Operator::I16x8Sub
|
||||||
|
| Operator::I16x8SubSaturateS
|
||||||
|
| Operator::I16x8SubSaturateU
|
||||||
|
| Operator::I16x8Mul
|
||||||
|
| Operator::I32x4Add
|
||||||
|
| Operator::I32x4Sub
|
||||||
|
| Operator::I32x4Mul
|
||||||
|
| Operator::I64x2Add
|
||||||
|
| Operator::I64x2Sub
|
||||||
|
| Operator::F32x4Add
|
||||||
|
| Operator::F32x4Sub
|
||||||
|
| Operator::F32x4Mul
|
||||||
|
| Operator::F32x4Div
|
||||||
|
| Operator::F32x4Min
|
||||||
|
| Operator::F32x4Max
|
||||||
|
| Operator::F64x2Add
|
||||||
|
| Operator::F64x2Sub
|
||||||
|
| Operator::F64x2Mul
|
||||||
|
| Operator::F64x2Div
|
||||||
|
| Operator::F64x2Min
|
||||||
|
| Operator::F64x2Max => {
|
||||||
|
self.check_simd_enabled()?;
|
||||||
|
self.check_operands_2(func_state, Type::V128, Type::V128)?;
|
||||||
|
OperatorAction::ChangeFrameWithType(2, Type::V128)
|
||||||
|
}
|
||||||
|
Operator::V128Not
|
||||||
|
| Operator::I8x16Neg
|
||||||
|
| Operator::I16x8Neg
|
||||||
|
| Operator::I32x4Neg
|
||||||
|
| Operator::I64x2Neg
|
||||||
|
| Operator::F32x4Abs
|
||||||
|
| Operator::F32x4Neg
|
||||||
|
| Operator::F32x4Sqrt
|
||||||
|
| Operator::F64x2Abs
|
||||||
|
| Operator::F64x2Neg
|
||||||
|
| Operator::F64x2Sqrt
|
||||||
|
| Operator::I32x4TruncSF32x4Sat
|
||||||
|
| Operator::I32x4TruncUF32x4Sat
|
||||||
|
| Operator::I64x2TruncSF64x2Sat
|
||||||
|
| Operator::I64x2TruncUF64x2Sat
|
||||||
|
| Operator::F32x4ConvertSI32x4
|
||||||
|
| Operator::F32x4ConvertUI32x4
|
||||||
|
| Operator::F64x2ConvertSI64x2
|
||||||
|
| Operator::F64x2ConvertUI64x2 => {
|
||||||
|
self.check_simd_enabled()?;
|
||||||
|
self.check_operands_1(func_state, Type::V128)?;
|
||||||
|
OperatorAction::ChangeFrameWithType(1, Type::V128)
|
||||||
|
}
|
||||||
|
Operator::V128Bitselect => {
|
||||||
|
self.check_simd_enabled()?;
|
||||||
|
self.check_operands(func_state, &[Type::V128, Type::V128, Type::V128])?;
|
||||||
|
OperatorAction::ChangeFrameWithType(2, Type::V128)
|
||||||
|
}
|
||||||
|
Operator::I8x16AnyTrue
|
||||||
|
| Operator::I8x16AllTrue
|
||||||
|
| Operator::I16x8AnyTrue
|
||||||
|
| Operator::I16x8AllTrue
|
||||||
|
| Operator::I32x4AnyTrue
|
||||||
|
| Operator::I32x4AllTrue
|
||||||
|
| Operator::I64x2AnyTrue
|
||||||
|
| Operator::I64x2AllTrue => {
|
||||||
|
self.check_simd_enabled()?;
|
||||||
|
self.check_operands_1(func_state, Type::V128)?;
|
||||||
|
OperatorAction::ChangeFrameWithType(1, Type::I32)
|
||||||
|
}
|
||||||
|
Operator::I8x16Shl
|
||||||
|
| Operator::I8x16ShrS
|
||||||
|
| Operator::I8x16ShrU
|
||||||
|
| Operator::I16x8Shl
|
||||||
|
| Operator::I16x8ShrS
|
||||||
|
| Operator::I16x8ShrU
|
||||||
|
| Operator::I32x4Shl
|
||||||
|
| Operator::I32x4ShrS
|
||||||
|
| Operator::I32x4ShrU
|
||||||
|
| Operator::I64x2Shl
|
||||||
|
| Operator::I64x2ShrS
|
||||||
|
| Operator::I64x2ShrU => {
|
||||||
|
self.check_simd_enabled()?;
|
||||||
|
self.check_operands_2(func_state, Type::V128, Type::I32)?;
|
||||||
|
OperatorAction::ChangeFrameWithType(1, Type::V128)
|
||||||
|
}
|
||||||
|
|
||||||
|
Operator::MemoryInit { segment } => {
|
||||||
|
self.check_bulk_memory_enabled()?;
|
||||||
|
if segment >= resources.data_count() {
|
||||||
|
return Err("segment index out of bounds");
|
||||||
|
}
|
||||||
|
self.check_memory_index(0, resources)?;
|
||||||
|
self.check_operands(func_state, &[Type::I32, Type::I32, Type::I32])?;
|
||||||
|
OperatorAction::ChangeFrame(3)
|
||||||
|
}
|
||||||
|
Operator::DataDrop { segment } => {
|
||||||
|
self.check_bulk_memory_enabled()?;
|
||||||
|
if segment >= resources.data_count() {
|
||||||
|
return Err("segment index out of bounds");
|
||||||
|
}
|
||||||
|
OperatorAction::None
|
||||||
|
}
|
||||||
|
Operator::MemoryCopy | Operator::MemoryFill => {
|
||||||
|
self.check_bulk_memory_enabled()?;
|
||||||
|
self.check_memory_index(0, resources)?;
|
||||||
|
self.check_operands(func_state, &[Type::I32, Type::I32, Type::I32])?;
|
||||||
|
OperatorAction::ChangeFrame(3)
|
||||||
|
}
|
||||||
|
Operator::TableInit { segment } => {
|
||||||
|
self.check_bulk_memory_enabled()?;
|
||||||
|
if segment >= resources.element_count() {
|
||||||
|
return Err("segment index out of bounds");
|
||||||
|
}
|
||||||
|
if 0 >= resources.tables().len() {
|
||||||
|
return Err("table index out of bounds");
|
||||||
|
}
|
||||||
|
self.check_operands(func_state, &[Type::I32, Type::I32, Type::I32])?;
|
||||||
|
OperatorAction::ChangeFrame(3)
|
||||||
|
}
|
||||||
|
Operator::ElemDrop { segment } => {
|
||||||
|
self.check_bulk_memory_enabled()?;
|
||||||
|
if segment >= resources.element_count() {
|
||||||
|
return Err("segment index out of bounds");
|
||||||
|
}
|
||||||
|
OperatorAction::None
|
||||||
|
}
|
||||||
|
Operator::TableCopy => {
|
||||||
|
self.check_bulk_memory_enabled()?;
|
||||||
|
if 0 >= resources.tables().len() {
|
||||||
|
return Err("table index out of bounds");
|
||||||
|
}
|
||||||
|
self.check_operands(func_state, &[Type::I32, Type::I32, Type::I32])?;
|
||||||
|
OperatorAction::ChangeFrame(3)
|
||||||
|
}
|
||||||
|
Operator::TableGet { table } => {
|
||||||
|
self.check_reference_types_enabled()?;
|
||||||
|
if table as usize >= resources.tables().len() {
|
||||||
|
return Err("table index out of bounds");
|
||||||
|
}
|
||||||
|
self.check_operands(func_state, &[Type::I32])?;
|
||||||
|
OperatorAction::ChangeFrameWithType(1, Type::AnyRef)
|
||||||
|
}
|
||||||
|
Operator::TableSet { table } => {
|
||||||
|
self.check_reference_types_enabled()?;
|
||||||
|
if table as usize >= resources.tables().len() {
|
||||||
|
return Err("table index out of bounds");
|
||||||
|
}
|
||||||
|
self.check_operands(func_state, &[Type::I32, Type::AnyRef])?;
|
||||||
|
OperatorAction::ChangeFrame(2)
|
||||||
|
}
|
||||||
|
Operator::TableGrow { table } => {
|
||||||
|
self.check_reference_types_enabled()?;
|
||||||
|
if table as usize >= resources.tables().len() {
|
||||||
|
return Err("table index out of bounds");
|
||||||
|
}
|
||||||
|
self.check_operands(func_state, &[Type::I32])?;
|
||||||
|
OperatorAction::ChangeFrameWithType(1, Type::I32)
|
||||||
|
}
|
||||||
|
Operator::TableSize { table } => {
|
||||||
|
self.check_reference_types_enabled()?;
|
||||||
|
if table as usize >= resources.tables().len() {
|
||||||
|
return Err("table index out of bounds");
|
||||||
|
}
|
||||||
|
OperatorAction::ChangeFrameWithType(1, Type::I32)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1278,11 +1639,14 @@ pub struct ValidatingParser<'a> {
|
||||||
tables: Vec<TableType>,
|
tables: Vec<TableType>,
|
||||||
memories: Vec<MemoryType>,
|
memories: Vec<MemoryType>,
|
||||||
globals: Vec<GlobalType>,
|
globals: Vec<GlobalType>,
|
||||||
|
element_count: u32,
|
||||||
|
data_count: Option<u32>,
|
||||||
|
data_found: u32,
|
||||||
func_type_indices: Vec<u32>,
|
func_type_indices: Vec<u32>,
|
||||||
current_func_index: u32,
|
current_func_index: u32,
|
||||||
func_imports_count: u32,
|
func_imports_count: u32,
|
||||||
init_expression_state: Option<InitExpressionState>,
|
init_expression_state: Option<InitExpressionState>,
|
||||||
exported_names: HashSet<Vec<u8>>,
|
exported_names: HashSet<String>,
|
||||||
current_operator_validator: Option<OperatorValidator>,
|
current_operator_validator: Option<OperatorValidator>,
|
||||||
config: ValidatingParserConfig,
|
config: ValidatingParserConfig,
|
||||||
}
|
}
|
||||||
|
|
@ -1307,6 +1671,14 @@ impl<'a> WasmModuleResources for ValidatingParser<'a> {
|
||||||
fn func_type_indices(&self) -> &[u32] {
|
fn func_type_indices(&self) -> &[u32] {
|
||||||
&self.func_type_indices
|
&self.func_type_indices
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn element_count(&self) -> u32 {
|
||||||
|
self.element_count
|
||||||
|
}
|
||||||
|
|
||||||
|
fn data_count(&self) -> u32 {
|
||||||
|
self.data_count.unwrap_or(0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ValidatingParser<'a> {
|
impl<'a> ValidatingParser<'a> {
|
||||||
|
|
@ -1327,6 +1699,9 @@ impl<'a> ValidatingParser<'a> {
|
||||||
init_expression_state: None,
|
init_expression_state: None,
|
||||||
exported_names: HashSet::new(),
|
exported_names: HashSet::new(),
|
||||||
config: config.unwrap_or(DEFAULT_VALIDATING_PARSER_CONFIG),
|
config: config.unwrap_or(DEFAULT_VALIDATING_PARSER_CONFIG),
|
||||||
|
element_count: 0,
|
||||||
|
data_count: None,
|
||||||
|
data_found: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1344,19 +1719,9 @@ impl<'a> ValidatingParser<'a> {
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_utf8(&self, bytes: &[u8]) -> ValidatorResult<'a, ()> {
|
|
||||||
match str::from_utf8(bytes) {
|
|
||||||
Ok(_) => Ok(()),
|
|
||||||
Err(utf8_error) => match utf8_error.error_len() {
|
|
||||||
None => self.create_error("Invalid utf-8: unexpected end of string"),
|
|
||||||
Some(_) => self.create_error("Invalid utf-8: unexpected byte"),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn check_value_type(&self, ty: Type) -> ValidatorResult<'a, ()> {
|
fn check_value_type(&self, ty: Type) -> ValidatorResult<'a, ()> {
|
||||||
match ty {
|
match ty {
|
||||||
Type::I32 | Type::I64 | Type::F32 | Type::F64 => Ok(()),
|
Type::I32 | Type::I64 | Type::F32 | Type::F64 | Type::V128 => Ok(()),
|
||||||
_ => self.create_error("invalid value type"),
|
_ => self.create_error("invalid value type"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1413,14 +1778,7 @@ impl<'a> ValidatingParser<'a> {
|
||||||
self.check_value_type(global_type.content_type)
|
self.check_value_type(global_type.content_type)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_import_entry(
|
fn check_import_entry(&self, import_type: &ImportSectionEntryType) -> ValidatorResult<'a, ()> {
|
||||||
&self,
|
|
||||||
module: &[u8],
|
|
||||||
field: &[u8],
|
|
||||||
import_type: &ImportSectionEntryType,
|
|
||||||
) -> ValidatorResult<'a, ()> {
|
|
||||||
self.check_utf8(module)?;
|
|
||||||
self.check_utf8(field)?;
|
|
||||||
match *import_type {
|
match *import_type {
|
||||||
ImportSectionEntryType::Function(type_index) => {
|
ImportSectionEntryType::Function(type_index) => {
|
||||||
if self.func_type_indices.len() >= MAX_WASM_FUNCTIONS {
|
if self.func_type_indices.len() >= MAX_WASM_FUNCTIONS {
|
||||||
|
|
@ -1481,12 +1839,11 @@ impl<'a> ValidatingParser<'a> {
|
||||||
|
|
||||||
fn check_export_entry(
|
fn check_export_entry(
|
||||||
&self,
|
&self,
|
||||||
field: &[u8],
|
field: &str,
|
||||||
kind: ExternalKind,
|
kind: ExternalKind,
|
||||||
index: u32,
|
index: u32,
|
||||||
) -> ValidatorResult<'a, ()> {
|
) -> ValidatorResult<'a, ()> {
|
||||||
self.check_utf8(field)?;
|
if self.exported_names.contains(field) {
|
||||||
if self.exported_names.contains(&Vec::from(field)) {
|
|
||||||
return self.create_error("non-unique export name");
|
return self.create_error("non-unique export name");
|
||||||
}
|
}
|
||||||
match kind {
|
match kind {
|
||||||
|
|
@ -1532,9 +1889,6 @@ impl<'a> ValidatingParser<'a> {
|
||||||
|
|
||||||
fn process_begin_section(&self, code: &SectionCode) -> ValidatorResult<'a, SectionOrderState> {
|
fn process_begin_section(&self, code: &SectionCode) -> ValidatorResult<'a, SectionOrderState> {
|
||||||
let order_state = SectionOrderState::from_section_code(code);
|
let order_state = SectionOrderState::from_section_code(code);
|
||||||
if let SectionCode::Custom { name, .. } = *code {
|
|
||||||
self.check_utf8(name)?;
|
|
||||||
}
|
|
||||||
Ok(match self.section_order_state {
|
Ok(match self.section_order_state {
|
||||||
SectionOrderState::Initial => {
|
SectionOrderState::Initial => {
|
||||||
if order_state.is_none() {
|
if order_state.is_none() {
|
||||||
|
|
@ -1582,12 +1936,8 @@ impl<'a> ValidatingParser<'a> {
|
||||||
self.types.push(func_type.clone());
|
self.types.push(func_type.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ParserState::ImportSectionEntry {
|
ParserState::ImportSectionEntry { ref ty, .. } => {
|
||||||
module,
|
let check = self.check_import_entry(ty);
|
||||||
field,
|
|
||||||
ref ty,
|
|
||||||
} => {
|
|
||||||
let check = self.check_import_entry(module, field, ty);
|
|
||||||
if check.is_err() {
|
if check.is_err() {
|
||||||
self.validation_error = check.err();
|
self.validation_error = check.err();
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1666,12 +2016,19 @@ impl<'a> ValidatingParser<'a> {
|
||||||
}
|
}
|
||||||
ParserState::ExportSectionEntry { field, kind, index } => {
|
ParserState::ExportSectionEntry { field, kind, index } => {
|
||||||
self.validation_error = self.check_export_entry(field, kind, index).err();
|
self.validation_error = self.check_export_entry(field, kind, index).err();
|
||||||
self.exported_names.insert(Vec::from(field));
|
self.exported_names.insert(field.to_string());
|
||||||
}
|
}
|
||||||
ParserState::StartSectionEntry(func_index) => {
|
ParserState::StartSectionEntry(func_index) => {
|
||||||
self.validation_error = self.check_start(func_index).err();
|
self.validation_error = self.check_start(func_index).err();
|
||||||
}
|
}
|
||||||
ParserState::BeginElementSectionEntry(table_index) => {
|
ParserState::DataCountSectionEntry(count) => {
|
||||||
|
self.data_count = Some(count);
|
||||||
|
}
|
||||||
|
ParserState::BeginPassiveElementSectionEntry(_ty) => {
|
||||||
|
self.element_count += 1;
|
||||||
|
}
|
||||||
|
ParserState::BeginActiveElementSectionEntry(table_index) => {
|
||||||
|
self.element_count += 1;
|
||||||
if table_index as usize >= self.tables.len() {
|
if table_index as usize >= self.tables.len() {
|
||||||
self.validation_error =
|
self.validation_error =
|
||||||
self.create_validation_error("element section table index out of bounds");
|
self.create_validation_error("element section table index out of bounds");
|
||||||
|
|
@ -1738,7 +2095,10 @@ impl<'a> ValidatingParser<'a> {
|
||||||
self.current_func_index += 1;
|
self.current_func_index += 1;
|
||||||
self.current_operator_validator = None;
|
self.current_operator_validator = None;
|
||||||
}
|
}
|
||||||
ParserState::BeginDataSectionEntry(memory_index) => {
|
ParserState::BeginDataSectionEntryBody(_) => {
|
||||||
|
self.data_found += 1;
|
||||||
|
}
|
||||||
|
ParserState::BeginActiveDataSectionEntry(memory_index) => {
|
||||||
if memory_index as usize >= self.memories.len() {
|
if memory_index as usize >= self.memories.len() {
|
||||||
self.validation_error =
|
self.validation_error =
|
||||||
self.create_validation_error("data section memory index out of bounds");
|
self.create_validation_error("data section memory index out of bounds");
|
||||||
|
|
@ -1750,6 +2110,22 @@ impl<'a> ValidatingParser<'a> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ParserState::EndWasm => {
|
||||||
|
if self.func_type_indices.len()
|
||||||
|
!= self.current_func_index as usize + self.func_imports_count as usize
|
||||||
|
{
|
||||||
|
self.validation_error = self.create_validation_error(
|
||||||
|
"function and code section have inconsistent lengths",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if let Some(data_count) = self.data_count {
|
||||||
|
if data_count != self.data_found {
|
||||||
|
self.validation_error = self.create_validation_error(
|
||||||
|
"data count section and passive data mismatch",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue