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:
Benjamin Bouvier 2019-04-15 10:39:28 +00:00
Родитель 5deee43687
Коммит da79779db2
93 изменённых файлов: 8293 добавлений и 824 удалений

Просмотреть файл

@ -22,9 +22,9 @@ git = "https://github.com/hsivonen/packed_simd"
branch = "rust_1_32"
replace-with = "vendored-sources"
[source."https://github.com/CraneStation/target-lexicon"]
git = "https://github.com/glandium/target-lexicon"
branch = "thumbv7neon-v0.2"
[source."https://github.com/CraneStation/Cranelift"]
git = "https://github.com/CraneStation/Cranelift"
rev = "542d799dd7a3b2cc15b91eefdcd85cace8fe5cee"
replace-with = "vendored-sources"
[source.vendored-sources]

76
Cargo.lock сгенерированный
Просмотреть файл

@ -168,11 +168,11 @@ name = "baldrdash"
version = "0.1.0"
dependencies = [
"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-wasm 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.30.0 (git+https://github.com/CraneStation/Cranelift?rev=542d799dd7a3b2cc15b91eefdcd85cace8fe5cee)",
"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)",
"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]]
@ -568,62 +568,62 @@ dependencies = [
[[package]]
name = "cranelift-bforest"
version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
version = "0.30.0"
source = "git+https://github.com/CraneStation/Cranelift?rev=542d799dd7a3b2cc15b91eefdcd85cace8fe5cee#542d799dd7a3b2cc15b91eefdcd85cace8fe5cee"
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]]
name = "cranelift-codegen"
version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
version = "0.30.0"
source = "git+https://github.com/CraneStation/Cranelift?rev=542d799dd7a3b2cc15b91eefdcd85cace8fe5cee#542d799dd7a3b2cc15b91eefdcd85cace8fe5cee"
dependencies = [
"cranelift-bforest 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cranelift-codegen-meta 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cranelift-entity 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.30.0 (git+https://github.com/CraneStation/Cranelift?rev=542d799dd7a3b2cc15b91eefdcd85cace8fe5cee)",
"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_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)",
"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]]
name = "cranelift-codegen-meta"
version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
version = "0.30.0"
source = "git+https://github.com/CraneStation/Cranelift?rev=542d799dd7a3b2cc15b91eefdcd85cace8fe5cee#542d799dd7a3b2cc15b91eefdcd85cace8fe5cee"
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]]
name = "cranelift-entity"
version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
version = "0.30.0"
source = "git+https://github.com/CraneStation/Cranelift?rev=542d799dd7a3b2cc15b91eefdcd85cace8fe5cee#542d799dd7a3b2cc15b91eefdcd85cace8fe5cee"
[[package]]
name = "cranelift-frontend"
version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
version = "0.30.0"
source = "git+https://github.com/CraneStation/Cranelift?rev=542d799dd7a3b2cc15b91eefdcd85cace8fe5cee#542d799dd7a3b2cc15b91eefdcd85cace8fe5cee"
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)",
"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]]
name = "cranelift-wasm"
version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
version = "0.30.0"
source = "git+https://github.com/CraneStation/Cranelift?rev=542d799dd7a3b2cc15b91eefdcd85cace8fe5cee#542d799dd7a3b2cc15b91eefdcd85cace8fe5cee"
dependencies = [
"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-entity 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cranelift-frontend 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.30.0 (git+https://github.com/CraneStation/Cranelift?rev=542d799dd7a3b2cc15b91eefdcd85cace8fe5cee)",
"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_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)",
"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]]
@ -2778,8 +2778,8 @@ dependencies = [
[[package]]
name = "target-lexicon"
version = "0.2.0"
source = "git+https://github.com/glandium/target-lexicon?branch=thumbv7neon-v0.2#b2d4b34509abb3e12b1c93d19b8593d02ddeed76"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"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)",
@ -3203,7 +3203,7 @@ dependencies = [
[[package]]
name = "wasmparser"
version = "0.23.0"
version = "0.29.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@ -3495,12 +3495,12 @@ dependencies = [
"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-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-codegen 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6c3b15a20577e6c823475953a5e25e758d9d3a3148a937d686c09460e5f2f4a0"
"checksum cranelift-codegen-meta 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e60ce3551e8172c966fbc6d9bfb90111d5d1cf37306c37dd7527467afe317d1"
"checksum cranelift-entity 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4e124e09cb7dc85fbe2162420aebbe8e9e3b8f9210901be7867416c5beec8226"
"checksum cranelift-frontend 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2833c6e1a93c524ce0c2ab31266cdc84d38c906349f79f19378a5e5995727b23"
"checksum cranelift-wasm 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e75efb45cd8d8700b4bdc225f0077bc7c615f84a5807ce001d59b4da48d85573"
"checksum cranelift-bforest 0.30.0 (git+https://github.com/CraneStation/Cranelift?rev=542d799dd7a3b2cc15b91eefdcd85cace8fe5cee)" = "<none>"
"checksum cranelift-codegen 0.30.0 (git+https://github.com/CraneStation/Cranelift?rev=542d799dd7a3b2cc15b91eefdcd85cace8fe5cee)" = "<none>"
"checksum cranelift-codegen-meta 0.30.0 (git+https://github.com/CraneStation/Cranelift?rev=542d799dd7a3b2cc15b91eefdcd85cace8fe5cee)" = "<none>"
"checksum cranelift-entity 0.30.0 (git+https://github.com/CraneStation/Cranelift?rev=542d799dd7a3b2cc15b91eefdcd85cace8fe5cee)" = "<none>"
"checksum cranelift-frontend 0.30.0 (git+https://github.com/CraneStation/Cranelift?rev=542d799dd7a3b2cc15b91eefdcd85cace8fe5cee)" = "<none>"
"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 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"
@ -3691,7 +3691,7 @@ dependencies = [
"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 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 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"
@ -3736,7 +3736,7 @@ dependencies = [
"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 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 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"

Просмотреть файл

@ -61,4 +61,5 @@ libudev-sys = { path = "dom/webauthn/libudev-sys" }
serde_derive = { git = "https://github.com/servo/serde", branch = "deserialize_from_enums10" }
winapi = { git = "https://github.com/froydnj/winapi-rs", branch = "aarch64" }
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"
[dependencies]
cranelift-codegen = { version = "0.29.0", default-features = false }
cranelift-wasm = "0.29.0"
target-lexicon = "0.2.0"
# The build system redirects the versions of cranelift-codegen and
# cranelift-wasm to pinned commits. If you want to update Cranelift in Gecko,
# 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"] }
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 поставляемый
Просмотреть файл

@ -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]
edition = "2018"
name = "cranelift-bforest"
version = "0.29.0"
authors = ["The Cranelift Project Developers"]
name = "cranelift-bforest"
version = "0.30.0"
description = "A forest of B+-trees"
license = "Apache-2.0 WITH LLVM-exception"
documentation = "https://cranelift.readthedocs.io/"
repository = "https://github.com/CraneStation/cranelift"
categories = ["no-std"]
readme = "README.md"
keywords = ["btree", "forest", "set", "map"]
categories = ["no-std"]
license = "Apache-2.0 WITH LLVM-exception"
repository = "https://github.com/CraneStation/cranelift"
[dependencies.cranelift-entity]
version = "0.29.0"
default-features = false
edition = "2018"
[dependencies]
cranelift-entity = { path = "../cranelift-entity", version = "0.30.0", default-features = false }
[features]
core = []
default = ["std"]
std = ["cranelift-entity/std"]
[badges.maintenance]
status = "experimental"
core = []
[badges.travis-ci]
repository = "CraneStation/cranelift"
[badges]
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]
edition = "2018"
name = "cranelift-codegen-meta"
version = "0.29.0"
authors = ["The Cranelift Project Developers"]
version = "0.30.0"
description = "Metaprogram for cranelift-codegen code generator library"
readme = "README.md"
license = "Apache-2.0 WITH LLVM-exception"
repository = "https://github.com/CraneStation/cranelift"
[dependencies.cranelift-entity]
version = "0.29.0"
[badges.maintenance]
status = "experimental"
readme = "README.md"
edition = "2018"
[badges.travis-ci]
repository = "CraneStation/cranelift"
[dependencies]
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 поставляемый 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 поставляемый 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 super::settings::SettingGroup;
use crate::cdsl::inst::InstructionGroup;
use crate::cdsl::regs::IsaRegs;
use crate::cdsl::settings::SettingGroup;
pub struct TargetIsa {
pub name: &'static str,
pub instructions: InstructionGroup,
pub settings: SettingGroup,
pub regs: IsaRegs,
}
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 {
name,
instructions,
settings,
regs,
}

Просмотреть файл

@ -3,10 +3,15 @@
//! This module defines the classes that are used to define Cranelift
//! instructions and other entities.
pub mod formats;
pub mod inst;
pub mod isa;
pub mod operands;
pub mod regs;
pub mod settings;
pub mod type_inference;
pub mod types;
pub mod typevar;
/// A macro that converts boolean settings into predicates to look more natural.
#[macro_export]

285
third_party/rust/cranelift-codegen-meta/src/cdsl/operands.rs поставляемый 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()
}

Просмотреть файл

@ -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.
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.
///
/// All SSA values have a type that is described by an instance of `ValueType`
/// or one of its subclasses.
#[derive(Debug)]
#[derive(Clone, Debug, PartialEq)]
pub enum ValueType {
BV(BVType),
Lane(LaneType),
@ -90,7 +90,7 @@ impl ValueType {
}
/// 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())
}
@ -147,7 +147,7 @@ impl From<VectorType> for ValueType {
}
/// A concrete scalar type that can appear as a vector lane too.
#[derive(Clone, Copy)]
#[derive(Clone, Copy, PartialEq)]
pub enum LaneType {
BoolType(shared_types::Bool),
FloatType(shared_types::Float),
@ -205,6 +205,43 @@ impl LaneType {
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 {
@ -290,6 +327,7 @@ impl Iterator for LaneTypeIterator {
///
/// A vector type has a lane type which is an instance of `LaneType`,
/// and a positive number of lanes.
#[derive(Clone, PartialEq)]
pub struct VectorType {
base: LaneType,
lanes: u64,
@ -320,6 +358,11 @@ impl VectorType {
self.lanes
}
/// Return the lane type.
pub fn lane_type(&self) -> LaneType {
self.base
}
/// Find the unique number associated with this vector type.
///
/// 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.
#[derive(Clone, PartialEq)]
pub struct BVType {
bits: u64,
}
impl BVType {
/// Initialize a new bitvector type with `n` bits.
pub fn _new(bits: u64) -> Self {
Self { bits }
pub fn new(bits: u16) -> Self {
Self { bits: bits.into() }
}
/// 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.
///
/// Special types cannot be used to form vectors.
#[derive(Clone, Copy)]
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub enum SpecialType {
Flag(shared_types::Flag),
}

901
third_party/rust/cranelift-codegen-meta/src/cdsl/typevar.rs поставляемый 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 = &copy.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, "}");
}
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();
gen_isa(&isa, &mut fmt);
fmt.update_file(format!("{}-{}.rs", base_filename, isa.name), out_dir)?;
fmt.update_file(filename, out_dir)?;
Ok(())
}

Просмотреть файл

@ -1,16 +1,14 @@
use crate::cdsl::camel_case;
use crate::cdsl::isa::TargetIsa;
use crate::cdsl::settings::{
BoolSetting, Predicate, Preset, Setting, SettingGroup, SpecificSetting,
};
use crate::constant_hash::{generate_table, simple_hash};
use crate::error;
use crate::shared;
use crate::srcgen::{Formatter, Match};
use crate::unique_table::UniqueTable;
use crate::unique_table::UniqueSeqTable;
use std::collections::HashMap;
enum ParentGroup {
pub enum ParentGroup {
None,
Shared,
}
@ -152,13 +150,9 @@ fn gen_getter(setting: &Setting, fmt: &mut Formatter) {
fmt.indent(|fmt| {
let mut m = Match::new(format!("self.bytes[{}]", setting.byte_offset));
for (i, v) in values.iter().enumerate() {
m.arm(
format!("{}", i),
vec![],
format!("{}::{}", ty, camel_case(v)),
);
m.arm_no_fields(format!("{}", i), format!("{}::{}", ty, camel_case(v)));
}
m.arm("_", vec![], "panic!(\"Invalid enum value\")");
m.arm_no_fields("_", "panic!(\"Invalid enum value\")");
fmt.add_match(m);
});
fmtln!(fmt, "}");
@ -191,12 +185,12 @@ fn gen_getters(group: &SettingGroup, fmt: &mut Formatter) {
fmt.doc_comment("Get a view of the boolean predicates.");
fmtln!(
fmt,
"pub fn predicate_view(&self) -> ::settings::PredicateView {"
"pub fn predicate_view(&self) -> crate::settings::PredicateView {"
);
fmt.indent(|fmt| {
fmtln!(
fmt,
"::settings::PredicateView::new(&self.bytes[{}..])",
"crate::settings::PredicateView::new(&self.bytes[{}..])",
group.bool_start_byte_offset
);
});
@ -242,7 +236,7 @@ impl<'a> SettingOrPreset<'a> {
/// Emits DESCRIPTORS, ENUMERATORS, HASH_TABLE and PRESETS.
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();
@ -445,17 +439,14 @@ fn gen_group(group: &SettingGroup, parent: ParentGroup, fmt: &mut Formatter) {
gen_display(group, fmt);
}
pub fn generate_common(filename: &str, out_dir: &str) -> Result<SettingGroup, error::Error> {
let settings = shared::settings::generate();
pub fn generate(
settings: &SettingGroup,
parent_group: ParentGroup,
filename: &str,
out_dir: &str,
) -> Result<(), error::Error> {
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)?;
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(())
}

Просмотреть файл

@ -1,6 +1,8 @@
use crate::cdsl::inst::InstructionGroup;
use crate::cdsl::isa::TargetIsa;
use crate::cdsl::regs::{IsaRegs, IsaRegsBuilder, RegBankBuilder, RegClassBuilder};
use crate::cdsl::settings::{SettingGroup, SettingGroupBuilder};
use crate::shared::Definitions as SharedDefinitions;
fn define_settings(_shared: &SettingGroup) -> SettingGroup {
let setting = SettingGroupBuilder::new("arm32");
@ -44,8 +46,11 @@ fn define_regs() -> IsaRegs {
regs.finish()
}
pub fn define(shared_settings: &SettingGroup) -> TargetIsa {
let settings = define_settings(shared_settings);
pub fn define(shared_defs: &mut SharedDefinitions) -> TargetIsa {
let settings = define_settings(&shared_defs.settings);
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::regs::{IsaRegs, IsaRegsBuilder, RegBankBuilder, RegClassBuilder};
use crate::cdsl::settings::{SettingGroup, SettingGroupBuilder};
use crate::shared::Definitions as SharedDefinitions;
fn define_settings(_shared: &SettingGroup) -> SettingGroup {
let setting = SettingGroupBuilder::new("arm64");
@ -40,8 +42,11 @@ fn define_registers() -> IsaRegs {
regs.finish()
}
pub fn define(shared_settings: &SettingGroup) -> TargetIsa {
let settings = define_settings(shared_settings);
pub fn define(shared_defs: &mut SharedDefinitions) -> TargetIsa {
let settings = define_settings(&shared_defs.settings);
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::settings::SettingGroup;
use crate::shared::Definitions as SharedDefinitions;
use std::fmt;
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()
.map(|isa| match isa {
Isa::Riscv => riscv::define(shared_settings),
Isa::X86 => x86::define(shared_settings),
Isa::Arm32 => arm32::define(shared_settings),
Isa::Arm64 => arm64::define(shared_settings),
Isa::Riscv => riscv::define(shared_defs),
Isa::X86 => x86::define(shared_defs),
Isa::Arm32 => arm32::define(shared_defs),
Isa::Arm64 => arm64::define(shared_defs),
})
.collect()
}

Просмотреть файл

@ -1,6 +1,8 @@
use crate::cdsl::inst::InstructionGroup;
use crate::cdsl::isa::TargetIsa;
use crate::cdsl::regs::{IsaRegs, IsaRegsBuilder, RegBankBuilder, RegClassBuilder};
use crate::cdsl::settings::{PredicateNode, SettingGroup, SettingGroupBuilder};
use crate::shared::Definitions as SharedDefinitions;
fn define_settings(shared: &SettingGroup) -> SettingGroup {
let mut setting = SettingGroupBuilder::new("riscv");
@ -76,8 +78,11 @@ fn define_registers() -> IsaRegs {
regs.finish()
}
pub fn define(shared_settings: &SettingGroup) -> TargetIsa {
let settings = define_settings(shared_settings);
pub fn define(shared_defs: &mut SharedDefinitions) -> TargetIsa {
let settings = define_settings(&shared_defs.settings);
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)
}

Просмотреть файл

@ -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::regs::{IsaRegs, IsaRegsBuilder, RegBankBuilder, RegClassBuilder};
use crate::cdsl::settings::{PredicateNode, SettingGroup, SettingGroupBuilder};
use crate::shared::Definitions as SharedDefinitions;
fn define_settings(_shared: &SettingGroup) -> SettingGroup {
let mut settings = SettingGroupBuilder::new("x86");
@ -109,8 +113,11 @@ fn define_registers() -> IsaRegs {
regs.finish()
}
pub fn define(shared_settings: &SettingGroup) -> TargetIsa {
let settings = define_settings(shared_settings);
pub fn define(shared_defs: &mut SharedDefinitions) -> TargetIsa {
let settings = define_settings(&shared_defs.settings);
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.
pub fn generate(isas: &Vec<isa::Isa>, out_dir: &str) -> Result<(), error::Error> {
// 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)?;
// Per ISA definitions.
let isas = isa::define(isas, &shared_settings);
let isas = isa::define(isas, &mut shared_defs);
for isa in isas {
gen_registers::generate(&isa, "registers", &out_dir)?;
gen_settings::generate(&isa, "new_settings", &out_dir)?;
gen_registers::generate(&isa, &format!("registers-{}.rs", isa.name), &out_dir)?;
gen_settings::generate(
&isa.settings,
gen_settings::ParentGroup::Shared,
&format!("new_settings-{}", isa.name),
&out_dir,
)?;
}
Ok(())

65
third_party/rust/cranelift-codegen-meta/src/shared/entities.rs поставляемый 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 поставляемый 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 поставляемый 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 поставляемый Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,4 +1,59 @@
//! Shared definitions for the Cranelift intermediate language.
pub mod entities;
pub mod formats;
pub mod immediates;
pub mod instructions;
pub mod settings;
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};
pub fn generate() -> SettingGroup {
pub fn define() -> SettingGroup {
let mut settings = SettingGroupBuilder::new("shared");
settings.add_enum(

Просмотреть файл

@ -113,7 +113,7 @@ impl Iterator for FloatIterator {
/// A type representing CPU flags.
///
/// Flags can't be stored in memory.
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
pub enum Flag {
/// CPU flags from an integer comparison.
IFlags,

Просмотреть файл

@ -25,6 +25,14 @@ macro_rules! fmtln {
($fmt:ident, $arg:expr) => {
$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 {
@ -84,6 +92,11 @@ impl Formatter {
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.
pub fn _outdented_line(&mut self, s: &str) {
let new_line = format!("{}{}", self._get_outdent(), s);
@ -112,7 +125,7 @@ impl Formatter {
}
/// 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));
}
@ -141,7 +154,7 @@ impl Formatter {
self.indent(|fmt| {
for (&(ref fields, ref body), ref names) in m.arms.iter() {
// name { fields } | name { fields } => { body }
let conditions: Vec<String> = names
let conditions = names
.iter()
.map(|name| {
if fields.len() > 0 {
@ -150,9 +163,20 @@ impl Formatter {
name.clone()
}
})
.collect();
let lhs = conditions.join(" | ");
fmtln!(fmt, "{} => {{", lhs);
.collect::<Vec<_>>()
.join(" |\n")
+ " => {";
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.line(body);
});
@ -239,27 +263,57 @@ fn parse_multiline(s: &str) -> Vec<String> {
pub struct Match {
expr: String,
arms: BTreeMap<(Vec<String>, String), BTreeSet<String>>,
/// The clause for the placeholder pattern _.
catch_all: Option<String>,
}
impl Match {
/// 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 {
expr: expr.into(),
arms: BTreeMap::new(),
catch_all: None,
}
}
/// Add an arm to the Match statement.
pub fn arm<T: Into<String>>(&mut self, name: T, fields: Vec<T>, body: T) {
// let key = (fields, body);
fn set_catch_all(&mut self, clause: String) {
assert!(self.catch_all.is_none());
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 fields = fields.into_iter().map(|x| x.into()).collect();
let match_arm = self
.arms
.entry((fields, body))
.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 } => {
different body
}
Orange { a, b } | Yellow { a, b } => {
Orange { a, b } |
Yellow { a, b } => {
some body
}
Blue { x, y } => {
@ -308,6 +363,36 @@ match x {
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]
fn parse_multiline_works() {
let input = "\n hello\n world\n";

Просмотреть файл

@ -1,21 +1,76 @@
use std::collections::HashMap;
use std::hash::Hash;
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.
pub struct UniqueTable<T: PartialEq + Clone> {
pub struct UniqueSeqTable<T: PartialEq + Clone> {
table: Vec<T>,
}
impl<T: PartialEq + Clone> UniqueTable<T> {
impl<T: PartialEq + Clone> UniqueSeqTable<T> {
pub fn new() -> Self {
Self { table: Vec::new() }
}
pub fn add(&mut self, values: &Vec<T>) -> usize {
if values.len() == 0 {
return 0;
}
if let Some(offset) = find_subsequence(values, &self.table) {
offset
} else {
let offset = self.table.len();
self.table.extend((*values).clone());
offset
let table_len = self.table.len();
// 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 {
@ -35,17 +90,10 @@ fn find_subsequence<T: PartialEq>(sub: &Vec<T>, whole: &Vec<T>) -> Option<usize>
if whole.len() < sub.len() {
return None;
}
let max = whole.len() + 1 - sub.len();
for i in 0..max {
let mut found: Option<usize> = Some(i);
for j in 0..sub.len() {
if sub[j] != whole[i + j] {
found = None;
break;
}
}
if found.is_some() {
return found;
let max = whole.len() - sub.len();
for i in 0..max + 1 {
if whole[i..i + sub.len()] == sub[..] {
return Some(i);
}
}
return None;
@ -66,3 +114,24 @@ fn test_find_subsequence() {
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);
}

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

105
third_party/rust/cranelift-codegen/Cargo.toml поставляемый
Просмотреть файл

@ -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]
edition = "2018"
name = "cranelift-codegen"
version = "0.29.0"
authors = ["The Cranelift Project Developers"]
build = "build.rs"
name = "cranelift-codegen"
version = "0.30.0"
description = "Low-level code generator library"
license = "Apache-2.0 WITH LLVM-exception"
documentation = "https://cranelift.readthedocs.io/"
repository = "https://github.com/CraneStation/cranelift"
categories = ["no-std"]
readme = "README.md"
keywords = ["compile", "compiler", "jit"]
categories = ["no-std"]
license = "Apache-2.0 WITH LLVM-exception"
repository = "https://github.com/CraneStation/cranelift"
[dependencies.cranelift-bforest]
version = "0.29.0"
default-features = false
build = "build.rs"
edition = "2018"
[dependencies.cranelift-entity]
version = "0.29.0"
default-features = false
[dependencies]
cranelift-entity = { path = "../cranelift-entity", version = "0.30.0", 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]
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.target-lexicon]
version = "0.2.0"
default-features = false
[build-dependencies.cranelift-codegen-meta]
version = "0.29.0"
[build-dependencies]
cranelift-codegen-meta = { path = "meta", version = "0.30.0", default-features = false }
[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 = []
arm64 = []
core = ["hashmap_core"]
default = ["std", "x86", "arm32", "arm64", "riscv"]
riscv = []
std = ["cranelift-entity/std", "cranelift-bforest/std", "target-lexicon/std"]
testing_hooks = []
x86 = []
[badges.maintenance]
status = "experimental"
[badges.travis-ci]
repository = "CraneStation/cranelift"
[badges]
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.
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.
sig_ref = EntityRefKind('sig_ref', 'A function signature.')

Просмотреть файл

@ -252,7 +252,7 @@ class Instruction(object):
for opnum in self.value_opnums:
typ = self.ins[opnum].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:
continue
# 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
# allows us to take advantage of the NonZero optimization, meaning that
# 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
with fmt.indented('pub enum Opcode {', '}'):
for g in groups:
@ -505,7 +505,7 @@ def gen_type_constraints(fmt, instrs):
# Table of operand constraint sequences (as tuples). Each operand
# constraint is represented as a string, one of:
# - `Concrete(vt)`, where `vt` is a value type name.
# - `Free(idx)` where `idx` isan index into `type_sets`.
# - `Free(idx)` where `idx` is an index into `type_sets`.
# - `Same`, `Lane`, `AsBool` for controlling typevar-derived constraints.
operand_seqs = UniqueSeqTable()

Просмотреть файл

@ -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
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
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();
cur.func.offsets[ebb] = offset;
while let Some(inst) = cur.next_inst() {
divert.apply(&cur.func.dfg[inst]);
let enc = cur.func.encodings[inst];
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.
if cur.func.offsets[ebb] != offset {
debug_assert!(
cur.func.offsets[ebb] < offset,
"Code shrinking during relaxation"
);
cur.func.offsets[ebb] = offset;
go_again = true;
}
@ -173,12 +170,12 @@ fn relax_branch(
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 ctrl_type = dfg.ctrl_typevar(inst);
if let Some(enc) = isa
.legal_encodings(cur.func, &dfg[inst], ctrl_type)
.find(|&enc| {
.filter(|&enc| {
let range = encinfo.branch_range(enc).expect("Branch with no range");
if !range.contains(offset, dest_offset) {
debug!(" trying [{}]: out of range", encinfo.display(enc));
@ -198,7 +195,9 @@ fn relax_branch(
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;
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
/// 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(
&mut self,
isa: &TargetIsa,
mem: &mut Vec<u8>,
relocs: &mut RelocSink,
traps: &mut TrapSink,
) -> CodegenResult<()> {
let code_size = self.compile(isa)?;
) -> CodegenResult<(CodeOffset, CodeOffset)> {
let total_size = self.compile(isa)?;
let old_len = mem.len();
mem.resize(old_len + code_size as usize, 0);
unsafe { self.emit_to_memory(isa, mem.as_mut_ptr().add(old_len), relocs, traps) };
Ok(())
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) };
Ok((code_size, total_size - code_size))
}
/// 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
/// 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> {
let _tt = timing::compile();
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,
/// 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(
&self,
isa: &TargetIsa,
mem: *mut u8,
relocs: &mut RelocSink,
traps: &mut TrapSink,
) {
) -> CodeOffset {
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.

Просмотреть файл

@ -246,7 +246,7 @@ mod tests {
}
#[test]
fn test_magicU32() {
fn test_magic_u32() {
assert_eq!(magic_u32(2u32), make_mu32(0x80000000u32, false, 0));
assert_eq!(magic_u32(3u32), make_mu32(0xaaaaaaabu32, false, 1));
assert_eq!(magic_u32(4u32), make_mu32(0x40000000u32, false, 0));
@ -279,8 +279,9 @@ mod tests {
make_mu32(0x80000001u32, false, 31)
);
}
#[test]
fn test_magicU64() {
fn test_magic_u64() {
assert_eq!(magic_u64(2u64), make_mu64(0x8000000000000000u64, false, 0));
assert_eq!(magic_u64(3u64), make_mu64(0xaaaaaaaaaaaaaaabu64, false, 1));
assert_eq!(magic_u64(4u64), make_mu64(0x4000000000000000u64, false, 0));
@ -346,8 +347,9 @@ mod tests {
make_mu64(0x8000000000000001u64, false, 63)
);
}
#[test]
fn test_magicS32() {
fn test_magic_s32() {
assert_eq!(
magic_s32(-0x80000000i32),
make_ms32(0x7fffffffu32 as i32, 30)
@ -390,8 +392,9 @@ mod tests {
make_ms32(0x40000001u32 as i32, 29)
);
}
#[test]
fn test_magicS64() {
fn test_magic_s64() {
assert_eq!(
magic_s64(-0x8000000000000000i64),
make_ms64(0x7fffffffffffffffu64 as i64, 62)
@ -515,6 +518,7 @@ mod tests {
make_ms64(0x4000000000000001u64 as i64, 61)
);
}
#[test]
fn test_magic_generators_dont_panic() {
// The point of this is to check that the magic number generators

Просмотреть файл

@ -1,18 +1,88 @@
//! 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 crate::ir;
use crate::abi::{legalize_args, ArgAction, ArgAssigner, ValueConversion};
use crate::ir::{self, AbiParam, ArgumentExtension, ArgumentLoc, Type};
use crate::isa::RegClass;
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`.
pub fn legalize_signature(
_sig: &mut ir::Signature,
_flags: &shared_settings::Flags,
_current: bool,
) {
unimplemented!()
pub fn legalize_signature(sig: &mut ir::Signature, triple: &Triple, _current: bool) {
let bits = triple.pointer_width().unwrap().bits();
let mut args = Args::new(bits);
legalize_args(&mut sig.params, &mut args);
}
/// 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) {
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 {

Просмотреть файл

@ -161,13 +161,14 @@ pub fn legalize_signature(sig: &mut ir::Signature, triple: &Triple, _current: bo
legalize_args(&mut sig.params, &mut args);
let regs = if sig.call_conv == CallConv::WindowsFastcall {
&RET_GPRS_WIN_FASTCALL_X64[..]
let (regs, fpr_limit) = if sig.call_conv == CallConv::WindowsFastcall {
// windows-x64 calling convention only uses XMM0 or RAX for return values
(&RET_GPRS_WIN_FASTCALL_X64[..], 1)
} 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);
}

Просмотреть файл

@ -14,13 +14,13 @@
//!
//! When legalizing a single instruction, it is wrapped in splits and concatenations:
//!
//!```clif
//! ```clif
//! v1 = bxor.i64 v2, v3
//! ```
//!
//! becomes:
//!
//!```clif
//! ```clif
//! v20, v21 = isplit v2
//! v30, v31 = isplit v3
//! v10 = bxor.i32 v20, v30

Просмотреть файл

@ -5,7 +5,9 @@ use crate::dominator_tree::DominatorTree;
use crate::entity::{EntityList, ListPool};
use crate::flowgraph::{BasicBlock, ControlFlowGraph};
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::loop_analysis::{Loop, LoopAnalysis};
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.
fn trivially_unsafe_for_licm(opcode: Opcode) -> bool {
opcode.can_load()
|| opcode.can_store()
opcode.can_store()
|| opcode.is_call()
|| opcode.is_branch()
|| opcode.is_terminator()
@ -156,12 +157,25 @@ fn trivially_unsafe_for_licm(opcode: Opcode) -> bool {
|| 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.
fn is_loop_invariant(inst: Inst, dfg: &DataFlowGraph, loop_values: &FxHashSet<Value>) -> bool {
if trivially_unsafe_for_licm(dfg[inst].opcode()) {
return false;
}
if is_unsafe_load(&dfg[inst]) {
return false;
}
let inst_args = dfg.inst_args(inst);
for arg in inst_args {
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.
let args = info.args.as_slice(&pos.func.dfg.value_lists)[1..].to_vec();
pos.goto_inst(info.cmp_inst);
pos.use_srcloc(info.cmp_inst);
match info.kind {
CmpBrKind::Icmp { mut cond, 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`.
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);
let inst = pos.built_inst();
self.liveness.move_def_locally(param, inst);
@ -347,6 +350,7 @@ impl<'a> Context<'a> {
pred_val: Value,
) -> Value {
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 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.
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() {
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! {
static CURRENT_PASS: Cell<Pass> = Cell::new(Pass::None);
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 поставляемый
Просмотреть файл

@ -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]
edition = "2018"
name = "cranelift-entity"
version = "0.29.0"
authors = ["The Cranelift Project Developers"]
name = "cranelift-entity"
version = "0.30.0"
description = "Data structures using entity references as mapping keys"
license = "Apache-2.0 WITH LLVM-exception"
documentation = "https://cranelift.readthedocs.io/"
repository = "https://github.com/CraneStation/cranelift"
categories = ["no-std"]
readme = "README.md"
keywords = ["entity", "set", "map"]
categories = ["no-std"]
license = "Apache-2.0 WITH LLVM-exception"
repository = "https://github.com/CraneStation/cranelift"
edition = "2018"
[features]
core = []
default = ["std"]
std = []
[badges.maintenance]
status = "experimental"
core = []
[badges.travis-ci]
repository = "CraneStation/cranelift"
[badges]
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}

Просмотреть файл

@ -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]
edition = "2018"
name = "cranelift-frontend"
version = "0.29.0"
authors = ["The Cranelift Project Developers"]
name = "cranelift-frontend"
version = "0.30.0"
description = "Cranelift IR builder helper"
documentation = "https://cranelift.readthedocs.io/"
readme = "README.md"
categories = ["no-std"]
license = "Apache-2.0 WITH LLVM-exception"
documentation = "https://cranelift.readthedocs.io/"
categories = ["no-std"]
repository = "https://github.com/CraneStation/cranelift"
[dependencies.cranelift-codegen]
version = "0.29.0"
default-features = false
readme = "README.md"
edition = "2018"
[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
[dependencies]
cranelift-codegen = { path = "../cranelift-codegen", version = "0.30.0", default-features = false }
target-lexicon = { version = "0.4.0", default-features = false }
log = { version = "0.4.6", default-features = false }
hashmap_core = { version = "0.1.9", optional = true }
[features]
core = ["hashmap_core", "cranelift-codegen/core"]
default = ["std"]
std = ["cranelift-codegen/std"]
[badges.maintenance]
status = "experimental"
core = ["hashmap_core", "cranelift-codegen/core"]
[badges.travis-ci]
repository = "CraneStation/cranelift"
[badges]
maintenance = { status = "experimental" }
travis-ci = { repository = "CraneStation/cranelift" }

Просмотреть файл

@ -9,6 +9,36 @@ type EntryIndex = u64;
/// 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.
///
/// # 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)]
pub struct Switch {
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> {
debug!("build_contiguous_case_ranges before: {:#?}", self.cases);
let mut cases = self.cases.into_iter().collect::<Vec<(_, _)>>();
@ -60,6 +98,7 @@ impl Switch {
contiguous_case_ranges
}
/// Binary search for the right `ContiguousCaseRange`.
fn build_search_tree(
bx: &mut FunctionBuilder,
val: Value,
@ -120,6 +159,7 @@ impl Switch {
cases_and_jt_ebbs
}
/// Linear search for the right `ContiguousCaseRange`.
fn build_search_branches(
bx: &mut FunctionBuilder,
val: Value,
@ -128,22 +168,41 @@ impl Switch {
cases_and_jt_ebbs: &mut Vec<(EntryIndex, Ebb, Vec<Ebb>)>,
) {
for ContiguousCaseRange { first_index, ebbs } in contiguous_case_ranges.into_iter().rev() {
if ebbs.len() == 1 {
let is_good_val = bx.ins().icmp_imm(IntCC::Equal, val, first_index as i64);
bx.ins().brnz(is_good_val, ebbs[0], &[]);
} else {
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, &[]);
cases_and_jt_ebbs.push((first_index, jt_ebb, ebbs));
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);
bx.ins().brnz(is_good_val, ebbs[0], &[]);
}
(_, 0) => {
// if `first_index` is 0, then `icmp_imm uge val, first_index` is trivially true
let jt_ebb = bx.create_ebb();
bx.ins().jump(jt_ebb, &[]);
cases_and_jt_ebbs.push((first_index, jt_ebb, ebbs));
// `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, &[]);
cases_and_jt_ebbs.push((first_index, jt_ebb, ebbs));
}
}
}
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(
bx: &mut FunctionBuilder,
val: Value,
@ -158,7 +217,11 @@ impl Switch {
let jump_table = bx.create_jump_table(jt_data);
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);
}
}
@ -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)]
struct ContiguousCaseRange {
/// The entry index of the first case. Eg. 10 when the entry indexes are 10, 11, 12 and 13.
first_index: EntryIndex,
/// The ebbs to jump to sorted in ascending order of entry index.
ebbs: Vec<Ebb>,
}
@ -237,8 +313,7 @@ mod tests {
"ebb0:
v0 = iconst.i8 0
v1 = uextend.i32 v0
v2 = icmp_imm eq v1, 0
brnz v2, ebb1
brz v1, ebb1
jump ebb0"
);
}
@ -267,13 +342,10 @@ mod tests {
ebb0:
v0 = iconst.i8 0
v1 = uextend.i32 v0
v2 = icmp_imm uge v1, 0
brnz v2, ebb3
jump ebb0
jump ebb3
ebb3:
v3 = iadd_imm.i32 v1, 0
br_table v3, ebb0, jt0"
br_table.i32 v1, ebb0, jt0"
);
}
@ -287,8 +359,7 @@ ebb3:
v1 = uextend.i32 v0
v2 = icmp_imm eq v1, 2
brnz v2, ebb2
v3 = icmp_imm eq v1, 0
brnz v3, ebb1
brz v1, ebb1
jump ebb0"
);
}
@ -318,17 +389,14 @@ ebb9:
ebb8:
v5 = icmp_imm.i32 eq v1, 5
brnz v5, ebb3
v6 = icmp_imm.i32 uge v1, 0
brnz v6, ebb11
jump ebb0
jump ebb11
ebb11:
v7 = iadd_imm.i32 v1, 0
br_table v7, ebb0, jt0
br_table.i32 v1, ebb0, jt0
ebb10:
v8 = iadd_imm.i32 v1, -10
br_table v8, ebb0, jt1"
v6 = iadd_imm.i32 v1, -10
br_table v6, ebb0, jt1"
);
}
@ -363,4 +431,23 @@ ebb10:
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 поставляемый
Просмотреть файл

@ -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]
edition = "2018"
name = "cranelift-wasm"
version = "0.29.0"
version = "0.30.0"
authors = ["The Cranelift Project Developers"]
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"
keywords = ["webassembly", "wasm"]
categories = ["no-std", "wasm"]
license = "Apache-2.0 WITH LLVM-exception"
repository = "https://github.com/CraneStation/cranelift"
[dependencies.cast]
version = "0.2.2"
default-features = false
edition = "2018"
[dependencies.cranelift-codegen]
version = "0.29.0"
default-features = false
[dependencies]
wasmparser = { version = "0.29.2", 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]
version = "0.29.0"
default-features = false
[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"
[dev-dependencies]
wabt = "0.7.0"
target-lexicon = "0.4.0"
[features]
core = ["hashmap_core", "cranelift-codegen/core", "cranelift-frontend/core", "wasmparser/core"]
default = ["std"]
std = ["cranelift-codegen/std", "cranelift-frontend/std", "wasmparser/std"]
[badges.maintenance]
status = "experimental"
core = ["hashmap_core", "cranelift-codegen/core", "cranelift-frontend/core", "wasmparser/core"]
[badges.travis-ci]
repository = "CraneStation/cranelift"
[badges]
maintenance = { status = "experimental" }
travis-ci = { repository = "CraneStation/cranelift" }

Просмотреть файл

@ -886,6 +886,161 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
Operator::RefNull | Operator::RefIsNull { .. } => {
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(())
}

Просмотреть файл

@ -12,15 +12,15 @@ use crate::translation_utils::{
type_to_type, FuncIndex, Global, GlobalIndex, GlobalInit, Memory, MemoryIndex, SignatureIndex,
Table, TableElementType, TableIndex,
};
use core::str::from_utf8;
use cranelift_codegen::ir::{self, AbiParam, Signature};
use cranelift_entity::EntityRef;
use std::vec::Vec;
use wasmparser::{
self, CodeSectionReader, Data, DataSectionReader, Element, ElementSectionReader, Export,
ExportSectionReader, ExternalKind, FuncType, FunctionSectionReader, GlobalSectionReader,
GlobalType, ImportSectionEntryType, ImportSectionReader, MemorySectionReader, MemoryType,
Operator, TableSectionReader, TypeSectionReader,
self, CodeSectionReader, Data, DataKind, DataSectionReader, Element, ElementKind,
ElementSectionReader, Export, ExportSectionReader, ExternalKind, FuncType,
FunctionSectionReader, GlobalSectionReader, GlobalType, ImportSectionEntryType,
ImportSectionReader, MemorySectionReader, MemoryType, Operator, TableSectionReader,
TypeSectionReader,
};
/// Parses the Type section of the wasm module.
@ -65,12 +65,8 @@ pub fn parse_import_section<'data>(
for entry in imports {
let import = entry?;
// The input has already been validated, so we should be able to
// 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();
let module_name = import.module;
let field_name = import.field;
match import.ty {
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
// assume valid UTF-8 and use `from_utf8_unchecked` if performance
// becomes a concern here.
let name = from_utf8(field).unwrap();
let index = index as usize;
match *kind {
ExternalKind::Function => environ.declare_func_export(FuncIndex::new(index), name),
ExternalKind::Table => environ.declare_table_export(TableIndex::new(index), name),
ExternalKind::Memory => environ.declare_memory_export(MemoryIndex::new(index), name),
ExternalKind::Global => environ.declare_global_export(GlobalIndex::new(index), name),
ExternalKind::Function => environ.declare_func_export(FuncIndex::new(index), field),
ExternalKind::Table => environ.declare_table_export(TableIndex::new(index), field),
ExternalKind::Memory => environ.declare_memory_export(MemoryIndex::new(index), field),
ExternalKind::Global => environ.declare_global_export(GlobalIndex::new(index), field),
}
}
@ -260,29 +255,35 @@ pub fn parse_element_section<'data>(
environ.reserve_table_elements(elements.get_count());
for entry in elements {
let Element {
let Element { kind, items } = entry?;
if let ElementKind::Active {
table_index,
init_expr,
items,
} = entry?;
let mut init_expr_reader = init_expr.get_binary_reader();
let (base, offset) = match init_expr_reader.read_operator()? {
Operator::I32Const { value } => (None, value as u32 as usize),
Operator::GetGlobal { global_index } => (Some(GlobalIndex::from_u32(global_index)), 0),
ref s => panic!("unsupported init expr in element section: {:?}", s),
};
let items_reader = items.get_items_reader()?;
let mut elems = Vec::with_capacity(cast::usize(items_reader.get_count()));
for item in items_reader {
let x = item?;
elems.push(FuncIndex::from_u32(x));
} = kind
{
let mut init_expr_reader = init_expr.get_binary_reader();
let (base, offset) = match init_expr_reader.read_operator()? {
Operator::I32Const { value } => (None, value as u32 as usize),
Operator::GetGlobal { global_index } => {
(Some(GlobalIndex::from_u32(global_index)), 0)
}
ref s => panic!("unsupported init expr in element section: {:?}", s),
};
let items_reader = items.get_items_reader()?;
let mut elems = Vec::with_capacity(cast::usize(items_reader.get_count()));
for item in items_reader {
let x = item?;
elems.push(FuncIndex::from_u32(x));
}
environ.declare_table_elements(
TableIndex::from_u32(table_index),
base,
offset,
elems.into_boxed_slice(),
)
} else {
panic!("unsupported passive elements section");
}
environ.declare_table_elements(
TableIndex::from_u32(table_index),
base,
offset,
elems.into_boxed_slice(),
)
}
Ok(())
}
@ -309,23 +310,29 @@ pub fn parse_data_section<'data>(
environ.reserve_data_initializers(data.get_count());
for entry in data {
let Data {
let Data { kind, data } = entry?;
if let DataKind::Active {
memory_index,
init_expr,
data,
} = entry?;
let mut init_expr_reader = init_expr.get_binary_reader();
let (base, offset) = match init_expr_reader.read_operator()? {
Operator::I32Const { value } => (None, value as u32 as usize),
Operator::GetGlobal { global_index } => (Some(GlobalIndex::from_u32(global_index)), 0),
ref s => panic!("unsupported init expr in data section: {:?}", s),
};
environ.declare_data_initialization(
MemoryIndex::from_u32(memory_index),
base,
offset,
data,
);
} = kind
{
let mut init_expr_reader = init_expr.get_binary_reader();
let (base, offset) = match init_expr_reader.read_operator()? {
Operator::I32Const { value } => (None, value as u32 as usize),
Operator::GetGlobal { global_index } => {
(Some(GlobalIndex::from_u32(global_index)), 0)
}
ref s => panic!("unsupported init expr in data section: {:?}", s),
};
environ.declare_data_initialization(
MemoryIndex::from_u32(memory_index),
base,
offset,
data,
);
} else {
panic!("unsupported passive data section");
}
}
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 поставляемый
Просмотреть файл

@ -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 поставляемый
Просмотреть файл

@ -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]
edition = "2018"
name = "target-lexicon"
version = "0.2.0"
version = "0.4.0"
authors = ["Dan Gohman <sunfish@mozilla.com>"]
description = "Targeting utilities for compilers and related tools"
documentation = "https://docs.rs/target-lexicon/"
@ -9,18 +22,22 @@ keywords = ["target", "host", "triple", "compiler", "jit"]
categories = ["no-std"]
license = "Apache-2.0 WITH LLVM-exception"
repository = "https://github.com/CraneStation/target-lexicon"
[dependencies.failure]
version = "0.1.3"
features = ["derive"]
default-features = false
[dependencies]
failure = { version = "0.1.3", default-features = false, features = ["derive"] }
failure_derive = { version = "0.1.3", default-features = false }
[build-dependencies]
serde_json = "1.0"
[dependencies.failure_derive]
version = "0.1.3"
default-features = false
[build-dependencies.serde_json]
version = "1.0"
[features]
default = ["std"]
std = []
[badges.maintenance]
status = "passively-maintained"
[badges]
maintenance = { status = "passively-maintained" }
travis-ci = { repository = "CraneStation/target-lexicon" }
[badges.travis-ci]
repository = "CraneStation/target-lexicon"

2
third_party/rust/target-lexicon/build.rs поставляемый
Просмотреть файл

@ -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
/// and build a `Triple` using its contents.

Просмотреть файл

@ -1,6 +1,6 @@
extern crate target_lexicon;
use std::str::FromStr;
use core::str::FromStr;
use target_lexicon::{Triple, HOST};
fn main() {

2
third_party/rust/target-lexicon/src/host.rs поставляемый
Просмотреть файл

@ -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
// about the current host.

21
third_party/rust/target-lexicon/src/lib.rs поставляемый
Просмотреть файл

@ -15,29 +15,24 @@
use_self
)
)]
#![cfg_attr(not(feature = "std"), no_std)]
#![no_std]
#![cfg_attr(not(feature = "std"), feature(alloc))]
#[cfg(not(feature = "std"))]
extern crate alloc;
extern crate alloc as std;
#[cfg(feature = "std")]
extern crate std;
extern crate failure;
#[macro_use]
extern crate failure_derive;
#[cfg(not(feature = "std"))]
mod std {
pub use alloc::{borrow, string};
pub use core::*;
}
mod host;
mod parse_error;
mod targets;
#[macro_use]
mod triple;
pub use host::HOST;
pub use parse_error::ParseError;
pub use targets::{Architecture, BinaryFormat, Environment, OperatingSystem, Vendor};
pub use triple::{CallingConvention, Endianness, PointerWidth, Triple};
pub use self::host::HOST;
pub use self::parse_error::ParseError;
pub use self::targets::{Architecture, BinaryFormat, Environment, OperatingSystem, Vendor};
pub use self::triple::{CallingConvention, Endianness, PointerWidth, Triple};

Просмотреть файл

@ -16,6 +16,4 @@ pub enum ParseError {
UnrecognizedBinaryFormat(String),
#[fail(display = "Unrecognized field: {}", _0)]
UnrecognizedField(String),
#[fail(display = "\"none\" requires an explicit binary format")]
NoneWithoutBinaryFormat,
}

172
third_party/rust/target-lexicon/src/targets.rs поставляемый
Просмотреть файл

@ -1,8 +1,8 @@
// This file defines all the identifier enums and target-aware logic.
use std::fmt;
use std::str::FromStr;
use triple::{Endianness, PointerWidth, Triple};
use crate::triple::{Endianness, PointerWidth, Triple};
use core::fmt;
use core::str::FromStr;
/// The "architecture" field, which in some cases also specifies a specific
/// subarchitecture.
@ -12,9 +12,12 @@ pub enum Architecture {
Unknown,
Aarch64,
Arm,
Armebv7r,
Armv4t,
Armv5te,
Armv6,
Armv7,
Armv7r,
Armv7s,
Asmjs,
I386,
@ -29,15 +32,20 @@ pub enum Architecture {
Powerpc64,
Powerpc64le,
Riscv32,
Riscv32imac,
Riscv32imc,
Riscv64,
S390x,
Sparc,
Sparc64,
Sparcv9,
Thumbv6m,
Thumbv7a,
Thumbv7em,
Thumbv7m,
Thumbv7neon,
Thumbv8mBase,
Thumbv8mMain,
Wasm32,
X86_64,
}
@ -50,6 +58,7 @@ pub enum Vendor {
Unknown,
Apple,
Experimental,
Fortanix,
Pc,
Rumprun,
Sun,
@ -69,14 +78,17 @@ pub enum OperatingSystem {
Freebsd,
Fuchsia,
Haiku,
Hermit,
Ios,
L4re,
Linux,
Nebulet,
Netbsd,
None_,
Openbsd,
Redox,
Solaris,
Uefi,
Windows,
}
@ -102,6 +114,7 @@ pub enum Environment {
Musleabihf,
Msvc,
Uclibc,
Sgx,
}
/// The "binary format" field, which is usually omitted, and the binary format
@ -125,7 +138,9 @@ impl Architecture {
| Architecture::Arm
| Architecture::Armv4t
| Architecture::Armv5te
| Architecture::Armv6
| Architecture::Armv7
| Architecture::Armv7r
| Architecture::Armv7s
| Architecture::Asmjs
| Architecture::I386
@ -136,14 +151,20 @@ impl Architecture {
| Architecture::Msp430
| Architecture::Powerpc64le
| Architecture::Riscv32
| Architecture::Riscv32imac
| Architecture::Riscv32imc
| Architecture::Riscv64
| Architecture::Thumbv6m
| Architecture::Thumbv7a
| Architecture::Thumbv7em
| Architecture::Thumbv7m
| Architecture::Thumbv7neon
| Architecture::Thumbv8mBase
| Architecture::Thumbv8mMain
| Architecture::Wasm32
| Architecture::X86_64 => Ok(Endianness::Little),
Architecture::Mips
Architecture::Armebv7r
| Architecture::Mips
| Architecture::Mips64
| Architecture::Powerpc
| Architecture::Powerpc64
@ -160,9 +181,12 @@ impl Architecture {
Architecture::Unknown => Err(()),
Architecture::Msp430 => Ok(PointerWidth::U16),
Architecture::Arm
| Architecture::Armebv7r
| Architecture::Armv4t
| Architecture::Armv5te
| Architecture::Armv6
| Architecture::Armv7
| Architecture::Armv7r
| Architecture::Armv7s
| Architecture::Asmjs
| Architecture::I386
@ -170,11 +194,16 @@ impl Architecture {
| Architecture::I686
| Architecture::Mipsel
| Architecture::Riscv32
| Architecture::Riscv32imac
| Architecture::Riscv32imc
| Architecture::Sparc
| Architecture::Thumbv6m
| Architecture::Thumbv7a
| Architecture::Thumbv7em
| Architecture::Thumbv7m
| Architecture::Thumbv7neon
| Architecture::Thumbv8mBase
| Architecture::Thumbv8mMain
| Architecture::Wasm32
| Architecture::Mips
| Architecture::Powerpc => Ok(PointerWidth::U32),
@ -196,6 +225,7 @@ impl Architecture {
/// `binary_format` field.
pub fn default_binary_format(triple: &Triple) -> BinaryFormat {
match triple.operating_system {
OperatingSystem::None_ => BinaryFormat::Unknown,
OperatingSystem::Darwin | OperatingSystem::Ios => BinaryFormat::Macho,
OperatingSystem::Windows => BinaryFormat::Coff,
OperatingSystem::Nebulet | OperatingSystem::Emscripten | OperatingSystem::Unknown => {
@ -214,9 +244,12 @@ impl fmt::Display for Architecture {
Architecture::Unknown => "unknown",
Architecture::Aarch64 => "aarch64",
Architecture::Arm => "arm",
Architecture::Armebv7r => "armebv7r",
Architecture::Armv4t => "armv4t",
Architecture::Armv5te => "armv5te",
Architecture::Armv6 => "armv6",
Architecture::Armv7 => "armv7",
Architecture::Armv7r => "armv7r",
Architecture::Armv7s => "armv7s",
Architecture::Asmjs => "asmjs",
Architecture::I386 => "i386",
@ -231,15 +264,20 @@ impl fmt::Display for Architecture {
Architecture::Powerpc64 => "powerpc64",
Architecture::Powerpc64le => "powerpc64le",
Architecture::Riscv32 => "riscv32",
Architecture::Riscv32imac => "riscv32imac",
Architecture::Riscv32imc => "riscv32imc",
Architecture::Riscv64 => "riscv64",
Architecture::S390x => "s390x",
Architecture::Sparc => "sparc",
Architecture::Sparc64 => "sparc64",
Architecture::Sparcv9 => "sparcv9",
Architecture::Thumbv6m => "thumbv6m",
Architecture::Thumbv7a => "thumbv7a",
Architecture::Thumbv7em => "thumbv7em",
Architecture::Thumbv7m => "thumbv7m",
Architecture::Thumbv7neon => "thumbv7neon",
Architecture::Thumbv8mBase => "thumbv8m.base",
Architecture::Thumbv8mMain => "thumbv8m.main",
Architecture::Wasm32 => "wasm32",
Architecture::X86_64 => "x86_64",
};
@ -255,9 +293,12 @@ impl FromStr for Architecture {
"unknown" => Architecture::Unknown,
"aarch64" => Architecture::Aarch64,
"arm" => Architecture::Arm,
"armebv7r" => Architecture::Armebv7r,
"armv4t" => Architecture::Armv4t,
"armv5te" => Architecture::Armv5te,
"armv6" => Architecture::Armv6,
"armv7" => Architecture::Armv7,
"armv7r" => Architecture::Armv7r,
"armv7s" => Architecture::Armv7s,
"asmjs" => Architecture::Asmjs,
"i386" => Architecture::I386,
@ -272,15 +313,20 @@ impl FromStr for Architecture {
"powerpc64" => Architecture::Powerpc64,
"powerpc64le" => Architecture::Powerpc64le,
"riscv32" => Architecture::Riscv32,
"riscv32imac" => Architecture::Riscv32imac,
"riscv32imc" => Architecture::Riscv32imc,
"riscv64" => Architecture::Riscv64,
"s390x" => Architecture::S390x,
"sparc" => Architecture::Sparc,
"sparc64" => Architecture::Sparc64,
"sparcv9" => Architecture::Sparcv9,
"thumbv6m" => Architecture::Thumbv6m,
"thumbv7a" => Architecture::Thumbv7a,
"thumbv7em" => Architecture::Thumbv7em,
"thumbv7m" => Architecture::Thumbv7m,
"thumbv7neon" => Architecture::Thumbv7neon,
"thumbv8m.base" => Architecture::Thumbv8mBase,
"thumbv8m.main" => Architecture::Thumbv8mMain,
"wasm32" => Architecture::Wasm32,
"x86_64" => Architecture::X86_64,
_ => return Err(()),
@ -294,6 +340,7 @@ impl fmt::Display for Vendor {
Vendor::Unknown => "unknown",
Vendor::Apple => "apple",
Vendor::Experimental => "experimental",
Vendor::Fortanix => "fortanix",
Vendor::Pc => "pc",
Vendor::Rumprun => "rumprun",
Vendor::Sun => "sun",
@ -310,6 +357,7 @@ impl FromStr for Vendor {
"unknown" => Vendor::Unknown,
"apple" => Vendor::Apple,
"experimental" => Vendor::Experimental,
"fortanix" => Vendor::Fortanix,
"pc" => Vendor::Pc,
"rumprun" => Vendor::Rumprun,
"sun" => Vendor::Sun,
@ -330,14 +378,17 @@ impl fmt::Display for OperatingSystem {
OperatingSystem::Freebsd => "freebsd",
OperatingSystem::Fuchsia => "fuchsia",
OperatingSystem::Haiku => "haiku",
OperatingSystem::Hermit => "hermit",
OperatingSystem::Ios => "ios",
OperatingSystem::L4re => "l4re",
OperatingSystem::Linux => "linux",
OperatingSystem::Nebulet => "nebulet",
OperatingSystem::Netbsd => "netbsd",
OperatingSystem::None_ => "none",
OperatingSystem::Openbsd => "openbsd",
OperatingSystem::Redox => "redox",
OperatingSystem::Solaris => "solaris",
OperatingSystem::Uefi => "uefi",
OperatingSystem::Windows => "windows",
};
f.write_str(s)
@ -358,14 +409,17 @@ impl FromStr for OperatingSystem {
"freebsd" => OperatingSystem::Freebsd,
"fuchsia" => OperatingSystem::Fuchsia,
"haiku" => OperatingSystem::Haiku,
"hermit" => OperatingSystem::Hermit,
"ios" => OperatingSystem::Ios,
"l4re" => OperatingSystem::L4re,
"linux" => OperatingSystem::Linux,
"nebulet" => OperatingSystem::Nebulet,
"netbsd" => OperatingSystem::Netbsd,
"none" => OperatingSystem::None_,
"openbsd" => OperatingSystem::Openbsd,
"redox" => OperatingSystem::Redox,
"solaris" => OperatingSystem::Solaris,
"uefi" => OperatingSystem::Uefi,
"windows" => OperatingSystem::Windows,
_ => return Err(()),
})
@ -391,6 +445,7 @@ impl fmt::Display for Environment {
Environment::Musleabihf => "musleabihf",
Environment::Msvc => "msvc",
Environment::Uclibc => "uclibc",
Environment::Sgx => "sgx",
};
f.write_str(s)
}
@ -417,6 +472,7 @@ impl FromStr for Environment {
"musleabihf" => Environment::Musleabihf,
"msvc" => Environment::Msvc,
"uclibc" => Environment::Uclibc,
"sgx" => Environment::Sgx,
_ => return Err(()),
})
}
@ -461,72 +517,19 @@ mod tests {
// "rustup target list" and "rustc --print target-list".
let targets = [
"aarch64-apple-ios",
"aarch64-fuchsia",
"aarch64-linux-android",
"aarch64-unknown-fuchsia",
"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-pc-windows-msvc",
"aarch64-unknown-cloudabi",
"aarch64-unknown-freebsd",
"aarch64-unknown-fuchsia",
"aarch64-unknown-hermit",
"aarch64-unknown-linux-gnu",
"aarch64-unknown-linux-musl",
"aarch64-unknown-netbsd",
"aarch64-unknown-none",
"aarch64-unknown-openbsd",
"armebv7r-none-eabi",
"armebv7r-none-eabihf",
"arm-linux-androideabi",
"arm-unknown-linux-gnueabi",
"arm-unknown-linux-gnueabihf",
@ -534,11 +537,19 @@ mod tests {
"arm-unknown-linux-musleabihf",
"armv4t-unknown-linux-gnueabi",
"armv5te-unknown-linux-gnueabi",
"armv5te-unknown-linux-musleabi",
"armv6-unknown-netbsd-eabihf",
"armv7-apple-ios",
"armv7-linux-androideabi",
"armv7r-none-eabi",
"armv7r-none-eabihf",
"armv7s-apple-ios",
"armv7-unknown-cloudabi-eabihf",
"armv7-unknown-linux-gnueabihf",
"armv7-unknown-linux-musleabihf",
"armv7-unknown-netbsd-eabihf",
"asmjs-unknown-emscripten",
"i386-apple-ios",
"i586-pc-windows-msvc",
"i586-unknown-linux-gnu",
"i586-unknown-linux-musl",
@ -554,33 +565,47 @@ mod tests {
"i686-unknown-linux-musl",
"i686-unknown-netbsd",
"i686-unknown-openbsd",
"mips-unknown-linux-gnu",
"mips-unknown-linux-musl",
"mips-unknown-linux-uclibc",
"mips64-unknown-linux-gnuabi64",
"mips64el-unknown-linux-gnuabi64",
"mips64-unknown-linux-gnuabi64",
"mipsel-unknown-linux-gnu",
"mipsel-unknown-linux-musl",
"mipsel-unknown-linux-uclibc",
"mips-unknown-linux-gnu",
"mips-unknown-linux-musl",
"mips-unknown-linux-uclibc",
"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-gnuspe",
"powerpc-unknown-linux-musl",
"powerpc-unknown-netbsd",
"powerpc64-unknown-linux-gnu",
"powerpc64le-unknown-linux-gnu",
"riscv32imac-unknown-none-elf",
"riscv32imc-unknown-none-elf",
"s390x-unknown-linux-gnu",
"sparc-unknown-linux-gnu",
"sparc64-unknown-linux-gnu",
"sparc64-unknown-netbsd",
"sparc-unknown-linux-gnu",
"sparcv9-sun-solaris",
"thumbv6m-none-eabi",
"thumbv7a-pc-windows-msvc",
"thumbv7em-none-eabi",
"thumbv7em-none-eabihf",
"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-unknown-emscripten",
"wasm32-unknown-unknown",
"x86_64-apple-darwin",
"x86_64-apple-ios",
"x86_64-fortanix-unknown-sgx",
"x86_64-fuchsia",
"x86_64-linux-android",
"x86_64-pc-windows-gnu",
"x86_64-pc-windows-msvc",
@ -590,8 +615,8 @@ mod tests {
"x86_64-unknown-cloudabi",
"x86_64-unknown-dragonfly",
"x86_64-unknown-freebsd",
"x86_64-unknown-fuchsia",
"x86_64-unknown-haiku",
"x86_64-unknown-hermit",
"x86_64-unknown-l4re-uclibc",
"x86_64-unknown-linux-gnu",
"x86_64-unknown-linux-gnux32",
@ -599,6 +624,7 @@ mod tests {
"x86_64-unknown-netbsd",
"x86_64-unknown-openbsd",
"x86_64-unknown-redox",
"x86_64-unknown-uefi",
];
for target in targets.iter() {

48
third_party/rust/target-lexicon/src/triple.rs поставляемый
Просмотреть файл

@ -1,12 +1,12 @@
// This file defines the `Triple` type and support code shared by all targets.
use parse_error::ParseError;
use std::borrow::ToOwned;
use std::fmt;
use std::str::FromStr;
use targets::{
use crate::parse_error::ParseError;
use crate::targets::{
default_binary_format, Architecture, BinaryFormat, Environment, OperatingSystem, Vendor,
};
use core::fmt;
use core::str::FromStr;
use std::borrow::ToOwned;
/// The target memory endianness.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
@ -155,17 +155,24 @@ impl fmt::Display for Triple {
write!(f, "{}", self.architecture)?;
if self.vendor == Vendor::Unknown
&& self.operating_system == OperatingSystem::Unknown
&& (self.environment != Environment::Unknown
|| self.binary_format != implied_binary_format)
&& ((self.operating_system == OperatingSystem::Linux
&& (self.environment == Environment::Android
|| 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)))
{
// "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::Androideabi)
{
// 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)?;
} else {
write!(f, "-{}-{}", self.vendor, self.operating_system)?;
@ -203,16 +210,7 @@ impl FromStr for Triple {
let mut has_vendor = false;
let mut has_operating_system = false;
if let Some(s) = current_part {
// "none" is special-case shorthand for unknown vendor and unknown operating system.
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) {
if let Ok(vendor) = Vendor::from_str(s) {
has_vendor = true;
result.vendor = vendor;
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 поставляемый
Просмотреть файл

@ -12,7 +12,7 @@
[package]
name = "wasmparser"
version = "0.23.0"
version = "0.29.2"
authors = ["Yury Delendik <ydelendik@mozilla.com>"]
exclude = ["fuzz/**/*", "tests/**/*"]
description = "A simple event-driven library for parsing WebAssembly binary files.\n"

12
third_party/rust/wasmparser/examples/dump.rs поставляемый
Просмотреть файл

@ -9,10 +9,6 @@ use wasmparser::Parser;
use wasmparser::ParserState;
use wasmparser::WasmDecoder;
fn get_name(bytes: &[u8]) -> &str {
str::from_utf8(bytes).ok().unwrap()
}
fn main() {
let args = env::args().collect::<Vec<_>>();
if args.len() != 2 {
@ -32,9 +28,7 @@ fn main() {
} => {
println!(
"ExportSectionEntry {{ field: \"{}\", kind: {:?}, index: {} }}",
get_name(field),
kind,
index
field, kind, index
);
}
ParserState::ImportSectionEntry {
@ -44,9 +38,7 @@ fn main() {
} => {
println!(
"ImportSectionEntry {{ module: \"{}\", field: \"{}\", ty: {:?} }}",
get_name(module),
get_name(field),
ty
module, field, ty
);
}
ParserState::EndWasm => break,

Просмотреть файл

@ -9,10 +9,6 @@ use wasmparser::Parser;
use wasmparser::ParserState;
use wasmparser::WasmDecoder;
fn get_name(bytes: &[u8]) -> &str {
str::from_utf8(bytes).ok().unwrap()
}
fn main() {
let args = env::args().collect::<Vec<_>>();
if args.len() != 2 {
@ -31,10 +27,10 @@ fn main() {
ParserState::ExportSectionEntry {
field, ref kind, ..
} => {
println!(" Export {} {:?}", get_name(field), kind);
println!(" Export {} {:?}", field, kind);
}
ParserState::ImportSectionEntry { module, field, .. } => {
println!(" Import {}::{}", get_name(module), get_name(field))
println!(" Import {}::{}", module, field)
}
ParserState::EndWasm => break,
ParserState::Error(err) => panic!("Error: {:?}", err),

Просмотреть файл

@ -14,6 +14,7 @@
*/
use std::boxed::Box;
use std::str;
use std::vec::Vec;
use limits::{
@ -24,35 +25,17 @@ use limits::{
use primitives::{
BinaryReaderError, BrTable, CustomSectionKind, ExternalKind, FuncType, GlobalType, Ieee32,
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;
fn is_name(name: &[u8], expected: &'static str) -> bool {
if name.len() != expected.len() {
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(name: &str, expected: &'static str) -> bool {
name == expected
}
fn is_name_prefix(name: &[u8], prefix: &'static str) -> bool {
if name.len() < prefix.len() {
return false;
}
let expected_bytes = prefix.as_bytes();
for i in 0..expected_bytes.len() {
if name[i] != expected_bytes[i] {
return false;
}
}
true
fn is_name_prefix(name: &str, prefix: &'static str) -> bool {
name.starts_with(prefix)
}
const WASM_MAGIC_NUMBER: u32 = 0x6d736100;
@ -123,6 +106,13 @@ impl<'a> BinaryReader<'a> {
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<()> {
if self.position < self.buffer.len() {
Ok(())
@ -185,6 +175,7 @@ impl<'a> BinaryReader<'a> {
-0x02 => Ok(Type::I64),
-0x03 => Ok(Type::F32),
-0x04 => Ok(Type::F64),
-0x05 => Ok(Type::V128),
-0x10 => Ok(Type::AnyFunc),
-0x11 => Ok(Type::AnyRef),
-0x20 => Ok(Type::Func),
@ -332,6 +323,8 @@ impl<'a> BinaryReader<'a> {
let name = self.read_string()?;
let kind = if is_name(name, "name") {
CustomSectionKind::Name
} else if is_name(name, "producers") {
CustomSectionKind::Producers
} else if is_name(name, "sourceMappingURL") {
CustomSectionKind::SourceMappingURL
} else if is_name_prefix(name, "reloc.") {
@ -354,6 +347,7 @@ impl<'a> BinaryReader<'a> {
9 => Ok(SectionCode::Element),
10 => Ok(SectionCode::Code),
11 => Ok(SectionCode::Data),
12 => Ok(SectionCode::DataCount),
_ => Err(BinaryReaderError {
message: "Invalid section code",
offset,
@ -376,6 +370,7 @@ impl<'a> BinaryReader<'a> {
self.skip_var_32()?;
Ok(BrTable {
buffer: &self.buffer[start..self.position],
cnt: targets_len as usize,
})
}
@ -558,7 +553,7 @@ impl<'a> BinaryReader<'a> {
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;
if len > MAX_WASM_STRING_SIZE {
return Err(BinaryReaderError {
@ -566,7 +561,11 @@ impl<'a> BinaryReader<'a> {
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> {
@ -786,7 +785,7 @@ impl<'a> BinaryReader<'a> {
return Err(BinaryReaderError {
message: "Unknown 0xFE opcode",
offset: self.original_position() - 1,
})
});
}
})
}
@ -822,7 +821,7 @@ impl<'a> BinaryReader<'a> {
},
0x11 => Operator::CallIndirect {
index: self.read_var_u32()?,
table_index: self.read_var_u1()?,
table_index: self.read_var_u32()?,
},
0x1a => Operator::Drop,
0x1b => Operator::Select,
@ -841,6 +840,12 @@ impl<'a> BinaryReader<'a> {
0x24 => Operator::SetGlobal {
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 {
memarg: self.read_memarg()?,
},
@ -1062,14 +1067,14 @@ impl<'a> BinaryReader<'a> {
0xd1 => Operator::RefIsNull,
0xfc => self.read_0xfc_operator()?,
0xfd => self.read_0xfd_operator()?,
0xfe => self.read_0xfe_operator()?,
_ => {
return Err(BinaryReaderError {
message: "Unknown opcode",
offset: self.original_position() - 1,
})
});
}
})
}
@ -1086,11 +1091,304 @@ impl<'a> BinaryReader<'a> {
0x06 => Operator::I64TruncSSatF64,
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 {
message: "Unknown 0xfc opcode",
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> {
/// Returns the number of `br_table` entries, not including the default
/// label
pub fn len(&self) -> usize {
self.cnt
}
/// Reads br_table entries.
///
/// # Examples

6
third_party/rust/wasmparser/src/lib.rs поставляемый
Просмотреть файл

@ -66,6 +66,7 @@ pub use primitives::Result;
pub use primitives::SectionCode;
pub use primitives::TableType;
pub use primitives::Type;
pub use primitives::V128;
pub use validator::validate;
pub use validator::OperatorValidatorConfig;
@ -76,10 +77,12 @@ pub use validator::WasmModuleResources;
pub use readers::CodeSectionReader;
pub use readers::Data;
pub use readers::DataKind;
pub use readers::DataSectionReader;
pub use readers::Element;
pub use readers::ElementItems;
pub use readers::ElementItemsReader;
pub use readers::ElementKind;
pub use readers::ElementSectionReader;
pub use readers::Export;
pub use readers::ExportSectionReader;
@ -98,6 +101,9 @@ pub use readers::Name;
pub use readers::NameSectionReader;
pub use readers::NamingReader;
pub use readers::OperatorsReader;
pub use readers::ProducersField;
pub use readers::ProducersFieldValue;
pub use readers::ProducersSectionReader;
pub use readers::Reloc;
pub use readers::RelocSectionReader;
pub use readers::Section;

112
third_party/rust/wasmparser/src/parser.rs поставляемый
Просмотреть файл

@ -28,11 +28,11 @@ use primitives::{
};
use readers::{
CodeSectionReader, Data, DataSectionReader, Element, ElementItems, ElementSectionReader,
Export, ExportSectionReader, FunctionBody, FunctionSectionReader, Global, GlobalSectionReader,
Import, ImportSectionReader, LinkingSectionReader, MemorySectionReader, ModuleReader, Name,
NameSectionReader, NamingReader, OperatorsReader, Reloc, RelocSectionReader, Section,
SectionReader, TableSectionReader, TypeSectionReader,
CodeSectionReader, Data, DataKind, DataSectionReader, Element, ElementItems, ElementKind,
ElementSectionReader, Export, ExportSectionReader, FunctionBody, FunctionSectionReader, Global,
GlobalSectionReader, Import, ImportSectionReader, LinkingSectionReader, MemorySectionReader,
ModuleReader, Name, NameSectionReader, NamingReader, OperatorsReader, Reloc,
RelocSectionReader, Section, SectionReader, TableSectionReader, TypeSectionReader,
};
use binary_reader::{BinaryReader, Range};
@ -47,7 +47,7 @@ pub struct LocalName<'a> {
#[derive(Debug)]
pub enum NameEntry<'a> {
Module(&'a [u8]),
Module(&'a str),
Function(Box<[Naming<'a>]>),
Local(Box<[LocalName<'a>]>),
}
@ -86,20 +86,21 @@ pub enum ParserState<'a> {
TypeSectionEntry(FuncType),
ImportSectionEntry {
module: &'a [u8],
field: &'a [u8],
module: &'a str,
field: &'a str,
ty: ImportSectionEntryType,
},
FunctionSectionEntry(u32),
TableSectionEntry(TableType),
MemorySectionEntry(MemoryType),
ExportSectionEntry {
field: &'a [u8],
field: &'a str,
kind: ExternalKind,
index: u32,
},
NameSectionEntry(NameEntry<'a>),
StartSectionEntry(u32),
DataCountSectionEntry(u32),
BeginInitExpressionBody,
InitExpressionOperator(Operator<'a>),
@ -115,11 +116,13 @@ pub enum ParserState<'a> {
EndFunctionBody,
SkippingFunctionBody,
BeginElementSectionEntry(u32),
BeginPassiveElementSectionEntry(Type),
BeginActiveElementSectionEntry(u32),
ElementSectionEntryBody(Box<[u32]>),
EndElementSectionEntry,
BeginDataSectionEntry(u32),
BeginPassiveDataSectionEntry,
BeginActiveDataSectionEntry(u32),
EndDataSectionEntry,
BeginDataSectionEntryBody(u32),
DataSectionEntryBodyChunk(&'a [u8]),
@ -132,7 +135,7 @@ pub enum ParserState<'a> {
RelocSectionEntry(RelocEntry),
LinkingSectionEntry(LinkingType),
SourceMappingURL(&'a [u8]),
SourceMappingURL(&'a str),
}
#[derive(Debug, Copy, Clone)]
@ -269,33 +272,33 @@ impl<'a> Parser<'a> {
ParserSectionReader::CodeSectionReader(ref reader) => return reader.original_position(),
ParserSectionReader::DataSectionReader(ref reader) => return reader.original_position(),
ParserSectionReader::ElementSectionReader(ref reader) => {
return reader.original_position()
return reader.original_position();
}
ParserSectionReader::ExportSectionReader(ref reader) => {
return reader.original_position()
return reader.original_position();
}
ParserSectionReader::FunctionSectionReader(ref reader) => {
return reader.original_position()
return reader.original_position();
}
ParserSectionReader::GlobalSectionReader(ref reader) => {
return reader.original_position()
return reader.original_position();
}
ParserSectionReader::ImportSectionReader(ref reader) => {
return reader.original_position()
return reader.original_position();
}
ParserSectionReader::MemorySectionReader(ref reader) => {
return reader.original_position()
return reader.original_position();
}
ParserSectionReader::TableSectionReader(ref reader) => {
return reader.original_position()
return reader.original_position();
}
ParserSectionReader::TypeSectionReader(ref reader) => return reader.original_position(),
ParserSectionReader::NameSectionReader(ref reader) => return reader.original_position(),
ParserSectionReader::LinkingSectionReader(ref reader) => {
return reader.original_position()
return reader.original_position();
}
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<()> {
let section = self.module_reader.as_mut().expect("module reader").read()?;
let code = section.code;
let range = section.get_range();
let range = section.range();
self.current_section = Some(section);
self.state = ParserState::BeginSection { code, range };
Ok(())
@ -408,13 +411,19 @@ impl<'a> Parser<'a> {
if self.section_entries_left == 0 {
return self.check_section_end();
}
let Element {
table_index,
init_expr,
items,
} = section_reader!(self, ElementSectionReader).read()?;
self.state = ParserState::BeginElementSectionEntry(table_index);
self.operators_reader = Some(init_expr.get_operators_reader());
let Element { kind, items } = section_reader!(self, ElementSectionReader).read()?;
match kind {
ElementKind::Passive(ty) => {
self.state = ParserState::BeginPassiveElementSectionEntry(ty);
}
ElementKind::Active {
table_index,
init_expr,
} => {
self.state = ParserState::BeginActiveElementSectionEntry(table_index);
self.operators_reader = Some(init_expr.get_operators_reader());
}
}
self.element_items = Some(items);
self.section_entries_left -= 1;
Ok(())
@ -447,7 +456,7 @@ impl<'a> Parser<'a> {
return self.check_section_end();
}
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.current_function_body = Some(function_body);
self.section_entries_left -= 1;
@ -529,13 +538,19 @@ impl<'a> Parser<'a> {
if self.section_entries_left == 0 {
return self.check_section_end();
}
let Data {
memory_index,
init_expr,
data,
} = section_reader!(self, DataSectionReader).read()?;
self.state = ParserState::BeginDataSectionEntry(memory_index);
self.operators_reader = Some(init_expr.get_operators_reader());
let Data { kind, data } = section_reader!(self, DataSectionReader).read()?;
match kind {
DataKind::Passive => {
self.state = ParserState::BeginPassiveDataSectionEntry;
}
DataKind::Active {
memory_index,
init_expr,
} => {
self.state = ParserState::BeginActiveDataSectionEntry(memory_index);
self.operators_reader = Some(init_expr.get_operators_reader());
}
}
self.current_data_segment = Some(data);
self.section_entries_left -= 1;
Ok(())
@ -731,6 +746,17 @@ impl<'a> Parser<'a> {
.get_start_section_content()?;
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 {
code: SectionCode::Custom { .. },
..
@ -774,7 +800,8 @@ impl<'a> Parser<'a> {
start_section_reader!(self, LinkingSectionReader, get_linking_section_reader);
self.read_linking_entry()?;
}
ParserState::ReadingCustomSection(CustomSectionKind::Unknown) => {
ParserState::ReadingCustomSection(CustomSectionKind::Producers)
| ParserState::ReadingCustomSection(CustomSectionKind::Unknown) => {
self.create_custom_section_binary_reader();
self.read_section_body_bytes()?;
}
@ -875,13 +902,17 @@ impl<'a> Parser<'a> {
self.read_init_expression_body(InitExpressionContinuation::GlobalSection)
}
ParserState::EndGlobalSectionEntry => self.read_global_entry()?,
ParserState::BeginElementSectionEntry(_) => {
ParserState::BeginPassiveElementSectionEntry(_) => self.read_element_entry_body()?,
ParserState::BeginActiveElementSectionEntry(_) => {
self.read_init_expression_body(InitExpressionContinuation::ElementSection)
}
ParserState::BeginInitExpressionBody | ParserState::InitExpressionOperator(_) => {
self.read_init_expression_operator()?
}
ParserState::BeginDataSectionEntry(_) => {
ParserState::BeginPassiveDataSectionEntry => {
self.read_data_entry_body()?;
}
ParserState::BeginActiveDataSectionEntry(_) => {
self.read_init_expression_body(InitExpressionContinuation::DataSection)
}
ParserState::EndInitExpressionBody => {
@ -917,6 +948,7 @@ impl<'a> Parser<'a> {
}
ParserState::EndElementSectionEntry => self.read_element_entry()?,
ParserState::StartSectionEntry(_) => self.position_to_section_end()?,
ParserState::DataCountSectionEntry(_) => self.position_to_section_end()?,
ParserState::NameSectionEntry(_) => self.read_name_entry()?,
ParserState::SourceMappingURL(_) => self.position_to_section_end()?,
ParserState::RelocSectionHeader(_) => {

208
third_party/rust/wasmparser/src/primitives.rs поставляемый
Просмотреть файл

@ -14,6 +14,8 @@
*/
use std::boxed::Box;
use std::error::Error;
use std::fmt;
use std::result;
#[derive(Debug, Copy, Clone)]
@ -24,10 +26,19 @@ pub struct 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)]
pub enum CustomSectionKind {
Unknown,
Name,
Producers,
SourceMappingURL,
Reloc,
Linking,
@ -39,20 +50,21 @@ pub enum CustomSectionKind {
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum SectionCode<'a> {
Custom {
name: &'a [u8],
name: &'a str,
kind: CustomSectionKind,
},
Type, // Function signature declarations
Import, // Import declarations
Function, // Function declarations
Table, // Indirect function table and other tables
Memory, // Memory attributes
Global, // Global declarations
Export, // Exports
Start, // Start function declaration
Element, // Elements section
Code, // Function bodies (code)
Data, // Data segments
Type, // Function signature declarations
Import, // Import declarations
Function, // Function declarations
Table, // Indirect function table and other tables
Memory, // Memory attributes
Global, // Global declarations
Export, // Exports
Start, // Start function declaration
Element, // Elements section
Code, // Function bodies (code)
Data, // Data segments
DataCount, // Count of passive data segments
}
/// Types as defined [here].
@ -64,6 +76,7 @@ pub enum Type {
I64,
F32,
F64,
V128,
AnyFunc,
AnyRef,
Func,
@ -129,7 +142,7 @@ pub struct MemoryImmediate {
#[derive(Debug, Copy, Clone)]
pub struct Naming<'a> {
pub index: u32,
pub name: &'a [u8],
pub name: &'a str,
}
#[derive(Debug, Copy, Clone)]
@ -160,6 +173,7 @@ pub enum RelocType {
#[derive(Debug)]
pub struct BrTable<'a> {
pub(crate) buffer: &'a [u8],
pub(crate) cnt: usize,
}
/// 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].
///
/// [here]: https://webassembly.github.io/spec/binary/instructions.html
@ -384,6 +409,20 @@ pub enum Operator<'a> {
I64TruncSSatF64,
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
// https://github.com/WebAssembly/threads/blob/master/proposals/threads/Overview.md
Wake { memarg: MemoryImmediate },
@ -452,4 +491,147 @@ pub enum Operator<'a> {
I64AtomicRmw8UCmpxchg { memarg: MemoryImmediate },
I64AtomicRmw16UCmpxchg { 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))
}
pub(crate) fn get_range(&self) -> Range {
pub fn range(&self) -> Range {
Range {
start: self.offset,
end: self.offset + self.data.len(),

28
third_party/rust/wasmparser/src/readers/data_count_section.rs поставляемый 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)]
pub struct Data<'a> {
pub memory_index: u32,
pub init_expr: InitExpr<'a>,
pub kind: DataKind<'a>,
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> {
reader: BinaryReader<'a>,
count: u32,
@ -64,7 +72,7 @@ impl<'a> DataSectionReader<'a> {
/// # 0x05, 0x03, 0x01, 0x00, 0x02,
/// # 0x0a, 0x05, 0x01, 0x03, 0x00, 0x01, 0x0b,
/// # 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 section = reader.read().expect("type section");
/// let section = reader.read().expect("function section");
@ -75,32 +83,48 @@ impl<'a> DataSectionReader<'a> {
/// for _ in 0..data_reader.get_count() {
/// let data = data_reader.read().expect("data");
/// println!("Data: {:?}", data);
/// let mut init_expr_reader = data.init_expr.get_binary_reader();
/// let op = init_expr_reader.read_operator().expect("op");
/// println!("Init const: {:?}", op);
/// 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");
/// println!("Init const: {:?}", op);
/// }
/// }
/// ```
pub fn read<'b>(&mut self) -> Result<Data<'b>>
where
'a: 'b,
{
let memory_index = self.reader.read_var_u32()?;
let init_expr = {
let expr_offset = self.reader.position;
self.reader.skip_init_expr()?;
let data = &self.reader.buffer[expr_offset..self.reader.position];
InitExpr::new(data, self.reader.original_offset + expr_offset)
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 expr_offset = self.reader.position;
self.reader.skip_init_expr()?;
let data = &self.reader.buffer[expr_offset..self.reader.position];
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_end = self.reader.position + data_len;
self.verify_data_end(data_end)?;
let data = &self.reader.buffer[self.reader.position..data_end];
self.reader.skip_to(data_end);
Ok(Data {
memory_index,
init_expr,
data,
})
Ok(Data { kind, data })
}
}

Просмотреть файл

@ -14,16 +14,25 @@
*/
use super::{
BinaryReader, InitExpr, Result, SectionIteratorLimited, SectionReader, SectionWithLimitedItems,
BinaryReader, BinaryReaderError, InitExpr, Result, SectionIteratorLimited, SectionReader,
SectionWithLimitedItems, Type,
};
#[derive(Debug, Copy, Clone)]
pub struct Element<'a> {
pub table_index: u32,
pub init_expr: InitExpr<'a>,
pub kind: ElementKind<'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)]
pub struct ElementItems<'a> {
offset: usize,
@ -129,7 +138,7 @@ impl<'a> ElementSectionReader<'a> {
/// # 0x05, 0x03, 0x01, 0x00, 0x02,
/// # 0x09, 0x07, 0x01, 0x00, 0x41, 0x00, 0x0B, 0x01, 0x00,
/// # 0x0a, 0x05, 0x01, 0x03, 0x00, 0x01, 0x0b];
/// use wasmparser::ModuleReader;
/// use wasmparser::{ModuleReader, ElementKind};
///use wasmparser::Result;
/// let mut reader = ModuleReader::new(data).expect("module reader");
/// let section = reader.read().expect("type section");
@ -140,9 +149,11 @@ impl<'a> ElementSectionReader<'a> {
/// for _ in 0..element_reader.get_count() {
/// let element = element_reader.read().expect("element");
/// println!("Element: {:?}", element);
/// let mut init_expr_reader = element.init_expr.get_binary_reader();
/// let op = init_expr_reader.read_operator().expect("op");
/// println!("Init const: {:?}", op);
/// 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");
/// println!("Init const: {:?}", op);
/// }
/// let mut items_reader = element.items.get_items_reader().expect("items reader");
/// for _ in 0..items_reader.get_count() {
/// let item = items_reader.read().expect("item");
@ -154,12 +165,31 @@ impl<'a> ElementSectionReader<'a> {
where
'a: 'b,
{
let table_index = self.reader.read_var_u32()?;
let init_expr = {
let expr_offset = self.reader.position;
self.reader.skip_init_expr()?;
let data = &self.reader.buffer[expr_offset..self.reader.position];
InitExpr::new(data, self.reader.original_offset + expr_offset)
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 expr_offset = self.reader.position;
self.reader.skip_init_expr()?;
let data = &self.reader.buffer[expr_offset..self.reader.position];
InitExpr::new(data, self.reader.original_offset + expr_offset)
};
ElementKind::Active {
table_index,
init_expr,
}
};
let data_start = self.reader.position;
let items_count = self.reader.read_var_u32()?;
@ -171,11 +201,7 @@ impl<'a> ElementSectionReader<'a> {
offset: self.reader.original_offset + data_start,
data: &self.reader.buffer[data_start..data_end],
};
Ok(Element {
table_index,
init_expr,
items,
})
Ok(Element { kind, items })
}
}

Просмотреть файл

@ -20,7 +20,7 @@ use super::{
#[derive(Debug, Copy, Clone)]
pub struct Export<'a> {
pub field: &'a [u8],
pub field: &'a str,
pub kind: ExternalKind,
pub index: u32,
}

Просмотреть файл

@ -20,8 +20,8 @@ use super::{
#[derive(Debug, Copy, Clone)]
pub struct Import<'a> {
pub module: &'a [u8],
pub field: &'a [u8],
pub module: &'a str,
pub field: &'a str,
pub ty: ImportSectionEntryType,
}

Просмотреть файл

@ -24,11 +24,14 @@ use super::SectionHeader;
pub use self::code_section::CodeSectionReader;
pub use self::code_section::FunctionBody;
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::DataKind;
pub use self::data_section::DataSectionReader;
pub use self::element_section::Element;
pub use self::element_section::ElementItems;
pub use self::element_section::ElementItemsReader;
pub use self::element_section::ElementKind;
pub use self::element_section::ElementSectionReader;
pub use self::export_section::Export;
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::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::reloc_section::Reloc;
@ -67,6 +74,7 @@ use self::sourcemappingurl_section::read_sourcemappingurl_section_content;
pub use self::operators::OperatorsReader;
mod code_section;
mod data_count_section;
mod data_section;
mod element_section;
mod export_section;
@ -79,6 +87,7 @@ mod memory_section;
mod module;
mod name_section;
mod operators;
mod producers_section;
mod reloc_section;
mod section_reader;
mod sourcemappingurl_section;

Просмотреть файл

@ -20,10 +20,11 @@ use super::{
};
use super::{
read_sourcemappingurl_section_content, read_start_section_content, CodeSectionReader,
DataSectionReader, ElementSectionReader, ExportSectionReader, FunctionSectionReader,
GlobalSectionReader, ImportSectionReader, LinkingSectionReader, MemorySectionReader,
NameSectionReader, RelocSectionReader, TableSectionReader, TypeSectionReader,
read_data_count_section_content, read_sourcemappingurl_section_content,
read_start_section_content, CodeSectionReader, DataSectionReader, ElementSectionReader,
ExportSectionReader, FunctionSectionReader, GlobalSectionReader, ImportSectionReader,
LinkingSectionReader, MemorySectionReader, NameSectionReader, ProducersSectionReader,
RelocSectionReader, TableSectionReader, TypeSectionReader,
};
#[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>>
where
'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
'a: 'b,
{
@ -220,7 +241,7 @@ impl<'a> Section<'a> {
BinaryReader::new_with_offset(self.data, self.offset)
}
pub(crate) fn get_range(&self) -> Range {
pub fn range(&self) -> Range {
Range {
start: self.offset,
end: self.offset + self.data.len(),

Просмотреть файл

@ -24,7 +24,7 @@ pub struct 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
'a: 'b,
{

192
third_party/rust/wasmparser/src/readers/producers_section.rs поставляемый 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>(
data: &'a [u8],
offset: usize,
) -> Result<&'a [u8]> {
) -> Result<&'a str> {
let mut reader = BinaryReader::new_with_offset(data, offset);
let url = reader.read_string()?;
if !reader.eof() {

2
third_party/rust/wasmparser/src/tests.rs поставляемый
Просмотреть файл

@ -27,6 +27,8 @@ mod simple_tests {
operator_config: OperatorValidatorConfig {
enable_threads: true,
enable_reference_types: true,
enable_simd: true,
enable_bulk_memory: true,
},
mutable_global_imports: true,
});

450
third_party/rust/wasmparser/src/validator.rs поставляемый
Просмотреть файл

@ -29,7 +29,7 @@ use binary_reader::BinaryReader;
use primitives::{
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};
@ -128,6 +128,7 @@ enum SectionOrderState {
Export,
Start,
Element,
DataCount,
Code,
Data,
}
@ -146,6 +147,7 @@ impl SectionOrderState {
SectionCode::Element => Some(SectionOrderState::Element),
SectionCode::Code => Some(SectionOrderState::Code),
SectionCode::Data => Some(SectionOrderState::Data),
SectionCode::DataCount => Some(SectionOrderState::DataCount),
_ => None,
}
}
@ -302,6 +304,8 @@ pub trait WasmModuleResources {
fn memories(&self) -> &[MemoryType];
fn globals(&self) -> &[GlobalType];
fn func_type_indices(&self) -> &[u32];
fn element_count(&self) -> u32;
fn data_count(&self) -> u32;
}
type OperatorValidatorResult<T> = result::Result<T, &'static str>;
@ -310,11 +314,15 @@ type OperatorValidatorResult<T> = result::Result<T, &'static str>;
pub struct OperatorValidatorConfig {
pub enable_threads: bool,
pub enable_reference_types: bool,
pub enable_simd: bool,
pub enable_bulk_memory: bool,
}
const DEFAULT_OPERATOR_VALIDATOR_CONFIG: OperatorValidatorConfig = OperatorValidatorConfig {
enable_threads: false,
enable_reference_types: false,
enable_simd: false,
enable_bulk_memory: false,
};
struct OperatorValidator {
@ -453,7 +461,7 @@ impl OperatorValidator {
}
let block = func_state.block_at(relative_depth as usize);
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 Ok(());
@ -549,6 +557,20 @@ impl OperatorValidator {
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(
&self,
_: &MemoryImmediate,
@ -558,6 +580,13 @@ impl OperatorValidator {
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<()> {
match ty {
Type::EmptyBlockType | Type::I32 | Type::I64 | Type::F32 | Type::F64 => Ok(()),
@ -1244,6 +1273,338 @@ impl OperatorValidator {
self.check_operands(func_state, &[Type::AnyRef])?;
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>,
memories: Vec<MemoryType>,
globals: Vec<GlobalType>,
element_count: u32,
data_count: Option<u32>,
data_found: u32,
func_type_indices: Vec<u32>,
current_func_index: u32,
func_imports_count: u32,
init_expression_state: Option<InitExpressionState>,
exported_names: HashSet<Vec<u8>>,
exported_names: HashSet<String>,
current_operator_validator: Option<OperatorValidator>,
config: ValidatingParserConfig,
}
@ -1307,6 +1671,14 @@ impl<'a> WasmModuleResources for ValidatingParser<'a> {
fn func_type_indices(&self) -> &[u32] {
&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> {
@ -1327,6 +1699,9 @@ impl<'a> ValidatingParser<'a> {
init_expression_state: None,
exported_names: HashSet::new(),
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, ()> {
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"),
}
}
@ -1413,14 +1778,7 @@ impl<'a> ValidatingParser<'a> {
self.check_value_type(global_type.content_type)
}
fn check_import_entry(
&self,
module: &[u8],
field: &[u8],
import_type: &ImportSectionEntryType,
) -> ValidatorResult<'a, ()> {
self.check_utf8(module)?;
self.check_utf8(field)?;
fn check_import_entry(&self, import_type: &ImportSectionEntryType) -> ValidatorResult<'a, ()> {
match *import_type {
ImportSectionEntryType::Function(type_index) => {
if self.func_type_indices.len() >= MAX_WASM_FUNCTIONS {
@ -1481,12 +1839,11 @@ impl<'a> ValidatingParser<'a> {
fn check_export_entry(
&self,
field: &[u8],
field: &str,
kind: ExternalKind,
index: u32,
) -> ValidatorResult<'a, ()> {
self.check_utf8(field)?;
if self.exported_names.contains(&Vec::from(field)) {
if self.exported_names.contains(field) {
return self.create_error("non-unique export name");
}
match kind {
@ -1532,9 +1889,6 @@ impl<'a> ValidatingParser<'a> {
fn process_begin_section(&self, code: &SectionCode) -> ValidatorResult<'a, SectionOrderState> {
let order_state = SectionOrderState::from_section_code(code);
if let SectionCode::Custom { name, .. } = *code {
self.check_utf8(name)?;
}
Ok(match self.section_order_state {
SectionOrderState::Initial => {
if order_state.is_none() {
@ -1582,12 +1936,8 @@ impl<'a> ValidatingParser<'a> {
self.types.push(func_type.clone());
}
}
ParserState::ImportSectionEntry {
module,
field,
ref ty,
} => {
let check = self.check_import_entry(module, field, ty);
ParserState::ImportSectionEntry { ref ty, .. } => {
let check = self.check_import_entry(ty);
if check.is_err() {
self.validation_error = check.err();
} else {
@ -1666,12 +2016,19 @@ impl<'a> ValidatingParser<'a> {
}
ParserState::ExportSectionEntry { field, kind, index } => {
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) => {
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() {
self.validation_error =
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_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() {
self.validation_error =
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",
);
}
}
}
_ => (),
};
}