diff --git a/.cargo/config.in b/.cargo/config.in index 417f096bedc9d225368b8f6f57b276412428dcbb..48fa8e63c50a1b33119a52047eea9d60ae03b151 100644 --- a/.cargo/config.in +++ b/.cargo/config.in @@ -25,7 +25,7 @@ replace-with = "vendored-sources" [source."https://github.com/CraneStation/Cranelift"] git = "https://github.com/CraneStation/Cranelift" replace-with = "vendored-sources" -rev = "9c6f8feb0f28f50434c0cf67f3f7c07486a42b7e" +rev = "182414f15c18538dfebbe040469ec8001e93ecc5" [source.crates-io] replace-with = "vendored-sources" diff --git a/Cargo.lock b/Cargo.lock index 090cba812b754a40858871991538f847528a5da5..22d99bb2418385c7e8353c7407fc154ebde3297b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -189,8 +189,8 @@ name = "baldrdash" version = "0.1.0" dependencies = [ "bindgen 0.51.1-oldsyn (registry+https://github.com/rust-lang/crates.io-index)", - "cranelift-codegen 0.42.0 (git+https://github.com/CraneStation/Cranelift?rev=9c6f8feb0f28f50434c0cf67f3f7c07486a42b7e)", - "cranelift-wasm 0.42.0 (git+https://github.com/CraneStation/Cranelift?rev=9c6f8feb0f28f50434c0cf67f3f7c07486a42b7e)", + "cranelift-codegen 0.44.0 (git+https://github.com/CraneStation/Cranelift?rev=182414f15c18538dfebbe040469ec8001e93ecc5)", + "cranelift-wasm 0.44.0 (git+https://github.com/CraneStation/Cranelift?rev=182414f15c18538dfebbe040469ec8001e93ecc5)", "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -587,20 +587,21 @@ dependencies = [ [[package]] name = "cranelift-bforest" -version = "0.42.0" -source = "git+https://github.com/CraneStation/Cranelift?rev=9c6f8feb0f28f50434c0cf67f3f7c07486a42b7e#9c6f8feb0f28f50434c0cf67f3f7c07486a42b7e" +version = "0.44.0" +source = "git+https://github.com/CraneStation/Cranelift?rev=182414f15c18538dfebbe040469ec8001e93ecc5#182414f15c18538dfebbe040469ec8001e93ecc5" dependencies = [ - "cranelift-entity 0.42.0 (git+https://github.com/CraneStation/Cranelift?rev=9c6f8feb0f28f50434c0cf67f3f7c07486a42b7e)", + "cranelift-entity 0.44.0 (git+https://github.com/CraneStation/Cranelift?rev=182414f15c18538dfebbe040469ec8001e93ecc5)", ] [[package]] name = "cranelift-codegen" -version = "0.42.0" -source = "git+https://github.com/CraneStation/Cranelift?rev=9c6f8feb0f28f50434c0cf67f3f7c07486a42b7e#9c6f8feb0f28f50434c0cf67f3f7c07486a42b7e" +version = "0.44.0" +source = "git+https://github.com/CraneStation/Cranelift?rev=182414f15c18538dfebbe040469ec8001e93ecc5#182414f15c18538dfebbe040469ec8001e93ecc5" dependencies = [ - "cranelift-bforest 0.42.0 (git+https://github.com/CraneStation/Cranelift?rev=9c6f8feb0f28f50434c0cf67f3f7c07486a42b7e)", - "cranelift-codegen-meta 0.42.0 (git+https://github.com/CraneStation/Cranelift?rev=9c6f8feb0f28f50434c0cf67f3f7c07486a42b7e)", - "cranelift-entity 0.42.0 (git+https://github.com/CraneStation/Cranelift?rev=9c6f8feb0f28f50434c0cf67f3f7c07486a42b7e)", + "cranelift-bforest 0.44.0 (git+https://github.com/CraneStation/Cranelift?rev=182414f15c18538dfebbe040469ec8001e93ecc5)", + "cranelift-codegen-meta 0.44.0 (git+https://github.com/CraneStation/Cranelift?rev=182414f15c18538dfebbe040469ec8001e93ecc5)", + "cranelift-codegen-shared 0.44.0 (git+https://github.com/CraneStation/Cranelift?rev=182414f15c18538dfebbe040469ec8001e93ecc5)", + "cranelift-entity 0.44.0 (git+https://github.com/CraneStation/Cranelift?rev=182414f15c18538dfebbe040469ec8001e93ecc5)", "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)", @@ -610,23 +611,29 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.42.0" -source = "git+https://github.com/CraneStation/Cranelift?rev=9c6f8feb0f28f50434c0cf67f3f7c07486a42b7e#9c6f8feb0f28f50434c0cf67f3f7c07486a42b7e" +version = "0.44.0" +source = "git+https://github.com/CraneStation/Cranelift?rev=182414f15c18538dfebbe040469ec8001e93ecc5#182414f15c18538dfebbe040469ec8001e93ecc5" dependencies = [ - "cranelift-entity 0.42.0 (git+https://github.com/CraneStation/Cranelift?rev=9c6f8feb0f28f50434c0cf67f3f7c07486a42b7e)", + "cranelift-codegen-shared 0.44.0 (git+https://github.com/CraneStation/Cranelift?rev=182414f15c18538dfebbe040469ec8001e93ecc5)", + "cranelift-entity 0.44.0 (git+https://github.com/CraneStation/Cranelift?rev=182414f15c18538dfebbe040469ec8001e93ecc5)", ] +[[package]] +name = "cranelift-codegen-shared" +version = "0.44.0" +source = "git+https://github.com/CraneStation/Cranelift?rev=182414f15c18538dfebbe040469ec8001e93ecc5#182414f15c18538dfebbe040469ec8001e93ecc5" + [[package]] name = "cranelift-entity" -version = "0.42.0" -source = "git+https://github.com/CraneStation/Cranelift?rev=9c6f8feb0f28f50434c0cf67f3f7c07486a42b7e#9c6f8feb0f28f50434c0cf67f3f7c07486a42b7e" +version = "0.44.0" +source = "git+https://github.com/CraneStation/Cranelift?rev=182414f15c18538dfebbe040469ec8001e93ecc5#182414f15c18538dfebbe040469ec8001e93ecc5" [[package]] name = "cranelift-frontend" -version = "0.42.0" -source = "git+https://github.com/CraneStation/Cranelift?rev=9c6f8feb0f28f50434c0cf67f3f7c07486a42b7e#9c6f8feb0f28f50434c0cf67f3f7c07486a42b7e" +version = "0.44.0" +source = "git+https://github.com/CraneStation/Cranelift?rev=182414f15c18538dfebbe040469ec8001e93ecc5#182414f15c18538dfebbe040469ec8001e93ecc5" dependencies = [ - "cranelift-codegen 0.42.0 (git+https://github.com/CraneStation/Cranelift?rev=9c6f8feb0f28f50434c0cf67f3f7c07486a42b7e)", + "cranelift-codegen 0.44.0 (git+https://github.com/CraneStation/Cranelift?rev=182414f15c18538dfebbe040469ec8001e93ecc5)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", "target-lexicon 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -634,16 +641,16 @@ dependencies = [ [[package]] name = "cranelift-wasm" -version = "0.42.0" -source = "git+https://github.com/CraneStation/Cranelift?rev=9c6f8feb0f28f50434c0cf67f3f7c07486a42b7e#9c6f8feb0f28f50434c0cf67f3f7c07486a42b7e" +version = "0.44.0" +source = "git+https://github.com/CraneStation/Cranelift?rev=182414f15c18538dfebbe040469ec8001e93ecc5#182414f15c18538dfebbe040469ec8001e93ecc5" dependencies = [ - "cranelift-codegen 0.42.0 (git+https://github.com/CraneStation/Cranelift?rev=9c6f8feb0f28f50434c0cf67f3f7c07486a42b7e)", - "cranelift-entity 0.42.0 (git+https://github.com/CraneStation/Cranelift?rev=9c6f8feb0f28f50434c0cf67f3f7c07486a42b7e)", - "cranelift-frontend 0.42.0 (git+https://github.com/CraneStation/Cranelift?rev=9c6f8feb0f28f50434c0cf67f3f7c07486a42b7e)", + "cranelift-codegen 0.44.0 (git+https://github.com/CraneStation/Cranelift?rev=182414f15c18538dfebbe040469ec8001e93ecc5)", + "cranelift-entity 0.44.0 (git+https://github.com/CraneStation/Cranelift?rev=182414f15c18538dfebbe040469ec8001e93ecc5)", + "cranelift-frontend 0.44.0 (git+https://github.com/CraneStation/Cranelift?rev=182414f15c18538dfebbe040469ec8001e93ecc5)", "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.37.0 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmparser 0.39.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3459,7 +3466,7 @@ dependencies = [ [[package]] name = "wasmparser" -version = "0.37.0" +version = "0.39.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -3803,12 +3810,13 @@ 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.42.0 (git+https://github.com/CraneStation/Cranelift?rev=9c6f8feb0f28f50434c0cf67f3f7c07486a42b7e)" = "<none>" -"checksum cranelift-codegen 0.42.0 (git+https://github.com/CraneStation/Cranelift?rev=9c6f8feb0f28f50434c0cf67f3f7c07486a42b7e)" = "<none>" -"checksum cranelift-codegen-meta 0.42.0 (git+https://github.com/CraneStation/Cranelift?rev=9c6f8feb0f28f50434c0cf67f3f7c07486a42b7e)" = "<none>" -"checksum cranelift-entity 0.42.0 (git+https://github.com/CraneStation/Cranelift?rev=9c6f8feb0f28f50434c0cf67f3f7c07486a42b7e)" = "<none>" -"checksum cranelift-frontend 0.42.0 (git+https://github.com/CraneStation/Cranelift?rev=9c6f8feb0f28f50434c0cf67f3f7c07486a42b7e)" = "<none>" -"checksum cranelift-wasm 0.42.0 (git+https://github.com/CraneStation/Cranelift?rev=9c6f8feb0f28f50434c0cf67f3f7c07486a42b7e)" = "<none>" +"checksum cranelift-bforest 0.44.0 (git+https://github.com/CraneStation/Cranelift?rev=182414f15c18538dfebbe040469ec8001e93ecc5)" = "<none>" +"checksum cranelift-codegen 0.44.0 (git+https://github.com/CraneStation/Cranelift?rev=182414f15c18538dfebbe040469ec8001e93ecc5)" = "<none>" +"checksum cranelift-codegen-meta 0.44.0 (git+https://github.com/CraneStation/Cranelift?rev=182414f15c18538dfebbe040469ec8001e93ecc5)" = "<none>" +"checksum cranelift-codegen-shared 0.44.0 (git+https://github.com/CraneStation/Cranelift?rev=182414f15c18538dfebbe040469ec8001e93ecc5)" = "<none>" +"checksum cranelift-entity 0.44.0 (git+https://github.com/CraneStation/Cranelift?rev=182414f15c18538dfebbe040469ec8001e93ecc5)" = "<none>" +"checksum cranelift-frontend 0.44.0 (git+https://github.com/CraneStation/Cranelift?rev=182414f15c18538dfebbe040469ec8001e93ecc5)" = "<none>" +"checksum cranelift-wasm 0.44.0 (git+https://github.com/CraneStation/Cranelift?rev=182414f15c18538dfebbe040469ec8001e93ecc5)" = "<none>" "checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1" "checksum crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71" "checksum crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9" @@ -4059,7 +4067,7 @@ dependencies = [ "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 warp 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)" = "33857527c63bc514452f885d0a57019f28139c58fef2b3566016ecc0d44e5d24" -"checksum wasmparser 0.37.0 (registry+https://github.com/rust-lang/crates.io-index)" = "82dbea680995dad585289fd47889cf9614133ebfcc3bda95737ef8bdc9e11db6" +"checksum wasmparser 0.39.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a026c1436af49d5537c7561c7474f81f7a754e36445fe52e6e88795a9747291c" "checksum weedle 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "26a4c67f132386d965390b8a734d5d10adbcd30eb5cc74bd9229af8b83f10044" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi 0.3.6 (git+https://github.com/froydnj/winapi-rs?branch=aarch64)" = "<none>" diff --git a/Cargo.toml b/Cargo.toml index 722880c2f6ef075170e151f1622f1e80e58927be..9f8db22bfce984de9238fbcdf3df626519e0568b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -64,11 +64,11 @@ packed_simd = { git = "https://github.com/hsivonen/packed_simd", branch = "rust_ [patch.crates-io.cranelift-codegen] git = "https://github.com/CraneStation/Cranelift" -rev = "9c6f8feb0f28f50434c0cf67f3f7c07486a42b7e" +rev = "182414f15c18538dfebbe040469ec8001e93ecc5" [patch.crates-io.cranelift-wasm] git = "https://github.com/CraneStation/Cranelift" -rev = "9c6f8feb0f28f50434c0cf67f3f7c07486a42b7e" +rev = "182414f15c18538dfebbe040469ec8001e93ecc5" [patch.crates-io.coreaudio-sys] path = "third_party/rust/coreaudio-sys" diff --git a/js/src/wasm/cranelift/Cargo.toml b/js/src/wasm/cranelift/Cargo.toml index b22a860f81146754a348ba6e9647249655c45fda..d8e972f22f61710368ec9d87eb7e5383319b07d6 100644 --- a/js/src/wasm/cranelift/Cargo.toml +++ b/js/src/wasm/cranelift/Cargo.toml @@ -13,8 +13,8 @@ name = "baldrdash" # cranelift-wasm to pinned commits. If you want to update Cranelift in Gecko, # you should update the following $TOP_LEVEL/Cargo.toml file: look for the # revision (rev) hashes of both cranelift dependencies (codegen and wasm). -cranelift-codegen = { version = "0.42", default-features = false } -cranelift-wasm = "0.42" +cranelift-codegen = { version = "0.44", default-features = false } +cranelift-wasm = "0.44" log = { version = "0.4.6", default-features = false, features = ["release_max_level_info"] } env_logger = "0.6" smallvec = { version = "0.6.6" } diff --git a/third_party/rust/cranelift-bforest/.cargo-checksum.json b/third_party/rust/cranelift-bforest/.cargo-checksum.json index c8d31b7866c96345101d137b14652f1de17a3166..a6097d2734d0323e1c260c3ef07676f86874cee1 100644 --- a/third_party/rust/cranelift-bforest/.cargo-checksum.json +++ b/third_party/rust/cranelift-bforest/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"5c0fac24938cd87403f8055d56082b820a284f40a45be73c0fcd63fad0704285","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"af367c67340fa7f6fb9a35b0aa637dcf303957f7ae7427a5f4f6356801c8bb04","src/lib.rs":"d821f2fe04df070a05a2e1de29b913f9970dfb500b35511a39c2976f1f26c977","src/map.rs":"5d891d62814941e19dfc88ff36538efa3da5479f3f97de8219a6f610c9a1ee32","src/node.rs":"e620c64e78488035f11723b14892c7986c06ad37dc5b115a35a453ff1ae66ca3","src/path.rs":"a86ee1c882c173e8af96fd53a416a0fb485dd3f045ac590ef313a9d9ecf90f56","src/pool.rs":"6090f8c0e0da16ebee0e31bca66392d0075b3aff529d30d4e716fa20cd0aef99","src/set.rs":"b411158f813a310c7a6c337d4ada3bf0a021088c443875dc25233415dcbe0633"},"package":null} \ No newline at end of file +{"files":{"Cargo.toml":"f6af616cc6e55e0ff0a292c52fb8bd5b093345fe5495e67f153dd94da153adab","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"af367c67340fa7f6fb9a35b0aa637dcf303957f7ae7427a5f4f6356801c8bb04","src/lib.rs":"d821f2fe04df070a05a2e1de29b913f9970dfb500b35511a39c2976f1f26c977","src/map.rs":"5d891d62814941e19dfc88ff36538efa3da5479f3f97de8219a6f610c9a1ee32","src/node.rs":"e620c64e78488035f11723b14892c7986c06ad37dc5b115a35a453ff1ae66ca3","src/path.rs":"a86ee1c882c173e8af96fd53a416a0fb485dd3f045ac590ef313a9d9ecf90f56","src/pool.rs":"56f987d338a9419696ffb3ff09a4322a0ec97554eeca255e8c5fae7941e44f57","src/set.rs":"b411158f813a310c7a6c337d4ada3bf0a021088c443875dc25233415dcbe0633"},"package":null} \ No newline at end of file diff --git a/third_party/rust/cranelift-bforest/Cargo.toml b/third_party/rust/cranelift-bforest/Cargo.toml index fee6d19b2e1122a12e7b8300413c67e60ea6a0f8..960827da52b542c77b359cffe418efc19d77758c 100644 --- a/third_party/rust/cranelift-bforest/Cargo.toml +++ b/third_party/rust/cranelift-bforest/Cargo.toml @@ -1,7 +1,7 @@ [package] authors = ["The Cranelift Project Developers"] name = "cranelift-bforest" -version = "0.42.0" +version = "0.44.0" description = "A forest of B+-trees" license = "Apache-2.0 WITH LLVM-exception" documentation = "https://cranelift.readthedocs.io/" @@ -12,7 +12,7 @@ keywords = ["btree", "forest", "set", "map"] edition = "2018" [dependencies] -cranelift-entity = { path = "../cranelift-entity", version = "0.42.0", default-features = false } +cranelift-entity = { path = "../cranelift-entity", version = "0.44.0", default-features = false } [features] default = ["std"] diff --git a/third_party/rust/cranelift-bforest/src/pool.rs b/third_party/rust/cranelift-bforest/src/pool.rs index 1b51cfe56bbb4e8915623136dee9795f9e813a4c..0848089eb6adaab03ea44afa905aee1dd95a3935 100644 --- a/third_party/rust/cranelift-bforest/src/pool.rs +++ b/third_party/rust/cranelift-bforest/src/pool.rs @@ -83,7 +83,7 @@ impl<F: Forest> NodePool<F> { NodeData<F>: fmt::Display, F::Key: fmt::Display, { - use crate::entity::SparseSet; + use crate::entity::EntitySet; use core::borrow::Borrow; use core::cmp::Ordering; use std::vec::Vec; @@ -94,7 +94,13 @@ impl<F: Forest> NodePool<F> { assert!(size > 0, "Root must have more than one sub-tree"); } - let mut done = SparseSet::new(); + let mut done = match self[node] { + NodeData::Inner { size, .. } | NodeData::Leaf { size, .. } => { + EntitySet::with_capacity(size.into()) + } + _ => EntitySet::new(), + }; + let mut todo = Vec::new(); // Todo-list entries are: @@ -104,11 +110,7 @@ impl<F: Forest> NodePool<F> { todo.push((None, node, None)); while let Some((lkey, node, rkey)) = todo.pop() { - assert_eq!( - done.insert(node), - None, - "Node appears more than once in tree" - ); + assert!(done.insert(node), "Node appears more than once in tree"); let mut lower = lkey; match self[node] { diff --git a/third_party/rust/cranelift-codegen-meta/.cargo-checksum.json b/third_party/rust/cranelift-codegen-meta/.cargo-checksum.json index 272698e152a1438237618f57bda5563299aa2efc..61afd2416ccb6ca1761f346b5df066ff8f3e7470 100644 --- a/third_party/rust/cranelift-codegen-meta/.cargo-checksum.json +++ b/third_party/rust/cranelift-codegen-meta/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"e4a42edddd547e9aff7d2ccc3469f3685ae1eff54cece29d8f4fa1d2e80b063d","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"b123f056d0d458396679c5f7f2a16d2762af0258fcda4ac14b6655a95e5a0022","src/cdsl/ast.rs":"7ff4532bb6c3c4570918cfac54c308f345d6710ad8696aa444503a60d42408a6","src/cdsl/cpu_modes.rs":"7c59ae347d6f9c769d6356fe49c8406934153eefa59d9bf37c182474fcbb9715","src/cdsl/encodings.rs":"da6fa16c95fe4a586c2d00ef4ccf79b4b0f64cd8923b3ca5a5a527da1e799a4f","src/cdsl/formats.rs":"5ed0d689b791d928e51f9608cb139dde7be810ff1dc4e03c58a6fe79e43eeffd","src/cdsl/instructions.rs":"cd1b1c6ccf90a3ba3506859d7bff9f7073a46c11aecf501b7b35af68e76240e2","src/cdsl/isa.rs":"9b6030a935f69b07726d239c23a78d654566785f1fed61ccefdaf7d4f0a97d0e","src/cdsl/mod.rs":"c85f62a7d8d6bedc81c673b8d02be01181f79f272dbc0325a76d52e7eec732e8","src/cdsl/operands.rs":"1cda258798d861c4f467783b5c70c1202a57f554861017eead6477af2ee34063","src/cdsl/recipes.rs":"9f50f29f243f2ed8dbca3ef8b2722e9671bc164b2956254a95ed62641315eab7","src/cdsl/regs.rs":"3e70d11c04a123c9d91075e14af6909a885f37a0c2f86df6aca1b337e2994763","src/cdsl/settings.rs":"7da3c5a9df8e47ed6ca7f1d820e28eae45e783f3759f6c55730d2f17d88f1013","src/cdsl/type_inference.rs":"c576403ca05921d6a416b21e7f5bd5a2219b635ad78ed1139dc8e3363ba61beb","src/cdsl/types.rs":"9f8221b5d3987b30943ba5f168190cb220b59350e9463ca264ecfd663dbbc3a2","src/cdsl/typevar.rs":"2b67b32524cdf783aeb1fcedbf82a33190104e87ed210ca0638cf6bb28eefd98","src/cdsl/xform.rs":"120be9a35b48d4b2c474bca9684c687797045d1d07554f639e1812cda16cc743","src/constant_hash.rs":"66d6f42c1e98cd4dbc95009997dc00256b57c11d2c2d9eac63b33e458c68a56f","src/default_map.rs":"8bbd6f4d9f93ef2126538cda633e6d9c80a5c7dc79b8d5a759c8be1fe2dbc605","src/error.rs":"5110a4e3c1e97396ba02d9f5abbb8af4b586f0cc4d33a5c2473f1718cc4bef05","src/gen_binemit.rs":"80c27e9c66d2ac3dc8a41cc545f046bd4297ba6530805539e86461984fd2667d","src/gen_encodings.rs":"bb598d4eeb8e7365a023ebbb4cc0d8c9f57163b4d0d489047f0fcdbe83880adb","src/gen_inst.rs":"c31663699705cb35697dd23ee4f34d2502414a2d2f716b872e47aac1ba56e710","src/gen_legalizer.rs":"0e8ea0810da954d812f9110e900b9ba3830ff81be46c5985e0340e69f75ebbe8","src/gen_registers.rs":"9b581bd79a1370cdc6920ed18e8da84751813a4b1c9697e891bf0da4eceefc0d","src/gen_settings.rs":"765ca86fa735342c1875021c34a92cbc39836ba3ad1c12aa615204372a1f7b61","src/gen_types.rs":"c062eaf3a2ed7368b87213922906107bbaec184fe821184a34dacb4e5b0fc3dc","src/isa/arm32/mod.rs":"5ca444f18d438f879edb857c75e129931067794a669b607350c4ed648fd92520","src/isa/arm64/mod.rs":"9a1acc8533a1c9be332c565f399cf1c9b5a0a85290bf7bcb82b778fc412d5fa5","src/isa/mod.rs":"a728d5063d34a4ac572ad63ff0f458da33703c58cdd901a0c36276f426fbb0d1","src/isa/riscv/encodings.rs":"695159378a75cb143482c401c4e5ffefa28082cbb996e944942ef0cdc3d10db6","src/isa/riscv/mod.rs":"4945ad95284ac157593935722b75f120b4a0e22b133e69a1e9784e6cd3615c0a","src/isa/riscv/recipes.rs":"5cfdc71a3d5640de6ec956eb8eb6a3a85135daa1d6e30d1d6a693b6ad2d12e0e","src/isa/x86/encodings.rs":"886c875d740ba0b4b3d34c2c06eb33e2089a529eba1103bf962452e0bc34c0e5","src/isa/x86/instructions.rs":"c438579d98562e6efb67edf5983ffab26a3c7c2d8b20dccbd2667687031fa7f4","src/isa/x86/legalize.rs":"1f44559eac3e9db307759bbed8db5d15b1166303e3fa3c9c5fb386ad990e32a5","src/isa/x86/mod.rs":"7a3aeebfed131b86244fc4746b3dc42f4968d48cbb23a10214efb0a0d56c94c9","src/isa/x86/recipes.rs":"a9c128c26918eb01b400b78d7eee04a3cc61784b1288d26bd43b4ea7224f2a82","src/isa/x86/registers.rs":"3cde7d3275971d651ae0f25c88bfb81128b7a35183a969aed81776d4c5141e0e","src/isa/x86/settings.rs":"4e84ff135d6f21595bbd8f56d2e561abd3c123566f2332ac93bb4a9c627f0c00","src/lib.rs":"bc458358fd81d092f368b243d07682259dbed7a336b1eed5bcdf5228368289e9","src/shared/entities.rs":"d3dc9d6cb5ba30b1bbdcbfa4505e4897618064dab0b99006fd247d0c93f0b3dc","src/shared/formats.rs":"c6a4622fad932aadb7b5341aee5453c53ff08e0f1e1ee848752cf217fbce62b1","src/shared/immediates.rs":"954ef3c5724f26d16178fc2539111e5ecabebe9ea83d24b2b90d5a8ab411c1a9","src/shared/instructions.rs":"a21d36e9917d7d67c188a46c744c38011d81e892d7a5d32a22437047aecebdbf","src/shared/legalize.rs":"07c6a74ced50bcd7e06731165ede44880c418da0d9785e6e6b8fc02cea218d84","src/shared/mod.rs":"6c9010c934e85c668e089fded99805e9a3aa09a9d9ad408382c5345b6cb375b6","src/shared/settings.rs":"22825dd2b9d924ec147c675836ac3644adffd6a059c31b9470581c4597905c28","src/shared/types.rs":"b47799d381f3a554adcccf40824d83be56cd3ef08245c550ceff53363dfa7ad4","src/srcgen.rs":"79fee2f603b33f76f7c9c8b9452c745a363d732c40c0814d84001ff3ef805677","src/unique_table.rs":"90b7203b29241a1ede70f0a3e50d96799e0b41d8f7455170d6ffb127f87f3cc3"},"package":null} \ No newline at end of file +{"files":{"Cargo.toml":"be4b8f4a7a9f0c0d345243f4b9bf51a5c0d72350c7602ae1dc2e9d5a44ed4ee3","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"b123f056d0d458396679c5f7f2a16d2762af0258fcda4ac14b6655a95e5a0022","src/cdsl/ast.rs":"7b9d59fb1ee9efd13e2347d20b76c508bfe5992e0e4d4ccb837be763de1843db","src/cdsl/cpu_modes.rs":"b42421b48f77804c2cfae744dc9e3c98c3787746c2649af201e0d4b8997eadae","src/cdsl/encodings.rs":"299dbec5e67907cbb7e8b798913bbc606f26833cb08790d9dae159ba7d8b8c66","src/cdsl/formats.rs":"5ed0d689b791d928e51f9608cb139dde7be810ff1dc4e03c58a6fe79e43eeffd","src/cdsl/instructions.rs":"42b55c2c07878df6c23ba9b1bff78a47c933e9652252421aefd564d8c1f171f0","src/cdsl/isa.rs":"ccabd6848b69eb069c10db61c7e7f86080777495714bb53d03e663c40541be94","src/cdsl/mod.rs":"c85f62a7d8d6bedc81c673b8d02be01181f79f272dbc0325a76d52e7eec732e8","src/cdsl/operands.rs":"1cda258798d861c4f467783b5c70c1202a57f554861017eead6477af2ee34063","src/cdsl/recipes.rs":"9f50f29f243f2ed8dbca3ef8b2722e9671bc164b2956254a95ed62641315eab7","src/cdsl/regs.rs":"3e70d11c04a123c9d91075e14af6909a885f37a0c2f86df6aca1b337e2994763","src/cdsl/settings.rs":"7da3c5a9df8e47ed6ca7f1d820e28eae45e783f3759f6c55730d2f17d88f1013","src/cdsl/type_inference.rs":"4ba2099e2c5df4f603f0a51a4ac19761a4723009cbc0ae66a3e9b82f5c851c05","src/cdsl/types.rs":"9f8221b5d3987b30943ba5f168190cb220b59350e9463ca264ecfd663dbbc3a2","src/cdsl/typevar.rs":"e375a0719b918ef1922296e71758ba1ddc236b9378635db0de980ea36d427049","src/cdsl/xform.rs":"4d4769d47580e25f57ac119a2193a5e33b946545c7e75b0642d255e9cf81575f","src/constant_hash.rs":"91db790f44df312a7478271056db6edf9d12389ee9c675e2d1bb1b60c98353c9","src/default_map.rs":"5e1aeff22953d78083f5184a62da53c92e8b908f5edea30353c048e5201af9e3","src/error.rs":"5110a4e3c1e97396ba02d9f5abbb8af4b586f0cc4d33a5c2473f1718cc4bef05","src/gen_binemit.rs":"dd850f3a34a80ece53bd8a40017e77c425c0d0ad044a4efd2c1ee02c71cb614f","src/gen_encodings.rs":"bb598d4eeb8e7365a023ebbb4cc0d8c9f57163b4d0d489047f0fcdbe83880adb","src/gen_inst.rs":"d2c157a9986f31515abd2f154d7d7d8ca61efc5a932bd7ae845af959b1fc1e66","src/gen_legalizer.rs":"9634204a42273d77f0a062bbb04b83e09b11452690af9cddb0faac990fa3b346","src/gen_registers.rs":"bcc1df255045b79d0772d2a1fc9aaac44764ed23ed7acf88f57050aca735dce2","src/gen_settings.rs":"4b34cdd93a52053e88cea7f00b8078518d69fec2e89da054c1d824a8144b666a","src/gen_types.rs":"f6c090e1646a43bf2fe81ae0a7029cc6f7dc6d43285368f56d86c35a21c469a6","src/isa/arm32/mod.rs":"5ca444f18d438f879edb857c75e129931067794a669b607350c4ed648fd92520","src/isa/arm64/mod.rs":"9a1acc8533a1c9be332c565f399cf1c9b5a0a85290bf7bcb82b778fc412d5fa5","src/isa/mod.rs":"a728d5063d34a4ac572ad63ff0f458da33703c58cdd901a0c36276f426fbb0d1","src/isa/riscv/encodings.rs":"cad44ff58cd7626d039824107b3d2d5e8d909e59a25e34c8b5c90ccad76a1c28","src/isa/riscv/mod.rs":"4945ad95284ac157593935722b75f120b4a0e22b133e69a1e9784e6cd3615c0a","src/isa/riscv/recipes.rs":"5cfdc71a3d5640de6ec956eb8eb6a3a85135daa1d6e30d1d6a693b6ad2d12e0e","src/isa/x86/encodings.rs":"e03d12d7ae5aadedc2ea5f0f7952a74b093adc2c747dd0b07be9202955d0ac47","src/isa/x86/instructions.rs":"c438579d98562e6efb67edf5983ffab26a3c7c2d8b20dccbd2667687031fa7f4","src/isa/x86/legalize.rs":"150cf83b605cf0bfc7618937c60d69dbc9504c6c4242806deeb87591b18f6793","src/isa/x86/mod.rs":"1d13c0a294ce85f09d60a2d33d24848733c6053b8d47298b7b0eefbc9b7ee317","src/isa/x86/opcodes.rs":"6558e45e8027b46b2201e0152affc7093a8b10d3e45ef2f457de37af3cc180a0","src/isa/x86/recipes.rs":"43744f2d242ff233e6bf4ed8e13b5c7b024bb0c4735ddd0f6012919f91ab0e85","src/isa/x86/registers.rs":"3cde7d3275971d651ae0f25c88bfb81128b7a35183a969aed81776d4c5141e0e","src/isa/x86/settings.rs":"4e84ff135d6f21595bbd8f56d2e561abd3c123566f2332ac93bb4a9c627f0c00","src/lib.rs":"bc458358fd81d092f368b243d07682259dbed7a336b1eed5bcdf5228368289e9","src/shared/entities.rs":"d3dc9d6cb5ba30b1bbdcbfa4505e4897618064dab0b99006fd247d0c93f0b3dc","src/shared/formats.rs":"2757a729ec9b38853b4810cacbd980f44fe8b200184f45b728eb98060578d1fc","src/shared/immediates.rs":"f13c09d14d148d03ab2c6dcfdcd96d5833d0842c49ea437cbf42a085f7cdb45f","src/shared/instructions.rs":"9128d67b0b9c0a86ccc278e637ec5484ce4e5a680f410ae9b0797598bcd42b8f","src/shared/legalize.rs":"e19c1b808b4c2930323b8de2b63fb478c470014d089cf1c4ad8b349c69259979","src/shared/mod.rs":"7b4de39ea3075ba8d1733319c03f1a19d903215b7bb55f877d0f8826f4b43c85","src/shared/settings.rs":"b141f6e6f0baa516ac5bfb919bc51c577353cd7b47ca796677e32eff2bdf16ce","src/shared/types.rs":"b47799d381f3a554adcccf40824d83be56cd3ef08245c550ceff53363dfa7ad4","src/srcgen.rs":"79fee2f603b33f76f7c9c8b9452c745a363d732c40c0814d84001ff3ef805677","src/unique_table.rs":"90b7203b29241a1ede70f0a3e50d96799e0b41d8f7455170d6ffb127f87f3cc3"},"package":null} \ No newline at end of file diff --git a/third_party/rust/cranelift-codegen-meta/Cargo.toml b/third_party/rust/cranelift-codegen-meta/Cargo.toml index c623493e30988907abae035b3809a8dbd09f6011..2d759573553ea64aca38dd0ea25dae6536175bf7 100644 --- a/third_party/rust/cranelift-codegen-meta/Cargo.toml +++ b/third_party/rust/cranelift-codegen-meta/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "cranelift-codegen-meta" authors = ["The Cranelift Project Developers"] -version = "0.42.0" +version = "0.44.0" description = "Metaprogram for cranelift-codegen code generator library" license = "Apache-2.0 WITH LLVM-exception" repository = "https://github.com/CraneStation/cranelift" @@ -9,7 +9,8 @@ readme = "README.md" edition = "2018" [dependencies] -cranelift-entity = { path = "../../cranelift-entity", version = "0.42.0", default-features = false } +cranelift-codegen-shared = { path = "../shared", version = "0.44.0" } +cranelift-entity = { path = "../../cranelift-entity", version = "0.44.0", default-features = false } [badges] maintenance = { status = "experimental" } diff --git a/third_party/rust/cranelift-codegen-meta/src/cdsl/ast.rs b/third_party/rust/cranelift-codegen-meta/src/cdsl/ast.rs index 798ee29d002375fbc1300de9db5078e76fd9e623..5618927bb47db9af5b76741d339990512fd4f122 100644 --- a/third_party/rust/cranelift-codegen-meta/src/cdsl/ast.rs +++ b/third_party/rust/cranelift-codegen-meta/src/cdsl/ast.rs @@ -4,12 +4,12 @@ use crate::cdsl::operands::{OperandKind, OperandKindFields}; use crate::cdsl::types::ValueType; use crate::cdsl::typevar::{TypeSetBuilder, TypeVar}; -use cranelift_entity::{entity_impl, PrimaryMap}; +use cranelift_entity::{entity_impl, PrimaryMap, SparseMap, SparseMapValue}; use std::fmt; +use std::iter::IntoIterator; -#[derive(Debug)] -pub enum Expr { +pub(crate) enum Expr { Var(VarIndex), Literal(Literal), } @@ -44,7 +44,7 @@ impl Expr { } /// An AST definition associates a set of variables with the values produced by an expression. -pub struct Def { +pub(crate) struct Def { pub apply: Apply, pub defined_vars: Vec<VarIndex>, } @@ -67,7 +67,7 @@ impl Def { } } -pub struct DefPool { +pub(crate) struct DefPool { pool: PrimaryMap<DefIndex, Def>, } @@ -83,7 +83,7 @@ impl DefPool { pub fn next_index(&self) -> DefIndex { self.pool.next_key() } - pub fn create(&mut self, apply: Apply, defined_vars: Vec<VarIndex>) -> DefIndex { + pub fn create_inst(&mut self, apply: Apply, defined_vars: Vec<VarIndex>) -> DefIndex { self.pool.push(Def { apply, defined_vars, @@ -92,57 +92,92 @@ impl DefPool { } #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub struct DefIndex(u32); +pub(crate) struct DefIndex(u32); entity_impl!(DefIndex); -#[derive(Debug, Clone)] -enum LiteralValue { +/// A definition which would lead to generate a block creation. +#[derive(Clone)] +pub(crate) struct Block { + /// Instruction index after which the block entry is set. + pub location: DefIndex, + /// Variable holding the new created block. + pub name: VarIndex, +} + +pub(crate) struct BlockPool { + pool: SparseMap<DefIndex, Block>, +} + +impl SparseMapValue<DefIndex> for Block { + fn key(&self) -> DefIndex { + self.location + } +} + +impl BlockPool { + pub fn new() -> Self { + Self { + pool: SparseMap::new(), + } + } + pub fn get(&self, index: DefIndex) -> Option<&Block> { + self.pool.get(index) + } + pub fn create_block(&mut self, name: VarIndex, location: DefIndex) { + if self.pool.contains_key(location) { + panic!("Attempt to insert 2 blocks after the same instruction") + } + self.pool.insert(Block { location, name }); + } + pub fn is_empty(&self) -> bool { + self.pool.is_empty() + } +} + +// Implement IntoIterator such that we can iterate over blocks which are in the block pool. +impl<'a> IntoIterator for &'a BlockPool { + type Item = <&'a SparseMap<DefIndex, Block> as IntoIterator>::Item; + type IntoIter = <&'a SparseMap<DefIndex, Block> as IntoIterator>::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.pool.into_iter() + } +} + +#[derive(Clone, Debug)] +pub(crate) enum Literal { /// A value of an enumerated immediate operand. /// /// Some immediate operand kinds like `intcc` and `floatcc` have an enumerated range of values /// corresponding to a Rust enum type. An `Enumerator` object is an AST leaf node representing one /// of the values. - Enumerator(&'static str), + Enumerator { + rust_type: String, + value: &'static str, + }, /// A bitwise value of an immediate operand, used for bitwise exact floating point constants. - Bits(u64), + Bits { rust_type: String, value: u64 }, /// A value of an integer immediate operand. Int(i64), -} - -#[derive(Clone)] -pub struct Literal { - kind: OperandKind, - value: LiteralValue, -} -impl fmt::Debug for Literal { - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { - write!( - fmt, - "Literal(kind={}, value={:?})", - self.kind.name, self.value - ) - } + /// A empty list of variable set of arguments. + EmptyVarArgs, } impl Literal { pub fn enumerator_for(kind: &OperandKind, value: &'static str) -> Self { - if let OperandKindFields::ImmEnum(values) = &kind.fields { - assert!( - values.get(value).is_some(), - format!( - "nonexistent value '{}' in enumeration '{}'", - value, kind.name - ) - ); - } else { - panic!("enumerator is for enum values"); - } - Self { - kind: kind.clone(), - value: LiteralValue::Enumerator(value), + let value = match &kind.fields { + OperandKindFields::ImmEnum(values) => values.get(value).expect(&format!( + "nonexistent value '{}' in enumeration '{}'", + value, kind.name + )), + _ => panic!("enumerator is for enum values"), + }; + Literal::Enumerator { + rust_type: kind.rust_type.clone(), + value, } } @@ -151,42 +186,36 @@ impl Literal { OperandKindFields::ImmValue => {} _ => panic!("bits_of is for immediate scalar types"), } - Self { - kind: kind.clone(), - value: LiteralValue::Bits(bits), + Literal::Bits { + rust_type: kind.rust_type.clone(), + value: bits, } } pub fn constant(kind: &OperandKind, value: i64) -> Self { match kind.fields { OperandKindFields::ImmValue => {} - _ => panic!("bits_of is for immediate scalar types"), - } - Self { - kind: kind.clone(), - value: LiteralValue::Int(value), + _ => panic!("constant is for immediate scalar types"), } + Literal::Int(value) } - pub fn to_rust_code(&self) -> String { - let maybe_values = match &self.kind.fields { - OperandKindFields::ImmEnum(values) => Some(values), - OperandKindFields::ImmValue => None, - _ => panic!("impossible per construction"), - }; + pub fn empty_vararg() -> Self { + Literal::EmptyVarArgs + } - match self.value { - LiteralValue::Enumerator(value) => { - format!("{}::{}", self.kind.rust_type, maybe_values.unwrap()[value]) - } - LiteralValue::Bits(bits) => format!("{}::with_bits({:#x})", self.kind.rust_type, bits), - LiteralValue::Int(val) => val.to_string(), + pub fn to_rust_code(&self) -> String { + match self { + Literal::Enumerator { rust_type, value } => format!("{}::{}", rust_type, value), + Literal::Bits { rust_type, value } => format!("{}::with_bits({:#x})", rust_type, value), + Literal::Int(val) => val.to_string(), + Literal::EmptyVarArgs => "&[]".into(), } } } #[derive(Clone, Copy, Debug)] -pub enum PatternPosition { +pub(crate) enum PatternPosition { Source, Destination, } @@ -208,7 +237,7 @@ pub enum PatternPosition { /// deleted immediately. /// /// Temporary values are defined only in the destination pattern. -pub struct Var { +pub(crate) struct Var { pub name: &'static str, /// The `Def` defining this variable in a source pattern. @@ -336,10 +365,10 @@ impl fmt::Debug for Var { } #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub struct VarIndex(u32); +pub(crate) struct VarIndex(u32); entity_impl!(VarIndex); -pub struct VarPool { +pub(crate) struct VarPool { pool: PrimaryMap<VarIndex, Var>, } @@ -364,8 +393,7 @@ impl VarPool { /// /// An `Apply` AST expression is created by using function call syntax on instructions. This /// applies to both bound and unbound polymorphic instructions. -#[derive(Debug)] -pub struct Apply { +pub(crate) struct Apply { pub inst: Instruction, pub args: Vec<Expr>, pub value_types: Vec<ValueType>, @@ -395,13 +423,38 @@ impl Apply { let arg = &args[imm_index]; if let Some(literal) = arg.maybe_literal() { let op = &inst.operands_in[imm_index]; - assert!( - op.kind.name == literal.kind.name, - format!( - "Passing literal of kind {} to field of wrong kind {}", - literal.kind.name, op.kind.name - ) - ); + match &op.kind.fields { + OperandKindFields::ImmEnum(values) => { + if let Literal::Enumerator { value, .. } = literal { + assert!( + values.iter().any(|(_key, v)| v == value), + "Nonexistent enum value '{}' passed to field of kind '{}' -- \ + did you use the right enum?", + value, + op.kind.name + ); + } else { + panic!( + "Passed non-enum field value {:?} to field of kind {}", + literal, op.kind.name + ); + } + } + OperandKindFields::ImmValue => match &literal { + Literal::Enumerator { value, .. } => panic!( + "Expected immediate value in immediate field of kind '{}', \ + obtained enum value '{}'", + op.kind.name, value + ), + Literal::Bits { .. } | Literal::Int(_) | Literal::EmptyVarArgs => {} + }, + _ => { + panic!( + "Literal passed to non-literal field of kind {}", + op.kind.name + ); + } + } } } @@ -511,14 +564,15 @@ impl Apply { // Simple helpers for legalize actions construction. -pub enum DummyExpr { +pub(crate) enum DummyExpr { Var(DummyVar), Literal(Literal), Apply(InstSpec, Vec<DummyExpr>), + Block(DummyVar), } #[derive(Clone)] -pub struct DummyVar { +pub(crate) struct DummyVar { pub name: &'static str, } @@ -533,16 +587,16 @@ impl Into<DummyExpr> for Literal { } } -pub fn var(name: &'static str) -> DummyVar { +pub(crate) fn var(name: &'static str) -> DummyVar { DummyVar { name } } -pub struct DummyDef { +pub(crate) struct DummyDef { pub expr: DummyExpr, pub defined_vars: Vec<DummyVar>, } -pub struct ExprBuilder { +pub(crate) struct ExprBuilder { expr: DummyExpr, } @@ -558,6 +612,11 @@ impl ExprBuilder { defined_vars, } } + + pub fn block(name: DummyVar) -> Self { + let expr = DummyExpr::Block(name); + Self { expr } + } } macro_rules! def_rhs { @@ -589,3 +648,11 @@ macro_rules! def { def_rhs!($($tt)*).assign_to(Vec::new()) } } + +// Helper macro to define legalization recipes. +macro_rules! ebb { + // An basic block definition, splitting the current block in 2. + ($block: ident) => { + ExprBuilder::block($block).assign_to(Vec::new()) + }; +} diff --git a/third_party/rust/cranelift-codegen-meta/src/cdsl/cpu_modes.rs b/third_party/rust/cranelift-codegen-meta/src/cdsl/cpu_modes.rs index 4b4406d2d3887fc5ca45f02289d1a05d4de6202f..6436d2e4a26d7af0ee72f048b2d263537997ebb5 100644 --- a/third_party/rust/cranelift-codegen-meta/src/cdsl/cpu_modes.rs +++ b/third_party/rust/cranelift-codegen-meta/src/cdsl/cpu_modes.rs @@ -5,7 +5,7 @@ use crate::cdsl::encodings::Encoding; use crate::cdsl::types::{LaneType, ValueType}; use crate::cdsl::xform::{TransformGroup, TransformGroupIndex}; -pub struct CpuMode { +pub(crate) struct CpuMode { pub name: &'static str, default_legalize: Option<TransformGroupIndex>, monomorphic_legalize: Option<TransformGroupIndex>, diff --git a/third_party/rust/cranelift-codegen-meta/src/cdsl/encodings.rs b/third_party/rust/cranelift-codegen-meta/src/cdsl/encodings.rs index cd05eb9b38afab8f0b4466564bbc5e882c8cc4c9..77d6bc737464e70da963b19f61b1b923911abe98 100644 --- a/third_party/rust/cranelift-codegen-meta/src/cdsl/encodings.rs +++ b/third_party/rust/cranelift-codegen-meta/src/cdsl/encodings.rs @@ -20,7 +20,7 @@ use crate::cdsl::types::ValueType; /// 3. With operands providing constraints: `icmp.i32(intcc.eq, x, y)`. /// /// If the instruction is polymorphic, all type variables must be provided. -pub struct EncodingContent { +pub(crate) struct EncodingContent { /// The `Instruction` or `BoundInstruction` being encoded. inst: InstSpec, @@ -49,9 +49,9 @@ impl EncodingContent { } } -pub type Encoding = Rc<EncodingContent>; +pub(crate) type Encoding = Rc<EncodingContent>; -pub struct EncodingBuilder { +pub(crate) struct EncodingBuilder { inst: InstSpec, recipe: EncodingRecipeNumber, encbits: u16, diff --git a/third_party/rust/cranelift-codegen-meta/src/cdsl/instructions.rs b/third_party/rust/cranelift-codegen-meta/src/cdsl/instructions.rs index 2737099cc442ba8b313d07e39c45464a6da340f6..178077e456fe76a0f8258c351fa5ca6225d5d798 100644 --- a/third_party/rust/cranelift-codegen-meta/src/cdsl/instructions.rs +++ b/third_party/rust/cranelift-codegen-meta/src/cdsl/instructions.rs @@ -13,6 +13,7 @@ use crate::cdsl::operands::Operand; use crate::cdsl::type_inference::Constraint; use crate::cdsl::types::{LaneType, ReferenceType, ValueType, VectorType}; use crate::cdsl::typevar::TypeVar; +use cranelift_codegen_shared::condcodes::IntCC; #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct OpcodeNumber(u32); @@ -614,6 +615,12 @@ pub enum FormatPredicateKind { /// Is the immediate format field member equal to zero? (float64 version) IsZero64BitFloat, + /// Is the immediate format field member equal zero in all lanes? + IsAllZeroes128Bit, + + /// Does the immediate format field member have ones in all bits of all lanes? + IsAllOnes128Bit, + /// Has the value list (in member_name) the size specified in parameter? LengthEquals(usize), @@ -622,6 +629,9 @@ pub enum FormatPredicateKind { /// Is the referenced data object colocated? IsColocatedData, + + /// Does the operation have a specific condition code? + HasConditionCode(IntCC), } #[derive(Clone, Hash, PartialEq, Eq)] @@ -690,6 +700,14 @@ impl FormatPredicateNode { FormatPredicateKind::IsZero64BitFloat => { format!("predicates::is_zero_64_bit_float({})", self.member_name) } + FormatPredicateKind::IsAllZeroes128Bit => format!( + "predicates::is_all_zeroes_128_bit(func.dfg.constants.get({}))", + self.member_name + ), + FormatPredicateKind::IsAllOnes128Bit => format!( + "predicates::is_all_ones_128_bit(func.dfg.constants.get({}))", + self.member_name + ), FormatPredicateKind::LengthEquals(num) => format!( "predicates::has_length_of({}, {}, func)", self.member_name, num @@ -700,6 +718,10 @@ impl FormatPredicateNode { FormatPredicateKind::IsColocatedData => { format!("predicates::is_colocated_data({}, func)", self.member_name) } + FormatPredicateKind::HasConditionCode(code) => format!( + "predicates::is_equal({}, IntCC::{:?})", + self.member_name, code + ), } } } @@ -929,6 +951,28 @@ impl InstructionPredicate { )) } + pub fn new_is_all_zeroes_128bit( + format: &InstructionFormat, + field_name: &'static str, + ) -> InstructionPredicateNode { + InstructionPredicateNode::FormatPredicate(FormatPredicateNode::new( + format, + field_name, + FormatPredicateKind::IsAllZeroes128Bit, + )) + } + + pub fn new_is_all_ones_128bit( + format: &InstructionFormat, + field_name: &'static str, + ) -> InstructionPredicateNode { + InstructionPredicateNode::FormatPredicate(FormatPredicateNode::new( + format, + field_name, + FormatPredicateKind::IsAllOnes128Bit, + )) + } + pub fn new_length_equals(format: &InstructionFormat, size: usize) -> InstructionPredicateNode { assert!( format.has_value_list, @@ -961,6 +1005,18 @@ impl InstructionPredicate { )) } + pub fn new_has_condition_code( + format: &InstructionFormat, + condition_code: IntCC, + field_name: &'static str, + ) -> InstructionPredicateNode { + InstructionPredicateNode::FormatPredicate(FormatPredicateNode::new( + format, + field_name, + FormatPredicateKind::HasConditionCode(condition_code), + )) + } + pub fn and(mut self, new_node: InstructionPredicateNode) -> Self { let node = self.node; let mut and_nodes = match node { diff --git a/third_party/rust/cranelift-codegen-meta/src/cdsl/isa.rs b/third_party/rust/cranelift-codegen-meta/src/cdsl/isa.rs index e561ce2e9cc884599632a15088f77c9172545d22..512105d09a3b3ffc7efbfbdf2ab5e8dad18aebd8 100644 --- a/third_party/rust/cranelift-codegen-meta/src/cdsl/isa.rs +++ b/third_party/rust/cranelift-codegen-meta/src/cdsl/isa.rs @@ -8,7 +8,7 @@ use crate::cdsl::regs::IsaRegs; use crate::cdsl::settings::SettingGroup; use crate::cdsl::xform::{TransformGroupIndex, TransformGroups}; -pub struct TargetIsa { +pub(crate) struct TargetIsa { pub name: &'static str, pub instructions: InstructionGroup, pub settings: SettingGroup, diff --git a/third_party/rust/cranelift-codegen-meta/src/cdsl/type_inference.rs b/third_party/rust/cranelift-codegen-meta/src/cdsl/type_inference.rs index a56d81463c558d6e65c73fee6dcf3c9eec921e16..51817399694fd2e1dfef073bf1bf60e9ebde4428 100644 --- a/third_party/rust/cranelift-codegen-meta/src/cdsl/type_inference.rs +++ b/third_party/rust/cranelift-codegen-meta/src/cdsl/type_inference.rs @@ -122,7 +122,7 @@ enum TypeEnvRank { } /// Class encapsulating the necessary bookkeeping for type inference. -pub struct TypeEnvironment { +pub(crate) struct TypeEnvironment { vars: HashSet<VarIndex>, ranks: HashMap<TypeVar, TypeEnvRank>, equivalency_map: HashMap<TypeVar, TypeVar>, @@ -602,7 +602,7 @@ fn infer_definition( } /// Perform type inference on an transformation. Return an updated type environment or error. -pub fn infer_transform( +pub(crate) fn infer_transform( src: DefIndex, dst: &Vec<DefIndex>, def_pool: &DefPool, diff --git a/third_party/rust/cranelift-codegen-meta/src/cdsl/typevar.rs b/third_party/rust/cranelift-codegen-meta/src/cdsl/typevar.rs index 71c2fd2e292a6d67b3a6de426abf9e85bd6027f0..78e702cacf1dc8bab575e73c35b82589608521c4 100644 --- a/third_party/rust/cranelift-codegen-meta/src/cdsl/typevar.rs +++ b/third_party/rust/cranelift-codegen-meta/src/cdsl/typevar.rs @@ -851,7 +851,7 @@ impl TypeSetBuilder { pub fn build(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) diff --git a/third_party/rust/cranelift-codegen-meta/src/cdsl/xform.rs b/third_party/rust/cranelift-codegen-meta/src/cdsl/xform.rs index b90d552b9a5b089b5f356cbd6707952937a1e617..6304469718b070532951da1c715997e8cef78cd5 100644 --- a/third_party/rust/cranelift-codegen-meta/src/cdsl/xform.rs +++ b/third_party/rust/cranelift-codegen-meta/src/cdsl/xform.rs @@ -1,5 +1,6 @@ use crate::cdsl::ast::{ - Apply, DefIndex, DefPool, DummyDef, DummyExpr, Expr, PatternPosition, VarIndex, VarPool, + Apply, BlockPool, DefIndex, DefPool, DummyDef, DummyExpr, Expr, PatternPosition, VarIndex, + VarPool, }; use crate::cdsl::instructions::Instruction; use crate::cdsl::type_inference::{infer_transform, TypeEnvironment}; @@ -17,11 +18,12 @@ use std::iter::FromIterator; /// cases when it applies. /// /// The source pattern can contain only a single instruction. -pub struct Transform { +pub(crate) struct Transform { pub src: DefIndex, pub dst: Vec<DefIndex>, pub var_pool: VarPool, pub def_pool: DefPool, + pub block_pool: BlockPool, pub type_env: TypeEnvironment, } @@ -31,6 +33,7 @@ impl Transform { fn new(src: DummyDef, dst: Vec<DummyDef>) -> Self { let mut var_pool = VarPool::new(); let mut def_pool = DefPool::new(); + let mut block_pool = BlockPool::new(); let mut input_vars: Vec<VarIndex> = Vec::new(); let mut defined_vars: Vec<VarIndex> = Vec::new(); @@ -47,6 +50,7 @@ impl Transform { &mut defined_vars, &mut var_pool, &mut def_pool, + &mut block_pool, )[0]; let num_src_inputs = input_vars.len(); @@ -59,6 +63,7 @@ impl Transform { &mut defined_vars, &mut var_pool, &mut def_pool, + &mut block_pool, ); // Sanity checks. @@ -122,6 +127,7 @@ impl Transform { dst, var_pool, def_pool, + block_pool, type_env, } } @@ -138,6 +144,27 @@ impl Transform { } } +/// Inserts, if not present, a name in the `symbol_table`. Then returns its index in the variable +/// pool `var_pool`. If the variable was not present in the symbol table, then add it to the list of +/// `defined_vars`. +fn var_index( + name: &'static str, + symbol_table: &mut SymbolTable, + defined_vars: &mut Vec<VarIndex>, + var_pool: &mut VarPool, +) -> VarIndex { + match symbol_table.get(name) { + Some(&existing_var) => existing_var, + None => { + // Materialize the variable. + let new_var = var_pool.create(name); + symbol_table.insert(name, new_var); + defined_vars.push(new_var); + new_var + } + } +} + /// Given a list of symbols defined in a Def, rewrite them to local symbols. Yield the new locals. fn rewrite_defined_vars( position: PatternPosition, @@ -149,16 +176,7 @@ fn rewrite_defined_vars( ) -> Vec<VarIndex> { let mut new_defined_vars = Vec::new(); for var in &dummy_def.defined_vars { - let own_var = match symbol_table.get(var.name) { - Some(&existing_var) => existing_var, - None => { - // Materialize the variable. - let new_var = var_pool.create(var.name); - symbol_table.insert(var.name, new_var); - defined_vars.push(new_var); - new_var - } - }; + let own_var = var_index(var.name, symbol_table, defined_vars, var_pool); var_pool.get_mut(own_var).set_def(position, def_index); new_defined_vars.push(own_var); } @@ -197,23 +215,12 @@ fn rewrite_expr( for (i, arg) in dummy_args.into_iter().enumerate() { match arg { DummyExpr::Var(var) => { - let own_var = match symbol_table.get(var.name) { - Some(&own_var) => { - let var = var_pool.get(own_var); - assert!( - var.is_input() || var.get_def(position).is_some(), - format!("{:?} used as both input and def", var) - ); - own_var - } - None => { - // First time we're using this variable. - let own_var = var_pool.create(var.name); - symbol_table.insert(var.name, own_var); - input_vars.push(own_var); - own_var - } - }; + let own_var = var_index(var.name, symbol_table, input_vars, var_pool); + let var = var_pool.get(own_var); + assert!( + var.is_input() || var.get_def(position).is_some(), + format!("{:?} used as both input and def", var) + ); args.push(Expr::Var(own_var)); } DummyExpr::Literal(literal) => { @@ -223,6 +230,9 @@ fn rewrite_expr( DummyExpr::Apply(..) => { panic!("Recursive apply is not allowed."); } + DummyExpr::Block(_block) => { + panic!("Blocks are not valid arguments."); + } } } @@ -237,8 +247,18 @@ fn rewrite_def_list( defined_vars: &mut Vec<VarIndex>, var_pool: &mut VarPool, def_pool: &mut DefPool, + block_pool: &mut BlockPool, ) -> Vec<DefIndex> { let mut new_defs = Vec::new(); + // Register variable names of new blocks first as a block name can be used to jump forward. Thus + // the name has to be registered first to avoid misinterpreting it as an input-var. + for dummy_def in dummy_defs.iter() { + if let DummyExpr::Block(ref var) = dummy_def.expr { + var_index(var.name, symbol_table, defined_vars, var_pool); + } + } + + // Iterate over the definitions and blocks, to map variables names to inputs or outputs. for dummy_def in dummy_defs { let def_index = def_pool.next_index(); @@ -250,25 +270,40 @@ fn rewrite_def_list( defined_vars, var_pool, ); - let new_apply = rewrite_expr(position, dummy_def.expr, symbol_table, input_vars, var_pool); + if let DummyExpr::Block(var) = dummy_def.expr { + let var_index = *symbol_table + .get(var.name) + .or_else(|| { + panic!( + "Block {} was not registered during the first visit", + var.name + ) + }) + .unwrap(); + var_pool.get_mut(var_index).set_def(position, def_index); + block_pool.create_block(var_index, def_index); + } else { + let new_apply = + rewrite_expr(position, dummy_def.expr, symbol_table, input_vars, var_pool); - assert!( - def_pool.next_index() == def_index, - "shouldn't have created new defs in the meanwhile" - ); - assert_eq!( - new_apply.inst.value_results.len(), - new_defined_vars.len(), - "number of Var results in instruction is incorrect" - ); + assert!( + def_pool.next_index() == def_index, + "shouldn't have created new defs in the meanwhile" + ); + assert_eq!( + new_apply.inst.value_results.len(), + new_defined_vars.len(), + "number of Var results in instruction is incorrect" + ); - new_defs.push(def_pool.create(new_apply, new_defined_vars)); + new_defs.push(def_pool.create_inst(new_apply, new_defined_vars)); + } } new_defs } /// A group of related transformations. -pub struct TransformGroup { +pub(crate) struct TransformGroup { pub name: &'static str, pub doc: &'static str, pub chain_with: Option<TransformGroupIndex>, @@ -294,10 +329,10 @@ impl TransformGroup { } #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub struct TransformGroupIndex(u32); +pub(crate) struct TransformGroupIndex(u32); entity_impl!(TransformGroupIndex); -pub struct TransformGroupBuilder { +pub(crate) struct TransformGroupBuilder { name: &'static str, doc: &'static str, chain_with: Option<TransformGroupIndex>, @@ -369,7 +404,7 @@ impl TransformGroupBuilder { } } -pub struct TransformGroups { +pub(crate) struct TransformGroups { groups: PrimaryMap<TransformGroupIndex, TransformGroup>, } diff --git a/third_party/rust/cranelift-codegen-meta/src/constant_hash.rs b/third_party/rust/cranelift-codegen-meta/src/constant_hash.rs index 4090e4d77d97dae8ff09bae9193106be24ae8940..ce6214efa81c3bb5990c6ede1cdaf75171b74f6a 100644 --- a/third_party/rust/cranelift-codegen-meta/src/constant_hash.rs +++ b/third_party/rust/cranelift-codegen-meta/src/constant_hash.rs @@ -1,6 +1,6 @@ use std::iter; -pub fn simple_hash(s: &str) -> usize { +pub(crate) fn simple_hash(s: &str) -> usize { let mut h: u32 = 5381; for c in s.chars() { h = (h ^ c as u32).wrapping_add(h.rotate_right(6)); @@ -11,7 +11,7 @@ pub fn simple_hash(s: &str) -> usize { /// Compute an open addressed, quadratically probed hash table containing /// `items`. The returned table is a list containing the elements of the /// iterable `items` and `None` in unused slots. -pub fn generate_table<'cont, T, I: iter::Iterator<Item = &'cont T>, H: Fn(&T) -> usize>( +pub(crate) fn generate_table<'cont, T, I: iter::Iterator<Item = &'cont T>, H: Fn(&T) -> usize>( items: I, num_items: usize, hash_function: H, diff --git a/third_party/rust/cranelift-codegen-meta/src/default_map.rs b/third_party/rust/cranelift-codegen-meta/src/default_map.rs index da6d471439af58092afb708bc8fab61d94c03008..0a2f7fc41a71836c62c504ddd1601499d0b36aa9 100644 --- a/third_party/rust/cranelift-codegen-meta/src/default_map.rs +++ b/third_party/rust/cranelift-codegen-meta/src/default_map.rs @@ -1,7 +1,7 @@ use std::collections::HashMap; use std::hash::Hash; -pub trait MapWithDefault<K, V: Default> { +pub(crate) trait MapWithDefault<K, V: Default> { fn get_or_default(&mut self, k: K) -> &mut V; } diff --git a/third_party/rust/cranelift-codegen-meta/src/gen_binemit.rs b/third_party/rust/cranelift-codegen-meta/src/gen_binemit.rs index 53929fe8c5a143351e797e316ab5d798a1f0d212..fed145cbd4f3241817c512a2e72f99e1a9531d45 100644 --- a/third_party/rust/cranelift-codegen-meta/src/gen_binemit.rs +++ b/third_party/rust/cranelift-codegen-meta/src/gen_binemit.rs @@ -211,7 +211,7 @@ fn gen_isa(formats: &FormatRegistry, isa_name: &str, recipes: &Recipes, fmt: &mu fmt.line("}"); } -pub fn generate( +pub(crate) fn generate( formats: &FormatRegistry, isa_name: &str, recipes: &Recipes, diff --git a/third_party/rust/cranelift-codegen-meta/src/gen_inst.rs b/third_party/rust/cranelift-codegen-meta/src/gen_inst.rs index 7d8353dad312d4f586555f9194568a18ef37f737..ed28a83794ba6eb9b8bff6d4f50721dadb888716 100644 --- a/third_party/rust/cranelift-codegen-meta/src/gen_inst.rs +++ b/third_party/rust/cranelift-codegen-meta/src/gen_inst.rs @@ -97,9 +97,14 @@ fn gen_instruction_data(registry: &FormatRegistry, fmt: &mut Formatter) { fn gen_arguments_method(registry: &FormatRegistry, fmt: &mut Formatter, is_mut: bool) { let (method, mut_, rslice, as_slice) = if is_mut { - ("arguments_mut", "mut ", "ref_slice_mut", "as_mut_slice") + ( + "arguments_mut", + "mut ", + "core::slice::from_mut", + "as_mut_slice", + ) } else { - ("arguments", "", "ref_slice", "as_slice") + ("arguments", "", "core::slice::from_ref", "as_slice") }; fmtln!( diff --git a/third_party/rust/cranelift-codegen-meta/src/gen_legalizer.rs b/third_party/rust/cranelift-codegen-meta/src/gen_legalizer.rs index da1fb1f58f584a0851e048a8409c25f7f70a8255..bceed3fac68f5dce9579124950291742412b87f5 100644 --- a/third_party/rust/cranelift-codegen-meta/src/gen_legalizer.rs +++ b/third_party/rust/cranelift-codegen-meta/src/gen_legalizer.rs @@ -401,14 +401,30 @@ fn gen_transform<'a>( // Guard the actual expansion by `predicate`. fmt.line("if predicate {"); fmt.indent(|fmt| { + // If we are adding some blocks, we need to recall the original block, such that we can + // recompute it. + if !transform.block_pool.is_empty() { + fmt.line("let orig_ebb = pos.current_ebb().unwrap();"); + } + // If we're going to delete `inst`, we need to detach its results first so they can be // reattached during pattern expansion. if !replace_inst { fmt.line("pos.func.dfg.clear_results(inst);"); } + // Emit new block creation. + for block in &transform.block_pool { + let var = transform.var_pool.get(block.name); + fmtln!(fmt, "let {} = pos.func.dfg.make_ebb();", var.name); + } + // Emit the destination pattern. for &def_index in &transform.dst { + if let Some(block) = transform.block_pool.get(def_index) { + let var = transform.var_pool.get(block.name); + fmtln!(fmt, "pos.insert_ebb({});", var.name); + } emit_dst_inst( transform.def_pool.get(def_index), &transform.def_pool, @@ -417,16 +433,32 @@ fn gen_transform<'a>( ); } + // Insert a new block after the last instruction, if needed. + let def_next_index = transform.def_pool.next_index(); + if let Some(block) = transform.block_pool.get(def_next_index) { + let var = transform.var_pool.get(block.name); + fmtln!(fmt, "pos.insert_ebb({});", var.name); + } + // Delete the original instruction if we didn't have an opportunity to replace it. if !replace_inst { fmt.line("let removed = pos.remove_inst();"); fmt.line("debug_assert_eq!(removed, inst);"); } - if transform.def_pool.get(transform.src).apply.inst.is_branch { - // A branch might have been legalized into multiple branches, so we need to recompute - // the cfg. - fmt.line("cfg.recompute_ebb(pos.func, pos.current_ebb().unwrap());"); + if transform.block_pool.is_empty() { + if transform.def_pool.get(transform.src).apply.inst.is_branch { + // A branch might have been legalized into multiple branches, so we need to recompute + // the cfg. + fmt.line("cfg.recompute_ebb(pos.func, pos.current_ebb().unwrap());"); + } + } else { + // Update CFG for the new blocks. + fmt.line("cfg.recompute_ebb(pos.func, orig_ebb);"); + for block in &transform.block_pool { + let var = transform.var_pool.get(block.name); + fmtln!(fmt, "cfg.recompute_ebb(pos.func, {});", var.name); + } } fmt.line("return true;"); @@ -577,7 +609,7 @@ fn gen_isa( } /// Generate the legalizer files. -pub fn generate( +pub(crate) fn generate( isas: &Vec<TargetIsa>, format_registry: &FormatRegistry, transform_groups: &TransformGroups, diff --git a/third_party/rust/cranelift-codegen-meta/src/gen_registers.rs b/third_party/rust/cranelift-codegen-meta/src/gen_registers.rs index 08edfa9e21960ce4b07c28b0a4ba952d9ec67b6c..8f778f8601073ccf03a1266398c3f1258f999ec5 100644 --- a/third_party/rust/cranelift-codegen-meta/src/gen_registers.rs +++ b/third_party/rust/cranelift-codegen-meta/src/gen_registers.rs @@ -133,7 +133,7 @@ fn gen_isa(isa: &TargetIsa, fmt: &mut Formatter) { fmtln!(fmt, "}"); } -pub fn generate(isa: &TargetIsa, filename: &str, out_dir: &str) -> Result<(), error::Error> { +pub(crate) 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(filename, out_dir)?; diff --git a/third_party/rust/cranelift-codegen-meta/src/gen_settings.rs b/third_party/rust/cranelift-codegen-meta/src/gen_settings.rs index cdd07d78bd64c9dbf7c372e0b641407b5ec92c77..84c81cddc4aa32a93be0f40e779f524486f66938 100644 --- a/third_party/rust/cranelift-codegen-meta/src/gen_settings.rs +++ b/third_party/rust/cranelift-codegen-meta/src/gen_settings.rs @@ -431,7 +431,7 @@ fn gen_group(group: &SettingGroup, parent: ParentGroup, fmt: &mut Formatter) { gen_display(group, fmt); } -pub fn generate( +pub(crate) fn generate( settings: &SettingGroup, parent_group: ParentGroup, filename: &str, diff --git a/third_party/rust/cranelift-codegen-meta/src/gen_types.rs b/third_party/rust/cranelift-codegen-meta/src/gen_types.rs index d4b4c60d65533dca8d4686d60147b5a9996a9cfb..6ced212b8d5402fa6e0e034499c08b242968fa44 100644 --- a/third_party/rust/cranelift-codegen-meta/src/gen_types.rs +++ b/third_party/rust/cranelift-codegen-meta/src/gen_types.rs @@ -68,7 +68,7 @@ fn emit_types(fmt: &mut srcgen::Formatter) -> Result<(), error::Error> { } /// Generate the types file. -pub fn generate(filename: &str, out_dir: &str) -> Result<(), error::Error> { +pub(crate) fn generate(filename: &str, out_dir: &str) -> Result<(), error::Error> { let mut fmt = srcgen::Formatter::new(); emit_types(&mut fmt)?; fmt.update_file(filename, out_dir)?; diff --git a/third_party/rust/cranelift-codegen-meta/src/isa/riscv/encodings.rs b/third_party/rust/cranelift-codegen-meta/src/isa/riscv/encodings.rs index 02a3bc7b61659128cd615d3831943dfb15b7d291..6ddc13b0a3320b3382b32869f4d6d026609928eb 100644 --- a/third_party/rust/cranelift-codegen-meta/src/isa/riscv/encodings.rs +++ b/third_party/rust/cranelift-codegen-meta/src/isa/riscv/encodings.rs @@ -18,7 +18,7 @@ fn enc(inst: impl Into<InstSpec>, recipe: EncodingRecipeNumber, bits: u16) -> En EncodingBuilder::new(inst.into(), recipe, bits) } -pub struct PerCpuModeEncodings<'defs> { +pub(crate) struct PerCpuModeEncodings<'defs> { pub inst_pred_reg: InstructionPredicateRegistry, pub enc32: Vec<Encoding>, pub enc64: Vec<Encoding>, diff --git a/third_party/rust/cranelift-codegen-meta/src/isa/x86/encodings.rs b/third_party/rust/cranelift-codegen-meta/src/isa/x86/encodings.rs index 9bdb751b26c1cc632b32c2e580a17104012bf21c..01f25d9d7f03c1e90ff833cfbfed2231bca87bbc 100644 --- a/third_party/rust/cranelift-codegen-meta/src/isa/x86/encodings.rs +++ b/third_party/rust/cranelift-codegen-meta/src/isa/x86/encodings.rs @@ -1,5 +1,6 @@ #![allow(non_snake_case)] +use cranelift_codegen_shared::condcodes::IntCC; use std::collections::HashMap; use crate::cdsl::encodings::{Encoding, EncodingBuilder}; @@ -16,9 +17,11 @@ use crate::shared::types::Int::{I16, I32, I64, I8}; use crate::shared::types::Reference::{R32, R64}; use crate::shared::Definitions as SharedDefinitions; +use crate::isa::x86::opcodes::*; + use super::recipes::{RecipeGroup, Template}; -pub struct PerCpuModeEncodings { +pub(crate) struct PerCpuModeEncodings { pub enc32: Vec<Encoding>, pub enc64: Vec<Encoding>, pub recipes: Recipes, @@ -150,6 +153,20 @@ impl PerCpuModeEncodings { self.enc64(inst.bind(I64), template.rex().w()); } + /// Add encodings for `inst.b32` to X86_32. + /// Add encodings for `inst.b32` to X86_64 with and without REX. + /// Add encodings for `inst.b64` to X86_64 with a REX.W prefix. + fn enc_b32_b64(&mut self, inst: impl Into<InstSpec>, template: Template) { + let inst: InstSpec = inst.into(); + self.enc32(inst.bind(B32), template.nonrex()); + + // REX-less encoding must come after REX encoding so we don't use it by default. Otherwise + // reg-alloc would never use r8 and up. + self.enc64(inst.bind(B32), template.rex()); + self.enc64(inst.bind(B32), template.nonrex()); + self.enc64(inst.bind(B64), template.rex().w()); + } + /// Add encodings for `inst.i32` to X86_32. /// Add encodings for `inst.i32` to X86_64 with a REX prefix. /// Add encodings for `inst.i64` to X86_64 with a REX.W prefix. @@ -279,6 +296,12 @@ impl PerCpuModeEncodings { } } + /// Add the same encoding/template pairing to both X86_32 and X86_64 + fn enc_32_64(&mut self, inst: impl Clone + Into<InstSpec>, template: Template) { + self.enc32(inst.clone(), template.clone()); + self.enc64(inst, template); + } + /// Add the same encoding/recipe pairing to both X86_32 and X86_64 fn enc_32_64_rec( &mut self, @@ -290,6 +313,20 @@ impl PerCpuModeEncodings { self.enc64_rec(inst, recipe, bits); } + /// Add the same encoding to both X86_32 and X86_64; assumes configuration (e.g. REX, operand binding) has already happened + fn enc_32_64_func<T>( + &mut self, + inst: impl Clone + Into<InstSpec>, + template: Template, + builder_closure: T, + ) where + T: FnOnce(EncodingBuilder) -> EncodingBuilder, + { + let encoding = self.make_encoding(inst.into(), template, builder_closure); + self.enc32.push(encoding.clone()); + self.enc64.push(encoding); + } + /// Add the same encoding to both X86_32 and X86_64; assumes configuration (e.g. REX, operand /// binding) has already happened. fn enc_32_64_maybe_isap( @@ -539,6 +576,7 @@ pub(crate) fn define( let rec_gvaddr4 = r.template("gvaddr4"); let rec_gvaddr8 = r.template("gvaddr8"); let rec_icscc = r.template("icscc"); + let rec_icscc_fpr = r.template("icscc_fpr"); let rec_icscc_ib = r.template("icscc_ib"); let rec_icscc_id = r.template("icscc_id"); let rec_indirect_jmp = r.template("indirect_jmp"); @@ -622,6 +660,7 @@ pub(crate) fn define( let rec_urm_noflags = r.template("urm_noflags"); let rec_urm_noflags_abcd = r.template("urm_noflags_abcd"); let rec_vconst = r.template("vconst"); + let rec_vconst_optimized = r.template("vconst_optimized"); // Predicates shorthands. let all_ones_funcaddrs_and_not_is_pic = @@ -644,82 +683,91 @@ pub(crate) fn define( e.enc64_rec(get_pinned_reg.bind(I64), rec_get_pinned_reg, 0); e.enc_x86_64( set_pinned_reg.bind(I64), - rec_set_pinned_reg.opcodes(vec![0x89]).rex().w(), + rec_set_pinned_reg.opcodes(&MOV_STORE).rex().w(), ); - e.enc_i32_i64(iadd, rec_rr.opcodes(vec![0x01])); - e.enc_i32_i64(iadd_ifcout, rec_rout.opcodes(vec![0x01])); - e.enc_i32_i64(iadd_ifcin, rec_rin.opcodes(vec![0x11])); - e.enc_i32_i64(iadd_ifcarry, rec_rio.opcodes(vec![0x11])); + e.enc_i32_i64(iadd, rec_rr.opcodes(&ADD)); + e.enc_i32_i64(iadd_ifcout, rec_rout.opcodes(&ADD)); + e.enc_i32_i64(iadd_ifcin, rec_rin.opcodes(&ADC)); + e.enc_i32_i64(iadd_ifcarry, rec_rio.opcodes(&ADC)); - e.enc_i32_i64(isub, rec_rr.opcodes(vec![0x29])); - e.enc_i32_i64(isub_ifbout, rec_rout.opcodes(vec![0x29])); - e.enc_i32_i64(isub_ifbin, rec_rin.opcodes(vec![0x19])); - e.enc_i32_i64(isub_ifborrow, rec_rio.opcodes(vec![0x19])); + e.enc_i32_i64(isub, rec_rr.opcodes(&SUB)); + e.enc_i32_i64(isub_ifbout, rec_rout.opcodes(&SUB)); + e.enc_i32_i64(isub_ifbin, rec_rin.opcodes(&SBB)); + e.enc_i32_i64(isub_ifborrow, rec_rio.opcodes(&SBB)); - e.enc_i32_i64(band, rec_rr.opcodes(vec![0x21])); - e.enc_i32_i64(bor, rec_rr.opcodes(vec![0x09])); - e.enc_i32_i64(bxor, rec_rr.opcodes(vec![0x31])); + e.enc_i32_i64(band, rec_rr.opcodes(&AND)); + e.enc_b32_b64(band, rec_rr.opcodes(&AND)); + e.enc_i32_i64(bor, rec_rr.opcodes(&OR)); + e.enc_b32_b64(bor, rec_rr.opcodes(&OR)); + e.enc_i32_i64(bxor, rec_rr.opcodes(&XOR)); + e.enc_b32_b64(bxor, rec_rr.opcodes(&XOR)); // x86 has a bitwise not instruction NOT. - e.enc_i32_i64(bnot, rec_ur.opcodes(vec![0xf7]).rrr(2)); + e.enc_i32_i64(bnot, rec_ur.opcodes(&NOT).rrr(2)); + e.enc_b32_b64(bnot, rec_ur.opcodes(&NOT).rrr(2)); // Also add a `b1` encodings for the logic instructions. // TODO: Should this be done with 8-bit instructions? It would improve partial register // dependencies. - e.enc_both(band.bind(B1), rec_rr.opcodes(vec![0x21])); - e.enc_both(bor.bind(B1), rec_rr.opcodes(vec![0x09])); - e.enc_both(bxor.bind(B1), rec_rr.opcodes(vec![0x31])); + e.enc_both(band.bind(B1), rec_rr.opcodes(&AND)); + e.enc_both(bor.bind(B1), rec_rr.opcodes(&OR)); + e.enc_both(bxor.bind(B1), rec_rr.opcodes(&XOR)); - e.enc_i32_i64(imul, rec_rrx.opcodes(vec![0x0f, 0xaf])); - e.enc_i32_i64(x86_sdivmodx, rec_div.opcodes(vec![0xf7]).rrr(7)); - e.enc_i32_i64(x86_udivmodx, rec_div.opcodes(vec![0xf7]).rrr(6)); + e.enc_i32_i64(imul, rec_rrx.opcodes(&IMUL)); + e.enc_i32_i64(x86_sdivmodx, rec_div.opcodes(&IDIV).rrr(7)); + e.enc_i32_i64(x86_udivmodx, rec_div.opcodes(&DIV).rrr(6)); - e.enc_i32_i64(x86_smulx, rec_mulx.opcodes(vec![0xf7]).rrr(5)); - e.enc_i32_i64(x86_umulx, rec_mulx.opcodes(vec![0xf7]).rrr(4)); + e.enc_i32_i64(x86_smulx, rec_mulx.opcodes(&IMUL_RDX_RAX).rrr(5)); + e.enc_i32_i64(x86_umulx, rec_mulx.opcodes(&MUL).rrr(4)); - e.enc_i32_i64(copy, rec_umr.opcodes(vec![0x89])); - e.enc_r32_r64_rex_only(copy, rec_umr.opcodes(vec![0x89])); - e.enc_both(copy.bind(B1), rec_umr.opcodes(vec![0x89])); - e.enc_both(copy.bind(I8), rec_umr.opcodes(vec![0x89])); - e.enc_both(copy.bind(I16), rec_umr.opcodes(vec![0x89])); + e.enc_i32_i64(copy, rec_umr.opcodes(&MOV_STORE)); + e.enc_r32_r64_rex_only(copy, rec_umr.opcodes(&MOV_STORE)); + e.enc_both(copy.bind(B1), rec_umr.opcodes(&MOV_STORE)); + e.enc_both(copy.bind(I8), rec_umr.opcodes(&MOV_STORE)); + e.enc_both(copy.bind(I16), rec_umr.opcodes(&MOV_STORE)); // TODO For x86-64, only define REX forms for now, since we can't describe the // special regunit immediate operands with the current constraint language. for &ty in &[I8, I16, I32] { - e.enc32(regmove.bind(ty), rec_rmov.opcodes(vec![0x89])); - e.enc64(regmove.bind(ty), rec_rmov.opcodes(vec![0x89]).rex()); - } - e.enc64(regmove.bind(I64), rec_rmov.opcodes(vec![0x89]).rex().w()); - e.enc_both(regmove.bind(B1), rec_rmov.opcodes(vec![0x89])); - e.enc_both(regmove.bind(I8), rec_rmov.opcodes(vec![0x89])); - e.enc32(regmove.bind_ref(R32), rec_rmov.opcodes(vec![0x89])); - e.enc64(regmove.bind_ref(R32), rec_rmov.opcodes(vec![0x89]).rex()); + e.enc32(regmove.bind(ty), rec_rmov.opcodes(&MOV_STORE)); + e.enc64(regmove.bind(ty), rec_rmov.opcodes(&MOV_STORE).rex()); + } + for &ty in &[B8, B16, B32] { + e.enc32(regmove.bind(ty), rec_rmov.opcodes(&MOV_STORE)); + e.enc64(regmove.bind(ty), rec_rmov.opcodes(&MOV_STORE).rex()); + } + e.enc64(regmove.bind(I64), rec_rmov.opcodes(&MOV_STORE).rex().w()); + e.enc64(regmove.bind(B64), rec_rmov.opcodes(&MOV_STORE).rex().w()); + e.enc_both(regmove.bind(B1), rec_rmov.opcodes(&MOV_STORE)); + e.enc_both(regmove.bind(I8), rec_rmov.opcodes(&MOV_STORE)); + e.enc32(regmove.bind_ref(R32), rec_rmov.opcodes(&MOV_STORE)); + e.enc64(regmove.bind_ref(R32), rec_rmov.opcodes(&MOV_STORE).rex()); e.enc64( regmove.bind_ref(R64), - rec_rmov.opcodes(vec![0x89]).rex().w(), + rec_rmov.opcodes(&MOV_STORE).rex().w(), ); - e.enc_i32_i64(iadd_imm, rec_r_ib.opcodes(vec![0x83]).rrr(0)); - e.enc_i32_i64(iadd_imm, rec_r_id.opcodes(vec![0x81]).rrr(0)); + e.enc_i32_i64(iadd_imm, rec_r_ib.opcodes(&ADD_IMM8_SIGN_EXTEND).rrr(0)); + e.enc_i32_i64(iadd_imm, rec_r_id.opcodes(&ADD_IMM).rrr(0)); - e.enc_i32_i64(band_imm, rec_r_ib.opcodes(vec![0x83]).rrr(4)); - e.enc_i32_i64(band_imm, rec_r_id.opcodes(vec![0x81]).rrr(4)); + e.enc_i32_i64(band_imm, rec_r_ib.opcodes(&AND_IMM8_SIGN_EXTEND).rrr(4)); + e.enc_i32_i64(band_imm, rec_r_id.opcodes(&AND_IMM).rrr(4)); - e.enc_i32_i64(bor_imm, rec_r_ib.opcodes(vec![0x83]).rrr(1)); - e.enc_i32_i64(bor_imm, rec_r_id.opcodes(vec![0x81]).rrr(1)); + e.enc_i32_i64(bor_imm, rec_r_ib.opcodes(&OR_IMM8_SIGN_EXTEND).rrr(1)); + e.enc_i32_i64(bor_imm, rec_r_id.opcodes(&OR_IMM).rrr(1)); - e.enc_i32_i64(bxor_imm, rec_r_ib.opcodes(vec![0x83]).rrr(6)); - e.enc_i32_i64(bxor_imm, rec_r_id.opcodes(vec![0x81]).rrr(6)); + e.enc_i32_i64(bxor_imm, rec_r_ib.opcodes(&XOR_IMM8_SIGN_EXTEND).rrr(6)); + e.enc_i32_i64(bxor_imm, rec_r_id.opcodes(&XOR_IMM).rrr(6)); // TODO: band_imm.i64 with an unsigned 32-bit immediate can be encoded as band_imm.i32. Can // even use the single-byte immediate for 0xffff_ffXX masks. // Immediate constants. - e.enc32(iconst.bind(I32), rec_pu_id.opcodes(vec![0xb8])); + e.enc32(iconst.bind(I32), rec_pu_id.opcodes(&MOV_IMM)); - e.enc64(iconst.bind(I32), rec_pu_id.rex().opcodes(vec![0xb8])); - e.enc64(iconst.bind(I32), rec_pu_id.opcodes(vec![0xb8])); + e.enc64(iconst.bind(I32), rec_pu_id.rex().opcodes(&MOV_IMM)); + e.enc64(iconst.bind(I32), rec_pu_id.opcodes(&MOV_IMM)); // The 32-bit immediate movl also zero-extends to 64 bits. let f_unary_imm = formats.get(formats.by_name("UnaryImm")); @@ -727,34 +775,32 @@ pub(crate) fn define( e.enc64_func( iconst.bind(I64), - rec_pu_id.opcodes(vec![0xb8]).rex(), + rec_pu_id.opcodes(&MOV_IMM).rex(), |encoding| encoding.inst_predicate(is_unsigned_int32.clone()), ); - e.enc64_func( - iconst.bind(I64), - rec_pu_id.opcodes(vec![0xb8]), - |encoding| encoding.inst_predicate(is_unsigned_int32), - ); + e.enc64_func(iconst.bind(I64), rec_pu_id.opcodes(&MOV_IMM), |encoding| { + encoding.inst_predicate(is_unsigned_int32) + }); // Sign-extended 32-bit immediate. e.enc64( iconst.bind(I64), - rec_u_id.rex().opcodes(vec![0xc7]).rrr(0).w(), + rec_u_id.rex().opcodes(&MOV_IMM_SIGNEXTEND).rrr(0).w(), ); - // Finally, the 0xb8 opcode takes an 8-byte immediate with a REX.W prefix. - e.enc64(iconst.bind(I64), rec_pu_iq.opcodes(vec![0xb8]).rex().w()); + // Finally, the MOV_IMM opcode takes an 8-byte immediate with a REX.W prefix. + e.enc64(iconst.bind(I64), rec_pu_iq.opcodes(&MOV_IMM).rex().w()); // Bool constants (uses MOV) for &ty in &[B1, B8, B16, B32] { - e.enc_both(bconst.bind(ty), rec_pu_id_bool.opcodes(vec![0xb8])); + e.enc_both(bconst.bind(ty), rec_pu_id_bool.opcodes(&MOV_IMM)); } - e.enc64(bconst.bind(B64), rec_pu_id_bool.opcodes(vec![0xb8]).rex()); + e.enc64(bconst.bind(B64), rec_pu_id_bool.opcodes(&MOV_IMM).rex()); let is_zero_int = InstructionPredicate::new_is_zero_int(f_unary_imm, "imm"); e.enc_both_instp( iconst.bind(I8), - rec_u_id_z.opcodes(vec![0x30]), + rec_u_id_z.opcodes(&XORB), is_zero_int.clone(), ); // You may expect that i16 encodings would have an 0x66 prefix on the opcode to indicate that @@ -766,19 +812,15 @@ pub(crate) fn define( // an appropriate i16 encoding available. e.enc_both_instp( iconst.bind(I16), - rec_u_id_z.opcodes(vec![0x31]), + rec_u_id_z.opcodes(&XOR), is_zero_int.clone(), ); e.enc_both_instp( iconst.bind(I32), - rec_u_id_z.opcodes(vec![0x31]), + rec_u_id_z.opcodes(&XOR), is_zero_int.clone(), ); - e.enc_x86_64_instp( - iconst.bind(I64), - rec_u_id_z.opcodes(vec![0x31]), - is_zero_int, - ); + e.enc_x86_64_instp(iconst.bind(I64), rec_u_id_z.opcodes(&XOR), is_zero_int); // Shifts and rotates. // Note that the dynamic shift amount is only masked by 5 or 6 bits; the 8-bit @@ -789,97 +831,49 @@ pub(crate) fn define( // to bind any. e.enc32( inst.bind(I32).bind_any(), - rec_rc.opcodes(vec![0xd3]).rrr(rrr), + rec_rc.opcodes(&ROTATE_CL).rrr(rrr), ); e.enc64( inst.bind(I64).bind_any(), - rec_rc.opcodes(vec![0xd3]).rrr(rrr).rex().w(), + rec_rc.opcodes(&ROTATE_CL).rrr(rrr).rex().w(), ); e.enc64( inst.bind(I32).bind_any(), - rec_rc.opcodes(vec![0xd3]).rrr(rrr).rex(), + rec_rc.opcodes(&ROTATE_CL).rrr(rrr).rex(), ); e.enc64( inst.bind(I32).bind_any(), - rec_rc.opcodes(vec![0xd3]).rrr(rrr), + rec_rc.opcodes(&ROTATE_CL).rrr(rrr), ); } - for &(inst, rrr) in &[ - (rotl_imm, 0), - (rotr_imm, 1), - (ishl_imm, 4), - (ushr_imm, 5), - (sshr_imm, 7), - ] { - e.enc_i32_i64(inst, rec_r_ib.opcodes(vec![0xc1]).rrr(rrr)); - } + e.enc_i32_i64(rotl_imm, rec_r_ib.opcodes(&ROTATE_IMM8).rrr(0)); + e.enc_i32_i64(rotr_imm, rec_r_ib.opcodes(&ROTATE_IMM8).rrr(1)); + e.enc_i32_i64(ishl_imm, rec_r_ib.opcodes(&ROTATE_IMM8).rrr(4)); + e.enc_i32_i64(ushr_imm, rec_r_ib.opcodes(&ROTATE_IMM8).rrr(5)); + e.enc_i32_i64(sshr_imm, rec_r_ib.opcodes(&ROTATE_IMM8).rrr(7)); // Population count. - e.enc32_isap( - popcnt.bind(I32), - rec_urm.opcodes(vec![0xf3, 0x0f, 0xb8]), - use_popcnt, - ); + e.enc32_isap(popcnt.bind(I32), rec_urm.opcodes(&POPCNT), use_popcnt); e.enc64_isap( popcnt.bind(I64), - rec_urm.opcodes(vec![0xf3, 0x0f, 0xb8]).rex().w(), - use_popcnt, - ); - e.enc64_isap( - popcnt.bind(I32), - rec_urm.opcodes(vec![0xf3, 0x0f, 0xb8]).rex(), - use_popcnt, - ); - e.enc64_isap( - popcnt.bind(I32), - rec_urm.opcodes(vec![0xf3, 0x0f, 0xb8]), + rec_urm.opcodes(&POPCNT).rex().w(), use_popcnt, ); + e.enc64_isap(popcnt.bind(I32), rec_urm.opcodes(&POPCNT).rex(), use_popcnt); + e.enc64_isap(popcnt.bind(I32), rec_urm.opcodes(&POPCNT), use_popcnt); // Count leading zero bits. - e.enc32_isap( - clz.bind(I32), - rec_urm.opcodes(vec![0xf3, 0x0f, 0xbd]), - use_lzcnt, - ); - e.enc64_isap( - clz.bind(I64), - rec_urm.opcodes(vec![0xf3, 0x0f, 0xbd]).rex().w(), - use_lzcnt, - ); - e.enc64_isap( - clz.bind(I32), - rec_urm.opcodes(vec![0xf3, 0x0f, 0xbd]).rex(), - use_lzcnt, - ); - e.enc64_isap( - clz.bind(I32), - rec_urm.opcodes(vec![0xf3, 0x0f, 0xbd]), - use_lzcnt, - ); + e.enc32_isap(clz.bind(I32), rec_urm.opcodes(&LZCNT), use_lzcnt); + e.enc64_isap(clz.bind(I64), rec_urm.opcodes(&LZCNT).rex().w(), use_lzcnt); + e.enc64_isap(clz.bind(I32), rec_urm.opcodes(&LZCNT).rex(), use_lzcnt); + e.enc64_isap(clz.bind(I32), rec_urm.opcodes(&LZCNT), use_lzcnt); // Count trailing zero bits. - e.enc32_isap( - ctz.bind(I32), - rec_urm.opcodes(vec![0xf3, 0x0f, 0xbc]), - use_bmi1, - ); - e.enc64_isap( - ctz.bind(I64), - rec_urm.opcodes(vec![0xf3, 0x0f, 0xbc]).rex().w(), - use_bmi1, - ); - e.enc64_isap( - ctz.bind(I32), - rec_urm.opcodes(vec![0xf3, 0x0f, 0xbc]).rex(), - use_bmi1, - ); - e.enc64_isap( - ctz.bind(I32), - rec_urm.opcodes(vec![0xf3, 0x0f, 0xbc]), - use_bmi1, - ); + e.enc32_isap(ctz.bind(I32), rec_urm.opcodes(&TZCNT), use_bmi1); + e.enc64_isap(ctz.bind(I64), rec_urm.opcodes(&TZCNT).rex().w(), use_bmi1); + e.enc64_isap(ctz.bind(I32), rec_urm.opcodes(&TZCNT).rex(), use_bmi1); + e.enc64_isap(ctz.bind(I32), rec_urm.opcodes(&TZCNT), use_bmi1); // Loads and stores. let f_load_complex = formats.get(formats.by_name("LoadComplex")); @@ -888,41 +882,41 @@ pub(crate) fn define( for recipe in &[rec_ldWithIndex, rec_ldWithIndexDisp8, rec_ldWithIndexDisp32] { e.enc_i32_i64_instp( load_complex, - recipe.opcodes(vec![0x8b]), + recipe.opcodes(&MOV_LOAD), is_load_complex_length_two.clone(), ); e.enc_x86_64_instp( uload32_complex, - recipe.opcodes(vec![0x8b]), + recipe.opcodes(&MOV_LOAD), is_load_complex_length_two.clone(), ); e.enc64_instp( sload32_complex, - recipe.opcodes(vec![0x63]).rex().w(), + recipe.opcodes(&MOVSXD).rex().w(), is_load_complex_length_two.clone(), ); e.enc_i32_i64_instp( uload16_complex, - recipe.opcodes(vec![0x0f, 0xb7]), + recipe.opcodes(&MOVZX_WORD), is_load_complex_length_two.clone(), ); e.enc_i32_i64_instp( sload16_complex, - recipe.opcodes(vec![0x0f, 0xbf]), + recipe.opcodes(&MOVSX_WORD), is_load_complex_length_two.clone(), ); e.enc_i32_i64_instp( uload8_complex, - recipe.opcodes(vec![0x0f, 0xb6]), + recipe.opcodes(&MOVZX_BYTE), is_load_complex_length_two.clone(), ); e.enc_i32_i64_instp( sload8_complex, - recipe.opcodes(vec![0x0f, 0xbe]), + recipe.opcodes(&MOVSX_BYTE), is_load_complex_length_two.clone(), ); } @@ -933,22 +927,22 @@ pub(crate) fn define( for recipe in &[rec_stWithIndex, rec_stWithIndexDisp8, rec_stWithIndexDisp32] { e.enc_i32_i64_instp( store_complex, - recipe.opcodes(vec![0x89]), + recipe.opcodes(&MOV_STORE), is_store_complex_length_three.clone(), ); e.enc_x86_64_instp( istore32_complex, - recipe.opcodes(vec![0x89]), + recipe.opcodes(&MOV_STORE), is_store_complex_length_three.clone(), ); e.enc_both_instp( istore16_complex.bind(I32), - recipe.opcodes(vec![0x66, 0x89]), + recipe.opcodes(&MOV_STORE_16), is_store_complex_length_three.clone(), ); e.enc_x86_64_instp( istore16_complex.bind(I64), - recipe.opcodes(vec![0x66, 0x89]), + recipe.opcodes(&MOV_STORE_16), is_store_complex_length_three.clone(), ); } @@ -960,20 +954,20 @@ pub(crate) fn define( ] { e.enc_both_instp( istore8_complex.bind(I32), - recipe.opcodes(vec![0x88]), + recipe.opcodes(&MOV_BYTE_STORE), is_store_complex_length_three.clone(), ); e.enc_x86_64_instp( istore8_complex.bind(I64), - recipe.opcodes(vec![0x88]), + recipe.opcodes(&MOV_BYTE_STORE), is_store_complex_length_three.clone(), ); } for recipe in &[rec_st, rec_stDisp8, rec_stDisp32] { - e.enc_i32_i64_ld_st(store, true, recipe.opcodes(vec![0x89])); - e.enc_x86_64(istore32.bind(I64).bind_any(), recipe.opcodes(vec![0x89])); - e.enc_i32_i64_ld_st(istore16, false, recipe.opcodes(vec![0x66, 0x89])); + e.enc_i32_i64_ld_st(store, true, recipe.opcodes(&MOV_STORE)); + e.enc_x86_64(istore32.bind(I64).bind_any(), recipe.opcodes(&MOV_STORE)); + e.enc_i32_i64_ld_st(istore16, false, recipe.opcodes(&MOV_STORE_16)); } // Byte stores are more complicated because the registers they can address @@ -981,40 +975,46 @@ pub(crate) fn define( // the corresponding st* recipes when a REX prefix is applied. for recipe in &[rec_st_abcd, rec_stDisp8_abcd, rec_stDisp32_abcd] { - e.enc_both(istore8.bind(I32).bind_any(), recipe.opcodes(vec![0x88])); - e.enc_x86_64(istore8.bind(I64).bind_any(), recipe.opcodes(vec![0x88])); + e.enc_both( + istore8.bind(I32).bind_any(), + recipe.opcodes(&MOV_BYTE_STORE), + ); + e.enc_x86_64( + istore8.bind(I64).bind_any(), + recipe.opcodes(&MOV_BYTE_STORE), + ); } - e.enc_i32_i64(spill, rec_spillSib32.opcodes(vec![0x89])); - e.enc_i32_i64(regspill, rec_regspill32.opcodes(vec![0x89])); - e.enc_r32_r64_rex_only(spill, rec_spillSib32.opcodes(vec![0x89])); - e.enc_r32_r64_rex_only(regspill, rec_regspill32.opcodes(vec![0x89])); + e.enc_i32_i64(spill, rec_spillSib32.opcodes(&MOV_STORE)); + e.enc_i32_i64(regspill, rec_regspill32.opcodes(&MOV_STORE)); + e.enc_r32_r64_rex_only(spill, rec_spillSib32.opcodes(&MOV_STORE)); + e.enc_r32_r64_rex_only(regspill, rec_regspill32.opcodes(&MOV_STORE)); // Use a 32-bit write for spilling `b1`, `i8` and `i16` to avoid // constraining the permitted registers. // See MIN_SPILL_SLOT_SIZE which makes this safe. - e.enc_both(spill.bind(B1), rec_spillSib32.opcodes(vec![0x89])); - e.enc_both(regspill.bind(B1), rec_regspill32.opcodes(vec![0x89])); + e.enc_both(spill.bind(B1), rec_spillSib32.opcodes(&MOV_STORE)); + e.enc_both(regspill.bind(B1), rec_regspill32.opcodes(&MOV_STORE)); for &ty in &[I8, I16] { - e.enc_both(spill.bind(ty), rec_spillSib32.opcodes(vec![0x89])); - e.enc_both(regspill.bind(ty), rec_regspill32.opcodes(vec![0x89])); + e.enc_both(spill.bind(ty), rec_spillSib32.opcodes(&MOV_STORE)); + e.enc_both(regspill.bind(ty), rec_regspill32.opcodes(&MOV_STORE)); } for recipe in &[rec_ld, rec_ldDisp8, rec_ldDisp32] { - e.enc_i32_i64_ld_st(load, true, recipe.opcodes(vec![0x8b])); - e.enc_x86_64(uload32.bind(I64), recipe.opcodes(vec![0x8b])); - e.enc64(sload32.bind(I64), recipe.opcodes(vec![0x63]).rex().w()); - e.enc_i32_i64_ld_st(uload16, true, recipe.opcodes(vec![0x0f, 0xb7])); - e.enc_i32_i64_ld_st(sload16, true, recipe.opcodes(vec![0x0f, 0xbf])); - e.enc_i32_i64_ld_st(uload8, true, recipe.opcodes(vec![0x0f, 0xb6])); - e.enc_i32_i64_ld_st(sload8, true, recipe.opcodes(vec![0x0f, 0xbe])); + e.enc_i32_i64_ld_st(load, true, recipe.opcodes(&MOV_LOAD)); + e.enc_x86_64(uload32.bind(I64), recipe.opcodes(&MOV_LOAD)); + e.enc64(sload32.bind(I64), recipe.opcodes(&MOVSXD).rex().w()); + e.enc_i32_i64_ld_st(uload16, true, recipe.opcodes(&MOVZX_WORD)); + e.enc_i32_i64_ld_st(sload16, true, recipe.opcodes(&MOVSX_WORD)); + e.enc_i32_i64_ld_st(uload8, true, recipe.opcodes(&MOVZX_BYTE)); + e.enc_i32_i64_ld_st(sload8, true, recipe.opcodes(&MOVSX_BYTE)); } - e.enc_i32_i64(fill, rec_fillSib32.opcodes(vec![0x8b])); - e.enc_i32_i64(regfill, rec_regfill32.opcodes(vec![0x8b])); - e.enc_r32_r64_rex_only(fill, rec_fillSib32.opcodes(vec![0x8b])); - e.enc_r32_r64_rex_only(regfill, rec_regfill32.opcodes(vec![0x8b])); + e.enc_i32_i64(fill, rec_fillSib32.opcodes(&MOV_LOAD)); + e.enc_i32_i64(regfill, rec_regfill32.opcodes(&MOV_LOAD)); + e.enc_r32_r64_rex_only(fill, rec_fillSib32.opcodes(&MOV_LOAD)); + e.enc_r32_r64_rex_only(regfill, rec_regfill32.opcodes(&MOV_LOAD)); // No-op fills, created by late-stage redundant-fill removal. for &ty in &[I64, I32, I16, I8] { @@ -1030,44 +1030,44 @@ pub(crate) fn define( // Load 32 bits from `b1`, `i8` and `i16` spill slots. See `spill.b1` above. - e.enc_both(fill.bind(B1), rec_fillSib32.opcodes(vec![0x8b])); - e.enc_both(regfill.bind(B1), rec_regfill32.opcodes(vec![0x8b])); + e.enc_both(fill.bind(B1), rec_fillSib32.opcodes(&MOV_LOAD)); + e.enc_both(regfill.bind(B1), rec_regfill32.opcodes(&MOV_LOAD)); for &ty in &[I8, I16] { - e.enc_both(fill.bind(ty), rec_fillSib32.opcodes(vec![0x8b])); - e.enc_both(regfill.bind(ty), rec_regfill32.opcodes(vec![0x8b])); + e.enc_both(fill.bind(ty), rec_fillSib32.opcodes(&MOV_LOAD)); + e.enc_both(regfill.bind(ty), rec_regfill32.opcodes(&MOV_LOAD)); } // Push and Pop. - e.enc32(x86_push.bind(I32), rec_pushq.opcodes(vec![0x50])); - e.enc_x86_64(x86_push.bind(I64), rec_pushq.opcodes(vec![0x50])); + e.enc32(x86_push.bind(I32), rec_pushq.opcodes(&PUSH_REG)); + e.enc_x86_64(x86_push.bind(I64), rec_pushq.opcodes(&PUSH_REG)); - e.enc32(x86_pop.bind(I32), rec_popq.opcodes(vec![0x58])); - e.enc_x86_64(x86_pop.bind(I64), rec_popq.opcodes(vec![0x58])); + e.enc32(x86_pop.bind(I32), rec_popq.opcodes(&POP_REG)); + e.enc_x86_64(x86_pop.bind(I64), rec_popq.opcodes(&POP_REG)); // Copy Special // For x86-64, only define REX forms for now, since we can't describe the // special regunit immediate operands with the current constraint language. - e.enc64(copy_special, rec_copysp.opcodes(vec![0x89]).rex().w()); - e.enc32(copy_special, rec_copysp.opcodes(vec![0x89])); + e.enc64(copy_special, rec_copysp.opcodes(&MOV_STORE).rex().w()); + e.enc32(copy_special, rec_copysp.opcodes(&MOV_STORE)); // Copy to SSA. These have to be done with special _rex_only encoders, because the standard // machinery for deciding whether a REX.{RXB} prefix is needed doesn't take into account // the source register, which is specified directly in the instruction. - e.enc_i32_i64_rex_only(copy_to_ssa, rec_umr_reg_to_ssa.opcodes(vec![0x89])); - e.enc_r32_r64_rex_only(copy_to_ssa, rec_umr_reg_to_ssa.opcodes(vec![0x89])); - e.enc_both_rex_only(copy_to_ssa.bind(B1), rec_umr_reg_to_ssa.opcodes(vec![0x89])); - e.enc_both_rex_only(copy_to_ssa.bind(I8), rec_umr_reg_to_ssa.opcodes(vec![0x89])); + e.enc_i32_i64_rex_only(copy_to_ssa, rec_umr_reg_to_ssa.opcodes(&MOV_STORE)); + e.enc_r32_r64_rex_only(copy_to_ssa, rec_umr_reg_to_ssa.opcodes(&MOV_STORE)); + e.enc_both_rex_only(copy_to_ssa.bind(B1), rec_umr_reg_to_ssa.opcodes(&MOV_STORE)); + e.enc_both_rex_only(copy_to_ssa.bind(I8), rec_umr_reg_to_ssa.opcodes(&MOV_STORE)); e.enc_both_rex_only( copy_to_ssa.bind(I16), - rec_umr_reg_to_ssa.opcodes(vec![0x89]), + rec_umr_reg_to_ssa.opcodes(&MOV_STORE), ); e.enc_both_rex_only( copy_to_ssa.bind(F64), - rec_furm_reg_to_ssa.opcodes(vec![0xf2, 0x0f, 0x10]), + rec_furm_reg_to_ssa.opcodes(&MOVSD_LOAD), ); e.enc_both_rex_only( copy_to_ssa.bind(F32), - rec_furm_reg_to_ssa.opcodes(vec![0xf3, 0x0f, 0x10]), + rec_furm_reg_to_ssa.opcodes(&MOVSS_LOAD), ); // Stack-slot-to-the-same-stack-slot copy, which is guaranteed to turn @@ -1083,204 +1083,159 @@ pub(crate) fn define( } // Adjust SP down by a dynamic value (or up, with a negative operand). - e.enc32(adjust_sp_down.bind(I32), rec_adjustsp.opcodes(vec![0x29])); + e.enc32(adjust_sp_down.bind(I32), rec_adjustsp.opcodes(&SUB)); e.enc64( adjust_sp_down.bind(I64), - rec_adjustsp.opcodes(vec![0x29]).rex().w(), + rec_adjustsp.opcodes(&SUB).rex().w(), ); // Adjust SP up by an immediate (or down, with a negative immediate). - e.enc32(adjust_sp_up_imm, rec_adjustsp_ib.opcodes(vec![0x83])); - e.enc32(adjust_sp_up_imm, rec_adjustsp_id.opcodes(vec![0x81])); + e.enc32(adjust_sp_up_imm, rec_adjustsp_ib.opcodes(&CMP_IMM8)); + e.enc32(adjust_sp_up_imm, rec_adjustsp_id.opcodes(&CMP_IMM)); e.enc64( adjust_sp_up_imm, - rec_adjustsp_ib.opcodes(vec![0x83]).rex().w(), + rec_adjustsp_ib.opcodes(&CMP_IMM8).rex().w(), ); e.enc64( adjust_sp_up_imm, - rec_adjustsp_id.opcodes(vec![0x81]).rex().w(), + rec_adjustsp_id.opcodes(&CMP_IMM).rex().w(), ); // Adjust SP down by an immediate (or up, with a negative immediate). e.enc32( adjust_sp_down_imm, - rec_adjustsp_ib.opcodes(vec![0x83]).rrr(5), - ); - e.enc32( - adjust_sp_down_imm, - rec_adjustsp_id.opcodes(vec![0x81]).rrr(5), + rec_adjustsp_ib.opcodes(&CMP_IMM8).rrr(5), ); + e.enc32(adjust_sp_down_imm, rec_adjustsp_id.opcodes(&CMP_IMM).rrr(5)); e.enc64( adjust_sp_down_imm, - rec_adjustsp_ib.opcodes(vec![0x83]).rrr(5).rex().w(), + rec_adjustsp_ib.opcodes(&CMP_IMM8).rrr(5).rex().w(), ); e.enc64( adjust_sp_down_imm, - rec_adjustsp_id.opcodes(vec![0x81]).rrr(5).rex().w(), + rec_adjustsp_id.opcodes(&CMP_IMM).rrr(5).rex().w(), ); // Float loads and stores. + e.enc_both(load.bind(F32).bind_any(), rec_fld.opcodes(&MOVSS_LOAD)); + e.enc_both(load.bind(F32).bind_any(), rec_fldDisp8.opcodes(&MOVSS_LOAD)); e.enc_both( load.bind(F32).bind_any(), - rec_fld.opcodes(vec![0xf3, 0x0f, 0x10]), - ); - e.enc_both( - load.bind(F32).bind_any(), - rec_fldDisp8.opcodes(vec![0xf3, 0x0f, 0x10]), - ); - e.enc_both( - load.bind(F32).bind_any(), - rec_fldDisp32.opcodes(vec![0xf3, 0x0f, 0x10]), + rec_fldDisp32.opcodes(&MOVSS_LOAD), ); e.enc_both( load_complex.bind(F32), - rec_fldWithIndex.opcodes(vec![0xf3, 0x0f, 0x10]), + rec_fldWithIndex.opcodes(&MOVSS_LOAD), ); e.enc_both( load_complex.bind(F32), - rec_fldWithIndexDisp8.opcodes(vec![0xf3, 0x0f, 0x10]), + rec_fldWithIndexDisp8.opcodes(&MOVSS_LOAD), ); e.enc_both( load_complex.bind(F32), - rec_fldWithIndexDisp32.opcodes(vec![0xf3, 0x0f, 0x10]), + rec_fldWithIndexDisp32.opcodes(&MOVSS_LOAD), ); + e.enc_both(load.bind(F64).bind_any(), rec_fld.opcodes(&MOVSD_LOAD)); + e.enc_both(load.bind(F64).bind_any(), rec_fldDisp8.opcodes(&MOVSD_LOAD)); e.enc_both( load.bind(F64).bind_any(), - rec_fld.opcodes(vec![0xf2, 0x0f, 0x10]), - ); - e.enc_both( - load.bind(F64).bind_any(), - rec_fldDisp8.opcodes(vec![0xf2, 0x0f, 0x10]), - ); - e.enc_both( - load.bind(F64).bind_any(), - rec_fldDisp32.opcodes(vec![0xf2, 0x0f, 0x10]), + rec_fldDisp32.opcodes(&MOVSD_LOAD), ); e.enc_both( load_complex.bind(F64), - rec_fldWithIndex.opcodes(vec![0xf2, 0x0f, 0x10]), + rec_fldWithIndex.opcodes(&MOVSD_LOAD), ); e.enc_both( load_complex.bind(F64), - rec_fldWithIndexDisp8.opcodes(vec![0xf2, 0x0f, 0x10]), + rec_fldWithIndexDisp8.opcodes(&MOVSD_LOAD), ); e.enc_both( load_complex.bind(F64), - rec_fldWithIndexDisp32.opcodes(vec![0xf2, 0x0f, 0x10]), + rec_fldWithIndexDisp32.opcodes(&MOVSD_LOAD), ); + e.enc_both(store.bind(F32).bind_any(), rec_fst.opcodes(&MOVSS_STORE)); e.enc_both( store.bind(F32).bind_any(), - rec_fst.opcodes(vec![0xf3, 0x0f, 0x11]), + rec_fstDisp8.opcodes(&MOVSS_STORE), ); e.enc_both( store.bind(F32).bind_any(), - rec_fstDisp8.opcodes(vec![0xf3, 0x0f, 0x11]), - ); - e.enc_both( - store.bind(F32).bind_any(), - rec_fstDisp32.opcodes(vec![0xf3, 0x0f, 0x11]), + rec_fstDisp32.opcodes(&MOVSS_STORE), ); e.enc_both( store_complex.bind(F32), - rec_fstWithIndex.opcodes(vec![0xf3, 0x0f, 0x11]), + rec_fstWithIndex.opcodes(&MOVSS_STORE), ); e.enc_both( store_complex.bind(F32), - rec_fstWithIndexDisp8.opcodes(vec![0xf3, 0x0f, 0x11]), + rec_fstWithIndexDisp8.opcodes(&MOVSS_STORE), ); e.enc_both( store_complex.bind(F32), - rec_fstWithIndexDisp32.opcodes(vec![0xf3, 0x0f, 0x11]), + rec_fstWithIndexDisp32.opcodes(&MOVSS_STORE), ); + e.enc_both(store.bind(F64).bind_any(), rec_fst.opcodes(&MOVSD_STORE)); e.enc_both( store.bind(F64).bind_any(), - rec_fst.opcodes(vec![0xf2, 0x0f, 0x11]), + rec_fstDisp8.opcodes(&MOVSD_STORE), ); e.enc_both( store.bind(F64).bind_any(), - rec_fstDisp8.opcodes(vec![0xf2, 0x0f, 0x11]), - ); - e.enc_both( - store.bind(F64).bind_any(), - rec_fstDisp32.opcodes(vec![0xf2, 0x0f, 0x11]), + rec_fstDisp32.opcodes(&MOVSD_STORE), ); e.enc_both( store_complex.bind(F64), - rec_fstWithIndex.opcodes(vec![0xf2, 0x0f, 0x11]), + rec_fstWithIndex.opcodes(&MOVSD_STORE), ); e.enc_both( store_complex.bind(F64), - rec_fstWithIndexDisp8.opcodes(vec![0xf2, 0x0f, 0x11]), + rec_fstWithIndexDisp8.opcodes(&MOVSD_STORE), ); e.enc_both( store_complex.bind(F64), - rec_fstWithIndexDisp32.opcodes(vec![0xf2, 0x0f, 0x11]), + rec_fstWithIndexDisp32.opcodes(&MOVSD_STORE), ); - e.enc_both( - fill.bind(F32), - rec_ffillSib32.opcodes(vec![0xf3, 0x0f, 0x10]), - ); - e.enc_both( - regfill.bind(F32), - rec_fregfill32.opcodes(vec![0xf3, 0x0f, 0x10]), - ); - e.enc_both( - fill.bind(F64), - rec_ffillSib32.opcodes(vec![0xf2, 0x0f, 0x10]), - ); - e.enc_both( - regfill.bind(F64), - rec_fregfill32.opcodes(vec![0xf2, 0x0f, 0x10]), - ); + e.enc_both(fill.bind(F32), rec_ffillSib32.opcodes(&MOVSS_LOAD)); + e.enc_both(regfill.bind(F32), rec_fregfill32.opcodes(&MOVSS_LOAD)); + e.enc_both(fill.bind(F64), rec_ffillSib32.opcodes(&MOVSD_LOAD)); + e.enc_both(regfill.bind(F64), rec_fregfill32.opcodes(&MOVSD_LOAD)); - e.enc_both( - spill.bind(F32), - rec_fspillSib32.opcodes(vec![0xf3, 0x0f, 0x11]), - ); - e.enc_both( - regspill.bind(F32), - rec_fregspill32.opcodes(vec![0xf3, 0x0f, 0x11]), - ); - e.enc_both( - spill.bind(F64), - rec_fspillSib32.opcodes(vec![0xf2, 0x0f, 0x11]), - ); - e.enc_both( - regspill.bind(F64), - rec_fregspill32.opcodes(vec![0xf2, 0x0f, 0x11]), - ); + e.enc_both(spill.bind(F32), rec_fspillSib32.opcodes(&MOVSS_STORE)); + e.enc_both(regspill.bind(F32), rec_fregspill32.opcodes(&MOVSS_STORE)); + e.enc_both(spill.bind(F64), rec_fspillSib32.opcodes(&MOVSD_STORE)); + e.enc_both(regspill.bind(F64), rec_fregspill32.opcodes(&MOVSD_STORE)); // Function addresses. // Non-PIC, all-ones funcaddresses. e.enc32_isap( func_addr.bind(I32), - rec_fnaddr4.opcodes(vec![0xb8]), + rec_fnaddr4.opcodes(&MOV_IMM), not_all_ones_funcaddrs_and_not_is_pic, ); e.enc64_isap( func_addr.bind(I64), - rec_fnaddr8.opcodes(vec![0xb8]).rex().w(), + rec_fnaddr8.opcodes(&MOV_IMM).rex().w(), not_all_ones_funcaddrs_and_not_is_pic, ); // Non-PIC, all-zeros funcaddresses. e.enc32_isap( func_addr.bind(I32), - rec_allones_fnaddr4.opcodes(vec![0xb8]), + rec_allones_fnaddr4.opcodes(&MOV_IMM), all_ones_funcaddrs_and_not_is_pic, ); e.enc64_isap( func_addr.bind(I64), - rec_allones_fnaddr8.opcodes(vec![0xb8]).rex().w(), + rec_allones_fnaddr8.opcodes(&MOV_IMM).rex().w(), all_ones_funcaddrs_and_not_is_pic, ); @@ -1289,14 +1244,14 @@ pub(crate) fn define( let is_colocated_func = InstructionPredicate::new_is_colocated_func(f_func_addr, "func_ref"); e.enc64_instp( func_addr.bind(I64), - rec_pcrel_fnaddr8.opcodes(vec![0x8d]).rex().w(), + rec_pcrel_fnaddr8.opcodes(&LEA).rex().w(), is_colocated_func, ); // 64-bit, non-colocated, PIC. e.enc64_isap( func_addr.bind(I64), - rec_got_fnaddr8.opcodes(vec![0x8b]).rex().w(), + rec_got_fnaddr8.opcodes(&MOV_LOAD).rex().w(), is_pic, ); @@ -1305,19 +1260,19 @@ pub(crate) fn define( // Non-PIC. e.enc32_isap( symbol_value.bind(I32), - rec_gvaddr4.opcodes(vec![0xb8]), + rec_gvaddr4.opcodes(&MOV_IMM), not_is_pic, ); e.enc64_isap( symbol_value.bind(I64), - rec_gvaddr8.opcodes(vec![0xb8]).rex().w(), + rec_gvaddr8.opcodes(&MOV_IMM).rex().w(), not_is_pic, ); // PIC, colocated. e.enc64_func( symbol_value.bind(I64), - rec_pcrel_gvaddr8.opcodes(vec![0x8d]).rex().w(), + rec_pcrel_gvaddr8.opcodes(&LEA).rex().w(), |encoding| { encoding .isa_predicate(is_pic) @@ -1328,7 +1283,7 @@ pub(crate) fn define( // PIC, non-colocated. e.enc64_isap( symbol_value.bind(I64), - rec_got_gvaddr8.opcodes(vec![0x8b]).rex().w(), + rec_got_gvaddr8.opcodes(&MOV_LOAD).rex().w(), is_pic, ); @@ -1336,102 +1291,102 @@ pub(crate) fn define( // // TODO: Add encoding rules for stack_load and stack_store, so that they // don't get legalized to stack_addr + load/store. - e.enc32(stack_addr.bind(I32), rec_spaddr4_id.opcodes(vec![0x8d])); - e.enc64( - stack_addr.bind(I64), - rec_spaddr8_id.opcodes(vec![0x8d]).rex().w(), - ); + e.enc32(stack_addr.bind(I32), rec_spaddr4_id.opcodes(&LEA)); + e.enc64(stack_addr.bind(I64), rec_spaddr8_id.opcodes(&LEA).rex().w()); // Call/return // 32-bit, both PIC and non-PIC. - e.enc32(call, rec_call_id.opcodes(vec![0xe8])); + e.enc32(call, rec_call_id.opcodes(&CALL_RELATIVE)); // 64-bit, colocated, both PIC and non-PIC. Use the call instruction's pc-relative field. let f_call = formats.get(formats.by_name("Call")); let is_colocated_func = InstructionPredicate::new_is_colocated_func(f_call, "func_ref"); - e.enc64_instp(call, rec_call_id.opcodes(vec![0xe8]), is_colocated_func); + e.enc64_instp(call, rec_call_id.opcodes(&CALL_RELATIVE), is_colocated_func); // 64-bit, non-colocated, PIC. There is no 64-bit non-colocated non-PIC version, since non-PIC // is currently using the large model, which requires calls be lowered to // func_addr+call_indirect. - e.enc64_isap(call, rec_call_plt_id.opcodes(vec![0xe8]), is_pic); + e.enc64_isap(call, rec_call_plt_id.opcodes(&CALL_RELATIVE), is_pic); e.enc32( call_indirect.bind(I32), - rec_call_r.opcodes(vec![0xff]).rrr(2), + rec_call_r.opcodes(&JUMP_ABSOLUTE).rrr(2), ); e.enc64( call_indirect.bind(I64), - rec_call_r.opcodes(vec![0xff]).rrr(2).rex(), + rec_call_r.opcodes(&JUMP_ABSOLUTE).rrr(2).rex(), ); e.enc64( call_indirect.bind(I64), - rec_call_r.opcodes(vec![0xff]).rrr(2), + rec_call_r.opcodes(&JUMP_ABSOLUTE).rrr(2), ); - e.enc32(return_, rec_ret.opcodes(vec![0xc3])); - e.enc64(return_, rec_ret.opcodes(vec![0xc3])); + e.enc32(return_, rec_ret.opcodes(&RET_NEAR)); + e.enc64(return_, rec_ret.opcodes(&RET_NEAR)); // Branches. - e.enc32(jump, rec_jmpb.opcodes(vec![0xeb])); - e.enc64(jump, rec_jmpb.opcodes(vec![0xeb])); - e.enc32(jump, rec_jmpd.opcodes(vec![0xe9])); - e.enc64(jump, rec_jmpd.opcodes(vec![0xe9])); + e.enc32(jump, rec_jmpb.opcodes(&JUMP_SHORT)); + e.enc64(jump, rec_jmpb.opcodes(&JUMP_SHORT)); + e.enc32(jump, rec_jmpd.opcodes(&JUMP_NEAR_RELATIVE)); + e.enc64(jump, rec_jmpd.opcodes(&JUMP_NEAR_RELATIVE)); - e.enc_both(brif, rec_brib.opcodes(vec![0x70])); - e.enc_both(brif, rec_brid.opcodes(vec![0x0f, 0x80])); + e.enc_both(brif, rec_brib.opcodes(&JUMP_SHORT_IF_OVERFLOW)); + e.enc_both(brif, rec_brid.opcodes(&JUMP_NEAR_IF_OVERFLOW)); // Not all float condition codes are legal, see `supported_floatccs`. - e.enc_both(brff, rec_brfb.opcodes(vec![0x70])); - e.enc_both(brff, rec_brfd.opcodes(vec![0x0f, 0x80])); + e.enc_both(brff, rec_brfb.opcodes(&JUMP_SHORT_IF_OVERFLOW)); + e.enc_both(brff, rec_brfd.opcodes(&JUMP_NEAR_IF_OVERFLOW)); // Note that the tjccd opcode will be prefixed with 0x0f. - e.enc_i32_i64(brz, rec_tjccb.opcodes(vec![0x74])); - e.enc_i32_i64(brz, rec_tjccd.opcodes(vec![0x84])); - e.enc_i32_i64(brnz, rec_tjccb.opcodes(vec![0x75])); - e.enc_i32_i64(brnz, rec_tjccd.opcodes(vec![0x85])); + e.enc_i32_i64(brz, rec_tjccb.opcodes(&JUMP_SHORT_IF_EQUAL)); + e.enc_i32_i64(brz, rec_tjccd.opcodes(&TEST_BYTE_REG)); + e.enc_i32_i64(brnz, rec_tjccb.opcodes(&JUMP_SHORT_IF_NOT_EQUAL)); + e.enc_i32_i64(brnz, rec_tjccd.opcodes(&TEST_REG)); // Branch on a b1 value in a register only looks at the low 8 bits. See also // bint encodings below. // // Start with the worst-case encoding for X86_32 only. The register allocator // can't handle a branch with an ABCD-constrained operand. - e.enc32(brz.bind(B1), rec_t8jccd_long.opcodes(vec![0x84])); - e.enc32(brnz.bind(B1), rec_t8jccd_long.opcodes(vec![0x85])); + e.enc32(brz.bind(B1), rec_t8jccd_long.opcodes(&TEST_BYTE_REG)); + e.enc32(brnz.bind(B1), rec_t8jccd_long.opcodes(&TEST_REG)); - e.enc_both(brz.bind(B1), rec_t8jccb_abcd.opcodes(vec![0x74])); - e.enc_both(brz.bind(B1), rec_t8jccd_abcd.opcodes(vec![0x84])); - e.enc_both(brnz.bind(B1), rec_t8jccb_abcd.opcodes(vec![0x75])); - e.enc_both(brnz.bind(B1), rec_t8jccd_abcd.opcodes(vec![0x85])); + e.enc_both(brz.bind(B1), rec_t8jccb_abcd.opcodes(&JUMP_SHORT_IF_EQUAL)); + e.enc_both(brz.bind(B1), rec_t8jccd_abcd.opcodes(&TEST_BYTE_REG)); + e.enc_both( + brnz.bind(B1), + rec_t8jccb_abcd.opcodes(&JUMP_SHORT_IF_NOT_EQUAL), + ); + e.enc_both(brnz.bind(B1), rec_t8jccd_abcd.opcodes(&TEST_REG)); // Jump tables. e.enc64( jump_table_entry.bind(I64), - rec_jt_entry.opcodes(vec![0x63]).rex().w(), + rec_jt_entry.opcodes(&MOVSXD).rex().w(), ); - e.enc32(jump_table_entry.bind(I32), rec_jt_entry.opcodes(vec![0x8b])); + e.enc32(jump_table_entry.bind(I32), rec_jt_entry.opcodes(&MOV_LOAD)); e.enc64( jump_table_base.bind(I64), - rec_jt_base.opcodes(vec![0x8d]).rex().w(), + rec_jt_base.opcodes(&LEA).rex().w(), ); - e.enc32(jump_table_base.bind(I32), rec_jt_base.opcodes(vec![0x8d])); + e.enc32(jump_table_base.bind(I32), rec_jt_base.opcodes(&LEA)); e.enc_x86_64( indirect_jump_table_br.bind(I64), - rec_indirect_jmp.opcodes(vec![0xff]).rrr(4), + rec_indirect_jmp.opcodes(&JUMP_ABSOLUTE).rrr(4), ); e.enc32( indirect_jump_table_br.bind(I32), - rec_indirect_jmp.opcodes(vec![0xff]).rrr(4), + rec_indirect_jmp.opcodes(&JUMP_ABSOLUTE).rrr(4), ); // Trap as ud2 - e.enc32(trap, rec_trap.opcodes(vec![0x0f, 0x0b])); - e.enc64(trap, rec_trap.opcodes(vec![0x0f, 0x0b])); - e.enc32(resumable_trap, rec_trap.opcodes(vec![0x0f, 0x0b])); - e.enc64(resumable_trap, rec_trap.opcodes(vec![0x0f, 0x0b])); + e.enc32(trap, rec_trap.opcodes(&UNDEFINED2)); + e.enc64(trap, rec_trap.opcodes(&UNDEFINED2)); + e.enc32(resumable_trap, rec_trap.opcodes(&UNDEFINED2)); + e.enc64(resumable_trap, rec_trap.opcodes(&UNDEFINED2)); // Debug trap as int3 e.enc32_rec(debugtrap, rec_debugtrap, 0); @@ -1443,31 +1398,28 @@ pub(crate) fn define( e.enc64_rec(trapff, rec_trapff, 0); // Comparisons - e.enc_i32_i64(icmp, rec_icscc.opcodes(vec![0x39])); - e.enc_i32_i64(icmp_imm, rec_icscc_ib.opcodes(vec![0x83]).rrr(7)); - e.enc_i32_i64(icmp_imm, rec_icscc_id.opcodes(vec![0x81]).rrr(7)); - e.enc_i32_i64(ifcmp, rec_rcmp.opcodes(vec![0x39])); - e.enc_i32_i64(ifcmp_imm, rec_rcmp_ib.opcodes(vec![0x83]).rrr(7)); - e.enc_i32_i64(ifcmp_imm, rec_rcmp_id.opcodes(vec![0x81]).rrr(7)); + e.enc_i32_i64(icmp, rec_icscc.opcodes(&CMP_REG)); + e.enc_i32_i64(icmp_imm, rec_icscc_ib.opcodes(&CMP_IMM8).rrr(7)); + e.enc_i32_i64(icmp_imm, rec_icscc_id.opcodes(&CMP_IMM).rrr(7)); + e.enc_i32_i64(ifcmp, rec_rcmp.opcodes(&CMP_REG)); + e.enc_i32_i64(ifcmp_imm, rec_rcmp_ib.opcodes(&CMP_IMM8).rrr(7)); + e.enc_i32_i64(ifcmp_imm, rec_rcmp_id.opcodes(&CMP_IMM).rrr(7)); // TODO: We could special-case ifcmp_imm(x, 0) to TEST(x, x). - e.enc32(ifcmp_sp.bind(I32), rec_rcmp_sp.opcodes(vec![0x39])); - e.enc64( - ifcmp_sp.bind(I64), - rec_rcmp_sp.opcodes(vec![0x39]).rex().w(), - ); + e.enc32(ifcmp_sp.bind(I32), rec_rcmp_sp.opcodes(&CMP_REG)); + e.enc64(ifcmp_sp.bind(I64), rec_rcmp_sp.opcodes(&CMP_REG).rex().w()); // Convert flags to bool. // This encodes `b1` as an 8-bit low register with the value 0 or 1. - e.enc_both(trueif, rec_seti_abcd.opcodes(vec![0x0f, 0x90])); - e.enc_both(trueff, rec_setf_abcd.opcodes(vec![0x0f, 0x90])); + e.enc_both(trueif, rec_seti_abcd.opcodes(&SET_BYTE_IF_OVERFLOW)); + e.enc_both(trueff, rec_setf_abcd.opcodes(&SET_BYTE_IF_OVERFLOW)); // Conditional move (a.k.a integer select). - e.enc_i32_i64(selectif, rec_cmov.opcodes(vec![0x0f, 0x40])); + e.enc_i32_i64(selectif, rec_cmov.opcodes(&CMOV_OVERFLOW)); // Bit scan forwards and reverse - e.enc_i32_i64(x86_bsf, rec_bsf_and_bsr.opcodes(vec![0x0f, 0xbc])); - e.enc_i32_i64(x86_bsr, rec_bsf_and_bsr.opcodes(vec![0x0f, 0xbd])); + e.enc_i32_i64(x86_bsf, rec_bsf_and_bsr.opcodes(&BIT_SCAN_FORWARD)); + e.enc_i32_i64(x86_bsr, rec_bsf_and_bsr.opcodes(&BIT_SCAN_REVERSE)); // Convert bool to int. // @@ -1477,24 +1429,24 @@ pub(crate) fn define( // Encode movzbq as movzbl, because it's equivalent and shorter. e.enc32( bint.bind(I32).bind(B1), - rec_urm_noflags_abcd.opcodes(vec![0x0f, 0xb6]), + rec_urm_noflags_abcd.opcodes(&MOVZX_BYTE), ); e.enc64( bint.bind(I64).bind(B1), - rec_urm_noflags.opcodes(vec![0x0f, 0xb6]).rex(), + rec_urm_noflags.opcodes(&MOVZX_BYTE).rex(), ); e.enc64( bint.bind(I64).bind(B1), - rec_urm_noflags_abcd.opcodes(vec![0x0f, 0xb6]), + rec_urm_noflags_abcd.opcodes(&MOVZX_BYTE), ); e.enc64( bint.bind(I32).bind(B1), - rec_urm_noflags.opcodes(vec![0x0f, 0xb6]).rex(), + rec_urm_noflags.opcodes(&MOVZX_BYTE).rex(), ); e.enc64( bint.bind(I32).bind(B1), - rec_urm_noflags_abcd.opcodes(vec![0x0f, 0xb6]), + rec_urm_noflags_abcd.opcodes(&MOVZX_BYTE), ); // Numerical conversions. @@ -1517,103 +1469,103 @@ pub(crate) fn define( // movsbl e.enc32( sextend.bind(I32).bind(I8), - rec_urm_noflags_abcd.opcodes(vec![0x0f, 0xbe]), + rec_urm_noflags_abcd.opcodes(&MOVSX_BYTE), ); e.enc64( sextend.bind(I32).bind(I8), - rec_urm_noflags.opcodes(vec![0x0f, 0xbe]).rex(), + rec_urm_noflags.opcodes(&MOVSX_BYTE).rex(), ); e.enc64( sextend.bind(I32).bind(I8), - rec_urm_noflags_abcd.opcodes(vec![0x0f, 0xbe]), + rec_urm_noflags_abcd.opcodes(&MOVSX_BYTE), ); // movswl e.enc32( sextend.bind(I32).bind(I16), - rec_urm_noflags.opcodes(vec![0x0f, 0xbf]), + rec_urm_noflags.opcodes(&MOVSX_WORD), ); e.enc64( sextend.bind(I32).bind(I16), - rec_urm_noflags.opcodes(vec![0x0f, 0xbf]).rex(), + rec_urm_noflags.opcodes(&MOVSX_WORD).rex(), ); e.enc64( sextend.bind(I32).bind(I16), - rec_urm_noflags.opcodes(vec![0x0f, 0xbf]), + rec_urm_noflags.opcodes(&MOVSX_WORD), ); // movsbq e.enc64( sextend.bind(I64).bind(I8), - rec_urm_noflags.opcodes(vec![0x0f, 0xbe]).rex().w(), + rec_urm_noflags.opcodes(&MOVSX_BYTE).rex().w(), ); // movswq e.enc64( sextend.bind(I64).bind(I16), - rec_urm_noflags.opcodes(vec![0x0f, 0xbf]).rex().w(), + rec_urm_noflags.opcodes(&MOVSX_WORD).rex().w(), ); // movslq e.enc64( sextend.bind(I64).bind(I32), - rec_urm_noflags.opcodes(vec![0x63]).rex().w(), + rec_urm_noflags.opcodes(&MOVSXD).rex().w(), ); // movzbl e.enc32( uextend.bind(I32).bind(I8), - rec_urm_noflags_abcd.opcodes(vec![0x0f, 0xb6]), + rec_urm_noflags_abcd.opcodes(&MOVZX_BYTE), ); e.enc64( uextend.bind(I32).bind(I8), - rec_urm_noflags.opcodes(vec![0x0f, 0xb6]).rex(), + rec_urm_noflags.opcodes(&MOVZX_BYTE).rex(), ); e.enc64( uextend.bind(I32).bind(I8), - rec_urm_noflags_abcd.opcodes(vec![0x0f, 0xb6]), + rec_urm_noflags_abcd.opcodes(&MOVZX_BYTE), ); // movzwl e.enc32( uextend.bind(I32).bind(I16), - rec_urm_noflags.opcodes(vec![0x0f, 0xb7]), + rec_urm_noflags.opcodes(&MOVZX_WORD), ); e.enc64( uextend.bind(I32).bind(I16), - rec_urm_noflags.opcodes(vec![0x0f, 0xb7]).rex(), + rec_urm_noflags.opcodes(&MOVZX_WORD).rex(), ); e.enc64( uextend.bind(I32).bind(I16), - rec_urm_noflags.opcodes(vec![0x0f, 0xb7]), + rec_urm_noflags.opcodes(&MOVZX_WORD), ); // movzbq, encoded as movzbl because it's equivalent and shorter. e.enc64( uextend.bind(I64).bind(I8), - rec_urm_noflags.opcodes(vec![0x0f, 0xb6]).rex(), + rec_urm_noflags.opcodes(&MOVZX_BYTE).rex(), ); e.enc64( uextend.bind(I64).bind(I8), - rec_urm_noflags_abcd.opcodes(vec![0x0f, 0xb6]), + rec_urm_noflags_abcd.opcodes(&MOVZX_BYTE), ); // movzwq, encoded as movzwl because it's equivalent and shorter e.enc64( uextend.bind(I64).bind(I16), - rec_urm_noflags.opcodes(vec![0x0f, 0xb7]).rex(), + rec_urm_noflags.opcodes(&MOVZX_WORD).rex(), ); e.enc64( uextend.bind(I64).bind(I16), - rec_urm_noflags.opcodes(vec![0x0f, 0xb7]), + rec_urm_noflags.opcodes(&MOVZX_WORD), ); // A 32-bit register copy clears the high 32 bits. e.enc64( uextend.bind(I64).bind(I32), - rec_umr.opcodes(vec![0x89]).rex(), + rec_umr.opcodes(&MOV_STORE).rex(), ); - e.enc64(uextend.bind(I64).bind(I32), rec_umr.opcodes(vec![0x89])); + e.enc64(uextend.bind(I64).bind(I32), rec_umr.opcodes(&MOV_STORE)); // Floating point @@ -1623,7 +1575,7 @@ pub(crate) fn define( let is_zero_32_bit_float = InstructionPredicate::new_is_zero_32bit_float(f_unary_ieee32, "imm"); e.enc32_instp( f32const, - rec_f32imm_z.opcodes(vec![0x0f, 0x57]), + rec_f32imm_z.opcodes(&XORPS), is_zero_32_bit_float.clone(), ); @@ -1631,148 +1583,133 @@ pub(crate) fn define( let is_zero_64_bit_float = InstructionPredicate::new_is_zero_64bit_float(f_unary_ieee64, "imm"); e.enc32_instp( f64const, - rec_f64imm_z.opcodes(vec![0x66, 0x0f, 0x57]), + rec_f64imm_z.opcodes(&XORPD), is_zero_64_bit_float.clone(), ); - e.enc_x86_64_instp( - f32const, - rec_f32imm_z.opcodes(vec![0x0f, 0x57]), - is_zero_32_bit_float, - ); - e.enc_x86_64_instp( - f64const, - rec_f64imm_z.opcodes(vec![0x66, 0x0f, 0x57]), - is_zero_64_bit_float, - ); + e.enc_x86_64_instp(f32const, rec_f32imm_z.opcodes(&XORPS), is_zero_32_bit_float); + e.enc_x86_64_instp(f64const, rec_f64imm_z.opcodes(&XORPD), is_zero_64_bit_float); // movd e.enc_both( bitcast.bind(F32).bind(I32), - rec_frurm.opcodes(vec![0x66, 0x0f, 0x6e]), + rec_frurm.opcodes(&MOVD_LOAD_XMM), ); e.enc_both( bitcast.bind(I32).bind(F32), - rec_rfumr.opcodes(vec![0x66, 0x0f, 0x7e]), + rec_rfumr.opcodes(&MOVD_STORE_XMM), ); // movq e.enc64( bitcast.bind(F64).bind(I64), - rec_frurm.opcodes(vec![0x66, 0x0f, 0x6e]).rex().w(), + rec_frurm.opcodes(&MOVD_LOAD_XMM).rex().w(), ); e.enc64( bitcast.bind(I64).bind(F64), - rec_rfumr.opcodes(vec![0x66, 0x0f, 0x7e]).rex().w(), + rec_rfumr.opcodes(&MOVD_STORE_XMM).rex().w(), ); // movaps - e.enc_both(copy.bind(F32), rec_furm.opcodes(vec![0x0f, 0x28])); - e.enc_both(copy.bind(F64), rec_furm.opcodes(vec![0x0f, 0x28])); + e.enc_both(copy.bind(F32), rec_furm.opcodes(&MOVAPS_LOAD)); + e.enc_both(copy.bind(F64), rec_furm.opcodes(&MOVAPS_LOAD)); // TODO For x86-64, only define REX forms for now, since we can't describe the special regunit // immediate operands with the current constraint language. - e.enc32(regmove.bind(F32), rec_frmov.opcodes(vec![0x0f, 0x28])); - e.enc64(regmove.bind(F32), rec_frmov.opcodes(vec![0x0f, 0x28]).rex()); + e.enc32(regmove.bind(F32), rec_frmov.opcodes(&MOVAPS_LOAD)); + e.enc64(regmove.bind(F32), rec_frmov.opcodes(&MOVAPS_LOAD).rex()); // TODO For x86-64, only define REX forms for now, since we can't describe the special regunit // immediate operands with the current constraint language. - e.enc32(regmove.bind(F64), rec_frmov.opcodes(vec![0x0f, 0x28])); - e.enc64(regmove.bind(F64), rec_frmov.opcodes(vec![0x0f, 0x28]).rex()); + e.enc32(regmove.bind(F64), rec_frmov.opcodes(&MOVAPS_LOAD)); + e.enc64(regmove.bind(F64), rec_frmov.opcodes(&MOVAPS_LOAD).rex()); // cvtsi2ss - e.enc_i32_i64( - fcvt_from_sint.bind(F32), - rec_frurm.opcodes(vec![0xf3, 0x0f, 0x2a]), - ); + e.enc_i32_i64(fcvt_from_sint.bind(F32), rec_frurm.opcodes(&CVTSI2SS)); // cvtsi2sd - e.enc_i32_i64( - fcvt_from_sint.bind(F64), - rec_frurm.opcodes(vec![0xf2, 0x0f, 0x2a]), - ); + e.enc_i32_i64(fcvt_from_sint.bind(F64), rec_frurm.opcodes(&CVTSI2SD)); // cvtss2sd - e.enc_both( - fpromote.bind(F64).bind(F32), - rec_furm.opcodes(vec![0xf3, 0x0f, 0x5a]), - ); + e.enc_both(fpromote.bind(F64).bind(F32), rec_furm.opcodes(&CVTSS2SD)); // cvtsd2ss - e.enc_both( - fdemote.bind(F32).bind(F64), - rec_furm.opcodes(vec![0xf2, 0x0f, 0x5a]), - ); + e.enc_both(fdemote.bind(F32).bind(F64), rec_furm.opcodes(&CVTSD2SS)); // cvttss2si e.enc_both( x86_cvtt2si.bind(I32).bind(F32), - rec_rfurm.opcodes(vec![0xf3, 0x0f, 0x2c]), + rec_rfurm.opcodes(&CVTTSS2SI), ); e.enc64( x86_cvtt2si.bind(I64).bind(F32), - rec_rfurm.opcodes(vec![0xf3, 0x0f, 0x2c]).rex().w(), + rec_rfurm.opcodes(&CVTTSS2SI).rex().w(), ); // cvttsd2si e.enc_both( x86_cvtt2si.bind(I32).bind(F64), - rec_rfurm.opcodes(vec![0xf2, 0x0f, 0x2c]), + rec_rfurm.opcodes(&CVTTSD2SI), ); e.enc64( x86_cvtt2si.bind(I64).bind(F64), - rec_rfurm.opcodes(vec![0xf2, 0x0f, 0x2c]).rex().w(), + rec_rfurm.opcodes(&CVTTSD2SI).rex().w(), ); // Exact square roots. - e.enc_both(sqrt.bind(F32), rec_furm.opcodes(vec![0xf3, 0x0f, 0x51])); - e.enc_both(sqrt.bind(F64), rec_furm.opcodes(vec![0xf2, 0x0f, 0x51])); + e.enc_both(sqrt.bind(F32), rec_furm.opcodes(&SQRTSS)); + e.enc_both(sqrt.bind(F64), rec_furm.opcodes(&SQRTSD)); // Rounding. The recipe looks at the opcode to pick an immediate. for inst in &[nearest, floor, ceil, trunc] { - e.enc_both_isap( - inst.bind(F32), - rec_furmi_rnd.opcodes(vec![0x66, 0x0f, 0x3a, 0x0a]), - use_sse41, - ); - e.enc_both_isap( - inst.bind(F64), - rec_furmi_rnd.opcodes(vec![0x66, 0x0f, 0x3a, 0x0b]), - use_sse41, - ); + e.enc_both_isap(inst.bind(F32), rec_furmi_rnd.opcodes(&ROUNDSS), use_sse41); + e.enc_both_isap(inst.bind(F64), rec_furmi_rnd.opcodes(&ROUNDSD), use_sse41); } // Binary arithmetic ops. - for &(inst, opc) in &[ - (fadd, 0x58), - (fsub, 0x5c), - (fmul, 0x59), - (fdiv, 0x5e), - (x86_fmin, 0x5d), - (x86_fmax, 0x5f), - ] { - e.enc_both(inst.bind(F32), rec_fa.opcodes(vec![0xf3, 0x0f, opc])); - e.enc_both(inst.bind(F64), rec_fa.opcodes(vec![0xf2, 0x0f, opc])); - } + e.enc_both(fadd.bind(F32), rec_fa.opcodes(&ADDSS)); + e.enc_both(fadd.bind(F64), rec_fa.opcodes(&ADDSD)); + + e.enc_both(fsub.bind(F32), rec_fa.opcodes(&SUBSS)); + e.enc_both(fsub.bind(F64), rec_fa.opcodes(&SUBSD)); + + e.enc_both(fmul.bind(F32), rec_fa.opcodes(&MULSS)); + e.enc_both(fmul.bind(F64), rec_fa.opcodes(&MULSD)); + + e.enc_both(fdiv.bind(F32), rec_fa.opcodes(&DIVSS)); + e.enc_both(fdiv.bind(F64), rec_fa.opcodes(&DIVSD)); + + e.enc_both(x86_fmin.bind(F32), rec_fa.opcodes(&MINSS)); + e.enc_both(x86_fmin.bind(F64), rec_fa.opcodes(&MINSD)); + + e.enc_both(x86_fmax.bind(F32), rec_fa.opcodes(&MAXSS)); + e.enc_both(x86_fmax.bind(F64), rec_fa.opcodes(&MAXSD)); // Binary bitwise ops. - for &(inst, opc) in &[(band, 0x54), (bor, 0x56), (bxor, 0x57)] { - e.enc_both(inst.bind(F32), rec_fa.opcodes(vec![0x0f, opc])); - e.enc_both(inst.bind(F64), rec_fa.opcodes(vec![0x0f, opc])); - } + // + // The F64 version is intentionally encoded using the single-precision opcode: + // the operation is identical and the encoding is one byte shorter. + e.enc_both(band.bind(F32), rec_fa.opcodes(&ANDPS)); + e.enc_both(band.bind(F64), rec_fa.opcodes(&ANDPS)); + + e.enc_both(bor.bind(F32), rec_fa.opcodes(&ORPS)); + e.enc_both(bor.bind(F64), rec_fa.opcodes(&ORPS)); + + e.enc_both(bxor.bind(F32), rec_fa.opcodes(&XORPS)); + e.enc_both(bxor.bind(F64), rec_fa.opcodes(&XORPS)); // The `andnps(x,y)` instruction computes `~x&y`, while band_not(x,y)` is `x&~y. - e.enc_both(band_not.bind(F32), rec_fax.opcodes(vec![0x0f, 0x55])); - e.enc_both(band_not.bind(F64), rec_fax.opcodes(vec![0x0f, 0x55])); + e.enc_both(band_not.bind(F32), rec_fax.opcodes(&ANDNPS)); + e.enc_both(band_not.bind(F64), rec_fax.opcodes(&ANDNPS)); // Comparisons. // // This only covers the condition codes in `supported_floatccs`, the rest are // handled by legalization patterns. - e.enc_both(fcmp.bind(F32), rec_fcscc.opcodes(vec![0x0f, 0x2e])); - e.enc_both(fcmp.bind(F64), rec_fcscc.opcodes(vec![0x66, 0x0f, 0x2e])); - e.enc_both(ffcmp.bind(F32), rec_fcmp.opcodes(vec![0x0f, 0x2e])); - e.enc_both(ffcmp.bind(F64), rec_fcmp.opcodes(vec![0x66, 0x0f, 0x2e])); + e.enc_both(fcmp.bind(F32), rec_fcscc.opcodes(&UCOMISS)); + e.enc_both(fcmp.bind(F64), rec_fcscc.opcodes(&UCOMISD)); + e.enc_both(ffcmp.bind(F32), rec_fcmp.opcodes(&UCOMISS)); + e.enc_both(ffcmp.bind(F64), rec_fcmp.opcodes(&UCOMISD)); // SIMD vector size: eventually multiple vector sizes may be supported but for now only // SSE-sized vectors are available. @@ -1785,9 +1722,9 @@ pub(crate) fn define( let allowed_simd_type = |t: &LaneType| t.lane_bits() >= 8 && t.lane_bits() < 128; // PSHUFB, 8-bit shuffle using two XMM registers. - for ty in ValueType::all_lane_types().filter(|t| t.lane_bits() == 8) { + for ty in ValueType::all_lane_types().filter(allowed_simd_type) { let instruction = x86_pshufb.bind_vector_from_lane(ty, sse_vector_size); - let template = rec_fa.nonrex().opcodes(vec![0x66, 0x0f, 0x38, 00]); + let template = rec_fa.nonrex().opcodes(&PSHUFB); e.enc32_isap(instruction.clone(), template.clone(), use_ssse3_simd); e.enc64_isap(instruction, template, use_ssse3_simd); } @@ -1795,22 +1732,20 @@ pub(crate) fn define( // PSHUFD, 32-bit shuffle using one XMM register and a u8 immediate. for ty in ValueType::all_lane_types().filter(|t| t.lane_bits() == 32) { let instruction = x86_pshufd.bind_vector_from_lane(ty, sse_vector_size); - let template = rec_r_ib_unsigned_fpr - .nonrex() - .opcodes(vec![0x66, 0x0f, 0x70]); + let template = rec_r_ib_unsigned_fpr.nonrex().opcodes(&PSHUFD); e.enc32(instruction.clone(), template.clone()); e.enc64(instruction, template); } // SIMD scalar_to_vector; this uses MOV to copy the scalar value to an XMM register; according // to the Intel manual: "When the destination operand is an XMM register, the source operand is - // written to the low doubleword of the register and the regiser is zero-extended to 128 bits." + // written to the low doubleword of the register and the register is zero-extended to 128 bits." for ty in ValueType::all_lane_types().filter(allowed_simd_type) { let instruction = scalar_to_vector.bind_vector_from_lane(ty, sse_vector_size); if ty.is_float() { e.enc_32_64_rec(instruction, rec_null_fpr, 0); } else { - let template = rec_frurm.opcodes(vec![0x66, 0x0f, 0x6e]); // MOVD/MOVQ + let template = rec_frurm.opcodes(&MOVD_LOAD_XMM); if ty.lane_bits() < 64 { // no 32-bit encodings for 64-bit widths e.enc32(instruction.clone(), template.clone()); @@ -1820,17 +1755,17 @@ pub(crate) fn define( } // SIMD insertlane - let mut x86_pinsr_mapping: HashMap<u64, (Vec<u8>, Option<SettingPredicateNumber>)> = + let mut x86_pinsr_mapping: HashMap<u64, (&'static [u8], Option<SettingPredicateNumber>)> = HashMap::new(); - x86_pinsr_mapping.insert(8, (vec![0x66, 0x0f, 0x3a, 0x20], Some(use_sse41_simd))); // PINSRB - x86_pinsr_mapping.insert(16, (vec![0x66, 0x0f, 0xc4], None)); // PINSRW from SSE2 - x86_pinsr_mapping.insert(32, (vec![0x66, 0x0f, 0x3a, 0x22], Some(use_sse41_simd))); // PINSRD - x86_pinsr_mapping.insert(64, (vec![0x66, 0x0f, 0x3a, 0x22], Some(use_sse41_simd))); // PINSRQ, only x86_64 + x86_pinsr_mapping.insert(8, (&PINSRB, Some(use_sse41_simd))); + x86_pinsr_mapping.insert(16, (&PINSRW, None)); + x86_pinsr_mapping.insert(32, (&PINSR, Some(use_sse41_simd))); + x86_pinsr_mapping.insert(64, (&PINSR, Some(use_sse41_simd))); for ty in ValueType::all_lane_types().filter(allowed_simd_type) { if let Some((opcode, isap)) = x86_pinsr_mapping.get(&ty.lane_bits()) { let instruction = x86_pinsr.bind_vector_from_lane(ty, sse_vector_size); - let template = rec_r_ib_unsigned_r.opcodes(opcode.clone()); + let template = rec_r_ib_unsigned_r.opcodes(opcode); if ty.lane_bits() < 64 { e.enc_32_64_maybe_isap(instruction, template.nonrex(), isap.clone()); } else { @@ -1844,36 +1779,36 @@ pub(crate) fn define( // For legalizing insertlane with floats, INSERTPS from SSE4.1. { let instruction = x86_insertps.bind_vector_from_lane(F32, sse_vector_size); - let template = rec_fa_ib.nonrex().opcodes(vec![0x66, 0x0f, 0x3a, 0x21]); + let template = rec_fa_ib.nonrex().opcodes(&INSERTPS); e.enc_32_64_maybe_isap(instruction, template, Some(use_sse41_simd)); } // For legalizing insertlane with floats, MOVSD from SSE2. { let instruction = x86_movsd.bind_vector_from_lane(F64, sse_vector_size); - let template = rec_fa.nonrex().opcodes(vec![0xf2, 0x0f, 0x10]); + let template = rec_fa.nonrex().opcodes(&MOVSD_LOAD); e.enc_32_64_maybe_isap(instruction, template, None); // from SSE2 } // For legalizing insertlane with floats, MOVLHPS from SSE. { let instruction = x86_movlhps.bind_vector_from_lane(F64, sse_vector_size); - let template = rec_fa.nonrex().opcodes(vec![0x0f, 0x16]); + let template = rec_fa.nonrex().opcodes(&MOVLHPS); e.enc_32_64_maybe_isap(instruction, template, None); // from SSE } // SIMD extractlane - let mut x86_pextr_mapping: HashMap<u64, (Vec<u8>, Option<SettingPredicateNumber>)> = + let mut x86_pextr_mapping: HashMap<u64, (&'static [u8], Option<SettingPredicateNumber>)> = HashMap::new(); - x86_pextr_mapping.insert(8, (vec![0x66, 0x0f, 0x3a, 0x14], Some(use_sse41_simd))); // PEXTRB - x86_pextr_mapping.insert(16, (vec![0x66, 0x0f, 0xc5], None)); // PEXTRW from SSE2, SSE4.1 has a PEXTRW that can move to reg/m16 but the opcode is four bytes - x86_pextr_mapping.insert(32, (vec![0x66, 0x0f, 0x3a, 0x16], Some(use_sse41_simd))); // PEXTRD - x86_pextr_mapping.insert(64, (vec![0x66, 0x0f, 0x3a, 0x16], Some(use_sse41_simd))); // PEXTRQ, only x86_64 + x86_pextr_mapping.insert(8, (&PEXTRB, Some(use_sse41_simd))); + x86_pextr_mapping.insert(16, (&PEXTRW_SSE2, None)); + x86_pextr_mapping.insert(32, (&PEXTR, Some(use_sse41_simd))); + x86_pextr_mapping.insert(64, (&PEXTR, Some(use_sse41_simd))); for ty in ValueType::all_lane_types().filter(allowed_simd_type) { if let Some((opcode, isap)) = x86_pextr_mapping.get(&ty.lane_bits()) { let instruction = x86_pextr.bind_vector_from_lane(ty, sse_vector_size); - let template = rec_r_ib_unsigned_gpr.opcodes(opcode.clone()); + let template = rec_r_ib_unsigned_gpr.opcodes(opcode); if ty.lane_bits() < 64 { e.enc_32_64_maybe_isap(instruction, template.nonrex(), isap.clone()); } else { @@ -1917,6 +1852,28 @@ pub(crate) fn define( } } + // SIMD vconst for special cases (all zeroes, all ones) + // this must be encoded prior to the MOVUPS implementation (below) so the compiler sees this + // encoding first + for ty in ValueType::all_lane_types().filter(allowed_simd_type) { + let f_unary_const = formats.get(formats.by_name("UnaryConst")); + let instruction = vconst.bind_vector_from_lane(ty, sse_vector_size); + + let is_zero_128bit = + InstructionPredicate::new_is_all_zeroes_128bit(f_unary_const, "constant_handle"); + let template = rec_vconst_optimized.nonrex().opcodes(&PXOR); + e.enc_32_64_func(instruction.clone(), template, |builder| { + builder.inst_predicate(is_zero_128bit) + }); + + let is_ones_128bit = + InstructionPredicate::new_is_all_ones_128bit(f_unary_const, "constant_handle"); + let template = rec_vconst_optimized.nonrex().opcodes(&PCMPEQB); + e.enc_32_64_func(instruction, template, |builder| { + builder.inst_predicate(is_ones_128bit) + }); + } + // SIMD vconst using MOVUPS // TODO it would be ideal if eventually this became the more efficient MOVAPS but we would have // to guarantee that the constants are aligned when emitted and there is currently no mechanism @@ -1925,20 +1882,98 @@ pub(crate) fn define( // in memory) but some performance measurements are needed. for ty in ValueType::all_lane_types().filter(allowed_simd_type) { let instruction = vconst.bind_vector_from_lane(ty, sse_vector_size); - let template = rec_vconst.nonrex().opcodes(vec![0x0f, 0x10]); + let template = rec_vconst.nonrex().opcodes(&MOVUPS_LOAD); + e.enc_32_64_maybe_isap(instruction, template, None); // from SSE + } + + // SIMD bor using ORPS + for ty in ValueType::all_lane_types().filter(allowed_simd_type) { + let instruction = bor.bind_vector_from_lane(ty, sse_vector_size); + let template = rec_fa.nonrex().opcodes(&ORPS); e.enc_32_64_maybe_isap(instruction, template, None); // from SSE } + // SIMD register movement: store, load, spill, fill, regmove. All of these use encodings of + // MOVUPS and MOVAPS from SSE (TODO ideally all of these would either use MOVAPS when we have + // alignment or type-specific encodings, see https://github.com/CraneStation/cranelift/issues/1039). + for ty in ValueType::all_lane_types().filter(allowed_simd_type) { + // Store + let bound_store = store.bind_vector_from_lane(ty, sse_vector_size).bind_any(); + e.enc_32_64(bound_store.clone(), rec_fst.opcodes(&MOVUPS_STORE)); + e.enc_32_64(bound_store.clone(), rec_fstDisp8.opcodes(&MOVUPS_STORE)); + e.enc_32_64(bound_store, rec_fstDisp32.opcodes(&MOVUPS_STORE)); + + // Load + let bound_load = load.bind_vector_from_lane(ty, sse_vector_size).bind_any(); + e.enc_32_64(bound_load.clone(), rec_fld.opcodes(&MOVUPS_LOAD)); + e.enc_32_64(bound_load.clone(), rec_fldDisp8.opcodes(&MOVUPS_LOAD)); + e.enc_32_64(bound_load, rec_fldDisp32.opcodes(&MOVUPS_LOAD)); + + // Spill + let bound_spill = spill.bind_vector_from_lane(ty, sse_vector_size); + e.enc_32_64(bound_spill, rec_fspillSib32.opcodes(&MOVUPS_STORE)); + let bound_regspill = regspill.bind_vector_from_lane(ty, sse_vector_size); + e.enc_32_64(bound_regspill, rec_fregspill32.opcodes(&MOVUPS_STORE)); + + // Fill + let bound_fill = fill.bind_vector_from_lane(ty, sse_vector_size); + e.enc_32_64(bound_fill, rec_ffillSib32.opcodes(&MOVUPS_LOAD)); + let bound_regfill = regfill.bind_vector_from_lane(ty, sse_vector_size); + e.enc_32_64(bound_regfill, rec_fregfill32.opcodes(&MOVUPS_LOAD)); + let bound_fill_nop = fill_nop.bind_vector_from_lane(ty, sse_vector_size); + e.enc_32_64_rec(bound_fill_nop, rec_ffillnull, 0); + + // Regmove + let bound_regmove = regmove.bind_vector_from_lane(ty, sse_vector_size); + e.enc_32_64(bound_regmove, rec_frmov.opcodes(&MOVAPS_LOAD)); + + // Copy + let bound_copy = copy.bind_vector_from_lane(ty, sse_vector_size); + e.enc_32_64(bound_copy, rec_furm.opcodes(&MOVAPS_LOAD)); + let bound_copy_nop = copy_nop.bind_vector_from_lane(ty, sse_vector_size); + e.enc_32_64_rec(bound_copy_nop, rec_stacknull, 0); + } + + // SIMD integer addition + for (ty, opcodes) in &[(I8, &PADDB), (I16, &PADDW), (I32, &PADDD), (I64, &PADDQ)] { + let iadd = iadd.bind_vector_from_lane(ty.clone(), sse_vector_size); + e.enc_32_64(iadd, rec_fa.opcodes(*opcodes)); + } + + // SIMD icmp using PCMPEQ* + let mut pcmpeq_mapping: HashMap<u64, (&[u8], Option<SettingPredicateNumber>)> = HashMap::new(); + pcmpeq_mapping.insert(8, (&PCMPEQB, None)); + pcmpeq_mapping.insert(16, (&PCMPEQW, None)); + pcmpeq_mapping.insert(32, (&PCMPEQD, None)); + pcmpeq_mapping.insert(64, (&PCMPEQQ, Some(use_sse41_simd))); + for ty in ValueType::all_lane_types().filter(|t| t.is_int() && allowed_simd_type(t)) { + if let Some((opcodes, isa_predicate)) = pcmpeq_mapping.get(&ty.lane_bits()) { + let instruction = icmp.bind_vector_from_lane(ty, sse_vector_size); + let f_int_compare = formats.get(formats.by_name("IntCompare")); + let has_eq_condition_code = + InstructionPredicate::new_has_condition_code(f_int_compare, IntCC::Equal, "cond"); + let template = rec_icscc_fpr.nonrex().opcodes(*opcodes); + e.enc_32_64_func(instruction, template, |builder| { + let builder = builder.inst_predicate(has_eq_condition_code); + if let Some(p) = isa_predicate { + builder.isa_predicate(*p) + } else { + builder + } + }); + } + } + // Reference type instructions // Null references implemented as iconst 0. - e.enc32(null.bind_ref(R32), rec_pu_id_ref.opcodes(vec![0xb8])); + e.enc32(null.bind_ref(R32), rec_pu_id_ref.opcodes(&MOV_IMM)); - e.enc64(null.bind_ref(R64), rec_pu_id_ref.rex().opcodes(vec![0xb8])); - e.enc64(null.bind_ref(R64), rec_pu_id_ref.opcodes(vec![0xb8])); + e.enc64(null.bind_ref(R64), rec_pu_id_ref.rex().opcodes(&MOV_IMM)); + e.enc64(null.bind_ref(R64), rec_pu_id_ref.opcodes(&MOV_IMM)); // is_null, implemented by testing whether the value is 0. - e.enc_r32_r64_rex_only(is_null, rec_is_zero.opcodes(vec![0x85])); + e.enc_r32_r64_rex_only(is_null, rec_is_zero.opcodes(&TEST_REG)); // safepoint instruction calls sink, no actual encoding. e.enc32_rec(safepoint, rec_safepoint, 0); diff --git a/third_party/rust/cranelift-codegen-meta/src/isa/x86/legalize.rs b/third_party/rust/cranelift-codegen-meta/src/isa/x86/legalize.rs index dfd7f84334b78ebef3ef492f2be9909c2cd8d181..57057ce6bb4791b4014e6965738974c63323743b 100644 --- a/third_party/rust/cranelift-codegen-meta/src/isa/x86/legalize.rs +++ b/third_party/rust/cranelift-codegen-meta/src/isa/x86/legalize.rs @@ -45,6 +45,7 @@ pub(crate) fn define(shared: &mut SharedDefinitions, x86_instructions: &Instruct let selectif = insts.by_name("selectif"); let smulhi = insts.by_name("smulhi"); let splat = insts.by_name("splat"); + let shuffle = insts.by_name("shuffle"); let srem = insts.by_name("srem"); let udiv = insts.by_name("udiv"); let umulhi = insts.by_name("umulhi"); @@ -328,6 +329,7 @@ pub(crate) fn define(shared: &mut SharedDefinitions, x86_instructions: &Instruct def!(y = splat_any8x16(x)), vec![ def!(a = scalar_to_vector(x)), // move into the lowest 8 bits of an XMM register + // TODO replace the following two instructions with `vconst(0)` when this is possible; see https://github.com/CraneStation/cranelift/issues/1052 def!(b = f64const(ieee64_zero)), // zero out a different XMM register; the shuffle mask for moving the lowest byte to all other byte lanes is 0x0 def!(c = bitcast_f64_to_any8x16(b)), // no instruction emitted; informs the SSA that the 0 in b can be used as a vector of this type def!(y = x86_pshufb(a, c)), // PSHUFB takes two XMM operands, one of which is a shuffle mask (i.e. b) @@ -380,6 +382,7 @@ pub(crate) fn define(shared: &mut SharedDefinitions, x86_instructions: &Instruct ); } + narrow.custom_legalize(shuffle, "convert_shuffle"); narrow.custom_legalize(extractlane, "convert_extractlane"); narrow.custom_legalize(insertlane, "convert_insertlane"); diff --git a/third_party/rust/cranelift-codegen-meta/src/isa/x86/mod.rs b/third_party/rust/cranelift-codegen-meta/src/isa/x86/mod.rs index 6ced50939654a7dbe2579af41e6727052dc0a10a..e18c54ad640279b90d82e0655efc5d14c24d9aef 100644 --- a/third_party/rust/cranelift-codegen-meta/src/isa/x86/mod.rs +++ b/third_party/rust/cranelift-codegen-meta/src/isa/x86/mod.rs @@ -9,6 +9,7 @@ use crate::shared::Definitions as SharedDefinitions; mod encodings; mod instructions; mod legalize; +mod opcodes; mod recipes; mod registers; mod settings; diff --git a/third_party/rust/cranelift-codegen-meta/src/isa/x86/opcodes.rs b/third_party/rust/cranelift-codegen-meta/src/isa/x86/opcodes.rs new file mode 100644 index 0000000000000000000000000000000000000000..12b60e532b39732cebf17f5e09808406e13a03b1 --- /dev/null +++ b/third_party/rust/cranelift-codegen-meta/src/isa/x86/opcodes.rs @@ -0,0 +1,377 @@ +//! Static, named definitions of instruction opcodes. + +/// Empty opcode for use as a default. +pub static EMPTY: [u8; 0] = []; + +/// Add with carry flag r{16,32,64} to r/m of the same size. +pub static ADC: [u8; 1] = [0x11]; + +/// Add r{16,32,64} to r/m of the same size. +pub static ADD: [u8; 1] = [0x01]; + +/// Add imm{16,32} to r/m{16,32,64}, possibly sign-extended. +pub static ADD_IMM: [u8; 1] = [0x81]; + +/// Add sign-extended imm8 to r/m{16,32,64}. +pub static ADD_IMM8_SIGN_EXTEND: [u8; 1] = [0x83]; + +/// Add the low double-precision floating-point value from xmm2/mem to xmm1 +/// and store the result in xmm1. +pub static ADDSD: [u8; 3] = [0xf2, 0x0f, 0x58]; + +/// Add the low single-precision floating-point value from xmm2/mem to xmm1 +/// and store the result in xmm1. +pub static ADDSS: [u8; 3] = [0xf3, 0x0f, 0x58]; + +/// r/m{16,32,64} AND register of the same size (Intel docs have a typo). +pub static AND: [u8; 1] = [0x21]; + +/// imm{16,32} AND r/m{16,32,64}, possibly sign-extended. +pub static AND_IMM: [u8; 1] = [0x81]; + +/// r/m{16,32,64} AND sign-extended imm8. +pub static AND_IMM8_SIGN_EXTEND: [u8; 1] = [0x83]; + +/// Return the bitwise logical AND NOT of packed single-precision floating-point +/// values in xmm1 and xmm2/mem. +pub static ANDNPS: [u8; 2] = [0x0f, 0x55]; + +/// Return the bitwise logical AND of packed single-precision floating-point values +/// in xmm1 and xmm2/mem. +pub static ANDPS: [u8; 2] = [0x0f, 0x54]; + +/// Bit scan forward (stores index of first encountered 1 from the front). +pub static BIT_SCAN_FORWARD: [u8; 2] = [0x0f, 0xbc]; + +/// Bit scan reverse (stores index of first encountered 1 from the back). +pub static BIT_SCAN_REVERSE: [u8; 2] = [0x0f, 0xbd]; + +/// Call near, relative, displacement relative to next instruction (sign-extended). +pub static CALL_RELATIVE: [u8; 1] = [0xe8]; + +/// Move r/m{16,32,64} if overflow (OF=1). +pub static CMOV_OVERFLOW: [u8; 2] = [0x0f, 0x40]; + +/// Compare imm{16,32} with r/m{16,32,64} (sign-extended if 64). +pub static CMP_IMM: [u8; 1] = [0x81]; + +/// Compare imm8 with r/m{16,32,64}. +pub static CMP_IMM8: [u8; 1] = [0x83]; + +/// Compare r{16,32,64} with r/m of the same size. +pub static CMP_REG: [u8; 1] = [0x39]; + +/// Convert scalar double-precision floating-point value to scalar single-precision +/// floating-point value. +pub static CVTSD2SS: [u8; 3] = [0xf2, 0x0f, 0x5a]; + +/// Convert doubleword integer to scalar double-precision floating-point value. +pub static CVTSI2SD: [u8; 3] = [0xf2, 0x0f, 0x2a]; + +/// Convert doubleword integer to scalar single-precision floating-point value. +pub static CVTSI2SS: [u8; 3] = [0xf3, 0x0f, 0x2a]; + +/// Convert scalar single-precision floating-point value to scalar double-precision +/// float-point value. +pub static CVTSS2SD: [u8; 3] = [0xf3, 0x0f, 0x5a]; + +/// Convert with truncation scalar double-precision floating-point value to signed +/// integer. +pub static CVTTSD2SI: [u8; 3] = [0xf2, 0x0f, 0x2c]; + +/// Convert with truncation scalar single-precision floating-point value to integer. +pub static CVTTSS2SI: [u8; 3] = [0xf3, 0x0f, 0x2c]; + +/// Unsigned divide for {16,32,64}-bit. +pub static DIV: [u8; 1] = [0xf7]; + +/// Divide low double-precision floating-point value in xmm1 by low double-precision +/// floating-point value in xmm2/m64. +pub static DIVSD: [u8; 3] = [0xf2, 0x0f, 0x5e]; + +/// Divide low single-precision floating-point value in xmm1 by low single-precision +/// floating-point value in xmm2/m32. +pub static DIVSS: [u8; 3] = [0xf3, 0x0f, 0x5e]; + +/// Signed divide for {16,32,64}-bit. +pub static IDIV: [u8; 1] = [0xf7]; + +/// Signed multiply for {16,32,64}-bit, generic registers. +pub static IMUL: [u8; 2] = [0x0f, 0xaf]; + +/// Signed multiply for {16,32,64}-bit, storing into RDX:RAX. +pub static IMUL_RDX_RAX: [u8; 1] = [0xf7]; + +/// Insert scalar single-precision floating-point value. +pub static INSERTPS: [u8; 4] = [0x66, 0x0f, 0x3a, 0x21]; + +/// Either: +/// 1. Jump near, absolute indirect, RIP = 64-bit offset from register or memory. +/// 2. Jump far, absolute indirect, address given in m16:64. +pub static JUMP_ABSOLUTE: [u8; 1] = [0xff]; + +/// Jump near, relative, RIP = RIP + 32-bit displacement sign extended to 64 bits. +pub static JUMP_NEAR_RELATIVE: [u8; 1] = [0xe9]; + +/// Jump near (rel32) if overflow (OF=1). +pub static JUMP_NEAR_IF_OVERFLOW: [u8; 2] = [0x0f, 0x80]; + +/// Jump short, relative, RIP = RIP + 8-bit displacement sign extended to 64 bits. +pub static JUMP_SHORT: [u8; 1] = [0xeb]; + +/// Jump short (rel8) if equal (ZF=1). +pub static JUMP_SHORT_IF_EQUAL: [u8; 1] = [0x74]; + +/// Jump short (rel8) if not equal (ZF=0). +pub static JUMP_SHORT_IF_NOT_EQUAL: [u8; 1] = [0x75]; + +/// Jump short (rel8) if overflow (OF=1). +pub static JUMP_SHORT_IF_OVERFLOW: [u8; 1] = [0x70]; + +/// Store effective address for m in register r{16,32,64}. +pub static LEA: [u8; 1] = [0x8d]; + +/// Count the number of leading zero bits. +pub static LZCNT: [u8; 3] = [0xf3, 0x0f, 0xbd]; + +/// Return the maximum scalar double-precision floating-point value between +/// xmm2/m64 and xmm1. +pub static MAXSD: [u8; 3] = [0xf2, 0x0f, 0x5f]; + +/// Return the maximum scalar single-precision floating-point value between +/// xmm2/m32 and xmm1. +pub static MAXSS: [u8; 3] = [0xf3, 0x0f, 0x5f]; + +/// Return the minimum scalar double-precision floating-point value between +/// xmm2/m64 and xmm1. +pub static MINSD: [u8; 3] = [0xf2, 0x0f, 0x5d]; + +/// Return the minimum scalar single-precision floating-point value between +/// xmm2/m32 and xmm1. +pub static MINSS: [u8; 3] = [0xf3, 0x0f, 0x5d]; + +/// Move r8 to r/m8. +pub static MOV_BYTE_STORE: [u8; 1] = [0x88]; + +/// Move imm{16,32,64} to same-sized register. +pub static MOV_IMM: [u8; 1] = [0xb8]; + +/// Move imm{16,32} to r{16,32,64}, sign-extended if 64-bit target. +pub static MOV_IMM_SIGNEXTEND: [u8; 1] = [0xc7]; + +/// Move {r/m16, r/m32, r/m64} to same-sized register. +pub static MOV_LOAD: [u8; 1] = [0x8b]; + +/// Move r16 to r/m16. +pub static MOV_STORE_16: [u8; 2] = [0x66, 0x89]; + +/// Move {r16, r32, r64} to same-sized register or memory. +pub static MOV_STORE: [u8; 1] = [0x89]; + +/// Move aligned packed single-precision floating-point values from x/m to xmm (SSE). +pub static MOVAPS_LOAD: [u8; 2] = [0x0f, 0x28]; + +/// Move doubleword from r/m32 to xmm (SSE2). Quadword with REX prefix. +pub static MOVD_LOAD_XMM: [u8; 3] = [0x66, 0x0f, 0x6e]; + +/// Move doubleword from xmm to r/m32 (SSE2). Quadword with REX prefix. +pub static MOVD_STORE_XMM: [u8; 3] = [0x66, 0x0f, 0x7e]; + +/// Move packed single-precision floating-point values low to high (SSE). +pub static MOVLHPS: [u8; 2] = [0x0f, 0x16]; + +/// Move scalar double-precision floating-point value (from reg/mem to reg). +pub static MOVSD_LOAD: [u8; 3] = [0xf2, 0x0f, 0x10]; + +/// Move scalar double-precision floating-point value (from reg to reg/mem). +pub static MOVSD_STORE: [u8; 3] = [0xf2, 0x0f, 0x11]; + +/// Move scalar single-precision floating-point value (from reg to reg/mem). +pub static MOVSS_STORE: [u8; 3] = [0xf3, 0x0f, 0x11]; + +/// Move scalar single-precision floating-point-value (from reg/mem to reg). +pub static MOVSS_LOAD: [u8; 3] = [0xf3, 0x0f, 0x10]; + +/// Move byte to register with sign-extension. +pub static MOVSX_BYTE: [u8; 2] = [0x0f, 0xbe]; + +/// Move word to register with sign-extension. +pub static MOVSX_WORD: [u8; 2] = [0x0f, 0xbf]; + +/// Move doubleword to register with sign-extension. +pub static MOVSXD: [u8; 1] = [0x63]; + +/// Move unaligned packed single-precision floating-point from x/m to xmm (SSE). +pub static MOVUPS_LOAD: [u8; 2] = [0x0f, 0x10]; + +/// Move unaligned packed single-precision floating-point value from xmm to x/m (SSE). +pub static MOVUPS_STORE: [u8; 2] = [0x0f, 0x11]; + +/// Move byte to register with zero-extension. +pub static MOVZX_BYTE: [u8; 2] = [0x0f, 0xb6]; + +/// Move word to register with zero-extension. +pub static MOVZX_WORD: [u8; 2] = [0x0f, 0xb7]; + +/// Unsigned multiply for {16,32,64}-bit. +pub static MUL: [u8; 1] = [0xf7]; + +/// Multiply the low double-precision floating-point value in xmm2/m64 by the +/// low double-precision floating-point value in xmm1. +pub static MULSD: [u8; 3] = [0xf2, 0x0f, 0x59]; + +/// Multiply the low single-precision floating-point value in xmm2/m32 by the +/// low single-precision floating-point value in xmm1. +pub static MULSS: [u8; 3] = [0xf3, 0x0f, 0x59]; + +/// Reverse each bit of r/m{16,32,64}. +pub static NOT: [u8; 1] = [0xf7]; + +/// r{16,32,64} OR register of same size. +pub static OR: [u8; 1] = [0x09]; + +/// imm{16,32} OR r/m{16,32,64}, possibly sign-extended. +pub static OR_IMM: [u8; 1] = [0x81]; + +/// r/m{16,32,64} OR sign-extended imm8. +pub static OR_IMM8_SIGN_EXTEND: [u8; 1] = [0x83]; + +/// Return the bitwise logical OR of packed single-precision values in xmm and x/m (SSE). +pub static ORPS: [u8; 2] = [0x0f, 0x56]; + +/// Add packed byte integers from xmm2/m128 and xmm1 (SSE2). +pub static PADDB: [u8; 3] = [0x66, 0x0f, 0xfc]; + +/// Add packed doubleword integers from xmm2/m128 and xmm1 (SSE2). +pub static PADDD: [u8; 3] = [0x66, 0x0f, 0xfe]; + +/// Add packed quadword integers from xmm2/m128 and xmm1 (SSE2). +pub static PADDQ: [u8; 3] = [0x66, 0x0f, 0xd4]; + +/// Add packed word integers from xmm2/m128 and xmm1 (SSE2). +pub static PADDW: [u8; 3] = [0x66, 0x0f, 0xfd]; + +/// Compare packed data for equal (SSE2). +pub static PCMPEQB: [u8; 3] = [0x66, 0x0f, 0x74]; + +/// Compare packed data for equal (SSE2). +pub static PCMPEQD: [u8; 3] = [0x66, 0x0f, 0x76]; + +/// Compare packed data for equal (SSE4.1). +pub static PCMPEQQ: [u8; 4] = [0x66, 0x0f, 0x38, 0x29]; + +/// Compare packed data for equal (SSE2). +pub static PCMPEQW: [u8; 3] = [0x66, 0x0f, 0x75]; + +/// Extract doubleword or quadword, depending on REX.W (SSE4.1). +pub static PEXTR: [u8; 4] = [0x66, 0x0f, 0x3a, 0x16]; + +/// Extract byte (SSE4.1). +pub static PEXTRB: [u8; 4] = [0x66, 0x0f, 0x3a, 0x14]; + +/// Extract word (SSE2). There is a 4-byte SSE4.1 variant that can also move to m/16. +pub static PEXTRW_SSE2: [u8; 3] = [0x66, 0x0f, 0xc5]; + +/// Insert doubleword or quadword, depending on REX.W (SSE4.1). +pub static PINSR: [u8; 4] = [0x66, 0x0f, 0x3a, 0x22]; + +/// Insert byte (SSE4.1). +pub static PINSRB: [u8; 4] = [0x66, 0x0f, 0x3a, 0x20]; + +/// Insert word (SSE2). +pub static PINSRW: [u8; 3] = [0x66, 0x0f, 0xc4]; + +/// Pop top of stack into r{16,32,64}; increment stack pointer. +pub static POP_REG: [u8; 1] = [0x58]; + +/// Returns the count of number of bits set to 1. +pub static POPCNT: [u8; 3] = [0xf3, 0x0f, 0xb8]; + +/// Shuffle bytes in xmm1 according to contents of xmm2/m128 (SSE3). +pub static PSHUFB: [u8; 4] = [0x66, 0x0f, 0x38, 0x00]; + +/// Shuffle the doublewords in xmm2/m128 based on the encoding in imm8 and +/// store the result in xmm1 (SSE2). +pub static PSHUFD: [u8; 3] = [0x66, 0x0f, 0x70]; + +/// Push r{16,32,64}. +pub static PUSH_REG: [u8; 1] = [0x50]; + +/// Logical exclusive OR (SSE2). +pub static PXOR: [u8; 3] = [0x66, 0x0f, 0xef]; + +/// Near return to calling procedure. +pub static RET_NEAR: [u8; 1] = [0xc3]; + +/// General rotation opcode. Kind of rotation depends on encoding. +pub static ROTATE_CL: [u8; 1] = [0xd3]; + +/// General rotation opcode. Kind of rotation depends on encoding. +pub static ROTATE_IMM8: [u8; 1] = [0xc1]; + +/// Round scalar doubl-precision floating-point values. +pub static ROUNDSD: [u8; 4] = [0x66, 0x0f, 0x3a, 0x0b]; + +/// Round scalar single-precision floating-point values. +pub static ROUNDSS: [u8; 4] = [0x66, 0x0f, 0x3a, 0x0a]; + +/// Subtract with borrow r{16,32,64} from r/m of the same size. +pub static SBB: [u8; 1] = [0x19]; + +/// Set byte if overflow (OF=1). +pub static SET_BYTE_IF_OVERFLOW: [u8; 2] = [0x0f, 0x90]; + +/// Compute square root of scalar double-precision floating-point value. +pub static SQRTSD: [u8; 3] = [0xf2, 0x0f, 0x51]; + +/// Compute square root of scalar single-precision value. +pub static SQRTSS: [u8; 3] = [0xf3, 0x0f, 0x51]; + +/// Subtract r{16,32,64} from r/m of same size. +pub static SUB: [u8; 1] = [0x29]; + +/// Subtract the low double-precision floating-point value in xmm2/m64 from xmm1 +/// and store the result in xmm1. +pub static SUBSD: [u8; 3] = [0xf2, 0x0f, 0x5c]; + +/// Subtract the low single-precision floating-point value in xmm2/m32 from xmm1 +/// and store the result in xmm1. +pub static SUBSS: [u8; 3] = [0xf3, 0x0f, 0x5c]; + +/// AND r8 with r/m8; set SF, ZF, PF according to result. +pub static TEST_BYTE_REG: [u8; 1] = [0x84]; + +/// AND {r16, r32, r64} with r/m of the same size; set SF, ZF, PF according to result. +pub static TEST_REG: [u8; 1] = [0x85]; + +/// Count the number of trailing zero bits. +pub static TZCNT: [u8; 3] = [0xf3, 0x0f, 0xbc]; + +/// Compare low double-precision floating-point values in xmm1 and xmm2/mem64 +/// and set the EFLAGS flags accordingly. +pub static UCOMISD: [u8; 3] = [0x66, 0x0f, 0x2e]; + +/// Compare low single-precision floating-point values in xmm1 and xmm2/mem32 +/// and set the EFLAGS flags accordingly. +pub static UCOMISS: [u8; 2] = [0x0f, 0x2e]; + +/// Raise invalid opcode instruction. +pub static UNDEFINED2: [u8; 2] = [0x0f, 0x0b]; + +/// imm{16,32} XOR r/m{16,32,64}, possibly sign-extended. +pub static XOR_IMM: [u8; 1] = [0x81]; + +/// r/m{16,32,64} XOR sign-extended imm8. +pub static XOR_IMM8_SIGN_EXTEND: [u8; 1] = [0x83]; + +/// r/m{16,32,64} XOR register of the same size. +pub static XOR: [u8; 1] = [0x31]; + +/// r/m8 XOR r8. +pub static XORB: [u8; 1] = [0x30]; + +/// Bitwise logical XOR of packed double-precision floating-point values. +pub static XORPD: [u8; 3] = [0x66, 0x0f, 0x57]; + +/// Bitwise logical XOR of packed single-precision floating-point values. +pub static XORPS: [u8; 2] = [0x0f, 0x57]; diff --git a/third_party/rust/cranelift-codegen-meta/src/isa/x86/recipes.rs b/third_party/rust/cranelift-codegen-meta/src/isa/x86/recipes.rs index 11a9972d98079a5554ab81c5c09d070b485d038d..ce0999c04ccd0645ad0e30eba4d79e11dbd1445b 100644 --- a/third_party/rust/cranelift-codegen-meta/src/isa/x86/recipes.rs +++ b/third_party/rust/cranelift-codegen-meta/src/isa/x86/recipes.rs @@ -10,10 +10,12 @@ use crate::cdsl::regs::IsaRegs; use crate::cdsl::settings::SettingGroup; use crate::shared::Definitions as SharedDefinitions; +use crate::isa::x86::opcodes; + /// Helper data structure to create recipes and template recipes. /// It contains all the recipes and recipe templates that might be used in the encodings crate of /// this same directory. -pub struct RecipeGroup<'builder> { +pub(crate) struct RecipeGroup<'builder> { /// Memoized format pointer, to pass it to builders later. formats: &'builder FormatRegistry, @@ -186,7 +188,7 @@ pub struct Template<'builder> { /// Value of the RRR bits (between 0 and 0b111). rrr_bits: u16, /// Opcode bytes. - op_bytes: Vec<u8>, + op_bytes: &'static [u8], } impl<'builder> Template<'builder> { @@ -204,7 +206,7 @@ impl<'builder> Template<'builder> { rex: false, w_bit: 0, rrr_bits: 0, - op_bytes: Vec::new(), + op_bytes: &opcodes::EMPTY, } } @@ -226,7 +228,7 @@ impl<'builder> Template<'builder> { } // Copy setters. - pub fn opcodes(&self, op_bytes: Vec<u8>) -> Self { + pub fn opcodes(&self, op_bytes: &'static [u8]) -> Self { assert!(!op_bytes.is_empty()); let mut copy = self.clone(); copy.op_bytes = op_bytes; @@ -396,11 +398,11 @@ pub(crate) fn define<'shared>( let f_trap = formats.by_name("Trap"); let f_unary = formats.by_name("Unary"); let f_unary_bool = formats.by_name("UnaryBool"); + let f_unary_const = formats.by_name("UnaryConst"); let f_unary_global_value = formats.by_name("UnaryGlobalValue"); let f_unary_ieee32 = formats.by_name("UnaryIeee32"); let f_unary_ieee64 = formats.by_name("UnaryIeee64"); let f_unary_imm = formats.by_name("UnaryImm"); - let f_unary_imm128 = formats.by_name("UnaryImm128"); // Predicates shorthands. let use_sse41 = settings.predicate_by_name("use_sse41"); @@ -2437,14 +2439,26 @@ pub(crate) fn define<'shared>( ); recipes.add_template_recipe( - EncodingRecipeBuilder::new("vconst", f_unary_imm128, 5) + EncodingRecipeBuilder::new("vconst", f_unary_const, 5) .operands_out(vec![fpr]) .clobbers_flags(false) .emit( r#" {{PUT_OP}}(bits, rex2(0, out_reg0), sink); modrm_riprel(out_reg0, sink); - const_disp4(imm, func, sink); + const_disp4(constant_handle, func, sink); + "#, + ), + ); + + recipes.add_template_recipe( + EncodingRecipeBuilder::new("vconst_optimized", f_unary_const, 1) + .operands_out(vec![fpr]) + .clobbers_flags(false) + .emit( + r#" + {{PUT_OP}}(bits, rex2(out_reg0, out_reg0), sink); + modrm_rr(out_reg0, out_reg0, sink); "#, ), ); @@ -2908,26 +2922,27 @@ pub(crate) fn define<'shared>( {{PUT_OP}}(bits, rex2(in_reg0, in_reg1), sink); modrm_rr(in_reg0, in_reg1, sink); // `setCC` instruction, no REX. - use crate::ir::condcodes::IntCC::*; - let setcc = match cond { - Equal => 0x94, - NotEqual => 0x95, - SignedLessThan => 0x9c, - SignedGreaterThanOrEqual => 0x9d, - SignedGreaterThan => 0x9f, - SignedLessThanOrEqual => 0x9e, - UnsignedLessThan => 0x92, - UnsignedGreaterThanOrEqual => 0x93, - UnsignedGreaterThan => 0x97, - UnsignedLessThanOrEqual => 0x96, - }; + let setcc = 0x90 | icc2opc(cond); sink.put1(0x0f); - sink.put1(setcc); + sink.put1(setcc as u8); modrm_rr(out_reg0, 0, sink); "#, ), ); + recipes.add_template_recipe( + EncodingRecipeBuilder::new("icscc_fpr", f_int_compare, 1) + .operands_in(vec![fpr, fpr]) + .operands_out(vec![0]) + .emit( + r#" + // Comparison instruction. + {{PUT_OP}}(bits, rex2(in_reg1, in_reg0), sink); + modrm_rr(in_reg1, in_reg0, sink); + "#, + ), + ); + { let format = formats.get(f_int_compare_imm); @@ -2946,21 +2961,9 @@ pub(crate) fn define<'shared>( let imm: i64 = imm.into(); sink.put1(imm as u8); // `setCC` instruction, no REX. - use crate::ir::condcodes::IntCC::*; - let setcc = match cond { - Equal => 0x94, - NotEqual => 0x95, - SignedLessThan => 0x9c, - SignedGreaterThanOrEqual => 0x9d, - SignedGreaterThan => 0x9f, - SignedLessThanOrEqual => 0x9e, - UnsignedLessThan => 0x92, - UnsignedGreaterThanOrEqual => 0x93, - UnsignedGreaterThan => 0x97, - UnsignedLessThanOrEqual => 0x96, - }; + let setcc = 0x90 | icc2opc(cond); sink.put1(0x0f); - sink.put1(setcc); + sink.put1(setcc as u8); modrm_rr(out_reg0, 0, sink); "#, ), @@ -2981,21 +2984,9 @@ pub(crate) fn define<'shared>( let imm: i64 = imm.into(); sink.put4(imm as u32); // `setCC` instruction, no REX. - use crate::ir::condcodes::IntCC::*; - let setcc = match cond { - Equal => 0x94, - NotEqual => 0x95, - SignedLessThan => 0x9c, - SignedGreaterThanOrEqual => 0x9d, - SignedGreaterThan => 0x9f, - SignedLessThanOrEqual => 0x9e, - UnsignedLessThan => 0x92, - UnsignedGreaterThanOrEqual => 0x93, - UnsignedGreaterThan => 0x97, - UnsignedLessThanOrEqual => 0x96, - }; + let setcc = 0x90 | icc2opc(cond); sink.put1(0x0f); - sink.put1(setcc); + sink.put1(setcc as u8); modrm_rr(out_reg0, 0, sink); "#, ), diff --git a/third_party/rust/cranelift-codegen-meta/src/shared/formats.rs b/third_party/rust/cranelift-codegen-meta/src/shared/formats.rs index 5309afc1b0b3b319fe6b31e7ba2e6359ee6ae481..73aaa42634180b4c3b5de293f955c75efed43337 100644 --- a/third_party/rust/cranelift-codegen-meta/src/shared/formats.rs +++ b/third_party/rust/cranelift-codegen-meta/src/shared/formats.rs @@ -6,10 +6,10 @@ pub(crate) fn define(imm: &Immediates, entities: &EntityRefs) -> FormatRegistry registry.insert(Builder::new("Unary").value()); registry.insert(Builder::new("UnaryImm").imm(&imm.imm64)); - registry.insert(Builder::new("UnaryImm128").imm(&imm.uimm128)); registry.insert(Builder::new("UnaryIeee32").imm(&imm.ieee32)); registry.insert(Builder::new("UnaryIeee64").imm(&imm.ieee64)); registry.insert(Builder::new("UnaryBool").imm(&imm.boolean)); + registry.insert(Builder::new("UnaryConst").imm(&imm.pool_constant)); registry.insert(Builder::new("UnaryGlobalValue").imm(&entities.global_value)); registry.insert(Builder::new("Binary").value().value()); @@ -43,6 +43,12 @@ pub(crate) fn define(imm: &Immediates, entities: &EntityRefs) -> FormatRegistry .value() .imm_with_name("lane", &imm.uimm8), ); + registry.insert( + Builder::new("Shuffle") + .value() + .value() + .imm_with_name("mask", &imm.uimm128), + ); registry.insert(Builder::new("IntCompare").imm(&imm.intcc).value().value()); registry.insert( @@ -59,7 +65,7 @@ pub(crate) fn define(imm: &Immediates, entities: &EntityRefs) -> FormatRegistry .value() .value(), ); - registry.insert(Builder::new("FloatCond").imm(&imm.floatcc).value());; + registry.insert(Builder::new("FloatCond").imm(&imm.floatcc).value()); registry.insert( Builder::new("IntSelect") diff --git a/third_party/rust/cranelift-codegen-meta/src/shared/immediates.rs b/third_party/rust/cranelift-codegen-meta/src/shared/immediates.rs index 30c1a73970f4d82b4fd66cef01a2698446f7b486..f9c114a6a03dff3d4e062c60f940daaea15a2a2f 100644 --- a/third_party/rust/cranelift-codegen-meta/src/shared/immediates.rs +++ b/third_party/rust/cranelift-codegen-meta/src/shared/immediates.rs @@ -23,6 +23,12 @@ pub(crate) struct Immediates { /// const. pub uimm128: OperandKind, + /// A constant stored in the constant pool. + /// + /// This operand is used to pass constants to instructions like vconst while storing the + /// actual bytes in the constant pool. + pub pool_constant: OperandKind, + /// A 32-bit immediate signed offset. /// /// This is used to represent an immediate address offset in load/store instructions. @@ -84,6 +90,12 @@ impl Immediates { uimm128: Builder::new_imm("uimm128") .doc("A 128-bit immediate unsigned integer.") + .rust_type("ir::Immediate") + .build(), + + pool_constant: Builder::new_imm("poolConstant") + .doc("A constant stored in the constant pool.") + .default_member("constant_handle") .rust_type("ir::Constant") .build(), @@ -117,6 +129,8 @@ impl Immediates { intcc_values.insert("ugt", "UnsignedGreaterThan"); intcc_values.insert("ule", "UnsignedLessThanOrEqual"); intcc_values.insert("ult", "UnsignedLessThan"); + intcc_values.insert("of", "Overflow"); + intcc_values.insert("nof", "NotOverflow"); Builder::new_enum("intcc", intcc_values) .doc("An integer comparison condition code.") .default_member("cond") diff --git a/third_party/rust/cranelift-codegen-meta/src/shared/instructions.rs b/third_party/rust/cranelift-codegen-meta/src/shared/instructions.rs index bae1327b603359cb0bf202a4b4ccd28b439d9a9c..679ee1a2c12a1ddef2652c4a1a8985854569220d 100644 --- a/third_party/rust/cranelift-codegen-meta/src/shared/instructions.rs +++ b/third_party/rust/cranelift-codegen-meta/src/shared/instructions.rs @@ -1090,7 +1090,7 @@ pub(crate) fn define( let N = &operand_doc( "N", - &imm.uimm128, + &imm.pool_constant, "The 16 immediate bytes of a 128-bit vector", ); let a = &operand_doc("a", TxN, "A constant vector value"); @@ -1108,6 +1108,41 @@ pub(crate) fn define( .operands_out(vec![a]), ); + let mask = &operand_doc( + "mask", + &imm.uimm128, + "The 16 immediate bytes used for selecting the elements to shuffle", + ); + let Tx16 = &TypeVar::new( + "Tx16", + "A SIMD vector with exactly 16 lanes of 8-bit values; eventually this may support other \ + lane counts and widths", + TypeSetBuilder::new() + .ints(8..8) + .bools(8..8) + .simd_lanes(16..16) + .includes_scalars(false) + .build(), + ); + let a = &operand_doc("a", Tx16, "A vector value"); + let b = &operand_doc("b", Tx16, "A vector value"); + + ig.push( + Inst::new( + "shuffle", + r#" + SIMD vector shuffle. + + Shuffle two vectors using the given immediate bytes. For each of the 16 bytes of the + immediate, a value i of 0-15 selects the i-th element of the first vector and a value i of + 16-31 selects the (i-16)th element of the second vector. Immediate values outside of the + 0-31 range place a 0 in the resulting vector lane. + "#, + ) + .operands_in(vec![a, b, mask]) + .operands_out(vec![a]), + ); + let a = &operand_doc("a", Ref, "A constant reference null value"); ig.push( @@ -1551,6 +1586,8 @@ pub(crate) fn define( let x = &operand("x", Int); let y = &operand("y", Int); + // TODO(ryzokuken): Add documentation for unsigned overflow. + // TODO(ryzokuken): Add documentation for signed overflow. ig.push( Inst::new( "icmp", diff --git a/third_party/rust/cranelift-codegen-meta/src/shared/legalize.rs b/third_party/rust/cranelift-codegen-meta/src/shared/legalize.rs index f9cec3557e279312e52029022bf481fda347358d..fef4c1e1ecb29ed4df9fe3dfd47c1cde97bd55d0 100644 --- a/third_party/rust/cranelift-codegen-meta/src/shared/legalize.rs +++ b/third_party/rust/cranelift-codegen-meta/src/shared/legalize.rs @@ -64,7 +64,6 @@ pub(crate) fn define(insts: &InstructionGroup, imm: &Immediates) -> TransformGro let f64const = insts.by_name("f64const"); let fcopysign = insts.by_name("fcopysign"); let fcvt_from_sint = insts.by_name("fcvt_from_sint"); - let fcvt_from_uint = insts.by_name("fcvt_from_uint"); let fneg = insts.by_name("fneg"); let iadd = insts.by_name("iadd"); let iadd_cin = insts.by_name("iadd_cin"); @@ -94,6 +93,7 @@ pub(crate) fn define(insts: &InstructionGroup, imm: &Immediates) -> TransformGro let isub_borrow = insts.by_name("isub_borrow"); let isub_ifbin = insts.by_name("isub_ifbin"); let isub_ifbout = insts.by_name("isub_ifbout"); + let jump = insts.by_name("jump"); let load = insts.by_name("load"); let popcnt = insts.by_name("popcnt"); let rotl = insts.by_name("rotl"); @@ -190,6 +190,8 @@ pub(crate) fn define(insts: &InstructionGroup, imm: &Immediates) -> TransformGro let ah = var("ah"); let cc = var("cc"); let ebb = var("ebb"); + let ebb1 = var("ebb1"); + let ebb2 = var("ebb2"); let ptr = var("ptr"); let flags = var("flags"); let offset = var("off"); @@ -260,11 +262,13 @@ pub(crate) fn define(insts: &InstructionGroup, imm: &Immediates) -> TransformGro ); narrow.legalize( - def!(brnz.I128(x, ebb, vararg)), + def!(brnz.I128(x, ebb1, vararg)), vec![ def!((xl, xh) = isplit(x)), - def!(brnz(xl, ebb, vararg)), - def!(brnz(xh, ebb, vararg)), + def!(brnz(xl, ebb1, vararg)), + def!(jump(ebb2, Literal::empty_vararg())), + ebb!(ebb2), + def!(brnz(xh, ebb1, vararg)), ], ); @@ -542,21 +546,12 @@ pub(crate) fn define(insts: &InstructionGroup, imm: &Immediates) -> TransformGro ], ); - // Expansions for fcvt_from_{u,s}int for smaller integer types. - // These use expand and not widen because the controlling type variable for - // these instructions are f32/f64, which are legalized as part of the expand + // Expansion for fcvt_from_sint for smaller integer types. + // This uses expand and not widen because the controlling type variable for + // this instruction is f32/f64, which is legalized as part of the expand // group. for &dest_ty in &[F32, F64] { for &src_ty in &[I8, I16] { - let bound_inst = fcvt_from_uint.bind(dest_ty).bind(src_ty); - expand.legalize( - def!(a = bound_inst(b)), - vec![ - def!(x = uextend.I32(b)), - def!(a = fcvt_from_uint.dest_ty(x)), - ], - ); - let bound_inst = fcvt_from_sint.bind(dest_ty).bind(src_ty); expand.legalize( def!(a = bound_inst(b)), diff --git a/third_party/rust/cranelift-codegen-meta/src/shared/mod.rs b/third_party/rust/cranelift-codegen-meta/src/shared/mod.rs index 12921da5ef8a6bc53c8b4552ad5dc7081aa86224..73cdb4254d8c1a579f4a051569b3159bbe64e536 100644 --- a/third_party/rust/cranelift-codegen-meta/src/shared/mod.rs +++ b/third_party/rust/cranelift-codegen-meta/src/shared/mod.rs @@ -29,7 +29,7 @@ pub(crate) fn define() -> Definitions { let mut all_instructions = AllInstructions::new(); let immediates = Immediates::new(); - let entities = EntityRefs::new();; + let entities = EntityRefs::new(); let format_registry = formats::define(&immediates, &entities); let instructions = instructions::define( &mut all_instructions, diff --git a/third_party/rust/cranelift-codegen-meta/src/shared/settings.rs b/third_party/rust/cranelift-codegen-meta/src/shared/settings.rs index 63c5d3c01aeb575199d3cbfc80f052d4afc64e91..43fe357ab7030da3bc6bc03b745f1ed5a8f5e474 100644 --- a/third_party/rust/cranelift-codegen-meta/src/shared/settings.rs +++ b/third_party/rust/cranelift-codegen-meta/src/shared/settings.rs @@ -8,11 +8,12 @@ pub fn define() -> SettingGroup { r#" Optimization level: - - default: Very profitable optimizations enabled, none slow. - - best: Enable all optimizations - - fastest: Optimize for compile time by disabling most optimizations. + - none: Minimise compile time by disabling most optimizations. + - speed: Generate the fastest possible code + - speed_and_size: like "speed", but also perform transformations + aimed at reducing code size. "#, - vec!["default", "best", "fastest"], + vec!["none", "speed", "speed_and_size"], ); settings.add_bool( diff --git a/third_party/rust/cranelift-codegen-shared/.cargo-checksum.json b/third_party/rust/cranelift-codegen-shared/.cargo-checksum.json new file mode 100644 index 0000000000000000000000000000000000000000..c9e84bff2fd081819ed5ba145a7248676b48a6b2 --- /dev/null +++ b/third_party/rust/cranelift-codegen-shared/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"Cargo.toml":"17643920d895c99deb5b2849b2a9b55ff5cc61877f9c297914b8ba1987bb0731","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"a410bc2f5dcbde499c0cd299c2620bc8111e3c5b3fccdd9e2d85caf3c24fdab3","src/condcodes.rs":"838c9becb7d42ef0eb98e70505b52783a2e900b6532316708466f2157fa807d9","src/lib.rs":"f42e7d8606285e8e2b8994486bdad7e0796abc4778efdf55dbd20e4320a25e62"},"package":null} \ No newline at end of file diff --git a/third_party/rust/cranelift-codegen-shared/Cargo.toml b/third_party/rust/cranelift-codegen-shared/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..d58b92fd50467406c19208a1afd70190639760a4 --- /dev/null +++ b/third_party/rust/cranelift-codegen-shared/Cargo.toml @@ -0,0 +1,11 @@ +[package] +authors = ["The Cranelift Project Developers"] +name = "cranelift-codegen-shared" +version = "0.44.0" +description = "For code shared between cranelift-codegen-meta and cranelift-codegen" +license = "Apache-2.0 WITH LLVM-exception" +repository = "https://github.com/CraneStation/cranelift" +readme = "README.md" +edition = "2018" + +[dependencies] diff --git a/third_party/rust/cranelift-codegen-shared/LICENSE b/third_party/rust/cranelift-codegen-shared/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..f9d81955f4bcb8f96a025e2ecc46f39ec536d465 --- /dev/null +++ b/third_party/rust/cranelift-codegen-shared/LICENSE @@ -0,0 +1,220 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. + + +--- LLVM Exceptions to the Apache 2.0 License ---- + +As an exception, if, as a result of your compiling your source code, portions +of this Software are embedded into an Object form of such source code, you +may redistribute such embedded portions in such Object form without complying +with the conditions of Sections 4(a), 4(b) and 4(d) of the License. + +In addition, if you combine or link compiled forms of this Software with +software that is licensed under the GPLv2 ("Combined Software") and if a +court of competent jurisdiction determines that the patent provision (Section +3), the indemnity provision (Section 9) or other Section of the License +conflicts with the conditions of the GPLv2, you may retroactively and +prospectively choose to deem waived or otherwise exclude such Section(s) of +the License, but only in their entirety and only with respect to the Combined +Software. + diff --git a/third_party/rust/cranelift-codegen-shared/README.md b/third_party/rust/cranelift-codegen-shared/README.md new file mode 100644 index 0000000000000000000000000000000000000000..54f9f5d6d29d614713b5d3a382ca6c759c809145 --- /dev/null +++ b/third_party/rust/cranelift-codegen-shared/README.md @@ -0,0 +1,2 @@ +This crate contains shared definitions for use in both `cranelift-codegen-meta` and `cranelift +-codegen`. diff --git a/third_party/rust/cranelift-codegen/src/ir/condcodes.rs b/third_party/rust/cranelift-codegen-shared/src/condcodes.rs similarity index 95% rename from third_party/rust/cranelift-codegen/src/ir/condcodes.rs rename to third_party/rust/cranelift-codegen-shared/src/condcodes.rs index 743e30954d948606f759700a851f1c0892aeb197..1171eef2f6a7a1c9317e71e37bab47a9ffb60f97 100644 --- a/third_party/rust/cranelift-codegen/src/ir/condcodes.rs +++ b/third_party/rust/cranelift-codegen-shared/src/condcodes.rs @@ -51,6 +51,10 @@ pub enum IntCC { UnsignedGreaterThan, /// Unsigned `<=`. UnsignedLessThanOrEqual, + /// Signed Overflow. + Overflow, + /// Signed No Overflow. + NotOverflow, } impl CondCode for IntCC { @@ -67,6 +71,8 @@ impl CondCode for IntCC { UnsignedGreaterThanOrEqual => UnsignedLessThan, UnsignedGreaterThan => UnsignedLessThanOrEqual, UnsignedLessThanOrEqual => UnsignedGreaterThan, + Overflow => NotOverflow, + NotOverflow => Overflow, } } @@ -83,6 +89,8 @@ impl CondCode for IntCC { UnsignedGreaterThanOrEqual => UnsignedLessThanOrEqual, UnsignedLessThan => UnsignedGreaterThan, UnsignedLessThanOrEqual => UnsignedGreaterThanOrEqual, + Overflow => Overflow, + NotOverflow => NotOverflow, } } } @@ -101,6 +109,8 @@ impl Display for IntCC { UnsignedGreaterThanOrEqual => "uge", UnsignedLessThan => "ult", UnsignedLessThanOrEqual => "ule", + Overflow => "of", + NotOverflow => "nof", }) } } @@ -121,6 +131,8 @@ impl FromStr for IntCC { "ugt" => Ok(UnsignedGreaterThan), "ule" => Ok(UnsignedLessThanOrEqual), "ult" => Ok(UnsignedLessThan), + "of" => Ok(Overflow), + "nof" => Ok(NotOverflow), _ => Err(()), } } @@ -270,7 +282,7 @@ mod tests { use super::*; use std::string::ToString; - static INT_ALL: [IntCC; 10] = [ + static INT_ALL: [IntCC; 12] = [ IntCC::Equal, IntCC::NotEqual, IntCC::SignedLessThan, @@ -281,6 +293,8 @@ mod tests { IntCC::UnsignedGreaterThanOrEqual, IntCC::UnsignedGreaterThan, IntCC::UnsignedLessThanOrEqual, + IntCC::Overflow, + IntCC::NotOverflow, ]; #[test] diff --git a/third_party/rust/cranelift-codegen-shared/src/lib.rs b/third_party/rust/cranelift-codegen-shared/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..87de6e79516fbf412fda6406fd245ad41d846e0e --- /dev/null +++ b/third_party/rust/cranelift-codegen-shared/src/lib.rs @@ -0,0 +1,26 @@ +//! This library contains code that is common to both the `cranelift-codegen` and +//! `cranelift-codegen-meta` libraries. + +#![deny(missing_docs, trivial_numeric_casts, unused_extern_crates)] +#![warn(unused_import_braces)] +#![cfg_attr(feature = "std", deny(unstable_features))] +#![cfg_attr(feature = "clippy", plugin(clippy(conf_file = "../../clippy.toml")))] +#![cfg_attr(feature = "cargo-clippy", allow(clippy::new_without_default))] +#![cfg_attr( + feature = "cargo-clippy", + warn( + clippy::float_arithmetic, + clippy::mut_mut, + clippy::nonminimal_bool, + clippy::option_map_unwrap_or, + clippy::option_map_unwrap_or_else, + clippy::print_stdout, + clippy::unicode_not_nfc, + clippy::use_self + ) +)] + +pub mod condcodes; + +/// Version number of this crate. +pub const VERSION: &str = env!("CARGO_PKG_VERSION"); diff --git a/third_party/rust/cranelift-codegen/.cargo-checksum.json b/third_party/rust/cranelift-codegen/.cargo-checksum.json index 63ff84e15a8c55674844ca15b7fc2ef08d889158..99baf1647ff60bee610ca1b8c0b1a094051c0c12 100644 --- a/third_party/rust/cranelift-codegen/.cargo-checksum.json +++ b/third_party/rust/cranelift-codegen/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"99b4b834ec33e1d1917296497e286dad5819fed0600b5ce288a114133efbe734","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"e5127227a7db4a8aa92fa6613ed71801025790e696bb41b0323fb7f3c6f7495a","build.rs":"8587e8557a046dc858f7662f63f1fa54e57ff92ed87b30fbcdfce6feafda9d60","src/abi.rs":"76ee030cf0780fe63ccbf855b1161f215e3e2991cb9abe71ca9aff25e5f1dbc2","src/binemit/memorysink.rs":"da415b20c563e636bcccaafb43dbdb77d6c48f9c205b16229865abb1afa40964","src/binemit/mod.rs":"90c56d36091646bba7f0ab1b5064d68b8b0c24ece874fcf8c621830b743e9688","src/binemit/relaxation.rs":"7b1082203c688beab4d705e601ad4fde10c5bf1fec414ad1ee6993e4f6b95e01","src/binemit/shrink.rs":"5755efc978f5056a33c0ecb1bd5e08310397f54a67434ecead184fc6ee047133","src/binemit/stackmap.rs":"da3187d96d21b14927279061ccaba4c880d0ad7169b83bd32c1381d45a39af70","src/bitset.rs":"d57a79058a31b094b4bbe9d34876a5543286df1e08b5ceadfd05a9efc5a3b1ce","src/cfg_printer.rs":"a84dee96d8c6f4775b8ba022243cf1c0bcf847c6d7ec532698cfd331655aa453","src/constant_hash.rs":"77eb898f7b0a4ae3b8165a03c25fcd23ce9c1d0cd32c793fa6cb31666ce27eb1","src/context.rs":"54b0acb1fb10e98f20804c367d5b2343f8ec918900f8f843e12e0925649b7515","src/cursor.rs":"874d1c7ef6e114d6ae47e0a1f92da7c5cec2e555597558042a3b214da7bc5fe4","src/dbg.rs":"1898d94cff0975815eb348651702e95c8f2f63886501d3b7043ee75668480472","src/dce.rs":"d8ab7c0cac0416f9d75afdacc60ba02e532361ec927c3f8bd171b1a53ec8b31a","src/divconst_magic_numbers.rs":"09691389c9055bef7a0cfd5d77fbfeba4be468d05d981d4de088516a94b8b28e","src/dominator_tree.rs":"6817b893c2c5ba5f2fc4e632fb8f8b7210a9ea9862d389d5247ff94b992b0d27","src/flowgraph.rs":"c975c05949017f0b2efeff85bf82017b6a5779ed92e25f13742aeea76ca95c52","src/fx.rs":"8a5d07487906d8316a179e826fcd817a92a4860686256a6fd9d78ba47c63f330","src/ir/builder.rs":"6f111f2a65dfe27633dcec918f74b767277131a72cd94b7bec2e1ef5c4308d5b","src/ir/condcodes.rs":"5247c8d849e1372d2a22379c33a4a88226ec6187be18ca6f2c4e0f315d812aa8","src/ir/constant.rs":"378d02256c3e21d89b70c6b0956ef70c034a5f14c1d2aaaec1f172a38b7b2279","src/ir/dfg.rs":"03abeb42420006b5d655a396d3724f34507e27e815aec6b30902e5a3fbd52a13","src/ir/entities.rs":"976f51a1e704b63b0bc701eb814b10ec8eee373d8f93ee73ceeeaeeea2c5b821","src/ir/extfunc.rs":"f26200741eb91be0d9a72a7aea194fd28f78696754ed9c26e88c8dd277ecd082","src/ir/extname.rs":"ed2c0b52cdaecc7f0ba9a894ef9fffe139e09b520e43dcd6f0c887a3d41a31ac","src/ir/function.rs":"fdbd33def70bfc49648c232d9fdb65eb8ed694a6a1a8bde1e06d6e40d4970230","src/ir/globalvalue.rs":"906d29f3d4190b811f66fc549c4e0408bdd2807eac98e33c0b3d5c2b876acc02","src/ir/heap.rs":"a59d3e5901412b53c0b53a8cdf10765ff5921de9c410ae9acea226c89827df3c","src/ir/immediates.rs":"671cc8bfcc347d7409ddba2bc661d985979f144cd663da232d9ba6a54e5c94c5","src/ir/instructions.rs":"7fe853efeb0379486d7878f7925962144ce208d230107d83e5a9165997a07587","src/ir/jumptable.rs":"7764abc9aa027a5a89d22059b360372bd9a19686887c5a7830f7637d6f188e1e","src/ir/layout.rs":"b80c4609e6101228b6d7fa341b60730137ecdcc2f918120f6473dbf62f31b9ad","src/ir/libcall.rs":"3e540afdd1d9a68b1be0ddb983a8db39312a052aae9ba92fb2440746f69fef06","src/ir/memflags.rs":"dbcf3798ab66dc764b73fb7f139a621c54cc6bcc683f1f70a33ed7e8c3486bfd","src/ir/mod.rs":"7590a2035a6f88a830e6c440d3c5a22102e921445806d04627e46ee42d82d167","src/ir/progpoint.rs":"49433f22bd6ff3a96ad0733ff612f3617b312e4492b6b663187141966f6aa701","src/ir/sourceloc.rs":"e1442572958b138f7637a14b662200ea9f729a513b77108be2a39745d8c2a0d5","src/ir/stackslot.rs":"a116aec3d41fcb570044584d06c97e21fc65d68b31f921ab6b5d7a2daddb614b","src/ir/table.rs":"dcc3b663a989b2b084402b08dc9a0e928dbd052e194a46a1886cc6f0cf1a5f2c","src/ir/trapcode.rs":"59e223193617b8c1043ddd3a907c6131f2987e8fe0965ebfd9f7c056c064b7c5","src/ir/types.rs":"8cfe8028008c93c37a593e82c230f95e8674d727cce5715aa55c93e140da4ced","src/ir/valueloc.rs":"1bf764fde5ff8140fa2b59f0192086ed17e9ba7018c74719788b74fc5ca05636","src/isa/arm32/abi.rs":"74775c5f1eb95764e46815fa8b31891416a616fdd212972eb77aead43b3345a9","src/isa/arm32/binemit.rs":"eecd7296c27d2520db8e86dd462833ecf06afd33548b03ae676c02454cdd13c2","src/isa/arm32/enc_tables.rs":"e94b12af802de59484cab1124d2ac8a88d08433f6e1a476724ed0403f4b5967f","src/isa/arm32/mod.rs":"bf862e984034f09a83bf0f5f18eb93e09cb23f1a5a994b554c478d174d672c64","src/isa/arm32/registers.rs":"254b568a02480f46bb4967a24a438390231014258f0c159f0a41dbafe8e66d56","src/isa/arm32/settings.rs":"2314460f885c24f9571d640f9737a8e0b7d20ca02bcda1127f878fd3891c0529","src/isa/arm64/abi.rs":"52353ed2e2133dacddaad70a876ecebb9c179c19b911ffa823b5b89d3ee7a17c","src/isa/arm64/binemit.rs":"3afbb78f6d9ae5614d908023f84b774c0493c8757ad86fd8301baf0928bb0104","src/isa/arm64/enc_tables.rs":"73fedf7da610a982e37c76e5211dbce880f77841b71c678b0dab2b9e7217cb7c","src/isa/arm64/mod.rs":"49b7f398ec8baa2802a283f780bd039e2a630591e74cf1dddc8d9147345c2816","src/isa/arm64/registers.rs":"308cfcfd9ff2191d7656e7350bb36e41803664eb86ae490fb4b4d3549b25b6a2","src/isa/arm64/settings.rs":"5405ce3560b7ba0705ef525c706eb9f1593e901e1767b837c012084397639042","src/isa/call_conv.rs":"56dfbf8f23a82942566d2a81deaf2147777061b3b49532b4f9fdcd3aae51aa56","src/isa/constraints.rs":"bddb5c68e56b122a53d8be215e41d22ccf8c4563630b1486e6eb31c0d3337565","src/isa/enc_tables.rs":"382e714f9500afc292c563cb66d4c963d6787e58f197b1db242db7a099c22b9a","src/isa/encoding.rs":"7ea5b4400530172f96e263561682886ea6c67e706398d44a83933ef7f0ac98a5","src/isa/mod.rs":"79ecb214ca28d4690b2ace20f6d4cdc36f393ef03f679a9d18a03653d230e160","src/isa/registers.rs":"004b090b7390fa07c1add81ef4a8c79bd7a6001a22cb014a4a83a9fa6ae3aeca","src/isa/riscv/abi.rs":"36557b91ad16a1344c80fbb16a62b46eac88500d76cb9ebcd4eae224dd67b2de","src/isa/riscv/binemit.rs":"264d223da311d4482ebf2f55438b665c67b163058251bc78173c76ba983a31ef","src/isa/riscv/enc_tables.rs":"8491f2082b24c7dedeb7c36cfd913bf9aeaa0a4c8fc754166e9285f4ae002f40","src/isa/riscv/mod.rs":"41136889df9512d8311f8c015cf3f654557a17d784a17fcefeb0afa2f0ec3674","src/isa/riscv/registers.rs":"666c2abe1a93db5f1573d1603db6c13c37f3fc877c0c93b64d1b971921bfa950","src/isa/riscv/settings.rs":"f6362769e9bc5be0c12b091e414ce924b0d2053b05b0ae88fef118cb8c68761e","src/isa/stack.rs":"5d30e2e19662ff3b3a641888bbb29640094ccd51b9a73368a056352afee46320","src/isa/x86/abi.rs":"13013f247c8e0fca46fe43568ef3186616fa469a321dee0a41fc2cc25220ec10","src/isa/x86/binemit.rs":"75d88b4ce66ec125940a2543a28e975c542a81a841c3c81282fc98ef78c1e032","src/isa/x86/enc_tables.rs":"ad7e3e384a784c24cc9750bb75f16f3b1cc231ae8f34b6b5d4138ee76d66b2cc","src/isa/x86/mod.rs":"d69e7f441c049b87aa1820639aaf12436bde1b0286757b03bec19fe7492049cc","src/isa/x86/registers.rs":"bed70bbe1f56f3ef03ea7cd1bea68eb911913cb4c8b93167e044dfc639f7f461","src/isa/x86/settings.rs":"d3e403db3507830f79bcc976c17340b57052cf1b50877fcf1a79549f2a054458","src/iterators.rs":"f85f52d3fa707a0eb974c92215b3e976923ce8f9481219f7812e0f2869c2bd37","src/legalizer/boundary.rs":"70a6819cbb116f07d0a09f8e5b0e2fe91145f423ad02e10225f8879ff4e61351","src/legalizer/call.rs":"be6074c64c1a00e5e81159dd94c8401fef62205b22c15e07e0c56cf922554d00","src/legalizer/globalvalue.rs":"59ab09a0faf593c7f228500b3fd3bacfc0412bdcb2864ec3621aa65adc4a5693","src/legalizer/heap.rs":"ce25c9575dbc3ef102f199b3bd5652e8c6b88ff323711c89ae41d0070b61adcb","src/legalizer/libcall.rs":"875daf54ac05114e50eba801b25b2c201351e9f6c276ba0358b356498c54d1c6","src/legalizer/mod.rs":"7911a03e4229fa6ea371b714b3a50b677adbeeab749b8809bf29fe298cd9d7ff","src/legalizer/split.rs":"696d2a641f52eeb4f2a2106b0641f751f61c560e6e3cbbac544df28b203a4445","src/legalizer/table.rs":"c36d03525312e3191aba8ee00c26a87c1ea200f9a9a0370f0cc84eeacff71786","src/lib.rs":"357c72bc31010fdf0e412000efd7e5538a36361f8562accec6a60e750c111876","src/licm.rs":"07534926e2986c01e3b76a2faf2336f5b96411f06d93d44d74e991f76265e29d","src/loop_analysis.rs":"58fc3cc0e700f05e3131ff1b16ff975d4f32a68c790f095d8445bd300356d3c0","src/nan_canonicalization.rs":"9619bb5554791bd1be75ecd98564d6c9f5b65132bc07c5c4d8c210cd79b66f82","src/partition_slice.rs":"bc13504e7658aab565918d965a0b67e941eb572e583870571bc6dbb2b9aad272","src/postopt.rs":"d4c487f0299fb905bb5a5822e38dea6f70afa4d4577288988b5bec8660bc1ba0","src/predicates.rs":"f52499cc39778f5e935140ea42405ce23e8a2ef9a21faf6378445dcee7e6a0f0","src/print_errors.rs":"3fbd77a01b5404a4bbcf2970e44299ad33948c71f4014d92026415daa8325314","src/redundant_reload_remover.rs":"3b2e49280375c9294fb7e190a8b02ef4fcef05ffcf1cb9e6e583cdc8e484bde1","src/ref_slice.rs":"421a61323c11858a596d50220487f399e1bcedeff0e8d1b716dd4b3531eb01a5","src/regalloc/affinity.rs":"19cec5495c8bddc1fcc8f3c8659d527a5a3ea373ffcc130e3fbd5b462ef15930","src/regalloc/branch_splitting.rs":"50ff6a6d257a9cb35d302ed61fa45ff1be4d2ff0f695aa2cedd161bd725a598c","src/regalloc/coalescing.rs":"d83be1c1067eb56f2f8f16380450a327d6495b4c6f1f489ded68271c055aec07","src/regalloc/coloring.rs":"6308e0f4f71b24e8d5abc94a98c4d20eff753c02238872119c7f4390f026e0a4","src/regalloc/context.rs":"0b3d5009c23b58cc9ccca2ece9d85dbdea52f843f52452e7813dd7a3229547d3","src/regalloc/diversion.rs":"49edbe958591acb304093e601179de7a79de0a4557748b98ddb736a865ef6a43","src/regalloc/live_value_tracker.rs":"28823003dc72e8a4702776a8ab5ffd878712700a272b64376b0de2022e0ee31a","src/regalloc/liveness.rs":"a59673fda65d1e3c0e5b3f4468686d05a389c877bee7b10323264595c3c54677","src/regalloc/liverange.rs":"7a28454e5f70d570db439b966a01ead759b65eb65c5845f9c58bf2f230a5f2ab","src/regalloc/mod.rs":"50399d6569687a87bf1481304aca42506d946e34465e38ca8093e06485ab5fb6","src/regalloc/pressure.rs":"04738e95418f0f858885dfc45183efc3dfb59c8d2ad2fd88bbd9a73a62907730","src/regalloc/register_set.rs":"739909ac35f48619d67f161ffec30c398d6839797ebea00ba5abd4b0ad0065f0","src/regalloc/reload.rs":"0dc6620ac72545065c14fda91f37bbe7904bf8f99e578d5fe532f1ccc76b9b21","src/regalloc/safepoint.rs":"93a4f963990298a2f2d64148c72859a4a0d5d3176b404834ab743b756882bf56","src/regalloc/solver.rs":"3e133a4cd81a029cf34cc329fcaa0169ce6ce4a8642eb5b24faabc4a8a120191","src/regalloc/spilling.rs":"dff4af64409c9a1db7697423576826c3920c26c892fbdde89ee31c680d672e03","src/regalloc/virtregs.rs":"865d5cdd7a6e87c8a2e5d41f89ba9c1a95531653363fd43c19a4d80b309534d8","src/result.rs":"c10354d615f93caa446c3c8c49d6ba3af762816af470f9c4accf04315cce9753","src/scoped_hash_map.rs":"5afafb3a4039094c3a2aad1582354220d21f399aa50046e7f4a1259e1976597e","src/settings.rs":"a9bbb526efd0f88f35448d2d560cc41c2d804cca46ca1973d2be9e508c016c65","src/simple_gvn.rs":"c8feb380d4831badc59aa1e65efeafa6702711585817fe5f6b31de6b265fac24","src/simple_preopt.rs":"f54526eecc1ddc07069900bd3fbcf998abbfb594582bd700423c50ee5fba34b8","src/stack_layout.rs":"c5de271e296fc424f1a30017620bc88500369c8e553fef6e95beccb9c6640e7c","src/timing.rs":"a6808943eec68f5d3ff32132d40c07c142e6aa8073473561573a013978883e4f","src/topo_order.rs":"b01ed68a7300691f41ac434e58a5267b10a8b4a7056d65035e24aa8a6722122a","src/unreachable_code.rs":"40cc71a02887ee4065c76ce96dda0a363a8cc134ec784fe5ed1f276db76596ce","src/value_label.rs":"d3f4422bdea00f1efe7f2b35384f8e3dfa609dee5eae629721d45bedfe087e9f","src/verifier/cssa.rs":"e3e1d77b763c0ba82d3b59ab5b4667fd3152d5a08be50b58b0c82f86376bb062","src/verifier/flags.rs":"cac8ba7ed5fe621eaa425112b931423cb5f3523d580fcf0b7536deb252e96186","src/verifier/liveness.rs":"ac3413b464ee8b5aa5928bee724799b9a1e0cbbdce433c819b9d870483ed070a","src/verifier/locations.rs":"05db00e49552a1ca6cfa0e8ccf38d35778edd0ececc4f20a50b0fb81b37a8312","src/verifier/mod.rs":"8162be3e9008dd661075700285bc9ef39ea0dd152d5fd66c64cf578c214c155d","src/write.rs":"35dff9d0f5ed74779e536cbc6b1de7381cec521a0c54f6d8513041d118bbfc4b"},"package":null} \ No newline at end of file +{"files":{"Cargo.toml":"3809cc2ba9d09e454815c696dd901849becd4819983b7cd74c17c08360998c2f","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"e5127227a7db4a8aa92fa6613ed71801025790e696bb41b0323fb7f3c6f7495a","build.rs":"8587e8557a046dc858f7662f63f1fa54e57ff92ed87b30fbcdfce6feafda9d60","src/abi.rs":"76ee030cf0780fe63ccbf855b1161f215e3e2991cb9abe71ca9aff25e5f1dbc2","src/binemit/memorysink.rs":"da415b20c563e636bcccaafb43dbdb77d6c48f9c205b16229865abb1afa40964","src/binemit/mod.rs":"90c56d36091646bba7f0ab1b5064d68b8b0c24ece874fcf8c621830b743e9688","src/binemit/relaxation.rs":"7b1082203c688beab4d705e601ad4fde10c5bf1fec414ad1ee6993e4f6b95e01","src/binemit/shrink.rs":"5755efc978f5056a33c0ecb1bd5e08310397f54a67434ecead184fc6ee047133","src/binemit/stackmap.rs":"f7742f4daafef83a8748f6e5e10cb669eecc4fd18e02e73fdf06d56696b7efa9","src/bitset.rs":"d57a79058a31b094b4bbe9d34876a5543286df1e08b5ceadfd05a9efc5a3b1ce","src/cfg_printer.rs":"a84dee96d8c6f4775b8ba022243cf1c0bcf847c6d7ec532698cfd331655aa453","src/constant_hash.rs":"77eb898f7b0a4ae3b8165a03c25fcd23ce9c1d0cd32c793fa6cb31666ce27eb1","src/context.rs":"9c36ff1d2759997e52dd4c5db64423da46ce0cada5166aab29068a378a162f34","src/cursor.rs":"874d1c7ef6e114d6ae47e0a1f92da7c5cec2e555597558042a3b214da7bc5fe4","src/dbg.rs":"1898d94cff0975815eb348651702e95c8f2f63886501d3b7043ee75668480472","src/dce.rs":"d8ab7c0cac0416f9d75afdacc60ba02e532361ec927c3f8bd171b1a53ec8b31a","src/divconst_magic_numbers.rs":"09691389c9055bef7a0cfd5d77fbfeba4be468d05d981d4de088516a94b8b28e","src/dominator_tree.rs":"6817b893c2c5ba5f2fc4e632fb8f8b7210a9ea9862d389d5247ff94b992b0d27","src/flowgraph.rs":"c975c05949017f0b2efeff85bf82017b6a5779ed92e25f13742aeea76ca95c52","src/fx.rs":"8a5d07487906d8316a179e826fcd817a92a4860686256a6fd9d78ba47c63f330","src/ir/builder.rs":"6f111f2a65dfe27633dcec918f74b767277131a72cd94b7bec2e1ef5c4308d5b","src/ir/constant.rs":"378d02256c3e21d89b70c6b0956ef70c034a5f14c1d2aaaec1f172a38b7b2279","src/ir/dfg.rs":"8539e19a9b7548c8b2d177e9966a2306592aafa89f8bd38763bce53c41b7e95f","src/ir/entities.rs":"e6e5e857f77c59b51ea66888a1a034514dc3686fedc3ccdf453ab9855215d196","src/ir/extfunc.rs":"f26200741eb91be0d9a72a7aea194fd28f78696754ed9c26e88c8dd277ecd082","src/ir/extname.rs":"ed2c0b52cdaecc7f0ba9a894ef9fffe139e09b520e43dcd6f0c887a3d41a31ac","src/ir/function.rs":"fdbd33def70bfc49648c232d9fdb65eb8ed694a6a1a8bde1e06d6e40d4970230","src/ir/globalvalue.rs":"906d29f3d4190b811f66fc549c4e0408bdd2807eac98e33c0b3d5c2b876acc02","src/ir/heap.rs":"a59d3e5901412b53c0b53a8cdf10765ff5921de9c410ae9acea226c89827df3c","src/ir/immediates.rs":"ce0492c864c6c5dabcfb2716a09f05d6f26cbfb6bbcc8c69c70eeb9e91826ac1","src/ir/instructions.rs":"c65afa7cd6fe48ec8a7e70330e4cc50cca91981dc92eb3715d9b0a06dea20b67","src/ir/jumptable.rs":"7764abc9aa027a5a89d22059b360372bd9a19686887c5a7830f7637d6f188e1e","src/ir/layout.rs":"e2fa46073f973be1375d005bfe187d50ba353b369d6a8b424cd558d9c61ddd49","src/ir/libcall.rs":"3e540afdd1d9a68b1be0ddb983a8db39312a052aae9ba92fb2440746f69fef06","src/ir/memflags.rs":"dbcf3798ab66dc764b73fb7f139a621c54cc6bcc683f1f70a33ed7e8c3486bfd","src/ir/mod.rs":"cbe204ea9943ab5a1b4a433cccae49c97122912a48dd26e24d664ae08ae2f63b","src/ir/progpoint.rs":"49433f22bd6ff3a96ad0733ff612f3617b312e4492b6b663187141966f6aa701","src/ir/sourceloc.rs":"e1442572958b138f7637a14b662200ea9f729a513b77108be2a39745d8c2a0d5","src/ir/stackslot.rs":"a116aec3d41fcb570044584d06c97e21fc65d68b31f921ab6b5d7a2daddb614b","src/ir/table.rs":"dcc3b663a989b2b084402b08dc9a0e928dbd052e194a46a1886cc6f0cf1a5f2c","src/ir/trapcode.rs":"7098eafab9f8708124bb81507900f26316d34fa8343e465f5a677db8a415978f","src/ir/types.rs":"8cfe8028008c93c37a593e82c230f95e8674d727cce5715aa55c93e140da4ced","src/ir/valueloc.rs":"1bf764fde5ff8140fa2b59f0192086ed17e9ba7018c74719788b74fc5ca05636","src/isa/arm32/abi.rs":"74775c5f1eb95764e46815fa8b31891416a616fdd212972eb77aead43b3345a9","src/isa/arm32/binemit.rs":"eecd7296c27d2520db8e86dd462833ecf06afd33548b03ae676c02454cdd13c2","src/isa/arm32/enc_tables.rs":"e94b12af802de59484cab1124d2ac8a88d08433f6e1a476724ed0403f4b5967f","src/isa/arm32/mod.rs":"cfb590b852414c3a3757e4187976944a472a304af518b7921c3f4f750d72609e","src/isa/arm32/registers.rs":"254b568a02480f46bb4967a24a438390231014258f0c159f0a41dbafe8e66d56","src/isa/arm32/settings.rs":"2314460f885c24f9571d640f9737a8e0b7d20ca02bcda1127f878fd3891c0529","src/isa/arm64/abi.rs":"52353ed2e2133dacddaad70a876ecebb9c179c19b911ffa823b5b89d3ee7a17c","src/isa/arm64/binemit.rs":"3afbb78f6d9ae5614d908023f84b774c0493c8757ad86fd8301baf0928bb0104","src/isa/arm64/enc_tables.rs":"73fedf7da610a982e37c76e5211dbce880f77841b71c678b0dab2b9e7217cb7c","src/isa/arm64/mod.rs":"45aa2f74b323764b6334c09f65b8a27cd82dd1de3cc2d9b207b6d94e55bcbed6","src/isa/arm64/registers.rs":"308cfcfd9ff2191d7656e7350bb36e41803664eb86ae490fb4b4d3549b25b6a2","src/isa/arm64/settings.rs":"5405ce3560b7ba0705ef525c706eb9f1593e901e1767b837c012084397639042","src/isa/call_conv.rs":"56dfbf8f23a82942566d2a81deaf2147777061b3b49532b4f9fdcd3aae51aa56","src/isa/constraints.rs":"bddb5c68e56b122a53d8be215e41d22ccf8c4563630b1486e6eb31c0d3337565","src/isa/enc_tables.rs":"382e714f9500afc292c563cb66d4c963d6787e58f197b1db242db7a099c22b9a","src/isa/encoding.rs":"7ea5b4400530172f96e263561682886ea6c67e706398d44a83933ef7f0ac98a5","src/isa/mod.rs":"d32ab806081a2bf1ef06f1f9ae6f69846f333d797b6e539a364400c5d7aaeb84","src/isa/registers.rs":"004b090b7390fa07c1add81ef4a8c79bd7a6001a22cb014a4a83a9fa6ae3aeca","src/isa/riscv/abi.rs":"36557b91ad16a1344c80fbb16a62b46eac88500d76cb9ebcd4eae224dd67b2de","src/isa/riscv/binemit.rs":"264d223da311d4482ebf2f55438b665c67b163058251bc78173c76ba983a31ef","src/isa/riscv/enc_tables.rs":"8491f2082b24c7dedeb7c36cfd913bf9aeaa0a4c8fc754166e9285f4ae002f40","src/isa/riscv/mod.rs":"d7e5e1f4b8ba2a3058d1b416796f6a88522a9472816cb078b5859030f496ac44","src/isa/riscv/registers.rs":"666c2abe1a93db5f1573d1603db6c13c37f3fc877c0c93b64d1b971921bfa950","src/isa/riscv/settings.rs":"f6362769e9bc5be0c12b091e414ce924b0d2053b05b0ae88fef118cb8c68761e","src/isa/stack.rs":"5d30e2e19662ff3b3a641888bbb29640094ccd51b9a73368a056352afee46320","src/isa/x86/abi.rs":"13013f247c8e0fca46fe43568ef3186616fa469a321dee0a41fc2cc25220ec10","src/isa/x86/binemit.rs":"86622ac2971907d858d9d0a49ff9e51899db8e3f6930dc2ad2ed8c419668a603","src/isa/x86/enc_tables.rs":"b926172bbdaaf1259b0870a2e85228fb50f1274fbe16861b382a963aa00de23d","src/isa/x86/mod.rs":"6ed0ad8a7fa2bec526a99f3b1b9c9fc1cb5f62e5ea49685304e1721c85d81aae","src/isa/x86/registers.rs":"bed70bbe1f56f3ef03ea7cd1bea68eb911913cb4c8b93167e044dfc639f7f461","src/isa/x86/settings.rs":"d3e403db3507830f79bcc976c17340b57052cf1b50877fcf1a79549f2a054458","src/iterators.rs":"f85f52d3fa707a0eb974c92215b3e976923ce8f9481219f7812e0f2869c2bd37","src/legalizer/boundary.rs":"70a6819cbb116f07d0a09f8e5b0e2fe91145f423ad02e10225f8879ff4e61351","src/legalizer/call.rs":"be6074c64c1a00e5e81159dd94c8401fef62205b22c15e07e0c56cf922554d00","src/legalizer/globalvalue.rs":"59ab09a0faf593c7f228500b3fd3bacfc0412bdcb2864ec3621aa65adc4a5693","src/legalizer/heap.rs":"6f722a5ba720acdf19c58ba7c9820ea3a5b5017af3bda70adeeeb8b3c1408eb1","src/legalizer/libcall.rs":"875daf54ac05114e50eba801b25b2c201351e9f6c276ba0358b356498c54d1c6","src/legalizer/mod.rs":"7911a03e4229fa6ea371b714b3a50b677adbeeab749b8809bf29fe298cd9d7ff","src/legalizer/split.rs":"696d2a641f52eeb4f2a2106b0641f751f61c560e6e3cbbac544df28b203a4445","src/legalizer/table.rs":"c36d03525312e3191aba8ee00c26a87c1ea200f9a9a0370f0cc84eeacff71786","src/lib.rs":"579e060edc61558e05590ce3dd3a65b39a169e0c2b20c47a53fdee14cbbf7146","src/licm.rs":"07534926e2986c01e3b76a2faf2336f5b96411f06d93d44d74e991f76265e29d","src/loop_analysis.rs":"58fc3cc0e700f05e3131ff1b16ff975d4f32a68c790f095d8445bd300356d3c0","src/nan_canonicalization.rs":"9619bb5554791bd1be75ecd98564d6c9f5b65132bc07c5c4d8c210cd79b66f82","src/partition_slice.rs":"bc13504e7658aab565918d965a0b67e941eb572e583870571bc6dbb2b9aad272","src/postopt.rs":"d4c487f0299fb905bb5a5822e38dea6f70afa4d4577288988b5bec8660bc1ba0","src/predicates.rs":"89511e94976129136140515a7229b5d56f524e883c987296872322443d549adb","src/print_errors.rs":"3fbd77a01b5404a4bbcf2970e44299ad33948c71f4014d92026415daa8325314","src/redundant_reload_remover.rs":"3b2e49280375c9294fb7e190a8b02ef4fcef05ffcf1cb9e6e583cdc8e484bde1","src/regalloc/affinity.rs":"19cec5495c8bddc1fcc8f3c8659d527a5a3ea373ffcc130e3fbd5b462ef15930","src/regalloc/branch_splitting.rs":"50ff6a6d257a9cb35d302ed61fa45ff1be4d2ff0f695aa2cedd161bd725a598c","src/regalloc/coalescing.rs":"334820e453defd28e7aba1c2d6b5db6813bbe228c9a0607c55d1e792c3d8497d","src/regalloc/coloring.rs":"413ad9f6c1efc4775a173e8f3e8255946dbccce57c5ff2e640159f6b247e90c2","src/regalloc/context.rs":"0b3d5009c23b58cc9ccca2ece9d85dbdea52f843f52452e7813dd7a3229547d3","src/regalloc/diversion.rs":"49edbe958591acb304093e601179de7a79de0a4557748b98ddb736a865ef6a43","src/regalloc/live_value_tracker.rs":"34458e7ea99492250faf93adfef7731baed7c1db85483475a256f9b822f8b9cb","src/regalloc/liveness.rs":"1eeae58f9cf1bcf3379de7a1cba9610cd3fe42bc0668181e94cb0a37f1c9a5e2","src/regalloc/liverange.rs":"60f8c9a1707e2db1aa5dae23cc9db46689557556492f14a1b1002bcf0a71de1e","src/regalloc/mod.rs":"50399d6569687a87bf1481304aca42506d946e34465e38ca8093e06485ab5fb6","src/regalloc/pressure.rs":"04738e95418f0f858885dfc45183efc3dfb59c8d2ad2fd88bbd9a73a62907730","src/regalloc/register_set.rs":"739909ac35f48619d67f161ffec30c398d6839797ebea00ba5abd4b0ad0065f0","src/regalloc/reload.rs":"0dc6620ac72545065c14fda91f37bbe7904bf8f99e578d5fe532f1ccc76b9b21","src/regalloc/safepoint.rs":"93a4f963990298a2f2d64148c72859a4a0d5d3176b404834ab743b756882bf56","src/regalloc/solver.rs":"3e133a4cd81a029cf34cc329fcaa0169ce6ce4a8642eb5b24faabc4a8a120191","src/regalloc/spilling.rs":"6bba892c9ba7eafa7e45e5f3925f1a6a5b1023a98e3302bf11ffc65cabb3dd5f","src/regalloc/virtregs.rs":"90e6ddbeb364057a7d2b792c0534e1a3123281b0bd86c5004fe9ead311f5d82a","src/result.rs":"c10354d615f93caa446c3c8c49d6ba3af762816af470f9c4accf04315cce9753","src/scoped_hash_map.rs":"5afafb3a4039094c3a2aad1582354220d21f399aa50046e7f4a1259e1976597e","src/settings.rs":"5e342908104df9e9eca8816a01289edc6def8940e97b94ddd14d1cb77afeab31","src/simple_gvn.rs":"c8feb380d4831badc59aa1e65efeafa6702711585817fe5f6b31de6b265fac24","src/simple_preopt.rs":"f54526eecc1ddc07069900bd3fbcf998abbfb594582bd700423c50ee5fba34b8","src/stack_layout.rs":"c5de271e296fc424f1a30017620bc88500369c8e553fef6e95beccb9c6640e7c","src/timing.rs":"a6808943eec68f5d3ff32132d40c07c142e6aa8073473561573a013978883e4f","src/topo_order.rs":"674d4f482a9d68a0850d37fcf785ea64802ed30e3efce5a684d6a2c500efc515","src/unreachable_code.rs":"40cc71a02887ee4065c76ce96dda0a363a8cc134ec784fe5ed1f276db76596ce","src/value_label.rs":"10f6fd479bc3dca5a018f566620a15e190d7e3cfee9f90e918bafc7e365fe9af","src/verifier/cssa.rs":"1600586748a88843354e76e3f73a2fb837a4c6570eaf1473731e3ea77b87b43a","src/verifier/flags.rs":"2794b0165cc858e9ea2ef0437c5eb1b493754a8dd79f4f876d9eb8a533d5f427","src/verifier/liveness.rs":"97e339f9ff6aeeb304cfda5125ff6c1c693dc96421c8e330f48d4037c9d4fa82","src/verifier/locations.rs":"ed78d5675cf74901e4dbc486058f55a7dd3d21fdc8b0032a92f8a679c78440f0","src/verifier/mod.rs":"3badebb547382f612b3dd8e804f62910f6785b8020b724b7cc6fd15306b1a731","src/write.rs":"20513f9a001cf3505625f065a2098c245877a134adcd5c153257561dd8c5fcde"},"package":null} \ No newline at end of file diff --git a/third_party/rust/cranelift-codegen/Cargo.toml b/third_party/rust/cranelift-codegen/Cargo.toml index 2d81a660e84ee00e99440660775343071d5b44ac..eb6a1094c86dfc0554ea1b7a078dbd73612bebca 100644 --- a/third_party/rust/cranelift-codegen/Cargo.toml +++ b/third_party/rust/cranelift-codegen/Cargo.toml @@ -1,7 +1,7 @@ [package] authors = ["The Cranelift Project Developers"] name = "cranelift-codegen" -version = "0.42.0" +version = "0.44.0" description = "Low-level code generator library" license = "Apache-2.0 WITH LLVM-exception" documentation = "https://cranelift.readthedocs.io/" @@ -13,8 +13,9 @@ build = "build.rs" edition = "2018" [dependencies] -cranelift-entity = { path = "../cranelift-entity", version = "0.42.0", default-features = false } -cranelift-bforest = { path = "../cranelift-bforest", version = "0.42.0", default-features = false } +cranelift-codegen-shared = { path = "./shared", version = "0.44.0" } +cranelift-entity = { path = "../cranelift-entity", version = "0.44.0", default-features = false } +cranelift-bforest = { path = "../cranelift-bforest", version = "0.44.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 } @@ -28,7 +29,7 @@ smallvec = { version = "0.6.10" } # accomodated in `tests`. [build-dependencies] -cranelift-codegen-meta = { path = "meta", version = "0.42.0", default-features = false } +cranelift-codegen-meta = { path = "meta", version = "0.44.0", default-features = false } [features] default = ["std"] diff --git a/third_party/rust/cranelift-codegen/src/binemit/stackmap.rs b/third_party/rust/cranelift-codegen/src/binemit/stackmap.rs index 8d0d2a3204bc7b1fb228a242502d6b4cb046458a..4051b47e191cc48bad69aa8d543fddd291309652 100644 --- a/third_party/rust/cranelift-codegen/src/binemit/stackmap.rs +++ b/third_party/rust/cranelift-codegen/src/binemit/stackmap.rs @@ -3,10 +3,13 @@ use crate::ir; use crate::isa::TargetIsa; use std::vec::Vec; +type Num = u32; +const NUM_BITS: usize = std::mem::size_of::<Num>() * 8; + /// Wrapper class for longer bit vectors that cannot be represented by a single BitSet. #[derive(Clone, Debug)] pub struct Stackmap { - bitmap: Vec<BitSet<u32>>, + bitmap: Vec<BitSet<Num>>, } impl Stackmap { @@ -52,34 +55,32 @@ impl Stackmap { } } - Stackmap::from_vec(&vec) + Stackmap::from_slice(&vec) } - /// Create a vec of Bitsets from a vec of bools. - pub fn from_vec(vec: &Vec<bool>) -> Self { - let mut rem = vec.len(); - let num_word = ((rem as f32) / 32.0).ceil() as usize; + /// Create a vec of Bitsets from a slice of bools. + pub fn from_slice(vec: &[bool]) -> Self { + let len = vec.len(); + let num_word = len / NUM_BITS + (len % NUM_BITS != 0) as usize; let mut bitmap = Vec::with_capacity(num_word); - for i in 0..num_word { + for segment in vec.chunks(NUM_BITS) { let mut curr_word = 0; - let count = if rem > 32 { 32 } else { rem }; - for j in 0..count { - if vec[i * 32 + j] { - curr_word |= 1 << j; + for (i, set) in segment.iter().enumerate() { + if *set { + curr_word |= 1 << i; } } - bitmap.push(BitSet::<u32>(curr_word)); - rem -= count; + bitmap.push(BitSet(curr_word)); } Self { bitmap } } /// Returns a specified bit. pub fn get_bit(&self, bit_index: usize) -> bool { - assert!(bit_index < 32 * self.bitmap.len()); - let word_index = bit_index / 32; - let word_offset = (bit_index % 32) as u8; + assert!(bit_index < NUM_BITS * self.bitmap.len()); + let word_index = bit_index / NUM_BITS; + let word_offset = (bit_index % NUM_BITS) as u8; self.bitmap[word_index].contains(word_offset) } } @@ -91,26 +92,26 @@ mod tests { #[test] fn stackmaps() { let vec: Vec<bool> = Vec::new(); - assert!(Stackmap::from_vec(&vec).bitmap.is_empty()); + assert!(Stackmap::from_slice(&vec).bitmap.is_empty()); - let mut vec: [bool; 32] = Default::default(); + let mut vec: [bool; NUM_BITS] = Default::default(); let set_true_idx = [5, 7, 24, 31]; - for idx in set_true_idx.iter() { - vec[*idx] = true; + for &idx in &set_true_idx { + vec[idx] = true; } let mut vec = vec.to_vec(); assert_eq!( - vec![BitSet::<u32>(2164261024)], - Stackmap::from_vec(&vec).bitmap + vec![BitSet::<Num>(2164261024)], + Stackmap::from_slice(&vec).bitmap ); vec.push(false); vec.push(true); - let res = Stackmap::from_vec(&vec); + let res = Stackmap::from_slice(&vec); assert_eq!( - vec![BitSet::<u32>(2164261024), BitSet::<u32>(2)], + vec![BitSet::<Num>(2164261024), BitSet::<Num>(2)], res.bitmap ); diff --git a/third_party/rust/cranelift-codegen/src/context.rs b/third_party/rust/cranelift-codegen/src/context.rs index 0f4e9ad420cbee1a48afd7dc3bdcabf54f82b41c..8bbe2893de4f877dbdf210aa57382ee93b3c43c1 100644 --- a/third_party/rust/cranelift-codegen/src/context.rs +++ b/third_party/rust/cranelift-codegen/src/context.rs @@ -132,18 +132,18 @@ impl Context { self.verify_if(isa)?; debug!("Compiling:\n{}", self.func.display(isa)); + let opt_level = isa.flags().opt_level(); + self.compute_cfg(); - if isa.flags().opt_level() != OptLevel::Fastest { + if opt_level != OptLevel::None { self.preopt(isa)?; } if isa.flags().enable_nan_canonicalization() { self.canonicalize_nans(isa)?; } self.legalize(isa)?; - if isa.flags().opt_level() != OptLevel::Fastest { + if opt_level != OptLevel::None { self.postopt(isa)?; - } - if isa.flags().opt_level() == OptLevel::Best { self.compute_domtree(); self.compute_loop_analysis(); self.licm(isa)?; @@ -151,13 +151,15 @@ impl Context { } self.compute_domtree(); self.eliminate_unreachable_code(isa)?; - if isa.flags().opt_level() != OptLevel::Fastest { + if opt_level != OptLevel::None { self.dce(isa)?; } self.regalloc(isa)?; self.prologue_epilogue(isa)?; - if isa.flags().opt_level() == OptLevel::Best { + if opt_level == OptLevel::Speed || opt_level == OptLevel::SpeedAndSize { self.redundant_reload_remover(isa)?; + } + if opt_level == OptLevel::SpeedAndSize { self.shrink_instructions(isa)?; } let result = self.relax_branches(isa); diff --git a/third_party/rust/cranelift-codegen/src/ir/dfg.rs b/third_party/rust/cranelift-codegen/src/ir/dfg.rs index f4e2875952ae0bd6c0a9fca17698880617cd380c..5b3054b59d2a878303dbcceaba1bf873737b4ec1 100644 --- a/third_party/rust/cranelift-codegen/src/ir/dfg.rs +++ b/third_party/rust/cranelift-codegen/src/ir/dfg.rs @@ -5,7 +5,7 @@ use crate::ir; use crate::ir::builder::ReplaceBuilder; use crate::ir::extfunc::ExtFuncData; use crate::ir::instructions::{BranchInfo, CallInfo, InstructionData}; -use crate::ir::{types, ConstantPool}; +use crate::ir::{types, ConstantPool, Immediate}; use crate::ir::{ Ebb, FuncRef, Inst, SigRef, Signature, Type, Value, ValueLabelAssignments, ValueList, ValueListPool, @@ -19,6 +19,7 @@ use core::mem; use core::ops::{Index, IndexMut}; use core::u16; use std::collections::HashMap; +use std::vec::Vec; /// A data flow graph defines all instructions and extended basic blocks in a function as well as /// the data flow dependencies between them. The DFG also tracks values which can be either @@ -70,6 +71,9 @@ pub struct DataFlowGraph { /// Constants used within the function pub constants: ConstantPool, + + /// Stores large immediates that otherwise will not fit on InstructionData + pub immediates: PrimaryMap<Immediate, Vec<u8>>, } impl DataFlowGraph { @@ -85,6 +89,7 @@ impl DataFlowGraph { ext_funcs: PrimaryMap::new(), values_labels: None, constants: ConstantPool::new(), + immediates: PrimaryMap::new(), } } @@ -98,7 +103,8 @@ impl DataFlowGraph { self.signatures.clear(); self.ext_funcs.clear(); self.values_labels = None; - self.constants.clear() + self.constants.clear(); + self.immediates.clear(); } /// Get the total number of instructions created in this function, whether they are currently diff --git a/third_party/rust/cranelift-codegen/src/ir/entities.rs b/third_party/rust/cranelift-codegen/src/ir/entities.rs index ab78e0f3a82c06647e3a495fb09641a9b482ebb4..1f8e1fc6a231c86de2c46b1f001958891ecfd306 100644 --- a/third_party/rust/cranelift-codegen/src/ir/entities.rs +++ b/third_party/rust/cranelift-codegen/src/ir/entities.rs @@ -25,7 +25,12 @@ use core::u32; #[cfg(feature = "enable-serde")] use serde::{Deserialize, Serialize}; -/// An opaque reference to an extended basic block in a function. +/// An opaque reference to an [extended basic +/// block](https://en.wikipedia.org/wiki/Extended_basic_block) in a +/// [`Function`](super::function::Function). +/// +/// You can get an `Ebb` using +/// [`FunctionBuilder::create_ebb`](https://docs.rs/cranelift-frontend/*/cranelift_frontend/struct.FunctionBuilder.html#method.create_ebb) #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct Ebb(u32); entity_impl!(Ebb, "ebb"); @@ -44,6 +49,18 @@ impl Ebb { } /// An opaque reference to an SSA value. +/// +/// You can get a constant `Value` from the following +/// [`InstBuilder`](super::InstBuilder) instructions: +/// +/// - [`iconst`](super::InstBuilder::iconst) for integer constants +/// - [`f32const`](super::InstBuilder::f32const) for 32-bit float constants +/// - [`f64const`](super::InstBuilder::f64const) for 64-bit float constants +/// - [`bconst`](super::InstBuilder::bconst) for boolean constants +/// - [`vconst`](super::InstBuilder::vconst) for vector constants +/// - [`null`](super::InstBuilder::null) for null reference constants +/// +/// Any `InstBuilder` instruction that has an output will also return a `Value`. #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct Value(u32); entity_impl!(Value, "v"); @@ -62,12 +79,34 @@ impl Value { } } -/// An opaque reference to an instruction in a function. +/// An opaque reference to an instruction in a [`Function`](super::Function). +/// +/// Most usage of `Inst` is internal. `Inst`ructions are returned by +/// [`InstBuilder`](super::InstBuilder) instructions that do not return a +/// [`Value`], such as control flow and trap instructions. +/// +/// If you look around the API, you can find many inventive uses for `Inst`, +/// such as [annotating specific instructions with a comment][inst_comment] +/// or [performing reflection at compile time](super::DataFlowGraph::analyze_branch) +/// on the type of instruction. +/// +/// [inst_comment]: https://github.com/bjorn3/rustc_codegen_cranelift/blob/0f8814fd6da3d436a90549d4bb19b94034f2b19c/src/pretty_clif.rs #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct Inst(u32); entity_impl!(Inst, "inst"); /// An opaque reference to a stack slot. +/// +/// Stack slots represent an address on the +/// [call stack](https://en.wikipedia.org/wiki/Call_stack). +/// +/// `StackSlot`s can be created with +/// [`FunctionBuilder::create_stackslot`](https://docs.rs/cranelift-frontend/*/cranelift_frontend/struct.FunctionBuilder.html#method.create_stack_slot). +/// +/// `StackSlot`s are most often used with +/// [`stack_addr`](super::InstBuilder::stack_addr), +/// [`stack_load`](super::InstBuilder::stack_load), and +/// [`stack_store`](super::InstBuilder::stack_store). #[derive(Copy, Clone, PartialEq, Eq, Hash)] #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] pub struct StackSlot(u32); @@ -87,6 +126,22 @@ impl StackSlot { } /// An opaque reference to a global value. +/// +/// A `GlobalValue` is a [`Value`](Value) that will be live across the entire +/// function lifetime. It can be preloaded from other global values. +/// +/// You can create a `GlobalValue` in the following ways: +/// +/// - When compiling to WASM, you can use it to load values from a +/// [`VmContext`](super::GlobalValueData::VMContext) using +/// [`FuncEnvironment::make_global`](https://docs.rs/cranelift-wasm/*/cranelift_wasm/trait.FuncEnvironment.html#tymethod.make_global). +/// - When compiling to native code, you can use it for objects in static memory with +/// [`Module::declare_data_in_func`](https://docs.rs/cranelift-module/*/cranelift_module/struct.Module.html#method.declare_data_in_func). +/// - For any compilation target, it can be registered with +/// [`FunctionBuilder::create_global_value`](https://docs.rs/cranelift-frontend/*/cranelift_frontend/struct.FunctionBuilder.html#method.create_global_value). +/// +/// `GlobalValue`s can be retrieved with +/// [`InstBuilder:global_value`](super::InstBuilder::global_value). #[derive(Copy, Clone, PartialEq, Eq, Hash)] pub struct GlobalValue(u32); entity_impl!(GlobalValue, "gv"); @@ -104,7 +159,11 @@ impl GlobalValue { } } -/// An opaque reference to a constant +/// An opaque reference to a constant. +/// +/// You can store [`ConstantData`](super::ConstantData) in a +/// [`ConstantPool`](super::ConstantPool) for efficient storage and retrieval. +/// See [`ConstantPool::insert`](super::ConstantPool::insert). #[derive(Copy, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)] pub struct Constant(u32); entity_impl!(Constant, "const"); @@ -122,7 +181,39 @@ impl Constant { } } -/// An opaque reference to a jump table. +/// An opaque reference to an immediate. +/// +/// Some immediates (e.g. SIMD shuffle masks) are too large to store in the +/// [`InstructionData`](super::instructions::InstructionData) struct and therefore must be +/// tracked separately in [`DataFlowGraph::immediates`](super::dfg::DataFlowGraph). `Immediate` +/// provides a way to reference values stored there. +#[derive(Copy, Clone, PartialEq, Eq, Hash)] +pub struct Immediate(u32); +entity_impl!(Immediate, "imm"); + +impl Immediate { + /// Create an immediate reference from its number. + /// + /// This method is for use by the parser. + pub fn with_number(n: u32) -> Option<Self> { + if n < u32::MAX { + Some(Immediate(n)) + } else { + None + } + } +} + +/// An opaque reference to a [jump table](https://en.wikipedia.org/wiki/Branch_table). +/// +/// `JumpTable`s are used for indirect branching and are specialized for dense, +/// 0-based jump offsets. If you want a jump table which doesn't start at 0, +/// or is not contiguous, consider using a [`Switch`](https://docs.rs/cranelift-frontend/*/cranelift_frontend/struct.Switch.html) instead. +/// +/// `JumpTable` are used with [`br_table`](super::InstBuilder::br_table). +/// +/// `JumpTable`s can be created with +/// [`create_jump_table`](https://docs.rs/cranelift-frontend/*/cranelift_frontend/struct.FunctionBuilder.html#method.create_jump_table). #[derive(Copy, Clone, PartialEq, Eq, Hash)] #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] pub struct JumpTable(u32); @@ -141,7 +232,22 @@ impl JumpTable { } } -/// A reference to an external function. +/// An opaque reference to another [`Function`](super::Function). +/// +/// `FuncRef`s are used for [direct](super::InstBuilder::call) function calls +/// and by [`func_addr`](super::InstBuilder::func_addr) for use in +/// [indirect](super::InstBuilder::call_indirect) function calls. +/// +/// `FuncRef`s can be created with +/// +/// - [`FunctionBuilder::import_function`](https://docs.rs/cranelift-frontend/*/cranelift_frontend/struct.FunctionBuilder.html#method.import_function) +/// for external functions +/// - [`Module::declare_func_in_func`](https://docs.rs/cranelift-module/*/cranelift_module/struct.Module.html#method.declare_func_in_func) +/// for functions declared elsewhere in the same native +/// [`Module`](https://docs.rs/cranelift-module/*/cranelift_module/struct.Module.html) +/// - [`FuncEnvironment::make_direct_func`](https://docs.rs/cranelift-wasm/*/cranelift_wasm/trait.FuncEnvironment.html#tymethod.make_direct_func) +/// for functions declared in the same WebAssembly +/// [`FuncEnvironment`](https://docs.rs/cranelift-wasm/*/cranelift_wasm/trait.FuncEnvironment.html#tymethod.make_direct_func) #[derive(Copy, Clone, PartialEq, Eq, Hash)] pub struct FuncRef(u32); entity_impl!(FuncRef, "fn"); @@ -159,7 +265,18 @@ impl FuncRef { } } -/// A reference to a function signature. +/// An opaque reference to a function [`Signature`](super::Signature). +/// +/// `SigRef`s are used to declare a function with +/// [`FunctionBuiler::import_function`](https://docs.rs/cranelift-frontend/*/cranelift_frontend/struct.FunctionBuilder.html#method.import_function) +/// as well as to make an [indirect function call](super::InstBuilder::call_indirect). +/// +/// `SigRef`s can be created with +/// [`FunctionBuilder::import_signature`](https://docs.rs/cranelift-frontend/*/cranelift_frontend/struct.FunctionBuilder.html#method.import_signature). +/// +/// You can retrieve the [`Signature`](super::Signature) that was used to create a `SigRef` with +/// [`FunctionBuilder::signature`](https://docs.rs/cranelift-frontend/*/cranelift_frontend/struct.FunctionBuilder.html#method.signature) or +/// [`func.dfg.signatures`](super::dfg::DataFlowGraph::signatures). #[derive(Copy, Clone, PartialEq, Eq, Hash)] pub struct SigRef(u32); entity_impl!(SigRef, "sig"); @@ -177,7 +294,12 @@ impl SigRef { } } -/// A reference to a heap. +/// An opaque reference to a [heap](https://en.wikipedia.org/wiki/Memory_management#DYNAMIC). +/// +/// Heaps are used to access dynamically allocated memory through +/// [`heap_addr`](super::InstBuilder::heap_addr). +/// +/// To create a heap, use [`FunctionBuilder::create_heap`](https://docs.rs/cranelift-frontend/*/cranelift_frontend/struct.FunctionBuilder.html#method.create_heap). #[derive(Copy, Clone, PartialEq, Eq, Hash)] pub struct Heap(u32); entity_impl!(Heap, "heap"); @@ -195,7 +317,13 @@ impl Heap { } } -/// A reference to a table. +/// An opaque reference to a [WebAssembly +/// table](https://developer.mozilla.org/en-US/docs/WebAssembly/Understanding_the_text_format#WebAssembly_tables). +/// +/// `Table`s are used to store a list of function references. +/// They can be created with [`FuncEnvironment::make_table`](https://docs.rs/cranelift-wasm/*/cranelift_wasm/trait.FuncEnvironment.html#tymethod.make_table). +/// They can be used with +/// [`FuncEnvironment::translate_call_indirect`](https://docs.rs/cranelift-wasm/*/cranelift_wasm/trait.FuncEnvironment.html#tymethod.translate_call_indirect). #[derive(Copy, Clone, PartialEq, Eq, Hash)] pub struct Table(u32); entity_impl!(Table, "table"); @@ -213,7 +341,7 @@ impl Table { } } -/// A reference to any of the entities defined in this module that can appear in CLIF IR. +/// An opaque reference to any of the entities defined in this module that can appear in CLIF IR. #[derive(Copy, Clone, PartialEq, Eq, Hash)] pub enum AnyEntity { /// The whole function. diff --git a/third_party/rust/cranelift-codegen/src/ir/immediates.rs b/third_party/rust/cranelift-codegen/src/ir/immediates.rs index 2c5ee27c473ae5d740235cc800700084298608fe..408fe17cf3e39165f46db4af78130afd01dbbe14 100644 --- a/third_party/rust/cranelift-codegen/src/ir/immediates.rs +++ b/third_party/rust/cranelift-codegen/src/ir/immediates.rs @@ -6,7 +6,6 @@ use core::fmt::{self, Display, Formatter}; use core::iter::FromIterator; -use core::mem; use core::str::{from_utf8, FromStr}; use core::{i32, u32}; use std::vec::Vec; @@ -290,13 +289,13 @@ impl FromStr for Uimm32 { } } -/// A 128-bit unsigned integer immediate operand. +/// A 128-bit immediate operand. /// /// This is used as an immediate value in SIMD instructions. #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] -pub struct Uimm128(pub [u8; 16]); +pub struct V128Imm(pub [u8; 16]); -impl Uimm128 { +impl V128Imm { /// Iterate over the bytes in the constant pub fn bytes(&self) -> impl Iterator<Item = &u8> { self.0.iter() @@ -313,7 +312,7 @@ impl Uimm128 { } } -impl Display for Uimm128 { +impl Display for V128Imm { // Print a 128-bit vector in hexadecimal, e.g. 0x000102030405060708090a0b0c0d0e0f. fn fmt(&self, f: &mut Formatter) -> fmt::Result { write!(f, "0x")?; @@ -333,24 +332,24 @@ impl Display for Uimm128 { } } -impl From<u64> for Uimm128 { +impl From<u64> for V128Imm { fn from(x: u64) -> Self { let mut buffer: [u8; 16] = [0; 16]; // zero-fill (0..8).for_each(|byte| buffer[byte] = (x >> (byte as u64 * 8) & 0xff) as u8); // insert each byte from the u64 into v in little-endian order - Uimm128(buffer) + V128Imm(buffer) } } -impl From<&[u8]> for Uimm128 { +impl From<&[u8]> for V128Imm { fn from(slice: &[u8]) -> Self { assert_eq!(slice.len(), 16); let mut buffer = [0; 16]; buffer.copy_from_slice(slice); - Uimm128(buffer) + V128Imm(buffer) } } -impl FromStr for Uimm128 { +impl FromStr for V128Imm { type Err = &'static str; // parse a 128-bit vector from a hexadecimal string, formatted as above @@ -384,7 +383,7 @@ impl FromStr for Uimm128 { position = position.wrapping_sub(1); // should only wrap on the last iteration } - Ok(Uimm128(buffer)) + Ok(V128Imm(buffer)) } } } @@ -396,7 +395,7 @@ impl FromStr for Uimm128 { /// - this requires the input type (i.e. $ty) to implement ToBytes macro_rules! construct_uimm128_from_iterator_of { ( $ty:ident, $lanes:expr ) => { - impl FromIterator<$ty> for Uimm128 { + impl FromIterator<$ty> for V128Imm { fn from_iter<T: IntoIterator<Item = $ty>>(iter: T) -> Self { let mut buffer: [u8; 16] = [0; 16]; iter.into_iter() @@ -405,14 +404,14 @@ macro_rules! construct_uimm128_from_iterator_of { .flat_map(|b| b) .enumerate() .for_each(|(i, b)| buffer[i] = b); - Uimm128(buffer) + V128Imm(buffer) } } }; } /// Special case for booleans since we have to decide the bit-width based on the number of items -impl FromIterator<bool> for Uimm128 { +impl FromIterator<bool> for V128Imm { fn from_iter<T: IntoIterator<Item = bool>>(iter: T) -> Self { let bools = Vec::from_iter(iter); let count = bools.len(); @@ -425,7 +424,7 @@ impl FromIterator<bool> for Uimm128 { .enumerate() .map(|(i, &b)| (i * step, if b { 1 } else { 0 })) .for_each(|(i, b)| buffer[i] = b); - Uimm128(buffer) + V128Imm(buffer) } } @@ -809,7 +808,7 @@ impl Ieee32 { /// Create a new `Ieee32` representing the number `x`. pub fn with_float(x: f32) -> Self { - Ieee32(unsafe { mem::transmute(x) }) + Ieee32(x.to_bits()) } /// Get the bitwise representation. @@ -882,7 +881,7 @@ impl Ieee64 { /// Create a new `Ieee64` representing the number `x`. pub fn with_float(x: f64) -> Self { - Ieee64(unsafe { mem::transmute(x) }) + Ieee64(x.to_bits()) } /// Get the bitwise representation. @@ -931,6 +930,7 @@ impl IntoBytes for Ieee64 { mod tests { use super::*; use core::fmt::Display; + use core::mem; use core::str::FromStr; use core::{f32, f64}; use std::string::ToString; @@ -1069,51 +1069,51 @@ mod tests { #[test] fn format_uimm128() { - assert_eq!(Uimm128::from(0).to_string(), "0x00"); - assert_eq!(Uimm128::from(42).to_string(), "0x2a"); - assert_eq!(Uimm128::from(3735928559).to_string(), "0xdeadbeef"); + assert_eq!(V128Imm::from(0).to_string(), "0x00"); + assert_eq!(V128Imm::from(42).to_string(), "0x2a"); + assert_eq!(V128Imm::from(3735928559).to_string(), "0xdeadbeef"); assert_eq!( - Uimm128::from(0x0102030405060708).to_string(), + V128Imm::from(0x0102030405060708).to_string(), "0x0102030405060708" ); } #[test] fn parse_uimm128() { - parse_ok::<Uimm128>("0x00", "0x00"); - parse_ok::<Uimm128>("0x00000042", "0x42"); - parse_ok::<Uimm128>( + parse_ok::<V128Imm>("0x00", "0x00"); + parse_ok::<V128Imm>("0x00000042", "0x42"); + parse_ok::<V128Imm>( "0x0102030405060708090a0b0c0d0e0f00", "0x0102030405060708090a0b0c0d0e0f00", ); - parse_ok::<Uimm128>("0x_0000_0043_21", "0x4321"); + parse_ok::<V128Imm>("0x_0000_0043_21", "0x4321"); - parse_err::<Uimm128>("", "Expected a hexadecimal string, e.g. 0x1234"); - parse_err::<Uimm128>("0x", "Expected a hexadecimal string, e.g. 0x1234"); - parse_err::<Uimm128>( + parse_err::<V128Imm>("", "Expected a hexadecimal string, e.g. 0x1234"); + parse_err::<V128Imm>("0x", "Expected a hexadecimal string, e.g. 0x1234"); + parse_err::<V128Imm>( "0x042", "Hexadecimal string must have an even number of digits", ); - parse_err::<Uimm128>( + parse_err::<V128Imm>( "0x00000000000000000000000000000000000000000000000000", "Hexadecimal string has too many digits to fit in a 128-bit vector", ); - parse_err::<Uimm128>("0xrstu", "Unable to parse as hexadecimal"); - parse_err::<Uimm128>("0x__", "Hexadecimal string must have some digits"); + parse_err::<V128Imm>("0xrstu", "Unable to parse as hexadecimal"); + parse_err::<V128Imm>("0x__", "Hexadecimal string must have some digits"); } #[test] fn uimm128_equivalence() { assert_eq!( - "0x01".parse::<Uimm128>().unwrap().0, + "0x01".parse::<V128Imm>().unwrap().0, [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] ); assert_eq!( - Uimm128::from_iter(vec![1, 0, 0, 0]).0, + V128Imm::from_iter(vec![1, 0, 0, 0]).0, [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] ); assert_eq!( - Uimm128::from(1).0, + V128Imm::from(1).0, [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] ); } @@ -1121,19 +1121,19 @@ mod tests { #[test] fn uimm128_endianness() { assert_eq!( - "0x42".parse::<Uimm128>().unwrap().0, + "0x42".parse::<V128Imm>().unwrap().0, [0x42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] ); assert_eq!( - "0x00".parse::<Uimm128>().unwrap().0, + "0x00".parse::<V128Imm>().unwrap().0, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] ); assert_eq!( - "0x12345678".parse::<Uimm128>().unwrap().0, + "0x12345678".parse::<V128Imm>().unwrap().0, [0x78, 0x56, 0x34, 0x12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] ); assert_eq!( - "0x1234_5678".parse::<Uimm128>().unwrap().0, + "0x1234_5678".parse::<V128Imm>().unwrap().0, [0x78, 0x56, 0x34, 0x12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] ); } @@ -1141,17 +1141,17 @@ mod tests { #[test] fn uimm128_from_iter() { assert_eq!( - Uimm128::from_iter(vec![4, 3, 2, 1]).0, + V128Imm::from_iter(vec![4, 3, 2, 1]).0, [4, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0] ); assert_eq!( - Uimm128::from_iter(vec![false, true]).0, + V128Imm::from_iter(vec![false, true]).0, [/* false */ 0, 0, 0, 0, 0, 0, 0, 0, /* true */ 1, 0, 0, 0, 0, 0, 0, 0] ); assert_eq!( - Uimm128::from_iter(vec![false, true, false, true, false, true, false, true]).0, + V128Imm::from_iter(vec![false, true, false, true, false, true, false, true]).0, [0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0] ); @@ -1160,7 +1160,7 @@ mod tests { 1 as u8, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0, ]; assert_eq!( - Uimm128::from_iter(u8s).0, + V128Imm::from_iter(u8s).0, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0] ); @@ -1170,7 +1170,7 @@ mod tests { .map(|&f| Ieee32::from(f)) .collect(); assert_eq!( - Uimm128::from_iter(ieee32s).0, + V128Imm::from_iter(ieee32s).0, [ /* 32.4 == */ 0x9a, 0x99, 0x01, 0x42, /* 0 == */ 0, 0, 0, 0, /* 1 == */ 0, 0, 0x80, 0x3f, /* 6.6666 == */ 0xca, 0x54, 0xd5, 0x40, diff --git a/third_party/rust/cranelift-codegen/src/ir/instructions.rs b/third_party/rust/cranelift-codegen/src/ir/instructions.rs index 30e8d14689eabf4329870e936d3e85a705cf81b9..b3c3d0d2115d21969a8d7b9f1519ddb62ff80e94 100644 --- a/third_party/rust/cranelift-codegen/src/ir/instructions.rs +++ b/third_party/rust/cranelift-codegen/src/ir/instructions.rs @@ -18,7 +18,6 @@ use crate::isa; use crate::bitset::BitSet; use crate::entity; -use crate::ref_slice::{ref_slice, ref_slice_mut}; /// Some instructions use an external list of argument values because there is not enough space in /// the 16-byte `InstructionData` struct. These value lists are stored in a memory pool in diff --git a/third_party/rust/cranelift-codegen/src/ir/layout.rs b/third_party/rust/cranelift-codegen/src/ir/layout.rs index 78a46285767ee1daac2e0d41cdc63dc0f114521f..632c03dc590dbe1566b59ba58852541d8305d5a0 100644 --- a/third_party/rust/cranelift-codegen/src/ir/layout.rs +++ b/third_party/rust/cranelift-codegen/src/ir/layout.rs @@ -698,7 +698,7 @@ impl Layout { #[derive(Clone, Debug, Default)] struct InstNode { - // The Ebb containing this instruction, or `None` if the instruction is not yet inserted. + /// The Ebb containing this instruction, or `None` if the instruction is not yet inserted. ebb: PackedOption<Ebb>, prev: PackedOption<Inst>, next: PackedOption<Inst>, diff --git a/third_party/rust/cranelift-codegen/src/ir/mod.rs b/third_party/rust/cranelift-codegen/src/ir/mod.rs index 930f5d496d79dbdb5d5b4639b6bea0a6f89d3323..2ee589f6af948b331463482301bd10e1520eae9c 100644 --- a/third_party/rust/cranelift-codegen/src/ir/mod.rs +++ b/third_party/rust/cranelift-codegen/src/ir/mod.rs @@ -1,7 +1,6 @@ //! Representation of Cranelift IR functions. mod builder; -pub mod condcodes; pub mod constant; pub mod dfg; pub mod entities; @@ -31,7 +30,8 @@ pub use crate::ir::builder::{InsertBuilder, InstBuilder, InstBuilderBase, InstIn pub use crate::ir::constant::{ConstantData, ConstantOffset, ConstantPool}; pub use crate::ir::dfg::{DataFlowGraph, ValueDef}; pub use crate::ir::entities::{ - Constant, Ebb, FuncRef, GlobalValue, Heap, Inst, JumpTable, SigRef, StackSlot, Table, Value, + Constant, Ebb, FuncRef, GlobalValue, Heap, Immediate, Inst, JumpTable, SigRef, StackSlot, + Table, Value, }; pub use crate::ir::extfunc::{ AbiParam, ArgumentExtension, ArgumentPurpose, ExtFuncData, Signature, @@ -54,6 +54,7 @@ pub use crate::ir::table::TableData; pub use crate::ir::trapcode::TrapCode; pub use crate::ir::types::Type; pub use crate::ir::valueloc::{ArgumentLoc, ValueLoc}; +pub use cranelift_codegen_shared::condcodes; use crate::binemit; use crate::entity::{entity_impl, PrimaryMap, SecondaryMap}; diff --git a/third_party/rust/cranelift-codegen/src/ir/trapcode.rs b/third_party/rust/cranelift-codegen/src/ir/trapcode.rs index 273a77670cc9ef617559af47aa8064e301e735b9..5621e1d91cf3e39abc42071b05429e9720718725 100644 --- a/third_party/rust/cranelift-codegen/src/ir/trapcode.rs +++ b/third_party/rust/cranelift-codegen/src/ir/trapcode.rs @@ -2,11 +2,14 @@ use core::fmt::{self, Display, Formatter}; use core::str::FromStr; +#[cfg(feature = "enable-serde")] +use serde::{Deserialize, Serialize}; /// A trap code describing the reason for a trap. /// /// All trap instructions have an explicit trap code. #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] +#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] pub enum TrapCode { /// The current stack space was exhausted. /// diff --git a/third_party/rust/cranelift-codegen/src/isa/arm32/mod.rs b/third_party/rust/cranelift-codegen/src/isa/arm32/mod.rs index ced1b88767e9c1aad1a37ff848cd73da157c1f7a..ed5854593b651d933b3cf1f7d46e7330593a69c0 100644 --- a/third_party/rust/cranelift-codegen/src/isa/arm32/mod.rs +++ b/third_party/rust/cranelift-codegen/src/isa/arm32/mod.rs @@ -126,6 +126,14 @@ impl TargetIsa for Isa { fn emit_function_to_memory(&self, func: &ir::Function, sink: &mut MemoryCodeSink) { emit_function(func, binemit::emit_inst, sink, self) } + + fn unsigned_add_overflow_condition(&self) -> ir::condcodes::IntCC { + ir::condcodes::IntCC::UnsignedLessThan + } + + fn unsigned_sub_overflow_condition(&self) -> ir::condcodes::IntCC { + ir::condcodes::IntCC::UnsignedGreaterThanOrEqual + } } impl fmt::Display for Isa { diff --git a/third_party/rust/cranelift-codegen/src/isa/arm64/mod.rs b/third_party/rust/cranelift-codegen/src/isa/arm64/mod.rs index d787524a6a8c7ab7ba5fa6b8f43850b574fb0253..71ae93c0fe50d60ab95b6596d58685c7ad13009c 100644 --- a/third_party/rust/cranelift-codegen/src/isa/arm64/mod.rs +++ b/third_party/rust/cranelift-codegen/src/isa/arm64/mod.rs @@ -114,6 +114,14 @@ impl TargetIsa for Isa { fn emit_function_to_memory(&self, func: &ir::Function, sink: &mut MemoryCodeSink) { emit_function(func, binemit::emit_inst, sink, self) } + + fn unsigned_add_overflow_condition(&self) -> ir::condcodes::IntCC { + ir::condcodes::IntCC::UnsignedLessThan + } + + fn unsigned_sub_overflow_condition(&self) -> ir::condcodes::IntCC { + ir::condcodes::IntCC::UnsignedGreaterThanOrEqual + } } impl fmt::Display for Isa { diff --git a/third_party/rust/cranelift-codegen/src/isa/mod.rs b/third_party/rust/cranelift-codegen/src/isa/mod.rs index c36d29ce2b74249a6df6d06b2aa68767e506bb50..6457eb9ad792a93784ba686958c48f387381c647 100644 --- a/third_party/rust/cranelift-codegen/src/isa/mod.rs +++ b/third_party/rust/cranelift-codegen/src/isa/mod.rs @@ -371,4 +371,10 @@ pub trait TargetIsa: fmt::Display + Sync { /// Emit a whole function into memory. fn emit_function_to_memory(&self, func: &ir::Function, sink: &mut binemit::MemoryCodeSink); + + /// IntCC condition for Unsigned Addition Overflow (Carry). + fn unsigned_add_overflow_condition(&self) -> ir::condcodes::IntCC; + + /// IntCC condition for Unsigned Subtraction Overflow (Borrow/Carry). + fn unsigned_sub_overflow_condition(&self) -> ir::condcodes::IntCC; } diff --git a/third_party/rust/cranelift-codegen/src/isa/riscv/mod.rs b/third_party/rust/cranelift-codegen/src/isa/riscv/mod.rs index 233e92a3bbfb0dc6d2702e5d1a5dce754626ca36..93ef3787f0e79914433515d4c548f425ba30ab50 100644 --- a/third_party/rust/cranelift-codegen/src/isa/riscv/mod.rs +++ b/third_party/rust/cranelift-codegen/src/isa/riscv/mod.rs @@ -121,6 +121,14 @@ impl TargetIsa for Isa { fn emit_function_to_memory(&self, func: &ir::Function, sink: &mut MemoryCodeSink) { emit_function(func, binemit::emit_inst, sink, self) } + + fn unsigned_add_overflow_condition(&self) -> ir::condcodes::IntCC { + unimplemented!() + } + + fn unsigned_sub_overflow_condition(&self) -> ir::condcodes::IntCC { + unimplemented!() + } } #[cfg(test)] diff --git a/third_party/rust/cranelift-codegen/src/isa/x86/binemit.rs b/third_party/rust/cranelift-codegen/src/isa/x86/binemit.rs index a5924ed0303123c244909b87fb387e47fc6ad36a..cda6ae58074f76231988f9b0bcfd5c0c02629dd9 100644 --- a/third_party/rust/cranelift-codegen/src/isa/x86/binemit.rs +++ b/third_party/rust/cranelift-codegen/src/isa/x86/binemit.rs @@ -272,8 +272,8 @@ fn sib<CS: CodeSink + ?Sized>(scale: u8, index: RegUnit, base: RegUnit, sink: &m fn icc2opc(cond: IntCC) -> u16 { use crate::ir::condcodes::IntCC::*; match cond { - // 0x0 = Overflow. - // 0x1 = !Overflow. + Overflow => 0x0, + NotOverflow => 0x1, UnsignedLessThan => 0x2, UnsignedGreaterThanOrEqual => 0x3, Equal => 0x4, diff --git a/third_party/rust/cranelift-codegen/src/isa/x86/enc_tables.rs b/third_party/rust/cranelift-codegen/src/isa/x86/enc_tables.rs index f67d7f0b69831b3c7104de43fe43ba58ac96187e..94333116e66c7a31da9421bc71b113c2e34e7b53 100644 --- a/third_party/rust/cranelift-codegen/src/isa/x86/enc_tables.rs +++ b/third_party/rust/cranelift-codegen/src/isa/x86/enc_tables.rs @@ -406,12 +406,16 @@ fn expand_fcvt_from_uint( let mut pos = FuncCursor::new(func).at_inst(inst); pos.use_srcloc(inst); - // Conversion from unsigned 32-bit is easy on x86-64. - // TODO: This should be guarded by an ISA check. - if xty == ir::types::I32 { - let wide = pos.ins().uextend(ir::types::I64, x); - pos.func.dfg.replace(inst).fcvt_from_sint(ty, wide); - return; + // Conversion from an unsigned int smaller than 64bit is easy on x86-64. + match xty { + ir::types::I8 | ir::types::I16 | ir::types::I32 => { + // TODO: This should be guarded by an ISA check. + let wide = pos.ins().uextend(ir::types::I64, x); + pos.func.dfg.replace(inst).fcvt_from_sint(ty, wide); + return; + } + ir::types::I64 => {} + _ => unimplemented!(), } let old_ebb = pos.func.layout.pp_ebb(inst); @@ -895,6 +899,80 @@ fn expand_fcvt_to_uint_sat( cfg.recompute_ebb(pos.func, done); } +/// Convert shuffle instructions. +fn convert_shuffle( + inst: ir::Inst, + func: &mut ir::Function, + _cfg: &mut ControlFlowGraph, + _isa: &dyn TargetIsa, +) { + let mut pos = FuncCursor::new(func).at_inst(inst); + pos.use_srcloc(inst); + + if let ir::InstructionData::Shuffle { args, mask, .. } = pos.func.dfg[inst] { + // A mask-building helper: in 128-bit SIMD, 0-15 indicate which lane to read from and a 1 + // in the most significant position zeroes the lane. + let zero_unknown_lane_index = |b: u8| if b > 15 { 0b10000000 } else { b }; + + // We only have to worry about aliasing here because copies will be introduced later (in + // regalloc). + let a = pos.func.dfg.resolve_aliases(args[0]); + let b = pos.func.dfg.resolve_aliases(args[1]); + let mask = pos + .func + .dfg + .immediates + .get(mask) + .expect("The shuffle immediate should have been recorded before this point") + .clone(); + if a == b { + // PSHUFB the first argument (since it is the same as the second). + let constructed_mask = mask + .iter() + // If the mask is greater than 15 it still may be referring to a lane in b. + .map(|&b| if b > 15 { b.wrapping_sub(16) } else { b }) + .map(zero_unknown_lane_index) + .collect(); + let handle = pos.func.dfg.constants.insert(constructed_mask); + // Move the built mask into another XMM register. + let a_type = pos.func.dfg.value_type(a); + let mask_value = pos.ins().vconst(a_type, handle); + // Shuffle the single incoming argument. + pos.func.dfg.replace(inst).x86_pshufb(a, mask_value); + } else { + // PSHUFB the first argument, placing zeroes for unused lanes. + let constructed_mask = mask.iter().cloned().map(zero_unknown_lane_index).collect(); + let handle = pos.func.dfg.constants.insert(constructed_mask); + // Move the built mask into another XMM register. + let a_type = pos.func.dfg.value_type(a); + let mask_value = pos.ins().vconst(a_type, handle); + // Shuffle the first argument. + let shuffled_first_arg = pos.ins().x86_pshufb(a, mask_value); + + // PSHUFB the second argument, placing zeroes for unused lanes. + let constructed_mask = mask + .iter() + .map(|b| b.wrapping_sub(16)) + .map(zero_unknown_lane_index) + .collect(); + let handle = pos.func.dfg.constants.insert(constructed_mask); + // Move the built mask into another XMM register. + let b_type = pos.func.dfg.value_type(b); + let mask_value = pos.ins().vconst(b_type, handle); + // Shuffle the second argument. + let shuffled_second_arg = pos.ins().x86_pshufb(b, mask_value); + + // OR the vectors together to form the final shuffled value. + pos.func + .dfg + .replace(inst) + .bor(shuffled_first_arg, shuffled_second_arg); + + // TODO when AVX512 is enabled we should replace this sequence with a single VPERMB + }; + } +} + /// Because floats already exist in XMM registers, we can keep them there when executing a CLIF /// extractlane instruction fn convert_extractlane( diff --git a/third_party/rust/cranelift-codegen/src/isa/x86/mod.rs b/third_party/rust/cranelift-codegen/src/isa/x86/mod.rs index 52ab055440f74cd89f331dc6ab7beca94c9b7aeb..8136170cd70039e9df29e80fe690318d81697920 100644 --- a/third_party/rust/cranelift-codegen/src/isa/x86/mod.rs +++ b/third_party/rust/cranelift-codegen/src/isa/x86/mod.rs @@ -142,6 +142,14 @@ impl TargetIsa for Isa { let _tt = timing::prologue_epilogue(); abi::prologue_epilogue(func, self) } + + fn unsigned_add_overflow_condition(&self) -> ir::condcodes::IntCC { + ir::condcodes::IntCC::UnsignedLessThan + } + + fn unsigned_sub_overflow_condition(&self) -> ir::condcodes::IntCC { + ir::condcodes::IntCC::UnsignedLessThan + } } impl fmt::Display for Isa { diff --git a/third_party/rust/cranelift-codegen/src/legalizer/heap.rs b/third_party/rust/cranelift-codegen/src/legalizer/heap.rs index 332553e803f97291fcde141f48c10008d20f4086..a6d9d9637d34392fbf835a04bcd887e8f94ef7fd 100644 --- a/third_party/rust/cranelift-codegen/src/legalizer/heap.rs +++ b/third_party/rust/cranelift-codegen/src/legalizer/heap.rs @@ -83,7 +83,11 @@ fn dynamic_addr( // We need an overflow check for the adjusted offset. let access_size_val = pos.ins().iconst(offset_ty, access_size as i64); let (adj_offset, overflow) = pos.ins().iadd_ifcout(offset, access_size_val); - pos.ins().trapnz(overflow, ir::TrapCode::HeapOutOfBounds); + pos.ins().trapif( + isa.unsigned_add_overflow_condition(), + overflow, + ir::TrapCode::HeapOutOfBounds, + ); oob = pos .ins() .icmp(IntCC::UnsignedGreaterThan, adj_offset, bound); diff --git a/third_party/rust/cranelift-codegen/src/lib.rs b/third_party/rust/cranelift-codegen/src/lib.rs index 1e97dfd6e0d17672ee848ee2159e34ef340fa8a3..73f2114561d6584a9998e4b203e6552f8126f8b7 100644 --- a/third_party/rust/cranelift-codegen/src/lib.rs +++ b/third_party/rust/cranelift-codegen/src/lib.rs @@ -95,7 +95,6 @@ mod partition_slice; mod postopt; mod predicates; mod redundant_reload_remover; -mod ref_slice; mod regalloc; mod result; mod scoped_hash_map; diff --git a/third_party/rust/cranelift-codegen/src/predicates.rs b/third_party/rust/cranelift-codegen/src/predicates.rs index f9005461116bd82f7fdd4be1efdfde4fda21a658..16672b145b80482959a972034c7adf3206b7d64f 100644 --- a/third_party/rust/cranelift-codegen/src/predicates.rs +++ b/third_party/rust/cranelift-codegen/src/predicates.rs @@ -31,6 +31,18 @@ pub fn is_zero_32_bit_float<T: Into<ir::immediates::Ieee32>>(x: T) -> bool { x32.bits() == 0 } +/// Check that a 128-bit vector contains all zeroes. +#[allow(dead_code)] +pub fn is_all_zeroes_128_bit<'b, T: PartialEq<&'b [u8; 16]>>(x: T) -> bool { + x.eq(&&[0; 16]) +} + +/// Check that a 128-bit vector contains all ones. +#[allow(dead_code)] +pub fn is_all_ones_128_bit<'b, T: PartialEq<&'b [u8; 16]>>(x: T) -> bool { + x.eq(&&[0xff; 16]) +} + /// Check that `x` is the same as `y`. #[allow(dead_code)] pub fn is_equal<T: Eq + Copy, O: Into<T> + Copy>(x: T, y: O) -> bool { @@ -109,4 +121,19 @@ mod tests { assert!(!is_signed_int(x1, 16, 4)); assert!(!is_signed_int(x2, 16, 4)); } + + #[test] + fn is_all_zeroes() { + assert!(is_all_zeroes_128_bit(&[0; 16])); + assert!(is_all_zeroes_128_bit(vec![ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + ])); + assert!(!is_all_zeroes_128_bit(&[1; 16])); + } + + #[test] + fn is_all_ones() { + assert!(!is_all_ones_128_bit(&[0; 16])); + assert!(is_all_ones_128_bit(&[0xff; 16])); + } } diff --git a/third_party/rust/cranelift-codegen/src/ref_slice.rs b/third_party/rust/cranelift-codegen/src/ref_slice.rs deleted file mode 100644 index 2fad921cea31a487e0688a1c102706d8e8975933..0000000000000000000000000000000000000000 --- a/third_party/rust/cranelift-codegen/src/ref_slice.rs +++ /dev/null @@ -1,18 +0,0 @@ -//! Functions for converting a reference into a singleton slice. -//! -//! See also the [`ref_slice` crate](https://crates.io/crates/ref_slice). -//! -//! We define the functions here to avoid external dependencies, and to ensure that they are -//! inlined in this crate. -//! -//! Despite their using an unsafe block, these functions are completely safe. - -use core::slice; - -pub fn ref_slice<T>(s: &T) -> &[T] { - unsafe { slice::from_raw_parts(s, 1) } -} - -pub fn ref_slice_mut<T>(s: &mut T) -> &mut [T] { - unsafe { slice::from_raw_parts_mut(s, 1) } -} diff --git a/third_party/rust/cranelift-codegen/src/regalloc/coalescing.rs b/third_party/rust/cranelift-codegen/src/regalloc/coalescing.rs index 4ba19ebbf4713aef49011d2ffead285510630db9..8a1f1d81bb622458468bf2967d3c99e779ce0126 100644 --- a/third_party/rust/cranelift-codegen/src/regalloc/coalescing.rs +++ b/third_party/rust/cranelift-codegen/src/regalloc/coalescing.rs @@ -199,7 +199,8 @@ impl<'a> Context<'a> { if self.liveness[param].reaches_use( pred_inst, pred_ebb, - self.liveness.context(&self.func.layout), + self.liveness.forest(), + &self.func.layout, ) { self.isolate_param(ebb, param); } @@ -240,7 +241,6 @@ impl<'a> Context<'a> { // `ebb`, it can never be used as an EBB argument. let interference = { let lr = &self.liveness[arg]; - let ctx = self.liveness.context(&self.func.layout); // There are two ways the argument value can interfere with `ebb`: // @@ -255,7 +255,7 @@ impl<'a> Context<'a> { ); // The only other possibility is that `arg` is live-in to `ebb`. - lr.is_livein(ebb, ctx) + lr.is_livein(ebb, self.liveness.forest(), &self.func.layout) }; if interference { @@ -435,8 +435,12 @@ impl<'a> Context<'a> { // Check for interference between `parent` and `value`. Since `parent` dominates // `value`, we only have to check if it overlaps the definition. - let ctx = self.liveness.context(&self.func.layout); - if self.liveness[parent.value].overlaps_def(node.def, node.ebb, ctx) { + if self.liveness[parent.value].overlaps_def( + node.def, + node.ebb, + self.liveness.forest(), + &self.func.layout, + ) { // The two values are interfering, so they can't be in the same virtual register. debug!("-> interference: {} overlaps def of {}", parent, value); return false; @@ -593,7 +597,6 @@ impl<'a> Context<'a> { // This gives us the closest dominating value def for each of the values. self.forest.clear(); self.values.clear(); - let ctx = self.liveness.context(&self.func.layout); for node in nodes { // Accumulate ordered values for the new vreg. if node.is_value() { @@ -623,7 +626,12 @@ impl<'a> Context<'a> { // Check if the parent value interferes with the virtual copy. let inst = node.def.unwrap_inst(); if node.set_id != parent.set_id - && self.liveness[parent.value].reaches_use(inst, node.ebb, ctx) + && self.liveness[parent.value].reaches_use( + inst, + node.ebb, + self.liveness.forest(), + &self.func.layout, + ) { debug!( " - interference: {} overlaps vcopy at {}:{}", @@ -647,7 +655,12 @@ impl<'a> Context<'a> { // Both node and parent are values, so check for interference. debug_assert!(node.is_value() && parent.is_value()); if node.set_id != parent.set_id - && self.liveness[parent.value].overlaps_def(node.def, node.ebb, ctx) + && self.liveness[parent.value].overlaps_def( + node.def, + node.ebb, + self.liveness.forest(), + &self.func.layout, + ) { // The two values are interfering. debug!(" - interference: {} overlaps def of {}", parent, node.value); diff --git a/third_party/rust/cranelift-codegen/src/regalloc/coloring.rs b/third_party/rust/cranelift-codegen/src/regalloc/coloring.rs index 1e69c342a91218b3d836b16f29699843cba33771..23a546a479fd6b52e22e37a55eade6f34a0feb09 100644 --- a/third_party/rust/cranelift-codegen/src/regalloc/coloring.rs +++ b/third_party/rust/cranelift-codegen/src/regalloc/coloring.rs @@ -54,7 +54,7 @@ use crate::regalloc::affinity::Affinity; use crate::regalloc::diversion::RegDiversions; use crate::regalloc::live_value_tracker::{LiveValue, LiveValueTracker}; use crate::regalloc::liveness::Liveness; -use crate::regalloc::liverange::{LiveRange, LiveRangeContext}; +use crate::regalloc::liverange::{LiveRange, LiveRangeForest}; use crate::regalloc::register_set::RegisterSet; use crate::regalloc::solver::{Solver, SolverError}; use crate::timing; @@ -461,7 +461,7 @@ impl<'a> Context<'a> { "Can't handle EBB arguments: {}", self.cur.display_inst(inst) ); - self.undivert_regs(|lr, _| !lr.is_local()); + self.undivert_regs(|lr, _, _| !lr.is_local()); } } @@ -725,8 +725,13 @@ impl<'a> Context<'a> { // This code runs after calling `solver.inputs_done()` so we must identify // the new variable as killed or live-through. Always special-case the // pinned register as a through variable. - let ctx = self.liveness.context(&self.cur.func.layout); - if self.liveness[value].killed_at(inst, ctx.order.pp_ebb(inst), ctx) { + let layout = &self.cur.func.layout; + if self.liveness[value].killed_at( + inst, + layout.pp_ebb(inst), + self.liveness.forest(), + layout, + ) { self.solver.add_killed_var(value, op.regclass, cur_reg); } else { self.solver.add_through_var(value, op.regclass, cur_reg); @@ -755,7 +760,7 @@ impl<'a> Context<'a> { // // Values with a global live range that are not live in to `dest` could appear as branch // arguments, so they can't always be un-diverted. - self.undivert_regs(|lr, ctx| lr.is_livein(dest, ctx)); + self.undivert_regs(|lr, forest, layout| lr.is_livein(dest, forest, layout)); // Now handle the EBB arguments. let br_args = self.cur.func.dfg.inst_variable_args(inst); @@ -825,14 +830,14 @@ impl<'a> Context<'a> { /// are reallocated to their global register assignments. fn undivert_regs<Pred>(&mut self, mut pred: Pred) where - Pred: FnMut(&LiveRange, LiveRangeContext<Layout>) -> bool, + Pred: FnMut(&LiveRange, &LiveRangeForest, &Layout) -> bool, { for (&value, rdiv) in self.divert.iter() { let lr = self .liveness .get(value) .expect("Missing live range for diverted register"); - if pred(lr, self.liveness.context(&self.cur.func.layout)) { + if pred(lr, self.liveness.forest(), &self.cur.func.layout) { if let Affinity::Reg(rci) = lr.affinity { let rc = self.reginfo.rc(rci); // Stack diversions should not be possible here. They only live transiently @@ -1080,20 +1085,21 @@ impl<'a> Context<'a> { use crate::ir::instructions::BranchInfo::*; let inst = self.cur.current_inst().expect("Not on an instruction"); - let ctx = self.liveness.context(&self.cur.func.layout); + let layout = &self.cur.func.layout; + let forest = self.liveness.forest(); match self.cur.func.dfg.analyze_branch(inst) { NotABranch => false, SingleDest(ebb, _) => { let lr = &self.liveness[value]; - lr.is_livein(ebb, ctx) + lr.is_livein(ebb, forest, layout) } Table(jt, ebb) => { let lr = &self.liveness[value]; !lr.is_local() - && (ebb.map_or(false, |ebb| lr.is_livein(ebb, ctx)) + && (ebb.map_or(false, |ebb| lr.is_livein(ebb, forest, layout)) || self.cur.func.jump_tables[jt] .iter() - .any(|ebb| lr.is_livein(*ebb, ctx))) + .any(|ebb| lr.is_livein(*ebb, forest, layout))) } } } diff --git a/third_party/rust/cranelift-codegen/src/regalloc/live_value_tracker.rs b/third_party/rust/cranelift-codegen/src/regalloc/live_value_tracker.rs index 1b08862e37b25505821aac7b01b1f65749169ba9..adfe56c410ecd0702ec0c864311cf99ba7a2d756 100644 --- a/third_party/rust/cranelift-codegen/src/regalloc/live_value_tracker.rs +++ b/third_party/rust/cranelift-codegen/src/regalloc/live_value_tracker.rs @@ -191,7 +191,6 @@ impl LiveValueTracker { .idom_sets .get(&idom) .expect("No stored live set for dominator"); - let ctx = liveness.context(layout); // Get just the values that are live-in to `ebb`. for &value in idom_live_list.as_slice(&self.idom_pool) { let lr = liveness @@ -199,7 +198,7 @@ impl LiveValueTracker { .expect("Immediate dominator value has no live range"); // Check if this value is live-in here. - if let Some(endpoint) = lr.livein_local_end(ebb, ctx) { + if let Some(endpoint) = lr.livein_local_end(ebb, liveness.forest(), layout) { self.live.push(value, endpoint, lr); } } diff --git a/third_party/rust/cranelift-codegen/src/regalloc/liveness.rs b/third_party/rust/cranelift-codegen/src/regalloc/liveness.rs index 7b31aedd541ab9874b46293bc43306933c3eda9b..1ace6bf6d15116349410bdb752464dd2d1967204 100644 --- a/third_party/rust/cranelift-codegen/src/regalloc/liveness.rs +++ b/third_party/rust/cranelift-codegen/src/regalloc/liveness.rs @@ -181,7 +181,7 @@ use crate::ir::dfg::ValueDef; use crate::ir::{Ebb, Function, Inst, Layout, ProgramPoint, Value}; use crate::isa::{EncInfo, OperandConstraint, TargetIsa}; use crate::regalloc::affinity::Affinity; -use crate::regalloc::liverange::{LiveRange, LiveRangeContext, LiveRangeForest}; +use crate::regalloc::liverange::{LiveRange, LiveRangeForest}; use crate::timing; use core::mem; use core::ops::Index; @@ -314,16 +314,16 @@ impl Liveness { } } + /// Current forest storage. + pub fn forest(&self) -> &LiveRangeForest { + &self.forest + } + /// Current live ranges. pub fn ranges(&self) -> &LiveRangeSet { &self.ranges } - /// Get a context needed for working with a `LiveRange`. - pub fn context<'a>(&'a self, layout: &'a Layout) -> LiveRangeContext<'a, Layout> { - LiveRangeContext::new(layout, &self.forest) - } - /// Clear all data structures in this liveness analysis. pub fn clear(&mut self) { self.ranges.clear(); diff --git a/third_party/rust/cranelift-codegen/src/regalloc/liverange.rs b/third_party/rust/cranelift-codegen/src/regalloc/liverange.rs index 5629ea40ec2f94e9a62fd26f31471c1738484a8d..fb8fcc5fffbb0387e36da274fabbeddd35c30134 100644 --- a/third_party/rust/cranelift-codegen/src/regalloc/liverange.rs +++ b/third_party/rust/cranelift-codegen/src/regalloc/liverange.rs @@ -58,8 +58,16 @@ //! //! # Implementation notes //! -//! A few notes about the implementation of this data structure. This should not concern someone -//! only looking to use the public interface. +//! A few notes about the implementation of the live intervals field `liveins`. This should not +//! concern someone only looking to use the public interface. +//! +//! ## Current representation +//! +//! Our current implementation uses a B-tree map with the necessary interface for an efficient +//! implementation of coalescing, implemented as a generic data-structure bforest::Map. +//! +//! A `BTreeMap<Ebb, Inst>` could have been used for the live-in intervals, but it doesn't provide +//! the necessary API to make coalescing easy, nor does it optimize for our types' sizes. //! //! ## EBB ordering //! @@ -99,13 +107,6 @@ //! It is more complicated to work with, though, so it is probably not worth it. The performance //! benefits of switching to a numerical EBB order only appears if the binary search is doing //! EBB-EBB comparisons. -//! -//! ## B-tree representation -//! -//! A `BTreeMap<Ebb, Inst>` could also be used for the live-in intervals. It looks like the -//! standard library B-tree doesn't provide the necessary interface for an efficient implementation -//! of coalescing, so we would need to roll our own. -//! use crate::bforest; use crate::entity::SparseMapValue; @@ -141,13 +142,13 @@ use core::marker::PhantomData; /// Inserting new instructions in the layout is safe, but removing instructions is not. Besides the /// instructions using or defining their value, `LiveRange` structs can contain references to /// branch and jump instructions. -pub type LiveRange = GenLiveRange<Layout>; +pub type LiveRange = GenericLiveRange<Layout>; /// Generic live range implementation. /// /// The intended generic parameter is `PO=Layout`, but tests are simpler with a mock order. /// Use `LiveRange` instead of using this generic directly. -pub struct GenLiveRange<PO: ProgramOrder> { +pub struct GenericLiveRange<PO: ProgramOrder> { /// The value described by this live range. /// This member can't be modified in case the live range is stored in a `SparseMap`. value: Value, @@ -178,32 +179,6 @@ pub struct GenLiveRange<PO: ProgramOrder> { po: PhantomData<*const PO>, } -/// Context information needed to query a `LiveRange`. -pub struct LiveRangeContext<'a, PO: 'a + ProgramOrder> { - /// Ordering of EBBs. - pub order: &'a PO, - /// Memory pool. - pub forest: &'a bforest::MapForest<Ebb, Inst>, -} - -impl<'a, PO: ProgramOrder> LiveRangeContext<'a, PO> { - /// Make a new context. - pub fn new(order: &'a PO, forest: &'a bforest::MapForest<Ebb, Inst>) -> Self { - Self { order, forest } - } -} - -impl<'a, PO: ProgramOrder> Clone for LiveRangeContext<'a, PO> { - fn clone(&self) -> Self { - LiveRangeContext { - order: self.order, - forest: self.forest, - } - } -} - -impl<'a, PO: ProgramOrder> Copy for LiveRangeContext<'a, PO> {} - /// Forest of B-trees used for storing live ranges. pub type LiveRangeForest = bforest::MapForest<Ebb, Inst>; @@ -215,7 +190,23 @@ impl<'a, PO: ProgramOrder> bforest::Comparator<Ebb> for Cmp<'a, PO> { } } -impl<PO: ProgramOrder> GenLiveRange<PO> { +/// A simple helper macro to make comparisons more natural to read. +macro_rules! cmp { + ($order:ident, $a:ident > $b:expr) => { + $order.cmp($a, $b) == Ordering::Greater + }; + ($order:ident, $a:ident >= $b:expr) => { + $order.cmp($a, $b) != Ordering::Less + }; + ($order:ident, $a:ident < $b:expr) => { + $order.cmp($a, $b) == Ordering::Less + }; + ($order:ident, $a:ident <= $b:expr) => { + $order.cmp($a, $b) != Ordering::Greater + }; +} + +impl<PO: ProgramOrder> GenericLiveRange<PO> { /// Create a new live range for `value` defined at `def`. /// /// The live range will be created as dead, but it can be extended with `extend_in_ebb()`. @@ -252,15 +243,13 @@ impl<PO: ProgramOrder> GenLiveRange<PO> { // // We're assuming here that `to` never precedes `def_begin` in the same EBB, but we can't // check it without a method for getting `to`'s EBB. - if order.cmp(ebb, self.def_end) != Ordering::Greater - && order.cmp(to, self.def_begin) != Ordering::Less - { + if cmp!(order, ebb <= self.def_end) && cmp!(order, to >= self.def_begin) { let to_pp = to.into(); debug_assert_ne!( to_pp, self.def_begin, "Can't use value in the defining instruction." ); - if order.cmp(to, self.def_end) == Ordering::Greater { + if cmp!(order, to > self.def_end) { self.def_end = to_pp; } return false; @@ -274,7 +263,7 @@ impl<PO: ProgramOrder> GenLiveRange<PO> { if let Some(end) = c.goto(ebb) { // There's an interval beginning at `ebb`. See if it extends. first_time_livein = false; - if order.cmp(end, to) == Ordering::Less { + if cmp!(order, end < to) { *c.value_mut().unwrap() = to; } else { return first_time_livein; @@ -282,10 +271,10 @@ impl<PO: ProgramOrder> GenLiveRange<PO> { } else if let Some((_, end)) = c.prev() { // There's no interval beginning at `ebb`, but we could still be live-in at `ebb` with // a coalesced interval that begins before and ends after. - if order.cmp(end, ebb) == Ordering::Greater { + if cmp!(order, end > ebb) { // Yep, the previous interval overlaps `ebb`. first_time_livein = false; - if order.cmp(end, to) == Ordering::Less { + if cmp!(order, end < to) { *c.value_mut().unwrap() = to; } else { return first_time_livein; @@ -306,7 +295,7 @@ impl<PO: ProgramOrder> GenLiveRange<PO> { c.insert(ebb, to); } - // Now `c` to left pointing at an interval that ends in `to`. + // Now `c` is left pointing at an interval that ends in `to`. debug_assert_eq!(c.value(), Some(to)); // See if it can be coalesced with the following interval. @@ -370,13 +359,13 @@ impl<PO: ProgramOrder> GenLiveRange<PO> { /// If the live range is live through all of `ebb`, the terminator of `ebb` is a correct /// answer, but it is also possible that an even later program point is returned. So don't /// depend on the returned `Inst` to belong to `ebb`. - pub fn livein_local_end(&self, ebb: Ebb, ctx: LiveRangeContext<PO>) -> Option<Inst> { - let cmp = Cmp(ctx.order); + pub fn livein_local_end(&self, ebb: Ebb, forest: &LiveRangeForest, order: &PO) -> Option<Inst> { + let cmp = Cmp(order); self.liveins - .get_or_less(ebb, ctx.forest, &cmp) + .get_or_less(ebb, forest, &cmp) .and_then(|(_, inst)| { // We have an entry that ends at `inst`. - if ctx.order.cmp(inst, ebb) == Ordering::Greater { + if cmp!(order, inst > ebb) { Some(inst) } else { None @@ -387,16 +376,16 @@ impl<PO: ProgramOrder> GenLiveRange<PO> { /// Is this value live-in to `ebb`? /// /// An EBB argument is not considered to be live in. - pub fn is_livein(&self, ebb: Ebb, ctx: LiveRangeContext<PO>) -> bool { - self.livein_local_end(ebb, ctx).is_some() + pub fn is_livein(&self, ebb: Ebb, forest: &LiveRangeForest, order: &PO) -> bool { + self.livein_local_end(ebb, forest, order).is_some() } /// Get all the live-in intervals. /// /// Note that the intervals are stored in a compressed form so each entry may span multiple /// EBBs where the value is live in. - pub fn liveins<'a>(&'a self, ctx: LiveRangeContext<'a, PO>) -> bforest::MapIter<'a, Ebb, Inst> { - self.liveins.iter(ctx.forest) + pub fn liveins<'a>(&'a self, forest: &'a LiveRangeForest) -> bforest::MapIter<'a, Ebb, Inst> { + self.liveins.iter(forest) } /// Check if this live range overlaps a definition in `ebb`. @@ -404,7 +393,8 @@ impl<PO: ProgramOrder> GenLiveRange<PO> { &self, def: ExpandedProgramPoint, ebb: Ebb, - ctx: LiveRangeContext<PO>, + forest: &LiveRangeForest, + order: &PO, ) -> bool { // Two defs at the same program point always overlap, even if one is dead. if def == self.def_begin.into() { @@ -412,43 +402,40 @@ impl<PO: ProgramOrder> GenLiveRange<PO> { } // Check for an overlap with the local range. - if ctx.order.cmp(def, self.def_begin) != Ordering::Less - && ctx.order.cmp(def, self.def_end) == Ordering::Less - { + if cmp!(order, def >= self.def_begin) && cmp!(order, def < self.def_end) { return true; } // Check for an overlap with a live-in range. - match self.livein_local_end(ebb, ctx) { - Some(inst) => ctx.order.cmp(def, inst) == Ordering::Less, + match self.livein_local_end(ebb, forest, order) { + Some(inst) => cmp!(order, def < inst), None => false, } } /// Check if this live range reaches a use at `user` in `ebb`. - pub fn reaches_use(&self, user: Inst, ebb: Ebb, ctx: LiveRangeContext<PO>) -> bool { + pub fn reaches_use(&self, user: Inst, ebb: Ebb, forest: &LiveRangeForest, order: &PO) -> bool { // Check for an overlap with the local range. - if ctx.order.cmp(user, self.def_begin) == Ordering::Greater - && ctx.order.cmp(user, self.def_end) != Ordering::Greater - { + if cmp!(order, user > self.def_begin) && cmp!(order, user <= self.def_end) { return true; } // Check for an overlap with a live-in range. - match self.livein_local_end(ebb, ctx) { - Some(inst) => ctx.order.cmp(user, inst) != Ordering::Greater, + match self.livein_local_end(ebb, forest, order) { + Some(inst) => cmp!(order, user <= inst), None => false, } } /// Check if this live range is killed at `user` in `ebb`. - pub fn killed_at(&self, user: Inst, ebb: Ebb, ctx: LiveRangeContext<PO>) -> bool { - self.def_local_end() == user.into() || self.livein_local_end(ebb, ctx) == Some(user) + pub fn killed_at(&self, user: Inst, ebb: Ebb, forest: &LiveRangeForest, order: &PO) -> bool { + self.def_local_end() == user.into() + || self.livein_local_end(ebb, forest, order) == Some(user) } } /// Allow a `LiveRange` to be stored in a `SparseMap` indexed by values. -impl<PO: ProgramOrder> SparseMapValue<Value> for GenLiveRange<PO> { +impl<PO: ProgramOrder> SparseMapValue<Value> for GenericLiveRange<PO> { fn key(&self) -> Value { self.value } @@ -456,7 +443,7 @@ impl<PO: ProgramOrder> SparseMapValue<Value> for GenLiveRange<PO> { #[cfg(test)] mod tests { - use super::{GenLiveRange, LiveRangeContext}; + use super::GenericLiveRange; use crate::bforest; use crate::entity::EntityRef; use crate::ir::{Ebb, Inst, Value}; @@ -509,7 +496,11 @@ mod tests { } // Validate the live range invariants. - fn validate(&self, lr: &GenLiveRange<ProgOrder>, forest: &bforest::MapForest<Ebb, Inst>) { + fn validate( + &self, + lr: &GenericLiveRange<ProgOrder>, + forest: &bforest::MapForest<Ebb, Inst>, + ) { // The def interval must cover a single EBB. let def_ebb = self.pp_ebb(lr.def_begin); assert_eq!(def_ebb, self.pp_ebb(lr.def_end)); @@ -553,36 +544,34 @@ mod tests { let i1 = Inst::new(1); let i2 = Inst::new(2); let e2 = Ebb::new(2); - let lr = GenLiveRange::new(v0, i1.into(), Default::default()); + let lr = GenericLiveRange::new(v0, i1.into(), Default::default()); let forest = &bforest::MapForest::new(); - let ctx = LiveRangeContext::new(PO, forest); assert!(lr.is_dead()); assert!(lr.is_local()); assert_eq!(lr.def(), i1.into()); assert_eq!(lr.def_local_end(), i1.into()); - assert_eq!(lr.livein_local_end(e2, ctx), None); - PO.validate(&lr, ctx.forest); + assert_eq!(lr.livein_local_end(e2, forest, PO), None); + PO.validate(&lr, forest); // A dead live range overlaps its own def program point. - assert!(lr.overlaps_def(i1.into(), e0, ctx)); - assert!(!lr.overlaps_def(i2.into(), e0, ctx)); - assert!(!lr.overlaps_def(e0.into(), e0, ctx)); + assert!(lr.overlaps_def(i1.into(), e0, forest, PO)); + assert!(!lr.overlaps_def(i2.into(), e0, forest, PO)); + assert!(!lr.overlaps_def(e0.into(), e0, forest, PO)); } #[test] fn dead_arg_range() { let v0 = Value::new(0); let e2 = Ebb::new(2); - let lr = GenLiveRange::new(v0, e2.into(), Default::default()); + let lr = GenericLiveRange::new(v0, e2.into(), Default::default()); let forest = &bforest::MapForest::new(); - let ctx = LiveRangeContext::new(PO, forest); assert!(lr.is_dead()); assert!(lr.is_local()); assert_eq!(lr.def(), e2.into()); assert_eq!(lr.def_local_end(), e2.into()); // The def interval of an EBB argument does not count as live-in. - assert_eq!(lr.livein_local_end(e2, ctx), None); - PO.validate(&lr, ctx.forest); + assert_eq!(lr.livein_local_end(e2, forest, PO), None); + PO.validate(&lr, forest); } #[test] @@ -592,7 +581,7 @@ mod tests { let i11 = Inst::new(11); let i12 = Inst::new(12); let i13 = Inst::new(13); - let mut lr = GenLiveRange::new(v0, i11.into(), Default::default()); + let mut lr = GenericLiveRange::new(v0, i11.into(), Default::default()); let forest = &mut bforest::MapForest::new(); assert_eq!(lr.extend_in_ebb(e10, i13, PO, forest), false); @@ -616,7 +605,7 @@ mod tests { let i11 = Inst::new(11); let i12 = Inst::new(12); let i13 = Inst::new(13); - let mut lr = GenLiveRange::new(v0, e10.into(), Default::default()); + let mut lr = GenericLiveRange::new(v0, e10.into(), Default::default()); let forest = &mut bforest::MapForest::new(); // Extending a dead EBB argument in its own block should not indicate that a live-in @@ -651,7 +640,7 @@ mod tests { let i21 = Inst::new(21); let i22 = Inst::new(22); let i23 = Inst::new(23); - let mut lr = GenLiveRange::new(v0, i11.into(), Default::default()); + let mut lr = GenericLiveRange::new(v0, i11.into(), Default::default()); let forest = &mut bforest::MapForest::new(); assert_eq!(lr.extend_in_ebb(e10, i12, PO, forest), false); @@ -659,25 +648,16 @@ mod tests { // Adding a live-in interval. assert_eq!(lr.extend_in_ebb(e20, i22, PO, forest), true); PO.validate(&lr, forest); - assert_eq!( - lr.livein_local_end(e20, LiveRangeContext::new(PO, forest)), - Some(i22) - ); + assert_eq!(lr.livein_local_end(e20, forest, PO), Some(i22)); // Non-extending the live-in. assert_eq!(lr.extend_in_ebb(e20, i21, PO, forest), false); - assert_eq!( - lr.livein_local_end(e20, LiveRangeContext::new(PO, forest)), - Some(i22) - ); + assert_eq!(lr.livein_local_end(e20, forest, PO), Some(i22)); // Extending the existing live-in. assert_eq!(lr.extend_in_ebb(e20, i23, PO, forest), false); PO.validate(&lr, forest); - assert_eq!( - lr.livein_local_end(e20, LiveRangeContext::new(PO, forest)), - Some(i23) - ); + assert_eq!(lr.livein_local_end(e20, forest, PO), Some(i23)); } #[test] @@ -690,56 +670,33 @@ mod tests { let i31 = Inst::new(31); let e40 = Ebb::new(40); let i41 = Inst::new(41); - let mut lr = GenLiveRange::new(v0, i11.into(), Default::default()); + let mut lr = GenericLiveRange::new(v0, i11.into(), Default::default()); let forest = &mut bforest::MapForest::new(); assert_eq!(lr.extend_in_ebb(e30, i31, PO, forest), true); - assert_eq!( - lr.liveins(LiveRangeContext::new(PO, forest)) - .collect::<Vec<_>>(), - [(e30, i31)] - ); + assert_eq!(lr.liveins(forest).collect::<Vec<_>>(), [(e30, i31)]); // Coalesce to previous assert_eq!(lr.extend_in_ebb(e40, i41, PO, forest), true); - assert_eq!( - lr.liveins(LiveRangeContext::new(PO, forest)) - .collect::<Vec<_>>(), - [(e30, i41)] - ); + assert_eq!(lr.liveins(forest).collect::<Vec<_>>(), [(e30, i41)]); // Coalesce to next assert_eq!(lr.extend_in_ebb(e20, i21, PO, forest), true); - assert_eq!( - lr.liveins(LiveRangeContext::new(PO, forest)) - .collect::<Vec<_>>(), - [(e20, i41)] - ); + assert_eq!(lr.liveins(forest).collect::<Vec<_>>(), [(e20, i41)]); - let mut lr = GenLiveRange::new(v0, i11.into(), Default::default()); + let mut lr = GenericLiveRange::new(v0, i11.into(), Default::default()); assert_eq!(lr.extend_in_ebb(e40, i41, PO, forest), true); - assert_eq!( - lr.liveins(LiveRangeContext::new(PO, forest)) - .collect::<Vec<_>>(), - [(e40, i41)] - ); + assert_eq!(lr.liveins(forest).collect::<Vec<_>>(), [(e40, i41)]); assert_eq!(lr.extend_in_ebb(e20, i21, PO, forest), true); assert_eq!( - lr.liveins(LiveRangeContext::new(PO, forest)) - .collect::<Vec<_>>(), + lr.liveins(forest).collect::<Vec<_>>(), [(e20, i21), (e40, i41)] ); // Coalesce to previous and next assert_eq!(lr.extend_in_ebb(e30, i31, PO, forest), true); - assert_eq!( - lr.liveins(LiveRangeContext::new(PO, forest)) - .collect::<Vec<_>>(), - [(e20, i41)] - ); + assert_eq!(lr.liveins(forest).collect::<Vec<_>>(), [(e20, i41)]); } - - // TODO: Add more tests that exercise the binary search algorithm. } diff --git a/third_party/rust/cranelift-codegen/src/regalloc/spilling.rs b/third_party/rust/cranelift-codegen/src/regalloc/spilling.rs index f45dd41c94e5d894a64a84195aeffd33f8b19f45..0012ad01d85837eb12615c897bc4ddc9984cd31c 100644 --- a/third_party/rust/cranelift-codegen/src/regalloc/spilling.rs +++ b/third_party/rust/cranelift-codegen/src/regalloc/spilling.rs @@ -319,17 +319,18 @@ impl<'a> Context<'a> { for (idx, (op, &arg)) in constraints.ins.iter().zip(args).enumerate() { let mut reguse = RegUse::new(arg, idx, op.regclass.into()); let lr = &self.liveness[arg]; - let ctx = self.liveness.context(&self.cur.func.layout); match op.kind { ConstraintKind::Stack => continue, ConstraintKind::FixedReg(_) => reguse.fixed = true, ConstraintKind::Tied(_) => { // A tied operand must kill the used value. - reguse.tied = !lr.killed_at(inst, ebb, ctx); + reguse.tied = + !lr.killed_at(inst, ebb, self.liveness.forest(), &self.cur.func.layout); } ConstraintKind::FixedTied(_) => { reguse.fixed = true; - reguse.tied = !lr.killed_at(inst, ebb, ctx); + reguse.tied = + !lr.killed_at(inst, ebb, self.liveness.forest(), &self.cur.func.layout); } ConstraintKind::Reg => {} } diff --git a/third_party/rust/cranelift-codegen/src/regalloc/virtregs.rs b/third_party/rust/cranelift-codegen/src/regalloc/virtregs.rs index fc267c3f610d36af20aabb2112cb9bd5f4042917..df2b4804905ad4725967a1b7ebdb1158f3c838f2 100644 --- a/third_party/rust/cranelift-codegen/src/regalloc/virtregs.rs +++ b/third_party/rust/cranelift-codegen/src/regalloc/virtregs.rs @@ -18,9 +18,9 @@ use crate::entity::{EntityList, ListPool}; use crate::entity::{Keys, PrimaryMap, SecondaryMap}; use crate::ir::{Function, Value}; use crate::packed_option::PackedOption; -use crate::ref_slice::ref_slice; use core::cmp::Ordering; use core::fmt; +use core::slice; use smallvec::SmallVec; use std::vec::Vec; @@ -104,7 +104,7 @@ impl VirtRegs { 'a: 'b, { self.get(*value) - .map_or_else(|| ref_slice(value), |vr| self.values(vr)) + .map_or_else(|| slice::from_ref(value), |vr| self.values(vr)) } /// Check if `a` and `b` belong to the same congruence class. diff --git a/third_party/rust/cranelift-codegen/src/settings.rs b/third_party/rust/cranelift-codegen/src/settings.rs index 99d3647cbdeb778f79ef409346b4c2b73c35ebd9..c310972170f27fa884a3ab6a9a6be74677d963e7 100644 --- a/third_party/rust/cranelift-codegen/src/settings.rs +++ b/third_party/rust/cranelift-codegen/src/settings.rs @@ -14,10 +14,10 @@ //! use cranelift_codegen::settings::{self, Configurable}; //! //! let mut b = settings::builder(); -//! b.set("opt_level", "fastest"); +//! b.set("opt_level", "speed_and_size"); //! //! let f = settings::Flags::new(b); -//! assert_eq!(f.opt_level(), settings::OptLevel::Fastest); +//! assert_eq!(f.opt_level(), settings::OptLevel::SpeedAndSize); //! ``` use crate::constant_hash::{probe, simple_hash}; @@ -378,7 +378,7 @@ mod tests { assert_eq!( f.to_string(), "[shared]\n\ - opt_level = \"default\"\n\ + opt_level = \"none\"\n\ libcall_call_conv = \"isa_default\"\n\ baldrdash_prologue_words = 0\n\ probestack_size_log2 = 12\n\ @@ -398,7 +398,7 @@ mod tests { probestack_func_adjusts_sp = false\n\ jump_tables_enabled = true\n" ); - assert_eq!(f.opt_level(), super::OptLevel::Default); + assert_eq!(f.opt_level(), super::OptLevel::None); assert_eq!(f.enable_simd(), false); assert_eq!(f.baldrdash_prologue_words(), 0); } @@ -428,13 +428,15 @@ mod tests { ); assert_eq!( b.set("opt_level", "true"), - Err(BadValue("any among default, best, fastest".to_string())) + Err(BadValue( + "any among none, speed, speed_and_size".to_string() + )) ); - assert_eq!(b.set("opt_level", "best"), Ok(())); + assert_eq!(b.set("opt_level", "speed"), Ok(())); assert_eq!(b.set("enable_simd", "0"), Ok(())); let f = Flags::new(b); assert_eq!(f.enable_simd(), false); - assert_eq!(f.opt_level(), super::OptLevel::Best); + assert_eq!(f.opt_level(), super::OptLevel::Speed); } } diff --git a/third_party/rust/cranelift-codegen/src/topo_order.rs b/third_party/rust/cranelift-codegen/src/topo_order.rs index 7dcec7274b062eeeccef953338ccd25165d3ed4c..8824f4cc0a8dc298e3ffed56a63a5b13c1eeb461 100644 --- a/third_party/rust/cranelift-codegen/src/topo_order.rs +++ b/third_party/rust/cranelift-codegen/src/topo_order.rs @@ -1,7 +1,7 @@ //! Topological order of EBBs, according to the dominator tree. use crate::dominator_tree::DominatorTree; -use crate::entity::SparseSet; +use crate::entity::EntitySet; use crate::ir::{Ebb, Layout}; use std::vec::Vec; @@ -19,7 +19,7 @@ pub struct TopoOrder { next: usize, /// Set of visited EBBs. - visited: SparseSet<Ebb>, + visited: EntitySet<Ebb>, /// Stack of EBBs to be visited next, already in `visited`. stack: Vec<Ebb>, @@ -31,7 +31,7 @@ impl TopoOrder { Self { preferred: Vec::new(), next: 0, - visited: SparseSet::new(), + visited: EntitySet::new(), stack: Vec::new(), } } @@ -64,6 +64,7 @@ impl TopoOrder { /// - All EBBs in the `preferred` iterator given to `reset` will be returned. /// - All dominators are visited before the EBB returned. pub fn next(&mut self, layout: &Layout, domtree: &DominatorTree) -> Option<Ebb> { + self.visited.resize(layout.ebb_capacity()); // Any entries in `stack` should be returned immediately. They have already been added to // `visited`. while self.stack.is_empty() { @@ -73,7 +74,7 @@ impl TopoOrder { // We have the next EBB in the preferred order. self.next += 1; // Push it along with any non-visited dominators. - while self.visited.insert(ebb).is_none() { + while self.visited.insert(ebb) { self.stack.push(ebb); match domtree.idom(ebb) { Some(idom) => ebb = layout.inst_ebb(idom).expect("idom not in layout"), diff --git a/third_party/rust/cranelift-codegen/src/value_label.rs b/third_party/rust/cranelift-codegen/src/value_label.rs index 2bd3bdc13df703aed743e494f9de470ef05d82ab..d3d1e0672caa88b3902801c5ac8a929954cf0754 100644 --- a/third_party/rust/cranelift-codegen/src/value_label.rs +++ b/third_party/rust/cranelift-codegen/src/value_label.rs @@ -96,8 +96,8 @@ where ebbs.sort_by_key(|ebb| func.offsets[*ebb]); // Ensure inst offsets always increase let encinfo = isa.encoding_info(); let values_locations = &func.locations; - let liveness_context = regalloc.liveness().context(&func.layout); let liveness_ranges = regalloc.liveness().ranges(); + let liveness_forest = regalloc.liveness().forest(); let mut ranges = HashMap::new(); let mut add_range = |label, range: (u32, u32), loc: ValueLoc| { @@ -126,7 +126,10 @@ where // Remove killed values. tracked_values.retain(|(x, label, start_offset, last_loc)| { let range = liveness_ranges.get(*x); - if range.expect("value").killed_at(inst, ebb, liveness_context) { + if range + .expect("value") + .killed_at(inst, ebb, &liveness_forest, &func.layout) + { add_range(*label, (*start_offset, end_offset), *last_loc); return false; } @@ -173,7 +176,7 @@ where // Ignore dead/inactive Values. let range = liveness_ranges.get(*v); match range { - Some(r) => r.reaches_use(inst, ebb, liveness_context), + Some(r) => r.reaches_use(inst, ebb, &liveness_forest, &func.layout), None => false, } }); diff --git a/third_party/rust/cranelift-codegen/src/verifier/cssa.rs b/third_party/rust/cranelift-codegen/src/verifier/cssa.rs index 6014ff803043ac4622d5c092b5145f64bc0520a4..3878f096d19cebbf03aee7b060790a6ce8590a09 100644 --- a/third_party/rust/cranelift-codegen/src/verifier/cssa.rs +++ b/third_party/rust/cranelift-codegen/src/verifier/cssa.rs @@ -118,8 +118,12 @@ impl<'a> CssaVerifier<'a> { if self.preorder.dominates(prev_ebb, def_ebb) && self.domtree.dominates(prev_def, def, &self.func.layout) { - let ctx = self.liveness.context(&self.func.layout); - if self.liveness[prev_val].overlaps_def(def, def_ebb, ctx) { + if self.liveness[prev_val].overlaps_def( + def, + def_ebb, + self.liveness.forest(), + &self.func.layout, + ) { return fatal!( errors, val, diff --git a/third_party/rust/cranelift-codegen/src/verifier/flags.rs b/third_party/rust/cranelift-codegen/src/verifier/flags.rs index 43a235def5309bad2095c8dfe2169f99a5731a29..d39b6e048796556be094bf433511baf6e649c45e 100644 --- a/third_party/rust/cranelift-codegen/src/verifier/flags.rs +++ b/third_party/rust/cranelift-codegen/src/verifier/flags.rs @@ -1,6 +1,6 @@ //! Verify CPU flags values. -use crate::entity::{SecondaryMap, SparseSet}; +use crate::entity::{EntitySet, SecondaryMap}; use crate::flowgraph::{BasicBlock, ControlFlowGraph}; use crate::ir; use crate::ir::instructions::BranchInfo; @@ -50,7 +50,7 @@ impl<'a> FlagsVerifier<'a> { fn check(&mut self, errors: &mut VerifierErrors) -> VerifierStepResult<()> { // List of EBBs that need to be processed. EBBs may be re-added to this list when we detect // that one of their successor blocks needs a live-in flags value. - let mut worklist = SparseSet::new(); + let mut worklist = EntitySet::with_capacity(self.func.layout.ebb_capacity()); for ebb in self.func.layout.ebbs() { worklist.insert(ebb); } diff --git a/third_party/rust/cranelift-codegen/src/verifier/liveness.rs b/third_party/rust/cranelift-codegen/src/verifier/liveness.rs index c396a4680355ac8459b5ce2070a74024a93bd4ee..37b59c154dde1c93862629ccca30fd6f9b74c231 100644 --- a/third_party/rust/cranelift-codegen/src/verifier/liveness.rs +++ b/third_party/rust/cranelift-codegen/src/verifier/liveness.rs @@ -2,13 +2,12 @@ use crate::flowgraph::{BasicBlock, ControlFlowGraph}; use crate::ir::entities::AnyEntity; -use crate::ir::{ExpandedProgramPoint, Function, Inst, ProgramOrder, ProgramPoint, Value}; +use crate::ir::{ExpandedProgramPoint, Function, ProgramPoint, Value}; use crate::isa::TargetIsa; use crate::regalloc::liveness::Liveness; use crate::regalloc::liverange::LiveRange; use crate::timing; use crate::verifier::{VerifierErrors, VerifierStepResult}; -use core::cmp::Ordering; /// Verify liveness information for `func`. /// @@ -106,7 +105,9 @@ impl<'a> LivenessVerifier<'a> { Some(lr) => lr, None => return fatal!(errors, inst, "{} has no live range", val), }; - if !self.live_at_use(lr, inst) { + + debug_assert!(self.func.layout.inst_ebb(inst).unwrap() == ebb); + if !lr.reaches_use(inst, ebb, self.liveness.forest(), &self.func.layout) { return fatal!(errors, inst, "{} is not live at this use", val); } @@ -126,24 +127,6 @@ impl<'a> LivenessVerifier<'a> { Ok(()) } - /// Is `lr` live at the use `inst`? - fn live_at_use(&self, lr: &LiveRange, inst: Inst) -> bool { - let ctx = self.liveness.context(&self.func.layout); - - // Check if `inst` is in the def range, not including the def itself. - if ctx.order.cmp(lr.def(), inst) == Ordering::Less - && ctx.order.cmp(inst, lr.def_local_end()) != Ordering::Greater - { - return true; - } - - // Otherwise see if `inst` is in one of the live-in ranges. - match lr.livein_local_end(ctx.order.inst_ebb(inst).unwrap(), ctx) { - Some(end) => ctx.order.cmp(inst, end) != Ordering::Greater, - None => false, - } - } - /// Check the integrity of the live range `lr`. fn check_lr( &self, @@ -196,7 +179,7 @@ impl<'a> LivenessVerifier<'a> { } // Now check the live-in intervals against the CFG. - for (mut ebb, end) in lr.liveins(self.liveness.context(l)) { + for (mut ebb, end) in lr.liveins(self.liveness.forest()) { if !l.is_ebb_inserted(ebb) { return fatal!( errors, @@ -223,8 +206,8 @@ impl<'a> LivenessVerifier<'a> { // Check all the EBBs in the interval independently. loop { // If `val` is live-in at `ebb`, it must be live at all the predecessors. - for BasicBlock { inst: pred, .. } in self.cfg.pred_iter(ebb) { - if !self.live_at_use(lr, pred) { + for BasicBlock { inst: pred, ebb } in self.cfg.pred_iter(ebb) { + if !lr.reaches_use(pred, ebb, self.liveness.forest(), &self.func.layout) { return fatal!( errors, pred, diff --git a/third_party/rust/cranelift-codegen/src/verifier/locations.rs b/third_party/rust/cranelift-codegen/src/verifier/locations.rs index cf17ae13de669fdd8694d3a2de7c98f1401852a4..d32bb7e4bdc49dee0053db4456401d43832ba03e 100644 --- a/third_party/rust/cranelift-codegen/src/verifier/locations.rs +++ b/third_party/rust/cranelift-codegen/src/verifier/locations.rs @@ -334,10 +334,10 @@ impl<'a> LocationVerifier<'a> { let lr = &liveness[value]; if is_after_branch && unique_predecessor { // Forward diversions based on the targeted branch. - if !lr.is_livein(ebb, liveness.context(&self.func.layout)) { + if !lr.is_livein(ebb, liveness.forest(), &self.func.layout) { val_to_remove.push(value) } - } else if lr.is_livein(ebb, liveness.context(&self.func.layout)) { + } else if lr.is_livein(ebb, liveness.forest(), &self.func.layout) { return fatal!( errors, inst, @@ -359,7 +359,7 @@ impl<'a> LocationVerifier<'a> { for (&value, d) in divert.iter() { let lr = &liveness[value]; if let Some(ebb) = ebb { - if lr.is_livein(ebb, liveness.context(&self.func.layout)) { + if lr.is_livein(ebb, liveness.forest(), &self.func.layout) { return fatal!( errors, inst, @@ -371,7 +371,7 @@ impl<'a> LocationVerifier<'a> { } } for ebb in self.func.jump_tables[jt].iter() { - if lr.is_livein(*ebb, liveness.context(&self.func.layout)) { + if lr.is_livein(*ebb, liveness.forest(), &self.func.layout) { return fatal!( errors, inst, diff --git a/third_party/rust/cranelift-codegen/src/verifier/mod.rs b/third_party/rust/cranelift-codegen/src/verifier/mod.rs index 5bc10d9d92eb3344d91d2d6927347b639abf31f6..02cc3f0c526da3c233263048eec521be4343c4b7 100644 --- a/third_party/rust/cranelift-codegen/src/verifier/mod.rs +++ b/third_party/rust/cranelift-codegen/src/verifier/mod.rs @@ -696,10 +696,16 @@ impl<'a> Verifier<'a> { } } + Unary { + opcode: Opcode::Bitcast, + arg, + } => { + self.verify_bitcast(inst, arg, errors)?; + } + // Exhaustive list so we can't forget to add new formats Unary { .. } | UnaryImm { .. } - | UnaryImm128 { .. } | UnaryIeee32 { .. } | UnaryIeee64 { .. } | UnaryBool { .. } @@ -708,6 +714,8 @@ impl<'a> Verifier<'a> { | Ternary { .. } | InsertLane { .. } | ExtractLane { .. } + | UnaryConst { .. } + | Shuffle { .. } | IntCompare { .. } | IntCompareImm { .. } | IntCond { .. } @@ -981,6 +989,28 @@ impl<'a> Verifier<'a> { } } + fn verify_bitcast( + &self, + inst: Inst, + arg: Value, + errors: &mut VerifierErrors, + ) -> VerifierStepResult<()> { + let typ = self.func.dfg.ctrl_typevar(inst); + let value_type = self.func.dfg.value_type(arg); + + if typ.lane_bits() < value_type.lane_bits() { + fatal!( + errors, + inst, + "The bitcast argument {} doesn't fit in a type of {} bits", + arg, + typ.lane_bits() + ) + } else { + Ok(()) + } + } + fn domtree_integrity( &self, domtree: &DominatorTree, @@ -1746,21 +1776,47 @@ impl<'a> Verifier<'a> { ) -> VerifierStepResult<()> { let inst_data = &self.func.dfg[inst]; - // If this is some sort of a store instruction, get the memflags, else, just return. - let memflags = match *inst_data { + match *inst_data { ir::InstructionData::Store { flags, .. } - | ir::InstructionData::StoreComplex { flags, .. } => flags, - _ => return Ok(()), - }; - - if memflags.readonly() { - fatal!( - errors, - inst, - "A store instruction cannot have the `readonly` MemFlag" - ) - } else { - Ok(()) + | ir::InstructionData::StoreComplex { flags, .. } => { + if flags.readonly() { + fatal!( + errors, + inst, + "A store instruction cannot have the `readonly` MemFlag" + ) + } else { + Ok(()) + } + } + ir::InstructionData::ExtractLane { + opcode: ir::instructions::Opcode::Extractlane, + lane, + arg, + .. + } + | ir::InstructionData::InsertLane { + opcode: ir::instructions::Opcode::Insertlane, + lane, + args: [arg, _], + .. + } => { + // We must be specific about the opcodes above because other instructions are using + // the ExtractLane/InsertLane formats. + let ty = self.func.dfg.value_type(arg); + if u16::from(lane) >= ty.lane_count() { + fatal!( + errors, + inst, + "The lane {} does not index into the type {}", + lane, + ty + ) + } else { + Ok(()) + } + } + _ => Ok(()), } } @@ -1782,12 +1838,51 @@ impl<'a> Verifier<'a> { Ok(()) } + fn typecheck_function_signature(&self, errors: &mut VerifierErrors) -> VerifierStepResult<()> { + self.func + .signature + .params + .iter() + .enumerate() + .filter(|(_, ¶m)| param.value_type == types::INVALID) + .for_each(|(i, _)| { + report!( + errors, + AnyEntity::Function, + "Parameter at position {} has an invalid type", + i + ); + }); + + self.func + .signature + .returns + .iter() + .enumerate() + .filter(|(_, &ret)| ret.value_type == types::INVALID) + .for_each(|(i, _)| { + report!( + errors, + AnyEntity::Function, + "Return value at position {} has an invalid type", + i + ) + }); + + if errors.has_error() { + Err(()) + } else { + Ok(()) + } + } + pub fn run(&self, errors: &mut VerifierErrors) -> VerifierStepResult<()> { self.verify_global_values(errors)?; self.verify_heaps(errors)?; self.verify_tables(errors)?; self.verify_jump_tables(errors)?; self.typecheck_entry_block_params(errors)?; + self.typecheck_function_signature(errors)?; for ebb in self.func.layout.ebbs() { for inst in self.func.layout.ebb_insts(ebb) { @@ -1814,7 +1909,7 @@ mod tests { use super::{Verifier, VerifierError, VerifierErrors}; use crate::entity::EntityList; use crate::ir::instructions::{InstructionData, Opcode}; - use crate::ir::Function; + use crate::ir::{types, AbiParam, Function}; use crate::settings; macro_rules! assert_err_with_msg { @@ -1873,4 +1968,30 @@ mod tests { assert_err_with_msg!(errors, "instruction format"); } + + #[test] + fn test_function_invalid_param() { + let mut func = Function::new(); + func.signature.params.push(AbiParam::new(types::INVALID)); + + let mut errors = VerifierErrors::default(); + let flags = &settings::Flags::new(settings::builder()); + let verifier = Verifier::new(&func, flags.into()); + + let _ = verifier.typecheck_function_signature(&mut errors); + assert_err_with_msg!(errors, "Parameter at position 0 has an invalid type"); + } + + #[test] + fn test_function_invalid_return_value() { + let mut func = Function::new(); + func.signature.returns.push(AbiParam::new(types::INVALID)); + + let mut errors = VerifierErrors::default(); + let flags = &settings::Flags::new(settings::builder()); + let verifier = Verifier::new(&func, flags.into()); + + let _ = verifier.typecheck_function_signature(&mut errors); + assert_err_with_msg!(errors, "Return value at position 0 has an invalid type"); + } } diff --git a/third_party/rust/cranelift-codegen/src/write.rs b/third_party/rust/cranelift-codegen/src/write.rs index 4b616cab2ebb7123f738d7e7c8fa8c52730a2f4a..8d974c1ec54cba18f45a5193331feca06111b4df 100644 --- a/third_party/rust/cranelift-codegen/src/write.rs +++ b/third_party/rust/cranelift-codegen/src/write.rs @@ -5,7 +5,7 @@ use crate::entity::SecondaryMap; use crate::ir::entities::AnyEntity; -use crate::ir::immediates::Uimm128; +use crate::ir::immediates::V128Imm; use crate::ir::{ DataFlowGraph, DisplayFunctionAnnotations, Ebb, Function, Inst, SigRef, Type, Value, ValueDef, ValueLoc, @@ -488,11 +488,6 @@ pub fn write_operands( match dfg[inst] { Unary { arg, .. } => write!(w, " {}", arg), UnaryImm { imm, .. } => write!(w, " {}", imm), - UnaryImm128 { imm, .. } => { - let data = dfg.constants.get(imm); - let uimm128 = Uimm128::from(&data[..]); - write!(w, " {}", uimm128) - } UnaryIeee32 { imm, .. } => write!(w, " {}", imm), UnaryIeee64 { imm, .. } => write!(w, " {}", imm), UnaryBool { imm, .. } => write!(w, " {}", imm), @@ -510,6 +505,20 @@ pub fn write_operands( NullAry { .. } => write!(w, " "), InsertLane { lane, args, .. } => write!(w, " {}, {}, {}", args[0], lane, args[1]), ExtractLane { lane, arg, .. } => write!(w, " {}, {}", arg, lane), + UnaryConst { + constant_handle, .. + } => { + let data = dfg.constants.get(constant_handle); + let v128 = V128Imm::from(&data[..]); + write!(w, " {}", v128) + } + Shuffle { mask, args, .. } => { + let data = dfg.immediates.get(mask).expect( + "Expected the shuffle mask to already be inserted into the immediates table", + ); + let v128 = V128Imm::from(&data[..]); + write!(w, " {}, {}, {}", args[0], args[1], v128) + } IntCompare { cond, args, .. } => write!(w, " {} {}, {}", cond, args[0], args[1]), IntCompareImm { cond, arg, imm, .. } => write!(w, " {} {}, {}", cond, arg, imm), IntCond { cond, arg, .. } => write!(w, " {} {}", cond, arg), diff --git a/third_party/rust/cranelift-entity/.cargo-checksum.json b/third_party/rust/cranelift-entity/.cargo-checksum.json index b2f67d3a17f733f4690308a89a6f51b35767049f..898fbb1bd08b6593543e16abaf38dfa0ea8b0bbb 100644 --- a/third_party/rust/cranelift-entity/.cargo-checksum.json +++ b/third_party/rust/cranelift-entity/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"6625897aa38b637e103d905200be02306f4efd8fb06681d69ecf005468a965cb","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"96ceffbfd88fb06e3b41aa4d3087cffbbf8441d04eba7ab09662a72ab600a321","src/boxed_slice.rs":"687428ee0442013c0d5962dd78d0964830233bc4cb19aa530d30da0f1dc437a9","src/iter.rs":"4a4d3309fe9aad14fd7702f02459f4277b4ddb50dba700e58dcc75665ffebfb3","src/keys.rs":"b8c2fba26dee15bf3d1880bb2b41e8d66fe1428d242ee6d9fd30ee94bbd0407d","src/lib.rs":"c47e858b6a46f8b5f584ca7f83c466e0fa616bbed9cb28622c53d4c1faf197c4","src/list.rs":"fc3decc81bcef92e106aae53e586a0ef21d70916fa53a48f7b813c5da44b8dc2","src/map.rs":"7aa57f77ae010ceabbff08700eca020030ec8ca16342db1f7e7390d186b3c156","src/packed_option.rs":"9d47f5b8302ee685c096817e376144e363507d1c77ef562d3ae4dbddae568195","src/primary.rs":"8237b5c473fd219dc606efd7c989ec5216e4ae62c6cbb2857fbe11593c42aae9","src/set.rs":"97b860818c9577546201271f7ca457a5784c2e4447b68202a274f7fe75e937f2","src/sparse.rs":"cf345a81d69a5dddaed4778b6aaaf06c70da2c1fd4cd21e366ed6ca5906ffdab"},"package":null} \ No newline at end of file +{"files":{"Cargo.toml":"a355d658ab113a09938162676fde122551e54bd86be0699e3e763a0074b3c73f","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"96ceffbfd88fb06e3b41aa4d3087cffbbf8441d04eba7ab09662a72ab600a321","src/boxed_slice.rs":"687428ee0442013c0d5962dd78d0964830233bc4cb19aa530d30da0f1dc437a9","src/iter.rs":"4a4d3309fe9aad14fd7702f02459f4277b4ddb50dba700e58dcc75665ffebfb3","src/keys.rs":"b8c2fba26dee15bf3d1880bb2b41e8d66fe1428d242ee6d9fd30ee94bbd0407d","src/lib.rs":"c47e858b6a46f8b5f584ca7f83c466e0fa616bbed9cb28622c53d4c1faf197c4","src/list.rs":"fc3decc81bcef92e106aae53e586a0ef21d70916fa53a48f7b813c5da44b8dc2","src/map.rs":"7aa57f77ae010ceabbff08700eca020030ec8ca16342db1f7e7390d186b3c156","src/packed_option.rs":"9d47f5b8302ee685c096817e376144e363507d1c77ef562d3ae4dbddae568195","src/primary.rs":"8237b5c473fd219dc606efd7c989ec5216e4ae62c6cbb2857fbe11593c42aae9","src/set.rs":"eeb3b67030083aa6dd35c0ea7c50130d1cf6693ce302f902928440d5807d5472","src/sparse.rs":"cf345a81d69a5dddaed4778b6aaaf06c70da2c1fd4cd21e366ed6ca5906ffdab"},"package":null} \ No newline at end of file diff --git a/third_party/rust/cranelift-entity/Cargo.toml b/third_party/rust/cranelift-entity/Cargo.toml index 22b34d33d77df4cb8b789575903039ba17add429..65b9bc7aaae985d7e39716365ca45eea04cafd9b 100644 --- a/third_party/rust/cranelift-entity/Cargo.toml +++ b/third_party/rust/cranelift-entity/Cargo.toml @@ -1,7 +1,7 @@ [package] authors = ["The Cranelift Project Developers"] name = "cranelift-entity" -version = "0.42.0" +version = "0.44.0" description = "Data structures using entity references as mapping keys" license = "Apache-2.0 WITH LLVM-exception" documentation = "https://cranelift.readthedocs.io/" diff --git a/third_party/rust/cranelift-entity/src/set.rs b/third_party/rust/cranelift-entity/src/set.rs index a4759a17128fde1d9e244eb39a4208fd9201ed5b..fa74ba453fc1245fb74b1d3dfc810420e6e52712 100644 --- a/third_party/rust/cranelift-entity/src/set.rs +++ b/third_party/rust/cranelift-entity/src/set.rs @@ -33,6 +33,14 @@ where } } + /// Creates a new empty set with the specified capacity. + pub fn with_capacity(capacity: usize) -> Self { + Self { + elems: Vec::with_capacity((capacity + 7) / 8), + ..Self::new() + } + } + /// Get the element at `k` if it exists. pub fn contains(&self, k: K) -> bool { let index = k.index(); @@ -45,9 +53,11 @@ where /// Is this set completely empty? pub fn is_empty(&self) -> bool { - // Note that this implementation will become incorrect should it ever become possible - // to remove elements from an `EntitySet`. - self.len == 0 + if self.len != 0 { + false + } else { + self.elems.iter().all(|&e| e == 0) + } } /// Returns the cardinality of the set. More precisely, it returns the number of calls to @@ -93,6 +103,34 @@ where self.elems[index / 8] |= 1 << (index % 8); result } + + /// Removes and returns the entity from the set if it exists. + pub fn pop(&mut self) -> Option<K> { + if self.len == 0 { + return None; + } + + // Clear the last known entity in the list. + let last_index = self.len - 1; + self.elems[last_index / 8] &= !(1 << (last_index % 8)); + + // Set the length to the next last stored entity or zero if we pop'ed + // the last entity. + self.len = self + .elems + .iter() + .enumerate() + .rev() + .find(|(_, &byte)| byte != 0) + // Map `i` from byte index to bit level index. + // `(i + 1) * 8` = Last bit in byte. + // `last - byte.leading_zeros()` = last set bit in byte. + // `as usize` won't ever truncate as the potential range is `0..=8`. + .map(|(i, byte)| ((i + 1) * 8) - byte.leading_zeros() as usize) + .unwrap_or(0); + + Some(K::new(last_index)) + } } #[cfg(test)] @@ -101,7 +139,7 @@ mod tests { use core::u32; // `EntityRef` impl for testing. - #[derive(Clone, Copy, Debug, PartialEq, Eq)] + #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] struct E(u32); impl EntityRef for E { @@ -159,4 +197,51 @@ mod tests { m.clear(); assert!(m.is_empty()); } + + #[test] + fn pop_ordered() { + let r0 = E(0); + let r1 = E(1); + let r2 = E(2); + let mut m = EntitySet::new(); + m.insert(r0); + m.insert(r1); + m.insert(r2); + + assert_eq!(r2, m.pop().unwrap()); + assert_eq!(r1, m.pop().unwrap()); + assert_eq!(r0, m.pop().unwrap()); + assert!(m.pop().is_none()); + assert!(m.pop().is_none()); + } + + #[test] + fn pop_unordered() { + let mut ebbs = [ + E(0), + E(1), + E(6), + E(7), + E(5), + E(9), + E(10), + E(2), + E(3), + E(11), + E(12), + ]; + + let mut m = EntitySet::new(); + for &ebb in &ebbs { + m.insert(ebb); + } + assert_eq!(m.len, 13); + ebbs.sort(); + + for &ebb in ebbs.iter().rev() { + assert_eq!(ebb, m.pop().unwrap()); + } + + assert!(m.is_empty()); + } } diff --git a/third_party/rust/cranelift-frontend/.cargo-checksum.json b/third_party/rust/cranelift-frontend/.cargo-checksum.json index 8b9cdc8ba2ac7d5513f67468e4898200af305299..f8d531fc58aff87b7a803b45f0679eb4add142bb 100644 --- a/third_party/rust/cranelift-frontend/.cargo-checksum.json +++ b/third_party/rust/cranelift-frontend/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"d3ad74a39dc6d5efeb4c02171789e53f50b2ecbe34d4bd6dcfc7856b52e50be5","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"dea43e8044284df50f8b8772e9b48ba8b109b45c74111ff73619775d57ad8d67","src/frontend.rs":"3d306290ac5fa2f42cb97c5bae00b9baeefcbf20a911b1c3cd90ddcaaefe2bfe","src/lib.rs":"0e75d619694313f8f44d648ecffe18197844906aba7a1e3b8bb179c9c2389aa6","src/ssa.rs":"ca882f303e0ac8a269e77e511d657115fcb2bf739315dea43ee7828921048512","src/switch.rs":"5c540b9f0e5b805b9962c0079fec722fa63ad68d93fae1986fbc65e9cf15d16a","src/variable.rs":"f082efaa4b2d3c5eb48f6344149408074e1e15cb581f7a63f549313c7a1037be"},"package":null} \ No newline at end of file +{"files":{"Cargo.toml":"d664b9c245e2c8985efb57a604bd937b945549a3725d25f9e3825567dfb7946e","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"dea43e8044284df50f8b8772e9b48ba8b109b45c74111ff73619775d57ad8d67","src/frontend.rs":"3d306290ac5fa2f42cb97c5bae00b9baeefcbf20a911b1c3cd90ddcaaefe2bfe","src/lib.rs":"0e75d619694313f8f44d648ecffe18197844906aba7a1e3b8bb179c9c2389aa6","src/ssa.rs":"ca882f303e0ac8a269e77e511d657115fcb2bf739315dea43ee7828921048512","src/switch.rs":"5c540b9f0e5b805b9962c0079fec722fa63ad68d93fae1986fbc65e9cf15d16a","src/variable.rs":"f082efaa4b2d3c5eb48f6344149408074e1e15cb581f7a63f549313c7a1037be"},"package":null} \ No newline at end of file diff --git a/third_party/rust/cranelift-frontend/Cargo.toml b/third_party/rust/cranelift-frontend/Cargo.toml index 3cd888220165e636b57e3c9dc1076450da9d6473..e30bde657ed9f428143036362d1f597d4c7de088 100644 --- a/third_party/rust/cranelift-frontend/Cargo.toml +++ b/third_party/rust/cranelift-frontend/Cargo.toml @@ -1,7 +1,7 @@ [package] authors = ["The Cranelift Project Developers"] name = "cranelift-frontend" -version = "0.42.0" +version = "0.44.0" description = "Cranelift IR builder helper" license = "Apache-2.0 WITH LLVM-exception" documentation = "https://cranelift.readthedocs.io/" @@ -11,7 +11,7 @@ readme = "README.md" edition = "2018" [dependencies] -cranelift-codegen = { path = "../cranelift-codegen", version = "0.42.0", default-features = false } +cranelift-codegen = { path = "../cranelift-codegen", version = "0.44.0", default-features = false } target-lexicon = "0.8.1" log = { version = "0.4.6", default-features = false } hashmap_core = { version = "0.1.9", optional = true } diff --git a/third_party/rust/cranelift-wasm/.cargo-checksum.json b/third_party/rust/cranelift-wasm/.cargo-checksum.json index ee7a481209ab56aa1854439ed48a6c5a878291ee..d633e598b287d73fcb01745b0f825a9165f81448 100644 --- a/third_party/rust/cranelift-wasm/.cargo-checksum.json +++ b/third_party/rust/cranelift-wasm/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"3a4cfc0e561c29c298b550e6681a10a8bd99d5d33503604f9cb422c4f52831d3","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"87679cdb53e8cbec3b1aa45afb2124727c1c059f8bd10363d27daf318a9f9a36","src/code_translator.rs":"cb28478d7fc02ad68e82e52a80524a81db50463da982b23ce03abe1e7b50560f","src/environ/dummy.rs":"848079947623af4227935cfc980a8dfad03d314e9fa7408ee8a520a1043b68c8","src/environ/mod.rs":"b046f5344a1017357c1ee9d661d2193e0247327df293436fa1381a0f45f80584","src/environ/spec.rs":"d3363a0989ee2c31d5d31d7bd74d0bb23c3ae3b838b56661749f1f33ef986523","src/func_translator.rs":"2f1a80ede583cb14cfc2714c1d96855d6d0fdc5e044e092b0257179cd118d876","src/lib.rs":"43a29f5dfb3f3f0d3cf85a89eee68e699aae2f80252c09b62b56673c763a1c74","src/module_translator.rs":"7d41cd6b8c09eab6b9448cba46cc4c2f843ed6952b393338d257d5629dabfd62","src/sections_translator.rs":"e49fed0596052b82d0e0010d1fcfdf52e214a16a3aeaa8e57e871927b522c77d","src/state.rs":"fc2a8d468b4b681d9262fdb8762f3300ffce709cb0b2e48f3835a5b9164e7c93","src/translation_utils.rs":"aae22673eb5227840a225c9af831e68a272c6b2ad1300f54c3f0a6116ce88a65","tests/wasm_testsuite.rs":"fc3c9c7b7b504b199cb524b29a18e633f68704de289c865049496ac636c38e0b"},"package":null} \ No newline at end of file +{"files":{"Cargo.toml":"70f4c05be2e949e3f35c6c2e7990af6802916ded9e4017b679dc988079b621c2","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"87679cdb53e8cbec3b1aa45afb2124727c1c059f8bd10363d27daf318a9f9a36","src/code_translator.rs":"090fea0cff980468f423b1ea63a7cb1d8c4bf8349b588f577a700c90aa70a6c2","src/environ/dummy.rs":"848079947623af4227935cfc980a8dfad03d314e9fa7408ee8a520a1043b68c8","src/environ/mod.rs":"b046f5344a1017357c1ee9d661d2193e0247327df293436fa1381a0f45f80584","src/environ/spec.rs":"00911480a1eb3c85d635a197ff833e5180936364b2f61f9215f545b06829f362","src/func_translator.rs":"8f921c722f3e6b18c52a72e96d916b4f990bcdd42228e5be0ce3f182acc0eccb","src/lib.rs":"9c77bfa21596b8336e628e7808cde8cf167bbf1462b8f98abc6eddf90b1215d4","src/module_translator.rs":"c5d7506fffaf8f9034265273dad38983c898915cc7dbf445c659637b4838a3d3","src/sections_translator.rs":"55d0c1998f8007a559e7b3edd1c1fb3424f28596816fc0564acc2aae0dc08f3f","src/state.rs":"f7003dc78fdbb82c5c78188da1dca0bfcc0d907424dbdaa8a246184427850516","src/translation_utils.rs":"4b871e496e5bffc23e7094da01aa5d4cfa901e530e7d45f876e2c5bbe2ed897e","tests/wasm_testsuite.rs":"fc3c9c7b7b504b199cb524b29a18e633f68704de289c865049496ac636c38e0b"},"package":null} \ No newline at end of file diff --git a/third_party/rust/cranelift-wasm/Cargo.toml b/third_party/rust/cranelift-wasm/Cargo.toml index c140de53a7f2e0d00b881ed90a262b6d8d548bdd..fd7f51608d7c3482887b983845d7ff3616747daf 100644 --- a/third_party/rust/cranelift-wasm/Cargo.toml +++ b/third_party/rust/cranelift-wasm/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cranelift-wasm" -version = "0.42.0" +version = "0.44.0" authors = ["The Cranelift Project Developers"] description = "Translator from WebAssembly to Cranelift IR" repository = "https://github.com/CraneStation/cranelift" @@ -11,10 +11,10 @@ keywords = ["webassembly", "wasm"] edition = "2018" [dependencies] -wasmparser = { version = "0.37.0", default-features = false } -cranelift-codegen = { path = "../cranelift-codegen", version = "0.42.0", default-features = false } -cranelift-entity = { path = "../cranelift-entity", version = "0.42.0", default-features = false } -cranelift-frontend = { path = "../cranelift-frontend", version = "0.42.0", default-features = false } +wasmparser = { version = "0.39.1", default-features = false } +cranelift-codegen = { path = "../cranelift-codegen", version = "0.44.0", default-features = false } +cranelift-entity = { path = "../cranelift-entity", version = "0.44.0", default-features = false } +cranelift-frontend = { path = "../cranelift-frontend", version = "0.44.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 } diff --git a/third_party/rust/cranelift-wasm/src/code_translator.rs b/third_party/rust/cranelift-wasm/src/code_translator.rs index c420147550ffc9eab7a246e6423d9a018177b2ea..0bf7f4b0b466898fb7cbbfeec39fe79e8c752c33 100644 --- a/third_party/rust/cranelift-wasm/src/code_translator.rs +++ b/third_party/rust/cranelift-wasm/src/code_translator.rs @@ -907,7 +907,7 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>( | Operator::I64AtomicRmw16UCmpxchg { .. } | Operator::I64AtomicRmw32UCmpxchg { .. } | Operator::Fence { .. } => { - wasm_unsupported!("proposed thread operator {:?}", op); + return Err(wasm_unsupported!("proposed thread operator {:?}", op)); } Operator::MemoryInit { .. } | Operator::DataDrop { .. } @@ -920,7 +920,7 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>( | Operator::TableSet { .. } | Operator::TableGrow { .. } | Operator::TableSize { .. } => { - wasm_unsupported!("proposed bulk memory operator {:?}", op); + return Err(wasm_unsupported!("proposed bulk memory operator {:?}", op)); } Operator::V128Const { value } => { let handle = builder.func.dfg.constants.insert(value.bytes().to_vec()); @@ -974,9 +974,24 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>( builder, )) } + Operator::V8x16Shuffle { lanes, .. } => { + let (vector_a, vector_b) = state.pop2(); + let a = optionally_bitcast_vector(vector_a, I8X16, builder); + let b = optionally_bitcast_vector(vector_b, I8X16, builder); + let mask = builder.func.dfg.immediates.push(lanes.to_vec()); + let shuffled = builder.ins().shuffle(a, b, mask); + state.push1(shuffled) + // At this point the original types of a and b are lost; users of this value (i.e. this + // WASM-to-CLIF translator) may need to raw_bitcast for type-correctness. This is due + // to WASM using the less specific v128 type for certain operations and more specific + // types (e.g. i8x16) for others. + } + Operator::I8x16Add | Operator::I16x8Add | Operator::I32x4Add | Operator::I64x2Add => { + let (a, b) = state.pop2(); + state.push1(builder.ins().iadd(a, b)) + } Operator::V128Load { .. } | Operator::V128Store { .. } - | Operator::V8x16Shuffle { .. } | Operator::I8x16Eq | Operator::I8x16Ne | Operator::I8x16LtS @@ -1030,7 +1045,6 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>( | Operator::I8x16Shl | Operator::I8x16ShrS | Operator::I8x16ShrU - | Operator::I8x16Add | Operator::I8x16AddSaturateS | Operator::I8x16AddSaturateU | Operator::I8x16Sub @@ -1043,7 +1057,6 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>( | Operator::I16x8Shl | Operator::I16x8ShrS | Operator::I16x8ShrU - | Operator::I16x8Add | Operator::I16x8AddSaturateS | Operator::I16x8AddSaturateU | Operator::I16x8Sub @@ -1056,7 +1069,6 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>( | Operator::I32x4Shl | Operator::I32x4ShrS | Operator::I32x4ShrU - | Operator::I32x4Add | Operator::I32x4Sub | Operator::I32x4Mul | Operator::I64x2Neg @@ -1065,7 +1077,6 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>( | Operator::I64x2Shl | Operator::I64x2ShrS | Operator::I64x2ShrU - | Operator::I64x2Add | Operator::I64x2Sub | Operator::F32x4Abs | Operator::F32x4Neg @@ -1098,7 +1109,7 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>( | Operator::I16x8LoadSplat { .. } | Operator::I32x4LoadSplat { .. } | Operator::I64x2LoadSplat { .. } => { - wasm_unsupported!("proposed SIMD operator {:?}", op); + return Err(wasm_unsupported!("proposed SIMD operator {:?}", op)); } }; Ok(()) diff --git a/third_party/rust/cranelift-wasm/src/environ/spec.rs b/third_party/rust/cranelift-wasm/src/environ/spec.rs index ba87cc992a9ca2615b9c454f7f3e73b5224d0981..e83e675e72150b8a8e1d81387c43aed7d6294a37 100644 --- a/third_party/rust/cranelift-wasm/src/environ/spec.rs +++ b/third_party/rust/cranelift-wasm/src/environ/spec.rs @@ -6,7 +6,7 @@ //! //! [Wasmtime]: https://github.com/CraneStation/wasmtime -use crate::state::VisibleTranslationState; +use crate::state::TranslationState; use crate::translation_utils::{ FuncIndex, Global, GlobalIndex, Memory, MemoryIndex, SignatureIndex, Table, TableIndex, }; @@ -80,7 +80,7 @@ pub enum WasmError { /// on the arguments to this macro. #[macro_export] macro_rules! wasm_unsupported { - ($($arg:tt)*) => { return Err($crate::environ::WasmError::Unsupported(format!($($arg)*))) } + ($($arg:tt)*) => { $crate::environ::WasmError::Unsupported(format!($($arg)*)) } } impl From<BinaryReaderError> for WasmError { @@ -281,7 +281,7 @@ pub trait FuncEnvironment { &mut self, _op: &Operator, _builder: &mut FunctionBuilder, - _state: &VisibleTranslationState, + _state: &TranslationState, ) -> WasmResult<()> { Ok(()) } @@ -292,7 +292,7 @@ pub trait FuncEnvironment { &mut self, _op: &Operator, _builder: &mut FunctionBuilder, - _state: &VisibleTranslationState, + _state: &TranslationState, ) -> WasmResult<()> { Ok(()) } diff --git a/third_party/rust/cranelift-wasm/src/func_translator.rs b/third_party/rust/cranelift-wasm/src/func_translator.rs index b49cffd47489b72b152412e4abe4712a6bcd1354..f947ddd065304fa826e2ea790e616cc34d1880e5 100644 --- a/third_party/rust/cranelift-wasm/src/func_translator.rs +++ b/third_party/rust/cranelift-wasm/src/func_translator.rs @@ -6,7 +6,7 @@ use crate::code_translator::translate_operator; use crate::environ::{FuncEnvironment, ReturnMode, WasmResult}; -use crate::state::{TranslationState, VisibleTranslationState}; +use crate::state::TranslationState; use crate::translation_utils::get_vmctx_value_label; use crate::wasm_unsupported; use cranelift_codegen::entity::EntityRef; @@ -179,8 +179,12 @@ fn declare_locals<FE: FuncEnvironment + ?Sized>( I64 => builder.ins().iconst(ir::types::I64, 0), F32 => builder.ins().f32const(ir::immediates::Ieee32::with_bits(0)), F64 => builder.ins().f64const(ir::immediates::Ieee64::with_bits(0)), + V128 => { + let constant_handle = builder.func.dfg.constants.insert([0; 16].to_vec()); + builder.ins().vconst(ir::types::I8X16, constant_handle) + } AnyRef => builder.ins().null(environ.reference_type()), - ty => wasm_unsupported!("unsupported local type {:?}", ty), + ty => return Err(wasm_unsupported!("unsupported local type {:?}", ty)), }; let ty = builder.func.dfg.value_type(zeroval); @@ -211,9 +215,9 @@ fn parse_function_body<FE: FuncEnvironment + ?Sized>( while !state.control_stack.is_empty() { builder.set_srcloc(cur_srcloc(&reader)); let op = reader.read_operator()?; - environ.before_translate_operator(&op, builder, &VisibleTranslationState::new(state))?; + environ.before_translate_operator(&op, builder, state)?; translate_operator(&op, builder, state, environ)?; - environ.after_translate_operator(&op, builder, &VisibleTranslationState::new(state))?; + environ.after_translate_operator(&op, builder, state)?; } // The final `End` operator left us in the exit block where we need to manually add a return diff --git a/third_party/rust/cranelift-wasm/src/lib.rs b/third_party/rust/cranelift-wasm/src/lib.rs index 3c1065228babaf39a02ddefa0824ad948111b58e..d47feb631d0fc146c8b0a9df03aba6ee612a4c3b 100644 --- a/third_party/rust/cranelift-wasm/src/lib.rs +++ b/third_party/rust/cranelift-wasm/src/lib.rs @@ -62,7 +62,7 @@ pub use crate::environ::{ }; pub use crate::func_translator::FuncTranslator; pub use crate::module_translator::translate_module; -pub use crate::state::VisibleTranslationState; +pub use crate::state::TranslationState; pub use crate::translation_utils::{ get_vmctx_value_label, DefinedFuncIndex, DefinedGlobalIndex, DefinedMemoryIndex, DefinedTableIndex, FuncIndex, Global, GlobalIndex, GlobalInit, Memory, MemoryIndex, diff --git a/third_party/rust/cranelift-wasm/src/module_translator.rs b/third_party/rust/cranelift-wasm/src/module_translator.rs index 8d8b55397de2a4f9a1a9c6b3ea2137a9d14b59d7..462f79ab24818daa5b883c58202bc73b5144ef6b 100644 --- a/third_party/rust/cranelift-wasm/src/module_translator.rs +++ b/third_party/rust/cranelift-wasm/src/module_translator.rs @@ -7,7 +7,7 @@ use crate::sections_translator::{ parse_name_section, parse_start_section, parse_table_section, parse_type_section, }; use cranelift_codegen::timing; -use wasmparser::{CustomSectionKind, ModuleReader, SectionCode}; +use wasmparser::{CustomSectionContent, ModuleReader, SectionContent}; /// Translate a sequence of bytes forming a valid Wasm binary into a list of valid Cranelift IR /// [`Function`](cranelift_codegen::ir::Function). @@ -20,83 +20,73 @@ pub fn translate_module<'data>( while !reader.eof() { let section = reader.read()?; - match section.code { - SectionCode::Type => { - let types = section.get_type_section_reader()?; + match section.content()? { + SectionContent::Type(types) => { parse_type_section(types, environ)?; } - SectionCode::Import => { - let imports = section.get_import_section_reader()?; + SectionContent::Import(imports) => { parse_import_section(imports, environ)?; } - SectionCode::Function => { - let functions = section.get_function_section_reader()?; + SectionContent::Function(functions) => { parse_function_section(functions, environ)?; } - SectionCode::Table => { - let tables = section.get_table_section_reader()?; + SectionContent::Table(tables) => { parse_table_section(tables, environ)?; } - SectionCode::Memory => { - let memories = section.get_memory_section_reader()?; + SectionContent::Memory(memories) => { parse_memory_section(memories, environ)?; } - SectionCode::Global => { - let globals = section.get_global_section_reader()?; + SectionContent::Global(globals) => { parse_global_section(globals, environ)?; } - SectionCode::Export => { - let exports = section.get_export_section_reader()?; + SectionContent::Export(exports) => { parse_export_section(exports, environ)?; } - SectionCode::Start => { - let start = section.get_start_section_content()?; + SectionContent::Start(start) => { parse_start_section(start, environ)?; } - SectionCode::Element => { - let elements = section.get_element_section_reader()?; + SectionContent::Element(elements) => { parse_element_section(elements, environ)?; } - SectionCode::Code => { - let code = section.get_code_section_reader()?; + SectionContent::Code(code) => { parse_code_section(code, environ)?; } - SectionCode::Data => { - let data = section.get_data_section_reader()?; + SectionContent::Data(data) => { parse_data_section(data, environ)?; } - SectionCode::DataCount => { + SectionContent::DataCount(_) => { return Err(WasmError::InvalidWebAssembly { message: "don't know how to handle the data count section yet", offset: reader.current_position(), }); } - SectionCode::Custom { - kind: CustomSectionKind::Name, - name: _, - } => { - let names = section.get_name_section_reader()?; - parse_name_section(names, environ)?; - } - - SectionCode::Custom { name, kind: _ } => { - let mut reader = section.get_binary_reader(); - let len = reader.bytes_remaining(); - let payload = reader.read_bytes(len)?; - environ.custom_section(name, payload)?; - } + SectionContent::Custom { + name, + binary, + content, + } => match content { + Some(CustomSectionContent::Name(names)) => { + parse_name_section(names, environ)?; + } + _ => { + let mut reader = binary.clone(); + let len = reader.bytes_remaining(); + let payload = reader.read_bytes(len)?; + environ.custom_section(name, payload)?; + } + }, } } diff --git a/third_party/rust/cranelift-wasm/src/sections_translator.rs b/third_party/rust/cranelift-wasm/src/sections_translator.rs index 67830af3ff1bb6dda3fe14afcc389debb429ad94..a961a71ca9209ce4eef73c3f1836037eefdf71fa 100644 --- a/third_party/rust/cranelift-wasm/src/sections_translator.rs +++ b/third_party/rust/cranelift-wasm/src/sections_translator.rs @@ -14,6 +14,7 @@ use crate::translation_utils::{ }; use crate::{wasm_unsupported, HashMap}; use core::convert::TryFrom; +use cranelift_codegen::ir::immediates::V128Imm; use cranelift_codegen::ir::{self, AbiParam, Signature}; use cranelift_entity::EntityRef; use std::vec::Vec; @@ -52,7 +53,12 @@ pub fn parse_type_section( })); environ.declare_signature(sig)?; } - ty => wasm_unsupported!("unsupported type in type section: {:?}", ty), + ty => { + return Err(wasm_unsupported!( + "unsupported type in type section: {:?}", + ty + )) + } } } Ok(()) @@ -201,11 +207,17 @@ pub fn parse_global_section( Operator::I64Const { value } => GlobalInit::I64Const(value), Operator::F32Const { value } => GlobalInit::F32Const(value.bits()), Operator::F64Const { value } => GlobalInit::F64Const(value.bits()), + Operator::V128Const { value } => { + GlobalInit::V128Const(V128Imm::from(value.bytes().to_vec().as_slice())) + } Operator::GetGlobal { global_index } => { GlobalInit::GetGlobal(GlobalIndex::from_u32(global_index)) } ref s => { - wasm_unsupported!("unsupported init expr in global section: {:?}", s); + return Err(wasm_unsupported!( + "unsupported init expr in global section: {:?}", + s + )); } }; let global = Global { @@ -280,7 +292,10 @@ pub fn parse_element_section<'data>( (Some(GlobalIndex::from_u32(global_index)), 0) } ref s => { - wasm_unsupported!("unsupported init expr in element section: {:?}", s); + return Err(wasm_unsupported!( + "unsupported init expr in element section: {:?}", + s + )); } }; let items_reader = items.get_items_reader()?; @@ -296,7 +311,10 @@ pub fn parse_element_section<'data>( elems.into_boxed_slice(), )? } else { - wasm_unsupported!("unsupported passive elements section: {:?}", kind); + return Err(wasm_unsupported!( + "unsupported passive elements section: {:?}", + kind + )); } } Ok(()) @@ -336,7 +354,12 @@ pub fn parse_data_section<'data>( Operator::GetGlobal { global_index } => { (Some(GlobalIndex::from_u32(global_index)), 0) } - ref s => wasm_unsupported!("unsupported init expr in data section: {:?}", s), + ref s => { + return Err(wasm_unsupported!( + "unsupported init expr in data section: {:?}", + s + )) + } }; environ.declare_data_initialization( MemoryIndex::from_u32(memory_index), @@ -345,7 +368,10 @@ pub fn parse_data_section<'data>( data, )?; } else { - wasm_unsupported!("unsupported passive data section: {:?}", kind); + return Err(wasm_unsupported!( + "unsupported passive data section: {:?}", + kind + )); } } diff --git a/third_party/rust/cranelift-wasm/src/state.rs b/third_party/rust/cranelift-wasm/src/state.rs index 7016035b725d221ebae2eac1c9de78cc3d8f03eb..7359482893d86545b1cad4116b479614381d6a07 100644 --- a/third_party/rust/cranelift-wasm/src/state.rs +++ b/third_party/rust/cranelift-wasm/src/state.rs @@ -124,28 +124,6 @@ impl ControlStackFrame { } } -/// VisibleTranslationState wraps a TranslationState with an interface appropriate for users -/// outside this `cranelift-wasm`. -/// -/// VisibleTranslationState is currently very minimal (only exposing reachability information), but -/// is anticipated to grow in the future, with functions to inspect or modify the wasm operand -/// stack for example. -pub struct VisibleTranslationState<'a> { - state: &'a TranslationState, -} - -impl<'a> VisibleTranslationState<'a> { - /// Build a VisibleTranslationState from an existing TranslationState - pub fn new(state: &'a TranslationState) -> Self { - VisibleTranslationState { state } - } - - /// True if the current translation state expresses reachable code, false if it is unreachable - pub fn reachable(&self) -> bool { - self.state.reachable - } -} - /// Contains information passed along during the translation and that records: /// /// - The current value and control stacks. @@ -154,12 +132,12 @@ impl<'a> VisibleTranslationState<'a> { pub struct TranslationState { /// A stack of values corresponding to the active values in the input wasm function at this /// point. - pub stack: Vec<Value>, + pub(crate) stack: Vec<Value>, /// A stack of active control flow operations at this point in the input wasm function. - pub control_stack: Vec<ControlStackFrame>, + pub(crate) control_stack: Vec<ControlStackFrame>, /// Is the current translation state still reachable? This is false when translating operators /// like End, Return, or Unreachable. - pub reachable: bool, + pub(crate) reachable: bool, // Map of global variables that have already been created by `FuncEnvironment::make_global`. globals: HashMap<GlobalIndex, GlobalVariable>, @@ -181,9 +159,18 @@ pub struct TranslationState { functions: HashMap<FuncIndex, (ir::FuncRef, usize)>, } +// Public methods that are exposed to non-`cranelift_wasm` API consumers. +impl TranslationState { + /// True if the current translation state expresses reachable code, false if it is unreachable. + #[inline] + pub fn reachable(&self) -> bool { + self.reachable + } +} + impl TranslationState { /// Construct a new, empty, `TranslationState` - pub fn new() -> Self { + pub(crate) fn new() -> Self { Self { stack: Vec::new(), control_stack: Vec::new(), @@ -211,7 +198,7 @@ impl TranslationState { /// /// This resets the state to containing only a single block representing the whole function. /// The exit block is the last block in the function which will contain the return instruction. - pub fn initialize(&mut self, sig: &ir::Signature, exit_block: Ebb) { + pub(crate) fn initialize(&mut self, sig: &ir::Signature, exit_block: Ebb) { self.clear(); self.push_block( exit_block, @@ -223,34 +210,34 @@ impl TranslationState { } /// Push a value. - pub fn push1(&mut self, val: Value) { + pub(crate) fn push1(&mut self, val: Value) { self.stack.push(val); } /// Push multiple values. - pub fn pushn(&mut self, vals: &[Value]) { + pub(crate) fn pushn(&mut self, vals: &[Value]) { self.stack.extend_from_slice(vals); } /// Pop one value. - pub fn pop1(&mut self) -> Value { + pub(crate) fn pop1(&mut self) -> Value { self.stack.pop().unwrap() } /// Peek at the top of the stack without popping it. - pub fn peek1(&self) -> Value { + pub(crate) fn peek1(&self) -> Value { *self.stack.last().unwrap() } /// Pop two values. Return them in the order they were pushed. - pub fn pop2(&mut self) -> (Value, Value) { + pub(crate) fn pop2(&mut self) -> (Value, Value) { let v2 = self.stack.pop().unwrap(); let v1 = self.stack.pop().unwrap(); (v1, v2) } /// Pop three values. Return them in the order they were pushed. - pub fn pop3(&mut self) -> (Value, Value, Value) { + pub(crate) fn pop3(&mut self) -> (Value, Value, Value) { let v3 = self.stack.pop().unwrap(); let v2 = self.stack.pop().unwrap(); let v1 = self.stack.pop().unwrap(); @@ -260,18 +247,18 @@ impl TranslationState { /// Pop the top `n` values on the stack. /// /// The popped values are not returned. Use `peekn` to look at them before popping. - pub fn popn(&mut self, n: usize) { + pub(crate) fn popn(&mut self, n: usize) { let new_len = self.stack.len() - n; self.stack.truncate(new_len); } /// Peek at the top `n` values on the stack in the order they were pushed. - pub fn peekn(&self, n: usize) -> &[Value] { + pub(crate) fn peekn(&self, n: usize) -> &[Value] { &self.stack[self.stack.len() - n..] } /// Push a block on the control stack. - pub fn push_block(&mut self, following_code: Ebb, num_result_types: usize) { + pub(crate) fn push_block(&mut self, following_code: Ebb, num_result_types: usize) { self.control_stack.push(ControlStackFrame::Block { destination: following_code, original_stack_size: self.stack.len(), @@ -281,7 +268,7 @@ impl TranslationState { } /// Push a loop on the control stack. - pub fn push_loop(&mut self, header: Ebb, following_code: Ebb, num_result_types: usize) { + pub(crate) fn push_loop(&mut self, header: Ebb, following_code: Ebb, num_result_types: usize) { self.control_stack.push(ControlStackFrame::Loop { header, destination: following_code, @@ -291,7 +278,12 @@ impl TranslationState { } /// Push an if on the control stack. - pub fn push_if(&mut self, branch_inst: Inst, following_code: Ebb, num_result_types: usize) { + pub(crate) fn push_if( + &mut self, + branch_inst: Inst, + following_code: Ebb, + num_result_types: usize, + ) { self.control_stack.push(ControlStackFrame::If { branch_inst, destination: following_code, @@ -308,7 +300,7 @@ impl TranslationState { /// Get the `GlobalVariable` reference that should be used to access the global variable /// `index`. Create the reference if necessary. /// Also return the WebAssembly type of the global. - pub fn get_global<FE: FuncEnvironment + ?Sized>( + pub(crate) fn get_global<FE: FuncEnvironment + ?Sized>( &mut self, func: &mut ir::Function, index: u32, @@ -323,7 +315,7 @@ impl TranslationState { /// Get the `Heap` reference that should be used to access linear memory `index`. /// Create the reference if necessary. - pub fn get_heap<FE: FuncEnvironment + ?Sized>( + pub(crate) fn get_heap<FE: FuncEnvironment + ?Sized>( &mut self, func: &mut ir::Function, index: u32, @@ -338,7 +330,7 @@ impl TranslationState { /// Get the `Table` reference that should be used to access table `index`. /// Create the reference if necessary. - pub fn get_table<FE: FuncEnvironment + ?Sized>( + pub(crate) fn get_table<FE: FuncEnvironment + ?Sized>( &mut self, func: &mut ir::Function, index: u32, @@ -355,7 +347,7 @@ impl TranslationState { /// `index`. Also return the number of WebAssembly arguments in the signature. /// /// Create the signature if necessary. - pub fn get_indirect_sig<FE: FuncEnvironment + ?Sized>( + pub(crate) fn get_indirect_sig<FE: FuncEnvironment + ?Sized>( &mut self, func: &mut ir::Function, index: u32, @@ -375,7 +367,7 @@ impl TranslationState { /// `index`. Also return the number of WebAssembly arguments in the signature. /// /// Create the function reference if necessary. - pub fn get_direct_func<FE: FuncEnvironment + ?Sized>( + pub(crate) fn get_direct_func<FE: FuncEnvironment + ?Sized>( &mut self, func: &mut ir::Function, index: u32, diff --git a/third_party/rust/cranelift-wasm/src/translation_utils.rs b/third_party/rust/cranelift-wasm/src/translation_utils.rs index f033b8660c7306d5d59658f57a8434558d0d2b42..df910c534bdd82da45d3dd680db5cdc938a00977 100644 --- a/third_party/rust/cranelift-wasm/src/translation_utils.rs +++ b/third_party/rust/cranelift-wasm/src/translation_utils.rs @@ -4,6 +4,7 @@ use crate::wasm_unsupported; use core::u32; use cranelift_codegen::entity::entity_impl; use cranelift_codegen::ir; +use cranelift_codegen::ir::immediates::V128Imm; #[cfg(feature = "enable-serde")] use serde::{Deserialize, Serialize}; use wasmparser; @@ -65,7 +66,7 @@ pub struct Global { pub initializer: GlobalInit, } -/// Globals are initialized via the four `const` operators or by referring to another import. +/// Globals are initialized via the `const` operators or by referring to another import. #[derive(Debug, Clone, Copy, Hash)] pub enum GlobalInit { /// An `i32.const`. @@ -76,6 +77,8 @@ pub enum GlobalInit { F32Const(u32), /// An `f64.const`. F64Const(u64), + /// A `vconst`. + V128Const(V128Imm), /// A `get_global` of another global. GetGlobal(GlobalIndex), ///< The global is imported from, and thus initialized by, a different module. @@ -120,7 +123,8 @@ pub fn type_to_type(ty: wasmparser::Type) -> WasmResult<ir::Type> { wasmparser::Type::I64 => Ok(ir::types::I64), wasmparser::Type::F32 => Ok(ir::types::F32), wasmparser::Type::F64 => Ok(ir::types::F64), - ty => wasm_unsupported!("type_to_type: wasm type {:?}", ty), + wasmparser::Type::V128 => Ok(ir::types::I8X16), + ty => Err(wasm_unsupported!("type_to_type: wasm type {:?}", ty)), } } @@ -132,8 +136,12 @@ pub fn tabletype_to_type(ty: wasmparser::Type) -> WasmResult<Option<ir::Type>> { wasmparser::Type::I64 => Ok(Some(ir::types::I64)), wasmparser::Type::F32 => Ok(Some(ir::types::F32)), wasmparser::Type::F64 => Ok(Some(ir::types::F64)), + wasmparser::Type::V128 => Ok(Some(ir::types::I8X16)), wasmparser::Type::AnyFunc => Ok(None), - ty => wasm_unsupported!("tabletype_to_type: table wasm type {:?}", ty), + ty => Err(wasm_unsupported!( + "tabletype_to_type: table wasm type {:?}", + ty + )), } } @@ -145,13 +153,14 @@ pub fn blocktype_to_type(ty_or_ft: wasmparser::TypeOrFuncType) -> WasmResult<Opt wasmparser::Type::I64 => Ok(Some(ir::types::I64)), wasmparser::Type::F32 => Ok(Some(ir::types::F32)), wasmparser::Type::F64 => Ok(Some(ir::types::F64)), + wasmparser::Type::V128 => Ok(Some(ir::types::I8X16)), wasmparser::Type::EmptyBlockType => Ok(None), - ty => wasm_unsupported!("blocktype_to_type: type {:?}", ty), + ty => Err(wasm_unsupported!("blocktype_to_type: type {:?}", ty)), }, - wasmparser::TypeOrFuncType::FuncType(_) => wasm_unsupported!( + wasmparser::TypeOrFuncType::FuncType(_) => Err(wasm_unsupported!( "blocktype_to_type: multi-value block signature {:?}", ty_or_ft - ), + )), } } @@ -173,11 +182,12 @@ pub fn num_return_values(ty: wasmparser::TypeOrFuncType) -> WasmResult<usize> { wasmparser::Type::I32 | wasmparser::Type::F32 | wasmparser::Type::I64 - | wasmparser::Type::F64 => Ok(1), - ty => wasm_unsupported!("unsupported return value type {:?}", ty), + | wasmparser::Type::F64 + | wasmparser::Type::V128 => Ok(1), + ty => Err(wasm_unsupported!("unsupported return value type {:?}", ty)), }, wasmparser::TypeOrFuncType::FuncType(_) => { - wasm_unsupported!("multi-value block signature {:?}", ty); + Err(wasm_unsupported!("multi-value block signature {:?}", ty)) } } } diff --git a/third_party/rust/wasmparser/.cargo-checksum.json b/third_party/rust/wasmparser/.cargo-checksum.json index d26ed3d342aa03e34b26e3aedc4c6b8b887697e3..0cbe8f9f1e759495455ba0cd2d9433b6e7f805f0 100644 --- a/third_party/rust/wasmparser/.cargo-checksum.json +++ b/third_party/rust/wasmparser/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.lock":"adda6d221a7562818654f99b9f3a577dfde76db43726eb12248dc5b255b0d44e","Cargo.toml":"4616d1871f9a1ad11f50e46800ac5cc424a06234be2edde1ef9bec05dbf7ef99","LICENSE":"a6c48161a09acc75a0e25503bab66a731eb5fba5392ed4bb4743e4ba5085327a","README.md":"13ea373a411dfa7371cd994736289bb000db51957da92315fecbcc9fe7dcab92","benches/benchmark.rs":"951abd671bd1a5a33d09379b023de000e89fc5f99a5950f0b3b2f571021aa402","compare-master.sh":"165490eab36ef4eceb2913a6c5cdeff479a05e1e0119a7f4551b03dbcda51ad4","examples/dump.rs":"de2bbdba75e21b9ff92b32697b3d9941f8695b8f7e3a8dee8fc5d7f4c3a0649c","examples/simple.rs":"c79ae542913e72cfcd03711543d173b2e8f62783e6c206459953bdb94dbb8c0c","format-all.sh":"6b02a40629ef3d2c0b9671222582a6217d526317a41262ae06c7a95de53bcbeb","src/binary_reader.rs":"39e0a785a41e2513926ab140a1e07f38a6e898737d098d1d038ba5229e7c24b3","src/lib.rs":"abcb8d4f9a604fbc0997add13a0213bc9abc163ac6c2d4534096a3d620a0bd0f","src/limits.rs":"4e4f9b7ed1d26e7a6727e36b136015cd9f4e38f596b3c8f82236789f45905cae","src/operators_validator.rs":"3c7b9acc1abab2ceb931047301b1f43385d32ecd3274b3fae217b4096e82f3ac","src/parser.rs":"c5afcf039a62952f4e674773416d4c4507711d10b4248ed3bce5e1223cc97034","src/primitives.rs":"e04f3ef6463a24f917c0d8b0377f9db86a3c756d99d5278226046122b76a52d5","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":"3b5e687874fd6211b8e083d7a8589c50dd80377eb85c605b21e505da5f546899","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":"9190318f1fdca501196eb4a1437ab7c74a46d19e9f9b9967d9f81c52d80f0019","src/validator.rs":"94700288b65cf2ff392bedffa2387b3a10d05d883b2343ba3315566759cf1d79","test-all.sh":"f36e3e9bf9c39456bab3ac170d3a09911becf2b7e0d0e2a58854ce1750da0d1f","test-no_std.sh":"f8bc939b378fe618b7ec6297152708e7c8740858eb94e5756464934a38796b8c"},"package":"82dbea680995dad585289fd47889cf9614133ebfcc3bda95737ef8bdc9e11db6"} \ No newline at end of file +{"files":{"Cargo.lock":"b5d7bacf94229b33c94e3d7c8f158334481a23f2fc86ccecd18ac671582d476f","Cargo.toml":"0f7b7d8e284e9faf9850ce67b1d494b1bb4d080d1ed9be01e8a09435a906d35c","LICENSE":"a6c48161a09acc75a0e25503bab66a731eb5fba5392ed4bb4743e4ba5085327a","README.md":"df9c5aa22ca3bcf6221c7e4297cd741cbbdfb39294b4ef28c4d382688395611a","benches/benchmark.rs":"951abd671bd1a5a33d09379b023de000e89fc5f99a5950f0b3b2f571021aa402","compare-master.sh":"165490eab36ef4eceb2913a6c5cdeff479a05e1e0119a7f4551b03dbcda51ad4","examples/dump.rs":"de2bbdba75e21b9ff92b32697b3d9941f8695b8f7e3a8dee8fc5d7f4c3a0649c","examples/simple.rs":"c79ae542913e72cfcd03711543d173b2e8f62783e6c206459953bdb94dbb8c0c","format-all.sh":"6b02a40629ef3d2c0b9671222582a6217d526317a41262ae06c7a95de53bcbeb","src/binary_reader.rs":"39e0a785a41e2513926ab140a1e07f38a6e898737d098d1d038ba5229e7c24b3","src/lib.rs":"a17f353162053e0e915a0e0d1f4d4ba86a7a8e4ff949c83faad004b707ac003f","src/limits.rs":"4e4f9b7ed1d26e7a6727e36b136015cd9f4e38f596b3c8f82236789f45905cae","src/operators_validator.rs":"147d2999314421361e0a20370178f638120c4199f4dc7388f9adca5e42b05d62","src/parser.rs":"c5afcf039a62952f4e674773416d4c4507711d10b4248ed3bce5e1223cc97034","src/primitives.rs":"65b7ddf0fb0bde4df0823a23ced952720e7dd8c4b630fdcd988096ccb8ea1379","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":"188aa45a893f4d17df7633a3df6a32438b64e192e001ddcc50543e007b4f7db4","src/readers/module.rs":"311b877264bf9d035280cad0c61eb3640c15505c4da5e8ba45c7bf9e067abbd4","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":"7397b77201d62a98e24858545a32597b782ff66d4ae6f02a5df59ff27925a9af","src/validator.rs":"4dfd7176fc1fced1730ecf6ee8c9225751a6ba3047862b9cfc8b151d9526a378","test-all.sh":"f36e3e9bf9c39456bab3ac170d3a09911becf2b7e0d0e2a58854ce1750da0d1f","test-no_std.sh":"f8bc939b378fe618b7ec6297152708e7c8740858eb94e5756464934a38796b8c"},"package":"a026c1436af49d5537c7561c7474f81f7a754e36445fe52e6e88795a9747291c"} \ No newline at end of file diff --git a/third_party/rust/wasmparser/Cargo.lock b/third_party/rust/wasmparser/Cargo.lock index d72a79860bbcc92eac485472dd0bec7864736152..2c6547dbb7dd305360d6e73380c2201c17f7f815 100644 --- a/third_party/rust/wasmparser/Cargo.lock +++ b/third_party/rust/wasmparser/Cargo.lock @@ -2,7 +2,7 @@ # It is not intended for manual editing. [[package]] name = "arrayvec" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", @@ -10,22 +10,37 @@ dependencies = [ [[package]] name = "atty" -version = "0.2.11" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", - "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "autocfg" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "bitflags" -version = "1.0.4" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "bstr" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-automata 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "byteorder" -version = "1.3.1" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -35,22 +50,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cc" -version = "1.0.40" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cfg-if" -version = "0.1.7" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "clap" -version = "2.32.0" +version = "2.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -58,102 +73,115 @@ name = "cloudabi" version = "0.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cmake" -version = "0.1.41" +version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "criterion" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", - "criterion-plot 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "csv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", + "criterion-plot 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "csv 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "rand_xoshiro 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", - "tinytemplate 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon-core 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "tinytemplate 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "criterion-plot" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "crossbeam-deque" -version = "0.2.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "crossbeam-epoch" -version = "0.3.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-queue" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "crossbeam-utils" -version = "0.2.2" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "csv" -version = "1.0.5" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "csv-core 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "bstr 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "csv-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "csv-core" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "either" -version = "1.5.1" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -176,36 +204,39 @@ name = "itertools" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "either 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "itoa" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "lazy_static" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.50" +version = "0.2.62" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "memchr" -version = "2.2.0" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "memoffset" -version = "0.2.1" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "nodrop" @@ -214,31 +245,34 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "num-traits" -version = "0.2.6" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "num_cpus" -version = "1.10.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "proc-macro2" -version = "0.4.27" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "quote" -version = "0.6.11" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -246,12 +280,12 @@ name = "rand_core" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_core" -version = "0.4.0" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -261,10 +295,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -272,29 +306,30 @@ name = "rand_xoshiro" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rayon" -version = "1.0.3" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "either 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon-core 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rayon-core" -version = "1.4.1" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -306,26 +341,29 @@ dependencies = [ ] [[package]] -name = "redox_syscall" -version = "0.1.51" +name = "regex-automata" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] -name = "redox_termios" -version = "0.1.1" +name = "rustc_version" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", + "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "ryu" -version = "0.2.7" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "same-file" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -333,124 +371,127 @@ dependencies = [ [[package]] name = "scopeguard" -version = "0.3.3" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.89" +version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" -version = "1.0.89" +version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_json" -version = "1.0.39" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "syn" -version = "0.15.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "termion" -version = "1.5.1" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "textwrap" -version = "0.10.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tinytemplate" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "unicode-width" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "unicode-xid" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "wabt" -version = "0.9.1" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", - "wabt-sys 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "wabt-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "wabt-sys" -version = "0.6.1" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", - "cmake 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", + "cmake 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "walkdir" -version = "2.2.7" +version = "2.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "wasmparser" -version = "0.37.0" +version = "0.39.1" dependencies = [ - "criterion 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "criterion 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "hashbrown 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "wabt 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "wabt 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "winapi" -version = "0.3.6" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -467,7 +508,7 @@ name = "winapi-util" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -476,63 +517,67 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] -"checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" -"checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" -"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" -"checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" +"checksum arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b8d73f9beda665eaa98ab9e4f7442bd4e7de6652587de55b2525e52e29c1b0ba" +"checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" +"checksum autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875" +"checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd" +"checksum bstr 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8d6c2c5b58ab920a4f5aeaaca34b4488074e8cc7596af94e6f8c6ff247c60245" +"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" "checksum cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "926013f2860c46252efceabb19f4a6b308197505082c609025aa6706c011d427" -"checksum cc 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "b548a4ee81fccb95919d4e22cfea83c7693ebfd78f0495493178db20b3139da7" -"checksum cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11d43355396e872eefb45ce6342e4374ed7bc2b3a502d1b28e36d6e23c05d1f4" -"checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e" +"checksum cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)" = "4fc9a35e1f4290eb9e5fc54ba6cf40671ed2a2514c3eeb2b2a908dda2ea5a1be" +"checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33" +"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -"checksum cmake 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "3c84c596dcf125d6781f58e3f4254677ec2a6d8aa56e8501ac277100990b3229" -"checksum criterion 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "1c6e5ee5b9652d4f851418c448af105642e1f99e9a2741a8ff45c0d2c911b1e0" -"checksum criterion-plot 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4107e4a5abb94267e0149922b8ff49dc70a87cc202820fdbfc0d3e1edbdc4b16" -"checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3" -"checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150" -"checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9" -"checksum csv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "9fd1c44c58078cfbeaf11fbb3eac9ae5534c23004ed770cc4bfb48e658ae4f04" -"checksum csv-core 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa5cdef62f37e6ffe7d1f07a381bc0db32b7a3ff1cac0de56cb0d81e71f53d65" -"checksum either 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c67353c641dc847124ea1902d69bd753dee9bb3beff9aa3662ecf86c971d1fac" +"checksum cmake 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "81fb25b677f8bf1eb325017cb6bb8452f87969db0fedb4f757b297bee78a7c62" +"checksum criterion 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "0363053954f3e679645fc443321ca128b7b950a6fe288cf5f9335cc22ee58394" +"checksum criterion-plot 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "76f9212ddf2f4a9eb2d401635190600656a1f88a932ef53d06e7fa4c7e02fb8e" +"checksum crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71" +"checksum crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9" +"checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" +"checksum crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6" +"checksum csv 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "37519ccdfd73a75821cac9319d4fce15a81b9fcf75f951df5b9988aa3a0af87d" +"checksum csv-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9b5cadb6b25c77aeff80ba701712494213f4a8418fcda2ee11b6560c3ad0bf4c" +"checksum either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5527cfe0d098f36e3f8839852688e63c8fff1c90b2b405aef730615f9a7bcf7b" "checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" "checksum hashbrown 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e1de41fb8dba9714efd92241565cdff73f78508c95697dd56787d3cba27e2353" "checksum itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358" -"checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" -"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" -"checksum libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)" = "aab692d7759f5cd8c859e169db98ae5b52c924add2af5fbbca11d12fefb567c1" -"checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39" -"checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" +"checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" +"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +"checksum libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba" +"checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" +"checksum memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ce6075db033bbbb7ee5a0bbd3a3186bbae616f57fb001c485c7ff77955f8177f" "checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" -"checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" -"checksum num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a23f0ed30a54abaa0c7e83b1d2d87ada7c3c23078d1d87815af3e3b6385fbba" -"checksum proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915" -"checksum quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cdd8e04bd9c52e0342b406469d494fcb033be4bdbe5c606016defbb1681411e1" +"checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32" +"checksum num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273" +"checksum proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e98a83a9f9b331f54b924e68a66acb1bb35cb01fb0a23645139967abefb697e8" +"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" "checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" -"checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" +"checksum rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" "checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" "checksum rand_xoshiro 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "03b418169fb9c46533f326efd6eed2576699c44ca92d3052a066214a8d828929" -"checksum rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "373814f27745b2686b350dd261bfd24576a6fb0e2c5919b3a2b6005f820b0473" -"checksum rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b055d1e92aba6877574d8fe604a63c8b5df60f60e5982bf7ccbb1338ea527356" +"checksum rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "83a27732a533a1be0a0035a111fe76db89ad312f6f0347004c220c57f209a123" +"checksum rayon-core 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "98dcf634205083b17d0861252431eb2acbfb698ab7478a2d20de07954f47ec7b" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" -"checksum redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)" = "423e376fffca3dfa06c9e9790a9ccd282fafb3cc6e6397d01dbf64f9bacc6b85" -"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" -"checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7" -"checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267" -"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" -"checksum serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)" = "92514fb95f900c9b5126e32d020f5c6d40564c27a5ea6d1d7d9f157a96623560" -"checksum serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)" = "bb6eabf4b5914e88e24eea240bb7c9f9a2cbc1bbbe8d961d381975ec3c6b806c" -"checksum serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)" = "5a23aa71d4a4d43fdbfaac00eff68ba8a06a51759a89ac3304323e800c4dd40d" -"checksum syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)" = "1825685f977249735d510a242a6727b46efe914bb67e38d30c071b1b72b1d5c2" -"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" -"checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6" -"checksum tinytemplate 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7655088894274afb52b807bd3c87072daa1fedd155068b8705cabfd628956115" -"checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" -"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" -"checksum wabt 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "94b5f5d6984ca42df66280baa8a15ac188a173ddaf4580b574a98931c01920e7" -"checksum wabt-sys 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b064c81821100adb4b71923cecfc67fef083db21c3bbd454b0162c7ffe63eeaa" -"checksum walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d9d7ed3431229a144296213105a390676cc49c9b6a72bd19f3176c98e129fa1" -"checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" +"checksum regex-automata 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "92b73c2a1770c255c240eaa4ee600df1704a38dc3feaa6e949e7fcd4f8dc09f9" +"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +"checksum ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997" +"checksum same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "585e8ddcedc187886a30fa705c47985c3fa88d06624095856b36ca0b82ff4421" +"checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" +"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" +"checksum serde 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)" = "f4473e8506b213730ff2061073b48fa51dcc66349219e2e7c5608f0296a1d95a" +"checksum serde_derive 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)" = "11e410fde43e157d789fc290d26bc940778ad0fdd47836426fbac36573710dbb" +"checksum serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "051c49229f282f7c6f3813f8286cc1e3323e8051823fce42c7ea80fe13521704" +"checksum syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf" +"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +"checksum tinytemplate 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4574b75faccaacddb9b284faecdf0b544b80b6b294f3d062d325c5726a209c20" +"checksum unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20" +"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" +"checksum wabt 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3c5c5c1286c6e578416982609f47594265f9d489f9b836157d403ad605a46693" +"checksum wabt-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "af5d153dc96aad7dc13ab90835b892c69867948112d95299e522d370c4e13a08" +"checksum walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9658c94fa8b940eab2250bd5a457f9c48b748420d71293b165c8cdbe2f55f71e" +"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" "checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/third_party/rust/wasmparser/Cargo.toml b/third_party/rust/wasmparser/Cargo.toml index d1c5f48155f418285a274d08b2dbb994f75177b8..6d2d22f7f5835095c3a8d50fa5182064180cb1c6 100644 --- a/third_party/rust/wasmparser/Cargo.toml +++ b/third_party/rust/wasmparser/Cargo.toml @@ -13,7 +13,7 @@ [package] edition = "2018" name = "wasmparser" -version = "0.37.0" +version = "0.39.1" authors = ["Yury Delendik <ydelendik@mozilla.com>"] exclude = ["fuzz/**/*", "tests/**/*", "testsuite/**/*"] description = "A simple event-driven library for parsing WebAssembly binary files.\n" @@ -31,7 +31,7 @@ optional = true version = "0.2" [dev-dependencies.wabt] -version = "0.9.1" +version = "0.9.2" [features] core = ["hashbrown"] diff --git a/third_party/rust/wasmparser/README.md b/third_party/rust/wasmparser/README.md index 87986366a4b48cec8d1363a24833ad9ab90aabbf..18bd6787be847e4aebde1a243a3025c99c01b11f 100644 --- a/third_party/rust/wasmparser/README.md +++ b/third_party/rust/wasmparser/README.md @@ -3,7 +3,7 @@ [](https://travis-ci.org/yurydelendik/wasmparser.rs) [](https://crates.io/crates/wasmparser) -The decoder library provides lightwight and fast decoding/parsing of WebAssembly binary files. +The decoder library provides lightweight and fast decoding/parsing of WebAssembly binary files. The other goal is minimal memory footprint. For this reason, there is no AST or IR of WebAssembly data. diff --git a/third_party/rust/wasmparser/src/lib.rs b/third_party/rust/wasmparser/src/lib.rs index 545cceae837159c33325df01477d9d10a367547c..4039660e58edec77d856248ca017f39b56bf3905 100644 --- a/third_party/rust/wasmparser/src/lib.rs +++ b/third_party/rust/wasmparser/src/lib.rs @@ -83,6 +83,7 @@ pub use crate::operators_validator::OperatorValidatorConfig; pub use crate::operators_validator::WasmModuleResources; pub use crate::readers::CodeSectionReader; +pub use crate::readers::CustomSectionContent; pub use crate::readers::Data; pub use crate::readers::DataKind; pub use crate::readers::DataSectionReader; @@ -114,6 +115,7 @@ pub use crate::readers::ProducersSectionReader; pub use crate::readers::Reloc; pub use crate::readers::RelocSectionReader; pub use crate::readers::Section; +pub use crate::readers::SectionContent; pub use crate::readers::SectionIterator; pub use crate::readers::SectionIteratorLimited; pub use crate::readers::SectionReader; diff --git a/third_party/rust/wasmparser/src/operators_validator.rs b/third_party/rust/wasmparser/src/operators_validator.rs index 07897d99cec06693302690ee63ad29989bb8094a..e575fe82b896059af6e87a1a85a4deacefdf5213 100644 --- a/third_party/rust/wasmparser/src/operators_validator.rs +++ b/third_party/rust/wasmparser/src/operators_validator.rs @@ -24,9 +24,12 @@ use crate::primitives::{ }; /// Test if `subtype` is a subtype of `supertype`. -fn is_subtype_supertype(subtype: Type, supertype: Type) -> bool { +pub(crate) fn is_subtype_supertype(subtype: Type, supertype: Type) -> bool { match supertype { - Type::AnyRef => subtype == Type::AnyRef || subtype == Type::AnyFunc, + Type::AnyRef => { + subtype == Type::AnyRef || subtype == Type::AnyFunc || subtype == Type::Null + } + Type::AnyFunc => subtype == Type::AnyFunc || subtype == Type::Null, _ => subtype == supertype, } } @@ -135,7 +138,13 @@ impl FuncState { } }; if block_type == BlockType::If { - self.stack_types.pop(); + let last_block = self.blocks.last().unwrap(); + if !last_block.is_stack_polymorphic() + || self.stack_types.len() > last_block.stack_starts_at + { + self.stack_types.pop(); + } + assert!(self.stack_types.len() >= last_block.stack_starts_at); } for (i, ty) in start_types.iter().rev().enumerate() { if !self.assert_stack_type_at(i, *ty) { @@ -563,6 +572,7 @@ impl OperatorValidator { | TypeOrFuncType::Type(Type::I64) | TypeOrFuncType::Type(Type::F32) | TypeOrFuncType::Type(Type::F64) => Ok(()), + TypeOrFuncType::Type(Type::V128) => self.check_simd_enabled(), TypeOrFuncType::FuncType(idx) => { let idx = idx as usize; let types = resources.types(); @@ -1312,12 +1322,12 @@ impl OperatorValidator { } Operator::RefNull => { self.check_reference_types_enabled()?; - self.func_state.change_frame_with_type(0, Type::AnyRef)?; + self.func_state.change_frame_with_type(0, Type::Null)?; } Operator::RefIsNull => { self.check_reference_types_enabled()?; self.check_operands(&[Type::AnyRef])?; - self.func_state.change_frame_with_type(0, Type::I32)?; + self.func_state.change_frame_with_type(1, Type::I32)?; } Operator::V128Load { ref memarg } => { self.check_simd_enabled()?; diff --git a/third_party/rust/wasmparser/src/primitives.rs b/third_party/rust/wasmparser/src/primitives.rs index 7fa8938ce24c9b078ec9eb98bacced40c5bc457d..1bb8db6d263f2c82d3d02fb874fcdca8e7438737 100644 --- a/third_party/rust/wasmparser/src/primitives.rs +++ b/third_party/rust/wasmparser/src/primitives.rs @@ -84,6 +84,7 @@ pub enum Type { AnyRef, Func, EmptyBlockType, + Null, } /// Either a value type or a function type. diff --git a/third_party/rust/wasmparser/src/readers/mod.rs b/third_party/rust/wasmparser/src/readers/mod.rs index 52488b195089506c47fa52bae71a2da200aaf3dd..3c6d58945800aa37c5377b7668c4dd68a26a93dc 100644 --- a/third_party/rust/wasmparser/src/readers/mod.rs +++ b/third_party/rust/wasmparser/src/readers/mod.rs @@ -42,8 +42,10 @@ pub use self::import_section::Import; pub use self::import_section::ImportSectionReader; pub use self::init_expr::InitExpr; pub use self::memory_section::MemorySectionReader; +pub use self::module::CustomSectionContent; pub use self::module::ModuleReader; pub use self::module::Section; +pub use self::module::SectionContent; use self::start_section::read_start_section_content; pub use self::table_section::TableSectionReader; pub use self::type_section::TypeSectionReader; diff --git a/third_party/rust/wasmparser/src/readers/module.rs b/third_party/rust/wasmparser/src/readers/module.rs index 535d99b669033a3cfc7c79c83d3527b9d640350e..36a9c3390b6b39e0bed0d7678bb849b6e23f2662 100644 --- a/third_party/rust/wasmparser/src/readers/module.rs +++ b/third_party/rust/wasmparser/src/readers/module.rs @@ -247,6 +247,86 @@ impl<'a> Section<'a> { end: self.offset + self.data.len(), } } + + pub fn content<'b>(&self) -> Result<SectionContent<'b>> + where + 'a: 'b, + { + let c = match self.code { + SectionCode::Type => SectionContent::Type(self.get_type_section_reader()?), + SectionCode::Function => SectionContent::Function(self.get_function_section_reader()?), + SectionCode::Code => SectionContent::Code(self.get_code_section_reader()?), + SectionCode::Export => SectionContent::Export(self.get_export_section_reader()?), + SectionCode::Import => SectionContent::Import(self.get_import_section_reader()?), + SectionCode::Global => SectionContent::Global(self.get_global_section_reader()?), + SectionCode::Memory => SectionContent::Memory(self.get_memory_section_reader()?), + SectionCode::Data => SectionContent::Data(self.get_data_section_reader()?), + SectionCode::Table => SectionContent::Table(self.get_table_section_reader()?), + SectionCode::Element => SectionContent::Element(self.get_element_section_reader()?), + SectionCode::Start => SectionContent::Start(self.get_start_section_content()?), + SectionCode::DataCount => { + SectionContent::DataCount(self.get_data_count_section_content()?) + } + SectionCode::Custom { kind, name } => { + let binary = self.get_binary_reader(); + let content = match kind { + CustomSectionKind::Name => { + Some(CustomSectionContent::Name(self.get_name_section_reader()?)) + } + CustomSectionKind::Producers => Some(CustomSectionContent::Producers( + self.get_producers_section_reader()?, + )), + CustomSectionKind::Linking => Some(CustomSectionContent::Linking( + self.get_linking_section_reader()?, + )), + CustomSectionKind::Reloc => Some(CustomSectionContent::Reloc( + self.get_reloc_section_reader()?, + )), + CustomSectionKind::SourceMappingURL => { + Some(CustomSectionContent::SourceMappingURL( + self.get_sourcemappingurl_section_content()?, + )) + } + + _ => None, + }; + SectionContent::Custom { + name, + binary, + content, + } + } + }; + Ok(c) + } +} + +pub enum SectionContent<'a> { + Type(TypeSectionReader<'a>), + Function(FunctionSectionReader<'a>), + Code(CodeSectionReader<'a>), + Export(ExportSectionReader<'a>), + Import(ImportSectionReader<'a>), + Global(GlobalSectionReader<'a>), + Memory(MemorySectionReader<'a>), + Data(DataSectionReader<'a>), + Table(TableSectionReader<'a>), + Element(ElementSectionReader<'a>), + Start(u32), + DataCount(u32), + Custom { + name: &'a str, + binary: BinaryReader<'a>, + content: Option<CustomSectionContent<'a>>, + }, +} + +pub enum CustomSectionContent<'a> { + Name(NameSectionReader<'a>), + Producers(ProducersSectionReader<'a>), + Linking(LinkingSectionReader<'a>), + Reloc(RelocSectionReader<'a>), + SourceMappingURL(&'a str), } /// Reads top-level WebAssembly file structure: header and sections. diff --git a/third_party/rust/wasmparser/src/tests.rs b/third_party/rust/wasmparser/src/tests.rs index 84386855b90ed70cf9e11614524e7a3df05cd2ef..247345740441c3b2a45c7cffee107360c076a1d7 100644 --- a/third_party/rust/wasmparser/src/tests.rs +++ b/third_party/rust/wasmparser/src/tests.rs @@ -45,6 +45,7 @@ mod simple_tests { data } + #[allow(dead_code)] fn scan_tests_files(prefix: &str) -> Vec<PathBuf> { let mut files = Vec::new(); @@ -325,11 +326,12 @@ mod wast_tests { use crate::BinaryReaderError; use std::fs::{read, read_dir}; use wabt::script::{Command, CommandKind, ModuleBinary, ScriptParser}; + use wabt::Features; const SPEC_TESTS_PATH: &str = "testsuite"; - fn validate_module(module: ModuleBinary) -> Result<(), BinaryReaderError> { - let config = ValidatingParserConfig { + fn default_config() -> ValidatingParserConfig { + ValidatingParserConfig { operator_config: OperatorValidatorConfig { enable_threads: false, enable_reference_types: false, @@ -340,8 +342,13 @@ mod wast_tests { #[cfg(feature = "deterministic")] deterministic_only: true, }, - }; + } + } + fn validate_module( + module: ModuleBinary, + config: ValidatingParserConfig, + ) -> Result<(), BinaryReaderError> { let data = &module.into_vec(); let mut parser = ValidatingParser::new(data.as_slice(), Some(config)); let mut max_iteration = 100000000; @@ -360,16 +367,35 @@ mod wast_tests { Ok(()) } - fn skip_test(filename: &str, line: u64) -> bool { - match (filename, line) { - _ => false, + fn to_features(config: &ValidatingParserConfig) -> Features { + let mut features = Features::new(); + if config.operator_config.enable_simd { + features.enable_simd(); } + if config.operator_config.enable_reference_types { + features.enable_reference_types(); + } + features } - fn run_wabt_scripts(filename: &str, wast: &[u8]) { + fn run_wabt_scripts<F>( + filename: &str, + wast: &[u8], + config: ValidatingParserConfig, + skip_test: F, + ) where + F: Fn(&str, u64) -> bool, + { println!("Parsing {:?}", filename); + // Check if we need to skip entire wast file test/parsing. + if skip_test(filename, /* line = */ 0) { + println!("{}: skipping", filename); + return; + } + + let features = to_features(&config); let mut parser: ScriptParser<f32, f64> = - ScriptParser::from_str(std::str::from_utf8(wast).expect("valid utf8 wast")) + ScriptParser::from_source_and_name_with_features(wast, filename, features) .expect("script parser"); while let Some(Command { kind, line }) = parser.next().expect("parser") { @@ -382,14 +408,14 @@ mod wast_tests { CommandKind::Module { module, .. } | CommandKind::AssertUninstantiable { module, .. } | CommandKind::AssertUnlinkable { module, .. } => { - if let Err(err) = validate_module(module) { + if let Err(err) = validate_module(module, config.clone()) { panic!("{}:{}: invalid module: {}", filename, line, err.message); } } CommandKind::AssertInvalid { module, .. } | CommandKind::AssertMalformed { module, .. } => { // TODO diffentiate between assert_invalid and assert_malformed - if let Ok(_) = validate_module(module) { + if let Ok(_) = validate_module(module, config.clone()) { panic!( "{}:{}: invalid module was successfully parsed", filename, line @@ -408,6 +434,76 @@ mod wast_tests { } } + fn run_proposal_tests<F>(name: &str, config: ValidatingParserConfig, skip_test: F) + where + F: Fn(&str, u64) -> bool, + { + let proposal_dir = format!("{}/proposals/{}", SPEC_TESTS_PATH, name); + for entry in read_dir(&proposal_dir).unwrap() { + let dir = entry.unwrap(); + if !dir.file_type().unwrap().is_file() + || dir.path().extension().map(|s| s.to_str().unwrap()) != Some("wast") + { + continue; + } + + let data = read(&dir.path()).expect("wast data"); + run_wabt_scripts( + dir.file_name().to_str().expect("name"), + &data, + config, + |name, line| skip_test(name, line), + ); + } + } + + #[test] + fn run_proposals_tests() { + run_proposal_tests( + "simd", + { + let mut config: ValidatingParserConfig = default_config(); + config.operator_config.enable_simd = true; + config + }, + |name, line| match (name, line) { + ("simd_address.wast", _) + | ("simd_const.wast", _) + | ("simd_f32x4_cmp.wast", _) + | ("simd_store.wast", _) + | ("simd_lane.wast", _) + | ("simd_load.wast", _) => true, + _ => false, + }, + ); + + run_proposal_tests( + "reference-types", + { + let mut config: ValidatingParserConfig = default_config(); + config.operator_config.enable_reference_types = true; + config + }, + |name, line| match (name, line) { + ("ref_null.wast", _) + | ("ref_is_null.wast", _) + | ("ref_func.wast", _) + | ("linking.wast", _) + | ("globals.wast", _) + | ("imports.wast", _) + | ("br_table.wast", _) + | ("select.wast", _) + | ("table_get.wast", _) + | ("table_set.wast", _) + | ("table_size.wast", _) + | ("table_fill.wast", _) + | ("table_grow.wast", _) + | ("exports.wast", _) => true, + _ => false, + }, + ); + } + #[test] fn run_spec_tests() { for entry in read_dir(SPEC_TESTS_PATH).unwrap() { @@ -419,7 +515,12 @@ mod wast_tests { } let data = read(&dir.path()).expect("wast data"); - run_wabt_scripts(dir.file_name().to_str().expect("name"), &data); + run_wabt_scripts( + dir.file_name().to_str().expect("name"), + &data, + default_config(), + |_, _| false, + ); } } } diff --git a/third_party/rust/wasmparser/src/validator.rs b/third_party/rust/wasmparser/src/validator.rs index d783a63b8c7b692738de4dbf4b0f3e7c53ddc1c0..b84ae69b63d60adec5fa2586f304ced6b2b26a37 100644 --- a/third_party/rust/wasmparser/src/validator.rs +++ b/third_party/rust/wasmparser/src/validator.rs @@ -34,8 +34,8 @@ use crate::primitives::{ use crate::parser::{Parser, ParserInput, ParserState, WasmDecoder}; use crate::operators_validator::{ - FunctionEnd, OperatorValidator, OperatorValidatorConfig, WasmModuleResources, - DEFAULT_OPERATOR_VALIDATOR_CONFIG, + is_subtype_supertype, FunctionEnd, OperatorValidator, OperatorValidatorConfig, + WasmModuleResources, DEFAULT_OPERATOR_VALIDATOR_CONFIG, }; use crate::readers::FunctionBody; @@ -196,6 +196,12 @@ impl<'a> ValidatingParser<'a> { fn check_value_type(&self, ty: Type) -> ValidatorResult<'a, ()> { match ty { Type::I32 | Type::I64 | Type::F32 | Type::F64 => Ok(()), + Type::Null | Type::AnyFunc | Type::AnyRef => { + if !self.config.operator_config.enable_reference_types { + return self.create_error("reference types support is not enabled"); + } + Ok(()) + } Type::V128 => { if !self.config.operator_config.enable_simd { return self.create_error("SIMD support is not enabled"); @@ -301,6 +307,12 @@ impl<'a> ValidatingParser<'a> { Operator::I64Const { .. } => Type::I64, Operator::F32Const { .. } => Type::F32, Operator::F64Const { .. } => Type::F64, + Operator::RefNull => { + if !self.config.operator_config.enable_reference_types { + return self.create_error("reference types support is not enabled"); + } + Type::Null + } Operator::V128Const { .. } => { if !self.config.operator_config.enable_simd { return self.create_error("SIMD support is not enabled"); @@ -315,7 +327,7 @@ impl<'a> ValidatingParser<'a> { } _ => return self.create_error("invalid init_expr operator"), }; - if ty != state.ty { + if !is_subtype_supertype(ty, state.ty) { return self.create_error("invalid init_expr type"); } Ok(()) @@ -781,67 +793,72 @@ impl<'b> ValidatingOperatorParser<'b> { /// The resources parameter contains all needed data to validate the operators. pub fn validate_function_body( bytes: &[u8], + offset: usize, func_index: u32, resources: &dyn WasmModuleResources, operator_config: Option<OperatorValidatorConfig>, -) -> bool { +) -> Result<()> { let operator_config = operator_config.unwrap_or(DEFAULT_OPERATOR_VALIDATOR_CONFIG); - let function_body = FunctionBody::new(0, bytes); - let mut locals_reader = if let Ok(r) = function_body.get_locals_reader() { - r - } else { - return false; - }; + let function_body = FunctionBody::new(offset, bytes); + let mut locals_reader = function_body.get_locals_reader()?; let local_count = locals_reader.get_count() as usize; if local_count > MAX_WASM_FUNCTION_LOCALS { - return false; + Err(BinaryReaderError { + message: "locals exceed maximum", + offset: locals_reader.original_position(), + })?; } let mut locals: Vec<(u32, Type)> = Vec::with_capacity(local_count); let mut locals_total: usize = 0; for _ in 0..local_count { - let (count, ty) = if let Ok(r) = locals_reader.read() { - r - } else { - return false; - }; - locals_total = if let Some(r) = locals_total.checked_add(count as usize) { - r - } else { - return false; - }; + let (count, ty) = locals_reader.read()?; + locals_total = + locals_total + .checked_add(count as usize) + .ok_or_else(|| BinaryReaderError { + message: "locals overflow", + offset: locals_reader.original_position(), + })?; if locals_total > MAX_WASM_FUNCTION_LOCALS { - return false; + Err(BinaryReaderError { + message: "locals exceed maximum", + offset: locals_reader.original_position(), + })?; } locals.push((count, ty)); } - let operators_reader = if let Ok(r) = function_body.get_operators_reader() { - r - } else { - return false; - }; + let operators_reader = function_body.get_operators_reader()?; let func_type_index = resources.func_type_indices()[func_index as usize]; let func_type = &resources.types()[func_type_index as usize]; let mut operator_validator = OperatorValidator::new(func_type, &locals, operator_config); let mut eof_found = false; - for op in operators_reader.into_iter() { - let op = match op { - Err(_) => return false, - Ok(ref op) => op, - }; - match operator_validator.process_operator(op, resources) { - Err(_) => return false, - Ok(FunctionEnd::Yes) => { + let mut last_op = 0; + for item in operators_reader.into_iter_with_offsets() { + let (ref op, offset) = item?; + match operator_validator + .process_operator(op, resources) + .map_err(|message| BinaryReaderError { message, offset })? + { + FunctionEnd::Yes => { eof_found = true; } - Ok(FunctionEnd::No) => (), + FunctionEnd::No => { + last_op = offset; + } } } - eof_found + if !eof_found { + Err(BinaryReaderError { + message: "end of function not found", + offset: last_op, + })?; + } + Ok(()) } /// Test whether the given buffer contains a valid WebAssembly module, /// analogous to WebAssembly.validate in the JS API. -pub fn validate(bytes: &[u8], config: Option<ValidatingParserConfig>) -> bool { +pub fn validate(bytes: &[u8], config: Option<ValidatingParserConfig>) -> Result<()> { let mut parser = ValidatingParser::new(bytes, config); let mut parser_input = None; let mut func_ranges = Vec::new(); @@ -850,7 +867,7 @@ pub fn validate(bytes: &[u8], config: Option<ValidatingParserConfig>) -> bool { let state = parser.read_with_input(next_input); match *state { ParserState::EndWasm => break, - ParserState::Error(_) => return false, + ParserState::Error(e) => Err(e)?, ParserState::BeginFunctionBody { range } => { parser_input = Some(ParserInput::SkipFunctionBody); func_ranges.push(range); @@ -862,23 +879,19 @@ pub fn validate(bytes: &[u8], config: Option<ValidatingParserConfig>) -> bool { for (i, range) in func_ranges.into_iter().enumerate() { let function_body = range.slice(bytes); let function_index = i as u32 + parser.func_imports_count; - if !validate_function_body( + validate_function_body( function_body, + range.start, function_index, &parser.resources, operator_config, - ) { - return false; - } + )?; } - true + Ok(()) } #[test] fn test_validate() { - assert!(validate(&[0x0, 0x61, 0x73, 0x6d, 0x1, 0x0, 0x0, 0x0], None)); - assert!(!validate( - &[0x0, 0x61, 0x73, 0x6d, 0x2, 0x0, 0x0, 0x0], - None - )); + assert!(validate(&[0x0, 0x61, 0x73, 0x6d, 0x1, 0x0, 0x0, 0x0], None).is_ok()); + assert!(validate(&[0x0, 0x61, 0x73, 0x6d, 0x2, 0x0, 0x0, 0x0], None).is_err()); }