Bug 1507819 - Update to Cranelift 0.25. r=bbouvier
authorDan Gohman <sunfish@mozilla.com>
Tue, 27 Nov 2018 00:06:00 +0200
changeset 504839 3d330442ef3b3beddb0e71a95573e5cce49207dc
parent 504838 e9a02a8a62e5ee81c00ff7cff86744cc0f4d4e41
child 504840 fd18c9b951806db012985c9daf81a07aaa0bfe12
push id10290
push userffxbld-merge
push dateMon, 03 Dec 2018 16:23:23 +0000
treeherdermozilla-beta@700bed2445e6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbbouvier
bugs1507819
milestone65.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1507819 - Update to Cranelift 0.25. r=bbouvier
Cargo.lock
js/src/wasm/cranelift/Cargo.toml
third_party/rust/cranelift-bforest/.cargo-checksum.json
third_party/rust/cranelift-bforest/Cargo.toml
third_party/rust/cranelift-codegen-meta/.cargo-checksum.json
third_party/rust/cranelift-codegen-meta/Cargo.toml
third_party/rust/cranelift-codegen-meta/src/cdsl/isa.rs
third_party/rust/cranelift-codegen-meta/src/cdsl/regs.rs
third_party/rust/cranelift-codegen-meta/src/isa/arm32/mod.rs
third_party/rust/cranelift-codegen-meta/src/isa/arm64/mod.rs
third_party/rust/cranelift-codegen-meta/src/isa/mod.rs
third_party/rust/cranelift-codegen-meta/src/isa/riscv/mod.rs
third_party/rust/cranelift-codegen-meta/src/isa/x86/mod.rs
third_party/rust/cranelift-codegen/.cargo-checksum.json
third_party/rust/cranelift-codegen/Cargo.toml
third_party/rust/cranelift-codegen/build.rs
third_party/rust/cranelift-codegen/meta-python/cdsl/isa.py
third_party/rust/cranelift-codegen/meta-python/isa/x86/recipes.py
third_party/rust/cranelift-codegen/src/context.rs
third_party/rust/cranelift-codegen/src/ir/dfg.rs
third_party/rust/cranelift-codegen/src/ir/extname.rs
third_party/rust/cranelift-codegen/src/ir/instructions.rs
third_party/rust/cranelift-codegen/src/isa/enc_tables.rs
third_party/rust/cranelift-codegen/src/isa/mod.rs
third_party/rust/cranelift-codegen/src/isa/x86/abi.rs
third_party/rust/cranelift-codegen/src/isa/x86/enc_tables.rs
third_party/rust/cranelift-codegen/src/legalizer/boundary.rs
third_party/rust/cranelift-codegen/src/legalizer/split.rs
third_party/rust/cranelift-codegen/src/licm.rs
third_party/rust/cranelift-codegen/src/print_errors.rs
third_party/rust/cranelift-codegen/src/regalloc/coalescing.rs
third_party/rust/cranelift-codegen/src/regalloc/register_set.rs
third_party/rust/cranelift-codegen/src/regalloc/reload.rs
third_party/rust/cranelift-codegen/src/regalloc/spilling.rs
third_party/rust/cranelift-codegen/src/regalloc/virtregs.rs
third_party/rust/cranelift-codegen/src/simple_gvn.rs
third_party/rust/cranelift-codegen/src/verifier/mod.rs
third_party/rust/cranelift-codegen/src/write.rs
third_party/rust/cranelift-entity/.cargo-checksum.json
third_party/rust/cranelift-entity/Cargo.toml
third_party/rust/cranelift-entity/src/primary.rs
third_party/rust/cranelift-frontend/.cargo-checksum.json
third_party/rust/cranelift-frontend/Cargo.toml
third_party/rust/cranelift-frontend/src/frontend.rs
third_party/rust/cranelift-wasm/.cargo-checksum.json
third_party/rust/cranelift-wasm/Cargo.toml
third_party/rust/cranelift-wasm/src/code_translator.rs
third_party/rust/cranelift-wasm/src/environ/dummy.rs
third_party/rust/cranelift-wasm/src/environ/spec.rs
third_party/rust/cranelift-wasm/src/lib.rs
third_party/rust/cranelift-wasm/src/sections_translator.rs
third_party/rust/cranelift-wasm/src/translation_utils.rs
third_party/rust/wasmparser/.cargo-checksum.json
third_party/rust/wasmparser/Cargo.toml
third_party/rust/wasmparser/README.md
third_party/rust/wasmparser/src/binary_reader.rs
third_party/rust/wasmparser/src/lib.rs
third_party/rust/wasmparser/src/parser.rs
third_party/rust/wasmparser/src/readers/code_section.rs
third_party/rust/wasmparser/src/readers/mod.rs
third_party/rust/wasmparser/src/readers/module.rs
third_party/rust/wasmparser/src/readers/operators.rs
third_party/rust/wasmparser/src/validator.rs
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -156,18 +156,18 @@ dependencies = [
  "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "baldrdash"
 version = "0.1.0"
 dependencies = [
  "bindgen 0.43.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "cranelift-codegen 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "cranelift-wasm 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cranelift-codegen 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cranelift-wasm 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "base64"
 version = "0.9.2"
@@ -452,71 +452,71 @@ name = "cose-c"
 version = "0.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cose 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "cranelift-bforest"
-version = "0.23.0"
+version = "0.25.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cranelift-entity 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cranelift-entity 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "cranelift-codegen"
-version = "0.23.0"
+version = "0.25.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cranelift-bforest 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "cranelift-codegen-meta 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "cranelift-entity 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cranelift-bforest 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cranelift-codegen-meta 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cranelift-entity 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "cranelift-codegen-meta"
-version = "0.23.0"
+version = "0.25.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cranelift-entity 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cranelift-entity 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "cranelift-entity"
-version = "0.23.0"
+version = "0.25.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "cranelift-frontend"
-version = "0.23.0"
+version = "0.25.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cranelift-codegen 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cranelift-codegen 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "cranelift-wasm"
-version = "0.23.0"
+version = "0.25.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cranelift-codegen 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "cranelift-entity 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "cranelift-frontend 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cranelift-codegen 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cranelift-entity 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cranelift-frontend 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "wasmparser 0.21.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "wasmparser 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "crc"
 version = "1.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "build_const 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2895,17 +2895,17 @@ source = "registry+https://github.com/ru
 dependencies = [
  "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "wasmparser"
-version = "0.21.8"
+version = "0.22.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "webdriver"
 version = "0.38.0"
 dependencies = [
  "base64 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "cookie 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3161,22 +3161,22 @@ dependencies = [
 "checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e"
 "checksum cookie 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1465f8134efa296b4c19db34d909637cb2bf0f7aaf21299e23e18fa29ac557cf"
 "checksum core-foundation 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c7caa6cb9e76ddddbea09a03266d6b3bc98cd41e9fb9b017c473e7cca593ec25"
 "checksum core-foundation-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b2a53cce0ddcf7e7e1f998738d757d5a3bf08bf799a180e50ebe50d298f52f5a"
 "checksum core-graphics 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)" = "62ceafe1622ffc9a332199096841d0ff9912ec8cf8f9cde01e254a7d5217cd10"
 "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.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8c5f8e1ab4f73b59a98531a8013d8ed3ca7edb4e36984cb301d9c06f6892787b"
-"checksum cranelift-codegen 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4437ec8212686e6cdacfea75aaedb4ab8b013869be1e8693a4cb97a60f135035"
-"checksum cranelift-codegen-meta 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4eac16097b96e9f609df735555f2d1658531750fbc3805bca1daca7671aef9eb"
-"checksum cranelift-entity 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9be3f82369346201c2e0cff720522e6eb55459e51c916b2199f25cff2058ca96"
-"checksum cranelift-frontend 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d5d18ab2bc89a09b4275442a9559dc0f947b9a8ad9ae9ee89452a057df54ced"
-"checksum cranelift-wasm 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e5906a111814d43d84002ef974eb0c023804fd4d1866b34f43c1bb588a759ad8"
+"checksum cranelift-bforest 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b2d527b241af388ff017d72f2b0b323929a70cf97342c6ec1534e3b0f4dfaa0"
+"checksum cranelift-codegen 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e92fa0fa287cf00a6739c46aba114957e0a8eeeb4f0d1aa65d6ed0699c34ca6b"
+"checksum cranelift-codegen-meta 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)" = "963262697a05d9aa63ca40f4670a7243e4525f4a098e10d654c3f5143fcef686"
+"checksum cranelift-entity 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc9a0329208e5e0d7d4d6e64cd50985d4c4cbfdbeeb594ae2157a094b98e8dcc"
+"checksum cranelift-frontend 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)" = "98d9eb4a2343435d520499236c805725c88d6d55eefb9a6ad0819b7970c76bdd"
+"checksum cranelift-wasm 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5022a3a3d1044fdc8c97909b5e8d701884982dcfb43885034d004cfdd9b7d577"
 "checksum crc 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bd5d02c0aac6bd68393ed69e00bbc2457f3e89075c6349db7189618dc4ddc1d7"
 "checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3"
 "checksum crossbeam-deque 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fe8153ef04a7594ded05b427ffad46ddeaf22e63fd48d42b3e1e3bb4db07cae7"
 "checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150"
 "checksum crossbeam-epoch 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2af0e75710d6181e234c8ecc79f14a97907850a541b13b0be1dd10992f2e4620"
 "checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9"
 "checksum crossbeam-utils 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d636a8b3bcc1b409d7ffd3facef8f21dcb4009626adbd0c5e6c4305c07253c7b"
 "checksum cssparser 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)" = "730363a45c4e248d4f21d3e5c1156d1a9cdec0855056c0d9539e814bc59865c3"
@@ -3391,17 +3391,17 @@ dependencies = [
 "checksum url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f808aadd8cfec6ef90e4a14eb46f24511824d1ac596b9682703c87056c8678b7"
 "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122"
 "checksum uuid 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e1436e58182935dcd9ce0add9ea0b558e8a87befe01c1a301e6020aeb0876363"
 "checksum vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9e0a7d8bed3178a8fb112199d466eeca9ed09a14ba8ad67718179b4fd5487d0b"
 "checksum vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887b5b631c2ad01628bbbaa7dd4c869f80d3186688f8d0b6f58774fbe324988c"
 "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
 "checksum walkdir 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "63636bd0eb3d00ccb8b9036381b526efac53caf112b7783b730ab3f8e44da369"
 "checksum want 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "797464475f30ddb8830cc529aaaae648d581f99e2036a928877dfde027ddf6b3"
-"checksum wasmparser 0.21.8 (registry+https://github.com/rust-lang/crates.io-index)" = "202e4cd4d99aa8adb8fe6280e099fdd2e5003c8d09c27de6969ff04dba60ef39"
+"checksum wasmparser 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1b4e0f66e314a8e63ff5c3cc5103f7d0a3de9ee98bb61a960adcf7f1d9debd2f"
 "checksum webidl 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0f807f7488d680893f7188aa09d7672a3a0a8461975a098a2edf0a52e3fee29"
 "checksum which 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4be6cfa54dab45266e98b5d7be2f8ce959ddd49abd141a05d52dce4b07f803bb"
 "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
 "checksum winapi 0.3.6 (git+https://github.com/froydnj/winapi-rs?branch=aarch64)" = "<none>"
 "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
 "checksum winapi-i686-pc-windows-gnu 0.4.0 (git+https://github.com/froydnj/winapi-rs?branch=aarch64)" = "<none>"
 "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (git+https://github.com/froydnj/winapi-rs?branch=aarch64)" = "<none>"
 "checksum wincolor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "eeb06499a3a4d44302791052df005d5232b927ed1a9658146d842165c4de7767"
--- a/js/src/wasm/cranelift/Cargo.toml
+++ b/js/src/wasm/cranelift/Cargo.toml
@@ -3,18 +3,18 @@ name = "baldrdash"
 version = "0.1.0"
 authors = ["The Spidermonkey and Cranelift developers"]
 
 [lib]
 crate-type = ["rlib"]
 name = "baldrdash"
 
 [dependencies]
-cranelift-codegen = "0.23.0"
-cranelift-wasm = "0.23.0"
+cranelift-codegen = "0.25.0"
+cranelift-wasm = "0.25.0"
 target-lexicon = "0.2.0"
 log = { version = "0.4.4", default-features = false, features = ["release_max_level_info"] }
 env_logger = "0.5.6"
 
 [build-dependencies]
 bindgen = {version = "0.43", default-features = false} # disable `logging` to reduce code size
 
 # Uncomment this to enable perf support in release mode.
--- a/third_party/rust/cranelift-bforest/.cargo-checksum.json
+++ b/third_party/rust/cranelift-bforest/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{"Cargo.toml":"a9d64466eee85b2f607e61ad354cb7b08cc17b925395fb2ec08eec61726773e9","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"af367c67340fa7f6fb9a35b0aa637dcf303957f7ae7427a5f4f6356801c8bb04","src/lib.rs":"01f8c9b8a077975c8f0803f793b8c20b583aaef2dc1f4400b9d90ba132ff4133","src/map.rs":"77eb9fd2ffdaafaf4daea609602a0c775c5012efae21c03547f63653271da163","src/node.rs":"309609acc70f1ce6be2f3c964430d23c0680bd7a647afab837a2aedc06235531","src/path.rs":"25326bacbb99189e873cb70e770f21c13fdef0fb2cd20f484830386fc4c75c6a","src/pool.rs":"196216124922dc42708a3aa944e98b6a57ef9bb770dab7e01f154b6382cab021","src/set.rs":"d4ff99fe51de9eefb4c774e919259d952ab5dde4dd3b99bd9974e4eedbb28938"},"package":"8c5f8e1ab4f73b59a98531a8013d8ed3ca7edb4e36984cb301d9c06f6892787b"}
\ No newline at end of file
+{"files":{"Cargo.toml":"8c219cb955621bfeb89eb1175dc9d810dc98323ccb54360e623425308c970e72","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"af367c67340fa7f6fb9a35b0aa637dcf303957f7ae7427a5f4f6356801c8bb04","src/lib.rs":"01f8c9b8a077975c8f0803f793b8c20b583aaef2dc1f4400b9d90ba132ff4133","src/map.rs":"77eb9fd2ffdaafaf4daea609602a0c775c5012efae21c03547f63653271da163","src/node.rs":"309609acc70f1ce6be2f3c964430d23c0680bd7a647afab837a2aedc06235531","src/path.rs":"25326bacbb99189e873cb70e770f21c13fdef0fb2cd20f484830386fc4c75c6a","src/pool.rs":"196216124922dc42708a3aa944e98b6a57ef9bb770dab7e01f154b6382cab021","src/set.rs":"d4ff99fe51de9eefb4c774e919259d952ab5dde4dd3b99bd9974e4eedbb28938"},"package":"7b2d527b241af388ff017d72f2b0b323929a70cf97342c6ec1534e3b0f4dfaa0"}
\ No newline at end of file
--- a/third_party/rust/cranelift-bforest/Cargo.toml
+++ b/third_party/rust/cranelift-bforest/Cargo.toml
@@ -7,27 +7,27 @@
 #
 # If you believe there's an error in this file please file an
 # issue against the rust-lang/cargo repository. If you're
 # editing this file be aware that the upstream Cargo.toml
 # will likely look very different (and much more reasonable)
 
 [package]
 name = "cranelift-bforest"
-version = "0.23.0"
+version = "0.25.0"
 authors = ["The Cranelift Project Developers"]
 description = "A forest of B+-trees"
 documentation = "https://cranelift.readthedocs.io/"
 readme = "README.md"
 keywords = ["btree", "forest", "set", "map"]
 categories = ["no-std"]
 license = "Apache-2.0 WITH LLVM-exception"
 repository = "https://github.com/CraneStation/cranelift"
 [dependencies.cranelift-entity]
-version = "0.23.0"
+version = "0.25.0"
 default-features = false
 
 [features]
 default = ["std"]
 std = ["cranelift-entity/std"]
 [badges.maintenance]
 status = "experimental"
 
--- a/third_party/rust/cranelift-codegen-meta/.cargo-checksum.json
+++ b/third_party/rust/cranelift-codegen-meta/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{"Cargo.toml":"56d43cc835cbea830d3659c9f32062f3413c85a0eba618acc633fe0f6640445d","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"b123f056d0d458396679c5f7f2a16d2762af0258fcda4ac14b6655a95e5a0022","src/base/mod.rs":"9320dfed2250bdb0347e01862b2ff7bf7db78920dae1719834b374de11131e87","src/base/types.rs":"a3e449db1f515d268f3ad21301740ba415444d399f8433dbc48979f78557f66a","src/cdsl/isa.rs":"52ab00f489acbf00ebda8e2866de6495f3ed0f57d06896418dc7a2e8def902d2","src/cdsl/mod.rs":"311726d7e4ad9278eab301fd4f6e31e697b7d4260733c6a00fe39cd61db977d3","src/cdsl/regs.rs":"fe24d2ea67d7eec9912c2f9c85bbec98a12c43c9a1dd12f219795abf2e8d962a","src/cdsl/types.rs":"f9756e483329f00a1d8a15e30bc05e8d4c8fa71ff1f649b808528ddeb5fbdfea","src/error.rs":"5110a4e3c1e97396ba02d9f5abbb8af4b586f0cc4d33a5c2473f1718cc4bef05","src/gen_registers.rs":"3d38ff5b0c6183209d4ba84bd1f14b1d84bea697c0589471aa5ce4abc209f20b","src/gen_types.rs":"5eb4e9bd0fda7f7644bb2428045f0bf16f2b698ff32cadcbbf7f2c7669f18de3","src/isa/arm32/mod.rs":"2a1aef09ead88fac19ca65f0ca01b5b38761001f7816984300d640001d818f33","src/isa/arm64/mod.rs":"5b034bcdcef2ab161c43afa860c7f176c81647f076c47cc4315917e13aa47810","src/isa/mod.rs":"927e5543dbe5c22bd6356b252318942ca16e3cbce466641a4f494a8a492443d9","src/isa/riscv/mod.rs":"f691fd37f2770919b32725ae0a2b523bc231aebb4aada4f9a591fc2acbbb2dc7","src/isa/x86/mod.rs":"0821384e048456475061c69f94a2f96868311114c18c758b841720c76f6daa71","src/lib.rs":"dd97d73d41ffee2d2cc62705f9f6f7ed6b9af982aff8d1fafb72590e097c513c","src/srcgen.rs":"abe118fb41a643ffc63577cc4b62de9a2286e1eeb34b95bff79648d0ea582886"},"package":"4eac16097b96e9f609df735555f2d1658531750fbc3805bca1daca7671aef9eb"}
\ No newline at end of file
+{"files":{"Cargo.toml":"0e4050095c283d025e30ccba0e3d9753b63340604b6373e4ea06d221eb3a97e1","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"b123f056d0d458396679c5f7f2a16d2762af0258fcda4ac14b6655a95e5a0022","src/base/mod.rs":"9320dfed2250bdb0347e01862b2ff7bf7db78920dae1719834b374de11131e87","src/base/types.rs":"a3e449db1f515d268f3ad21301740ba415444d399f8433dbc48979f78557f66a","src/cdsl/isa.rs":"b34150e2658dd7ab30e9846dece89f56a0acbfff0341927cec06bf0de1d9b419","src/cdsl/mod.rs":"311726d7e4ad9278eab301fd4f6e31e697b7d4260733c6a00fe39cd61db977d3","src/cdsl/regs.rs":"41cca844b390bba3ceefa147e7b0dec170aba2b5759a41ecb5b9cd7f2cc59f60","src/cdsl/types.rs":"f9756e483329f00a1d8a15e30bc05e8d4c8fa71ff1f649b808528ddeb5fbdfea","src/error.rs":"5110a4e3c1e97396ba02d9f5abbb8af4b586f0cc4d33a5c2473f1718cc4bef05","src/gen_registers.rs":"3d38ff5b0c6183209d4ba84bd1f14b1d84bea697c0589471aa5ce4abc209f20b","src/gen_types.rs":"5eb4e9bd0fda7f7644bb2428045f0bf16f2b698ff32cadcbbf7f2c7669f18de3","src/isa/arm32/mod.rs":"ceb8290344a245f11eb541d60c2678ddfe7beaf60cde491c22fd48090fa210ba","src/isa/arm64/mod.rs":"db7f828940372a21c62cf6f5aefca7cc05c974ba731b8db602da0a336e29ea1e","src/isa/mod.rs":"36c001f8ecdea4aaf8cadcad4f91fe79a82806e4f43182e216c2fa99cecf55dc","src/isa/riscv/mod.rs":"aecb127f8c06970a00dde8ad772fdebe5497b6e7f342fa2a0e859355ae027055","src/isa/x86/mod.rs":"2b3a181a226d66a8faf855d517fb4a13554a31020f6b8875ba75a2fe650f378a","src/lib.rs":"dd97d73d41ffee2d2cc62705f9f6f7ed6b9af982aff8d1fafb72590e097c513c","src/srcgen.rs":"abe118fb41a643ffc63577cc4b62de9a2286e1eeb34b95bff79648d0ea582886"},"package":"963262697a05d9aa63ca40f4670a7243e4525f4a098e10d654c3f5143fcef686"}
\ No newline at end of file
--- a/third_party/rust/cranelift-codegen-meta/Cargo.toml
+++ b/third_party/rust/cranelift-codegen-meta/Cargo.toml
@@ -7,21 +7,21 @@
 #
 # If you believe there's an error in this file please file an
 # issue against the rust-lang/cargo repository. If you're
 # editing this file be aware that the upstream Cargo.toml
 # will likely look very different (and much more reasonable)
 
 [package]
 name = "cranelift-codegen-meta"
-version = "0.23.0"
+version = "0.25.0"
 authors = ["The Cranelift Project Developers"]
 description = "Metaprogram for cranelift-codegen code generator library"
 readme = "README.md"
 license = "Apache-2.0 WITH LLVM-exception"
 repository = "https://github.com/CraneStation/cranelift"
 [dependencies.cranelift-entity]
-version = "0.23.0"
+version = "0.25.0"
 [badges.maintenance]
 status = "experimental"
 
 [badges.travis-ci]
 repository = "CraneStation/cranelift"
--- a/third_party/rust/cranelift-codegen-meta/src/cdsl/isa.rs
+++ b/third_party/rust/cranelift-codegen-meta/src/cdsl/isa.rs
@@ -1,109 +1,134 @@
 use cranelift_entity::PrimaryMap;
 
 use super::regs::{
-    RegBank, RegBankBuilder, RegBankIndex, RegClass, RegClassBuilder, RegClassIndex,
+    RegBank, RegBankBuilder, RegBankIndex, RegClass, RegClassBuilder, RegClassIndex, RegClassProto,
 };
 
 pub struct TargetIsa {
     pub name: &'static str,
     pub reg_banks: PrimaryMap<RegBankIndex, RegBank>,
     pub reg_classes: PrimaryMap<RegClassIndex, RegClass>,
 }
 
 impl TargetIsa {
     pub fn new(name: &'static str) -> Self {
         Self {
             name,
             reg_banks: PrimaryMap::new(),
             reg_classes: PrimaryMap::new(),
         }
     }
+}
+
+pub struct TargetIsaBuilder {
+    isa: TargetIsa,
+}
+
+impl TargetIsaBuilder {
+    pub fn new(name: &'static str) -> Self {
+        Self {
+            isa: TargetIsa::new(name),
+        }
+    }
 
     pub fn add_reg_bank(&mut self, builder: RegBankBuilder) -> RegBankIndex {
-        let first_unit = if self.reg_banks.len() == 0 {
+        let first_unit = if self.isa.reg_banks.len() == 0 {
             0
         } else {
-            let last = &self.reg_banks.last().unwrap();
+            let last = &self.isa.reg_banks.last().unwrap();
             let first_available_unit = (last.first_unit + last.units) as i8;
             let units = builder.units;
             let align = if units.is_power_of_two() {
                 units
             } else {
                 units.next_power_of_two()
             } as i8;
             (first_available_unit + align - 1) & -align
         } as u8;
 
-        self.reg_banks.push(RegBank::new(
+        self.isa.reg_banks.push(RegBank::new(
             builder.name,
             first_unit,
             builder.units,
             builder.names,
             builder.prefix,
             builder
                 .pressure_tracking
                 .expect("Pressure tracking must be explicitly set"),
         ))
     }
 
     pub fn add_reg_class(&mut self, builder: RegClassBuilder) -> RegClassIndex {
-        let reg_bank_units = self.reg_banks.get(builder.bank).unwrap().units;
+        let class_index = self.isa.reg_classes.next_key();
 
-        let start = builder.start;
+        // Finish delayed construction of RegClass.
+        let (bank, toprc, start, width) = match builder.proto {
+            RegClassProto::TopLevel(bank_index) => {
+                self.isa
+                    .reg_banks
+                    .get_mut(bank_index)
+                    .unwrap()
+                    .toprcs
+                    .push(class_index);
+                (bank_index, class_index, builder.start, builder.width)
+            }
+            RegClassProto::SubClass(parent_class_index) => {
+                assert!(builder.width == 0);
+                let (bank, toprc, start, width) = {
+                    let parent = self.isa.reg_classes.get(parent_class_index).unwrap();
+                    (parent.bank, parent.toprc, parent.start, parent.width)
+                };
+                for reg_class in self.isa.reg_classes.values_mut() {
+                    if reg_class.toprc == toprc {
+                        reg_class.subclasses.push(class_index);
+                    }
+                }
+                let subclass_start = start + builder.start * width;
+                (bank, toprc, subclass_start, width)
+            }
+        };
+
+        let reg_bank_units = self.isa.reg_banks.get(bank).unwrap().units;
         assert!(start < reg_bank_units);
 
         let count = if builder.count != 0 {
             builder.count
         } else {
-            reg_bank_units / builder.width
+            reg_bank_units / width
         };
 
-        let reg_class_index = builder.index;
-        assert!(
-            self.reg_classes.next_key() == reg_class_index,
-            "should have inserted RegClass where expected"
-        );
+        let reg_class = RegClass::new(builder.name, class_index, width, bank, toprc, count, start);
+        self.isa.reg_classes.push(reg_class);
 
-        let reg_class = RegClass::new(
-            builder.name,
-            reg_class_index,
-            builder.width,
-            builder.bank,
-            builder.toprc,
-            count,
-            start,
-        );
-        self.reg_classes.push(reg_class);
+        let reg_bank = self.isa.reg_banks.get_mut(bank).unwrap();
+        reg_bank.classes.push(class_index);
 
-        let reg_bank = self.reg_banks.get_mut(builder.bank).unwrap();
-        reg_bank.classes.push(reg_class_index);
-
-        reg_class_index
+        class_index
     }
 
     /// Checks that the set of register classes satisfies:
     ///
     /// 1. Closed under intersection: The intersection of any two register
     ///    classes in the set is either empty or identical to a member of the
     ///    set.
     /// 2. There are no identical classes under different names.
     /// 3. Classes are sorted topologically such that all subclasses have a
     ///    higher index that the superclass.
-    pub fn check(&self) {
-        for reg_bank in self.reg_banks.values() {
+    pub fn finish(self) -> TargetIsa {
+        for reg_bank in self.isa.reg_banks.values() {
             for i1 in reg_bank.classes.iter() {
                 for i2 in reg_bank.classes.iter() {
                     if i1 >= i2 {
                         continue;
                     }
 
-                    let rc1 = self.reg_classes.get(*i1).unwrap();
-                    let rc2 = self.reg_classes.get(*i2).unwrap();
+                    let rc1 = self.isa.reg_classes.get(*i1).unwrap();
+                    let rc2 = self.isa.reg_classes.get(*i2).unwrap();
 
                     let rc1_mask = rc1.mask(0);
                     let rc2_mask = rc2.mask(0);
 
                     assert!(
                         rc1.width != rc2.width || rc1_mask != rc2_mask,
                         "no duplicates"
                     );
@@ -121,22 +146,44 @@ impl TargetIsa {
 
                     // Classes must be topologically ordered, so the intersection can't be the
                     // superclass.
                     assert!(intersect != rc1_mask);
 
                     // If the intersection is the second one, then it must be a subclass.
                     if intersect == rc2_mask {
                         assert!(
-                            self.reg_classes
+                            self.isa
+                                .reg_classes
                                 .get(*i1)
                                 .unwrap()
                                 .subclasses
                                 .iter()
                                 .find(|x| **x == *i2)
                                 .is_some()
                         );
                     }
                 }
             }
         }
+
+        // This limit should be coordinated with the `RegClassMask` and `RegClassIndex` types in
+        // isa/registers.rs of the non-meta code.
+        assert!(
+            self.isa.reg_classes.len() <= 32,
+            "Too many register classes"
+        );
+
+        // The maximum number of top-level register classes which have pressure tracking should be
+        // kept in sync with the MAX_TRACKED_TOPRCS constant in isa/registers.rs of the non-meta
+        // code.
+        let num_toplevel = self
+            .isa
+            .reg_classes
+            .values()
+            .filter(|x| {
+                x.toprc == x.index && self.isa.reg_banks.get(x.bank).unwrap().pressure_tracking
+            }).count();
+        assert!(num_toplevel <= 4, "Too many top-level register classes");
+
+        self.isa
     }
 }
--- a/third_party/rust/cranelift-codegen-meta/src/cdsl/regs.rs
+++ b/third_party/rust/cranelift-codegen-meta/src/cdsl/regs.rs
@@ -1,12 +1,10 @@
 use cranelift_entity::EntityRef;
 
-use super::isa::TargetIsa;
-
 #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
 pub struct RegBankIndex(u32);
 entity_impl!(RegBankIndex);
 
 pub struct RegBank {
     pub name: &'static str,
     pub first_unit: u8,
     pub units: u8,
@@ -92,81 +90,63 @@ impl RegClass {
         for _ in 0..self.count {
             out_mask[u / 32] |= 1 << (u % 32);
             u += self.width as usize;
         }
         out_mask
     }
 }
 
+pub enum RegClassProto {
+    TopLevel(RegBankIndex),
+    SubClass(RegClassIndex),
+}
+
 pub struct RegClassBuilder {
     pub name: &'static str,
-    pub index: RegClassIndex,
     pub width: u8,
-    pub bank: RegBankIndex,
-    pub toprc: RegClassIndex,
     pub count: u8,
     pub start: u8,
+    pub proto: RegClassProto,
 }
 
 impl RegClassBuilder {
-    pub fn new_toplevel(isa: &mut TargetIsa, name: &'static str, bank: RegBankIndex) -> Self {
-        let index = isa.reg_classes.next_key();
-
-        // Add it to the top-level register classes of the register bank.
-        isa.reg_banks.get_mut(bank).unwrap().toprcs.push(index);
-
+    pub fn new_toplevel(name: &'static str, bank: RegBankIndex) -> Self {
         Self {
             name,
-            index,
             width: 1,
-            bank,
-            toprc: index,
             count: 0,
             start: 0,
+            proto: RegClassProto::TopLevel(bank),
         }
     }
-
     pub fn subclass_of(
-        isa: &mut TargetIsa,
         name: &'static str,
         parent_index: RegClassIndex,
         start: u8,
         stop: u8,
     ) -> Self {
         assert!(stop >= start);
-
-        let index = isa.reg_classes.next_key();
-
-        let toprc = isa.reg_classes.get(parent_index).unwrap().toprc;
-        for reg_class in isa.reg_classes.values_mut() {
-            if reg_class.toprc == toprc {
-                reg_class.subclasses.push(index);
-            }
-        }
-
-        let parent = &isa.reg_classes.get(parent_index).unwrap();
         Self {
             name,
+            width: 0,
             count: stop - start,
-            width: parent.width,
-            start: parent.start + start * parent.width,
-            bank: parent.bank,
-            toprc: parent.toprc,
-            index,
+            start: start,
+            proto: RegClassProto::SubClass(parent_index),
         }
     }
-
     pub fn count(mut self, count: u8) -> Self {
         self.count = count;
         self
     }
-
     pub fn width(mut self, width: u8) -> Self {
-        self.width = width;
+        match self.proto {
+            RegClassProto::TopLevel(_) => self.width = width,
+            RegClassProto::SubClass(_) => panic!("Subclasses inherit their parent's width."),
+        }
         self
     }
 }
 
 pub struct RegBankBuilder {
     pub name: &'static str,
     pub units: u8,
     pub names: Vec<&'static str>,
--- a/third_party/rust/cranelift-codegen-meta/src/isa/arm32/mod.rs
+++ b/third_party/rust/cranelift-codegen-meta/src/isa/arm32/mod.rs
@@ -1,13 +1,13 @@
+use cdsl::isa::{TargetIsa, TargetIsaBuilder};
 use cdsl::regs::{RegBankBuilder, RegClassBuilder};
-use isa;
 
-pub fn define() -> isa::TargetIsa {
-    let mut isa = isa::TargetIsa::new("arm32");
+pub fn define() -> TargetIsa {
+    let mut isa = TargetIsaBuilder::new("arm32");
 
     let builder = RegBankBuilder::new("FloatRegs", "s")
         .units(64)
         .track_pressure(true);
     let float_regs = isa.add_reg_bank(builder);
 
     let builder = RegBankBuilder::new("IntRegs", "r")
         .units(16)
@@ -15,25 +15,25 @@ pub fn define() -> isa::TargetIsa {
     let int_regs = isa.add_reg_bank(builder);
 
     let builder = RegBankBuilder::new("FlagRegs", "")
         .units(1)
         .names(vec!["nzcv"])
         .track_pressure(false);
     let flag_reg = isa.add_reg_bank(builder);
 
-    let builder = RegClassBuilder::new_toplevel(&mut isa, "S", float_regs).count(32);
+    let builder = RegClassBuilder::new_toplevel("S", float_regs).count(32);
     isa.add_reg_class(builder);
 
-    let builder = RegClassBuilder::new_toplevel(&mut isa, "D", float_regs).width(2);
+    let builder = RegClassBuilder::new_toplevel("D", float_regs).width(2);
     isa.add_reg_class(builder);
 
-    let builder = RegClassBuilder::new_toplevel(&mut isa, "Q", float_regs).width(4);
+    let builder = RegClassBuilder::new_toplevel("Q", float_regs).width(4);
     isa.add_reg_class(builder);
 
-    let builder = RegClassBuilder::new_toplevel(&mut isa, "GPR", int_regs);
+    let builder = RegClassBuilder::new_toplevel("GPR", int_regs);
     isa.add_reg_class(builder);
 
-    let builder = RegClassBuilder::new_toplevel(&mut isa, "FLAG", flag_reg);
+    let builder = RegClassBuilder::new_toplevel("FLAG", flag_reg);
     isa.add_reg_class(builder);
 
-    isa
+    isa.finish()
 }
--- a/third_party/rust/cranelift-codegen-meta/src/isa/arm64/mod.rs
+++ b/third_party/rust/cranelift-codegen-meta/src/isa/arm64/mod.rs
@@ -1,13 +1,13 @@
+use cdsl::isa::{TargetIsa, TargetIsaBuilder};
 use cdsl::regs::{RegBankBuilder, RegClassBuilder};
-use isa;
 
-pub fn define() -> isa::TargetIsa {
-    let mut isa = isa::TargetIsa::new("arm64");
+pub fn define() -> TargetIsa {
+    let mut isa = TargetIsaBuilder::new("arm64");
 
     // The `x31` regunit serves as the stack pointer / zero register depending on context. We
     // reserve it and don't model the difference.
     let builder = RegBankBuilder::new("IntRegs", "x")
         .units(32)
         .track_pressure(true);
     let int_regs = isa.add_reg_bank(builder);
 
@@ -17,19 +17,19 @@ pub fn define() -> isa::TargetIsa {
     let float_regs = isa.add_reg_bank(builder);
 
     let builder = RegBankBuilder::new("FlagRegs", "")
         .units(1)
         .names(vec!["nzcv"])
         .track_pressure(false);
     let flag_reg = isa.add_reg_bank(builder);
 
-    let builder = RegClassBuilder::new_toplevel(&mut isa, "GPR", int_regs);
+    let builder = RegClassBuilder::new_toplevel("GPR", int_regs);
     isa.add_reg_class(builder);
 
-    let builder = RegClassBuilder::new_toplevel(&mut isa, "FPR", float_regs);
+    let builder = RegClassBuilder::new_toplevel("FPR", float_regs);
     isa.add_reg_class(builder);
 
-    let builder = RegClassBuilder::new_toplevel(&mut isa, "FLAG", flag_reg);
+    let builder = RegClassBuilder::new_toplevel("FLAG", flag_reg);
     isa.add_reg_class(builder);
 
-    isa
+    isa.finish()
 }
--- a/third_party/rust/cranelift-codegen-meta/src/isa/mod.rs
+++ b/third_party/rust/cranelift-codegen-meta/src/isa/mod.rs
@@ -57,19 +57,15 @@ impl fmt::Display for Isa {
             Isa::X86 => write!(f, "x86"),
             Isa::Arm32 => write!(f, "arm32"),
             Isa::Arm64 => write!(f, "arm64"),
         }
     }
 }
 
 pub fn define_all() -> Vec<TargetIsa> {
-    let isas = vec![
+    vec![
         riscv::define(),
         arm32::define(),
         arm64::define(),
         x86::define(),
-    ];
-    for isa in isas.iter() {
-        isa.check();
-    }
-    isas
+    ]
 }
--- a/third_party/rust/cranelift-codegen-meta/src/isa/riscv/mod.rs
+++ b/third_party/rust/cranelift-codegen-meta/src/isa/riscv/mod.rs
@@ -1,24 +1,24 @@
+use cdsl::isa::{TargetIsa, TargetIsaBuilder};
 use cdsl::regs::{RegBankBuilder, RegClassBuilder};
-use isa;
 
-pub fn define() -> isa::TargetIsa {
-    let mut isa = isa::TargetIsa::new("riscv");
+pub fn define() -> TargetIsa {
+    let mut isa = TargetIsaBuilder::new("riscv");
 
     let builder = RegBankBuilder::new("IntRegs", "x")
         .units(32)
         .track_pressure(true);
     let int_regs = isa.add_reg_bank(builder);
 
     let builder = RegBankBuilder::new("FloatRegs", "f")
         .units(32)
         .track_pressure(true);
     let float_regs = isa.add_reg_bank(builder);
 
-    let builder = RegClassBuilder::new_toplevel(&mut isa, "GPR", int_regs);
+    let builder = RegClassBuilder::new_toplevel("GPR", int_regs);
     isa.add_reg_class(builder);
 
-    let builder = RegClassBuilder::new_toplevel(&mut isa, "FPR", float_regs);
+    let builder = RegClassBuilder::new_toplevel("FPR", float_regs);
     isa.add_reg_class(builder);
 
-    isa
+    isa.finish()
 }
--- a/third_party/rust/cranelift-codegen-meta/src/isa/x86/mod.rs
+++ b/third_party/rust/cranelift-codegen-meta/src/isa/x86/mod.rs
@@ -1,13 +1,13 @@
+use cdsl::isa::{TargetIsa, TargetIsaBuilder};
 use cdsl::regs::{RegBankBuilder, RegClassBuilder};
-use isa;
 
-pub fn define() -> isa::TargetIsa {
-    let mut isa = isa::TargetIsa::new("x86");
+pub fn define() -> TargetIsa {
+    let mut isa = TargetIsaBuilder::new("x86");
 
     let builder = RegBankBuilder::new("IntRegs", "r")
         .units(16)
         .names(vec!["rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi"])
         .track_pressure(true);
     let int_regs = isa.add_reg_bank(builder);
 
     let builder = RegBankBuilder::new("FloatRegs", "xmm")
@@ -16,28 +16,28 @@ pub fn define() -> isa::TargetIsa {
     let float_regs = isa.add_reg_bank(builder);
 
     let builder = RegBankBuilder::new("FlagRegs", "")
         .units(1)
         .names(vec!["rflags"])
         .track_pressure(false);
     let flag_reg = isa.add_reg_bank(builder);
 
-    let builder = RegClassBuilder::new_toplevel(&mut isa, "GPR", int_regs);
+    let builder = RegClassBuilder::new_toplevel("GPR", int_regs);
     let gpr = isa.add_reg_class(builder);
 
-    let builder = RegClassBuilder::new_toplevel(&mut isa, "FPR", float_regs);
+    let builder = RegClassBuilder::new_toplevel("FPR", float_regs);
     let fpr = isa.add_reg_class(builder);
 
-    let builder = RegClassBuilder::new_toplevel(&mut isa, "FLAG", flag_reg);
+    let builder = RegClassBuilder::new_toplevel("FLAG", flag_reg);
     isa.add_reg_class(builder);
 
-    let builder = RegClassBuilder::subclass_of(&mut isa, "GPR8", gpr, 0, 8);
+    let builder = RegClassBuilder::subclass_of("GPR8", gpr, 0, 8);
     let gpr8 = isa.add_reg_class(builder);
 
-    let builder = RegClassBuilder::subclass_of(&mut isa, "ABCD", gpr8, 0, 4);
+    let builder = RegClassBuilder::subclass_of("ABCD", gpr8, 0, 4);
     isa.add_reg_class(builder);
 
-    let builder = RegClassBuilder::subclass_of(&mut isa, "FPR8", fpr, 0, 8);
+    let builder = RegClassBuilder::subclass_of("FPR8", fpr, 0, 8);
     isa.add_reg_class(builder);
 
-    isa
+    isa.finish()
 }
--- a/third_party/rust/cranelift-codegen/.cargo-checksum.json
+++ b/third_party/rust/cranelift-codegen/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{"Cargo.toml":"0b0ed9a5aee750b88bed0d2a120fc9ca0a8dcf3a92a03582f08e7287ce3fbb4a","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"e5127227a7db4a8aa92fa6613ed71801025790e696bb41b0323fb7f3c6f7495a","build.rs":"513cfea9d05e69a1f3b596f91f40dd380ab0368931e5dc869dbd3959192b6792","meta-python/base/__init__.py":"4fac8bb055541dc964383bb04223bae6dfbfe348abf5e23f83655966cbb4aa8f","meta-python/base/entities.py":"0e146dd56dfb93cac88f9557a3501c9804cff584c2723db27435842bb5e2a1b7","meta-python/base/formats.py":"f9fb41210bc1f99a78cb7a60ee9f01c603412c6b1db7e69abbcc0f573cf9fb40","meta-python/base/immediates.py":"f42682d86bda7b569ec2fc2debd9036355999e61caaa9fbf8307e0be8a164814","meta-python/base/instructions.py":"4c3f8ee6c29e8cc9e19172f707890d613ed4173bda9b9de7857dae2b28babcbd","meta-python/base/legalize.py":"57b71ec3599fbf998c1926e4b48566661b7feec01dbd8bd177d0d2aaa26a44c2","meta-python/base/predicates.py":"53a5a9a37021a9762f0faec9f9e3c5b713411d47dd9192423cfe0f7a61916809","meta-python/base/semantics.py":"b90cbca9a143676ac37496c83634a66a83360248e4505ff7bda12b0d454efd92","meta-python/base/settings.py":"97fca9ddaab347f50f1594c93283f8f474e53a7232eae65949f56a6a702c2bba","meta-python/base/types.py":"9616d6fe4cab050827ab02eeb9843eacebbb8f7555521f504b5ee2ddf7214fdb","meta-python/build.py":"b72a80a54e09366878e92dca3a1508af394bf71a0c4b07a05e54058901373d34","meta-python/cdsl/__init__.py":"b531693b8228553ca8bd07e1dcd1aa5855f1ad3741b431d758fc27fdd162b024","meta-python/cdsl/ast.py":"b7c09f69b28b5754f494912ca5b77722dbd4ee416d5fad79cb48322eb544ea9f","meta-python/cdsl/formats.py":"fedfeaec754b40d6a9cc92b827976782c615d8eab1c7f47f6b47510cbef585f4","meta-python/cdsl/instructions.py":"b0ddfd8fd22889bd1e610c103d47087c9c6ae5882862ed44921dafc2ae0463a0","meta-python/cdsl/isa.py":"96e31674d699cfc846f65ee2ab62a199215e7ce012c6d43ea36ea5d2f839402e","meta-python/cdsl/operands.py":"e24914eae4059b88781bf5a5d7a14ecf98b10a701ed6cf6e88d15981b2ccbfdf","meta-python/cdsl/predicates.py":"def3f91712744671df9cf3d4f9c255a2061f341198689e31addf7db4efb63e36","meta-python/cdsl/registers.py":"939dafd1b8976a6cd456c9a5e4b374af81fafb9da979ea3a1f6d14e4645914a6","meta-python/cdsl/settings.py":"18dc27dd98a82c814c6aeb2686b40d1fed23661bef5e8b4cbf0fb4e7d39f4755","meta-python/cdsl/test_ast.py":"947e934e2862445a158bf266dff58a8c88aae31fb34a7f823309ee58a15c5393","meta-python/cdsl/test_package.py":"ffa53d20e023ecb89137294bb13614f4de9b09e1bf05d9772131570bf78f7987","meta-python/cdsl/test_ti.py":"57966c9eb027fa73bbc7ad81094ff55232053fbb2e16d78849ae3b6e9b1c2989","meta-python/cdsl/test_typevar.py":"714b2d564af1a843629279501436d681cd6590d1988b59e9f50ec940506538bb","meta-python/cdsl/test_xform.py":"ddb6633c7941bbf68570701cb887a81d6b4b27f4bc45eabccf2ce287ad9b77e9","meta-python/cdsl/ti.py":"a1a7ff79f8a2196aee491a3aafbd4f1b231004bbb5281992fc8f4e43f4fb951f","meta-python/cdsl/types.py":"adee4bbc1a9478288fa4b53ee1edeb5ee3296dba2c70bfbe01e923895064999e","meta-python/cdsl/typevar.py":"b5669934eddaf5b9cc0c27b966e2566b5f669f1c5a345f005960930fb499097e","meta-python/cdsl/xform.py":"5cdad80f12d50aa9491cd3d39797e6c0444936bb0874199d7c34e6d735658b34","meta-python/check.sh":"9e2f70f2d762c840f1d49519b024b4c1b93168137184b5e3e605e55813c62ea5","meta-python/constant_hash.py":"c752e6dadf3a9a5bd00c978e85ab27a20c49138a1ccdc6fc9a1904797a4bfe48","meta-python/gen_binemit.py":"76472fb199a330b934ba9ad0a1bbacfb52f0eae7c9a66d83f0d7890970323a2d","meta-python/gen_build_deps.py":"3920c5c89451c26102f7d87c61de64c94e915a545bc8a35d2e49106aecf019ec","meta-python/gen_encoding.py":"0b57d9d74a72a1b3b11721166fdbaa8b8c4b2d7493fc10b88736ac330b83256f","meta-python/gen_instr.py":"7ccd6a6bb1ce1800ea9c2c37e462ac7ded4f908e311d708080f7d21d92578316","meta-python/gen_legalizer.py":"187a47f1702e07487fb8a13076aadcf9c2de3e801d367424dc847ff7b0ed70f1","meta-python/gen_settings.py":"44c231ab8d2aa4f18cbe4fb5a33fb72103503d58f5af22c7b545eeffbf97da79","meta-python/isa/__init__.py":"e499c1206cd095a926fa0ca7eb9d0a50a802ed71c8eb7598e5d3a0f939c8ada5","meta-python/isa/arm32/__init__.py":"eecba73231aa398ded7304690bdba3450dc163afd4360f1b0ad02a28e2380363","meta-python/isa/arm32/defs.py":"01c41dbd7406c624e26229df6befa0992194bddcc7d11e8f6174abfe2b33bf61","meta-python/isa/arm32/registers.py":"c03ca6435828ad5f262049e42f1f71bcf74903831f85daa92c3f322a6c1050ea","meta-python/isa/arm32/settings.py":"afd5a04a9d029f578d6f62dc7c539191886cc9f9dea15d65fc66bf37a63b8814","meta-python/isa/arm64/__init__.py":"f6877253cf786d7ee972881e7d9b3c78c11e6b024e4e227487340dd01d0c44e4","meta-python/isa/arm64/defs.py":"797c5bb6d11fc7a44afe67476136dbd11c40f5e13a1c8f52f9f96be4441677b2","meta-python/isa/arm64/registers.py":"9bdd06edaa382be96042e1ac36d63137e73292292b61dcf4becb7d1428130317","meta-python/isa/arm64/settings.py":"f7b1f8733e775ea8005372ee35f1c2a627b3a69d722e837295599e4cf1f5eb43","meta-python/isa/riscv/__init__.py":"c11607c9eef0bc2707daa3edd4174e934c7a0dcc8ce90cee2c9292a85b1ac596","meta-python/isa/riscv/defs.py":"e73740055c4fb123c45453fc149a807e9720466de848022d5375049bdcfc311c","meta-python/isa/riscv/encodings.py":"ecaad5ea98273ade1cb10606354e893342c495bb48771df50121f789566d7be6","meta-python/isa/riscv/recipes.py":"3852e5b7aa6995fa721ba91744a0470343ce1834651e7b9cc97b5d69af7dfdc5","meta-python/isa/riscv/registers.py":"ef9aca3a6ec2b08ee8f5952186d232861b64a919b671b41911a365e7672b01bd","meta-python/isa/riscv/settings.py":"dfe29722d67be0620a70e08cfb802829a26f5fd339a9342a8ac2dd419daf8a85","meta-python/isa/x86/__init__.py":"ad579de68ea7bf5dc2bce0e3a6f09e7978b1697f1afec8a5ce5dc591136e590d","meta-python/isa/x86/defs.py":"b5eb7889b6f5e5b221ed3923d0137bbb1566c55b5961448cc39e4ea2f13cf4b7","meta-python/isa/x86/encodings.py":"dc758c5bf95b9271e70203c481df0dc9b3363c4f730cfc564e4e3f5f275a6433","meta-python/isa/x86/instructions.py":"530cde78e6b9f6e4ea2192985f4c5c77a987cdc19001d50fb47fa8e36a62f52e","meta-python/isa/x86/legalize.py":"1375ded072c29459e7c0e40ecb02f28d5395d9d8c603eb70e338b2bf2991c9cd","meta-python/isa/x86/recipes.py":"edc60f964816026e27136cb284eec28220f088b472a54e1bd90b3e8ccfe0648d","meta-python/isa/x86/registers.py":"ff934491d07ec6b51fbfd454b865a7c7c191ffbd31b1804615735266b120f4b2","meta-python/isa/x86/settings.py":"d779a768475cf00c2a8d3ddb5cd0a70ce34662e0ebb52ee26a7e1a495ec41aa2","meta-python/mypy.ini":"5ec2f7cc0bbc4fd0435643d6b72e715bd9568a3a0fe14c043f9e559c405b66fb","meta-python/semantics/__init__.py":"e8a25a111f2d9cc9fc7aa498a572a86403d31fe50a7ba59dd2e2560a17804e92","meta-python/semantics/elaborate.py":"3a3fbba83a6818c2d1ce236fd0413111380875a0307f7a5f4b5dd66d8ef714b1","meta-python/semantics/macros.py":"b218c52e1bd4f019dc14a27d315b4f3405a10e5bdc6f2523fe709c8faf91b418","meta-python/semantics/primitives.py":"4e5eb0c90fcc295686732c8c66ad7a793997645c9a676c97babf06823fd2b60d","meta-python/semantics/smtlib.py":"825edfbb9221bf59c02fea26e55d17cf32194da7a9f56ed0e035c44353481055","meta-python/semantics/test_elaborate.py":"3a4c850a7385007422c7549661b211903cd1dd1606dad7a86262ae27e697bca6","meta-python/srcgen.py":"999557d683e808a2ca90688c489ec4aff65798f44ac321ecf7de34d307261913","meta-python/stubs/z3/__init__.pyi":"6aaeb80f783b29c4364dee21da45f6df041c0a4807189a15777ee5447f6515dc","meta-python/stubs/z3/z3core.pyi":"c01a41d468e07cc4f8b405c292ed7f8c82bc1077f8b82dfde1e474577ade3335","meta-python/stubs/z3/z3types.pyi":"30009c951af99b9028d47cd4cabae95ff9742b77b690bd8dd63f6b7dba580759","meta-python/test_constant_hash.py":"157cf4f8964e0f04c041ffd349e889ce565b144453436690578c5d03c3a60216","meta-python/test_gen_legalizer.py":"f16edce7cb2ce53e55b1fc56b6f5ba6a0fc61b291ee4513ec859e36d69f0e285","meta-python/test_srcgen.py":"d6d7775e19a5b2621360c00eb6d92dfcb4568e49220993e0ceaac9628dbfd661","meta-python/unique_table.py":"5bd500667430c15f6ae586603d8612fb3bda07b072e40d86286e08392bdc3127","src/abi.rs":"29f505fdfcb6ec14e561bb408b99ab30ab69b96d1e283a1dcd55db9aff02dbe4","src/binemit/memorysink.rs":"8437e5f5c1b3e68b8e2d0de6fb3a4982f7a06390a0f8820b6379492408df8964","src/binemit/mod.rs":"2f95ea5f6ee20b8d56bdedcacdd41a609c5b999c02affca341d6a71eb59bc113","src/binemit/relaxation.rs":"5facfa8e15a26cba42210102a6fd735df1ba291adf512dabc85c0951239291f8","src/binemit/shrink.rs":"428679a02e44a7b3621a43c7d2e8d2f3b2cb50a36179a4d9862205c0ba34ae50","src/bitset.rs":"67fd02dd2acb9af73e45426e5cab1d2a74d568a11d11ee17ae6a4421f96cf741","src/cfg_printer.rs":"8c0fda88060c204985a6406ba46d7f0a69be96bb18c9fcfc70055d50986068ab","src/constant_hash.rs":"493cdf8f607eab01bb52f93d616fb6190c7c86d3a02e530b0ced30993d4bfda0","src/context.rs":"bfb491dc9c99c05cb906caec4a198a962ae4733ac32eda8f4aad127735511488","src/cursor.rs":"523899307d471f63e9ca35ee4b3340cf55041561a05b199e11cc60f6ad2714f4","src/dbg.rs":"bae915e1f7544f725817b368aed00a6aaa9e394a454dc847d65ad44e54d78cb9","src/dce.rs":"6d015824ae0325f01bb523606d7e15dd5feeb72a75b947f40385feeba94555c8","src/divconst_magic_numbers.rs":"eac50e2353e17ab6f7d1da3bd8e0e8dc9e3122a160efba594d407eb6a8936cc7","src/dominator_tree.rs":"73032e0e7a0ab694aa3181222bccb40630bd6fbda33885a391fd662f7de7d540","src/flowgraph.rs":"fccfade2b24038e18d469e273976f418757159fde140642b5faeb3c664a756ce","src/fx.rs":"2fb53f141b3e6be1882a1e4afac4bc607ce694f045d9329ee823e0aca415898e","src/ir/builder.rs":"19aa7cef76b7577bdd9d769fb1260080a959f9bfdbac569fb1e38307a721a03c","src/ir/condcodes.rs":"5456a25798516245b0923c9e12ae0af5cc98c097fc6f3bc0bf2d7af5008667f7","src/ir/dfg.rs":"bc975909538056b9f1dc1dacf4f6078d93f2983ad7de1c8fba3c4bee028dcc85","src/ir/entities.rs":"1505347c2baa256b04f69384d1391f52e007d533cb4319d3826cf3046ec1df27","src/ir/extfunc.rs":"9a3535730a39a6b71ca9f1ed679f588e6c3fa48ee7a50489d90803f3134db4a6","src/ir/extname.rs":"839e3d694e5c109bb594fe31c7d9dfe4f156bbc2eb695f3412fd39c325374b91","src/ir/function.rs":"55feb0b0a2bf4a0d194a4d11fc297616c78d5edfa41504795742fd25e7af1399","src/ir/globalvalue.rs":"bf9b76430f6ba564d4e5db85dbebfddf952678be6914326a5549b569c064d03d","src/ir/heap.rs":"dc9d4f0eade20d58b3e2678c329452fbd5965c46d6121cbf5889f2588ae88772","src/ir/immediates.rs":"5f57bc2a46b7ca11e1e495e657cedbf493194025eceb6591ba8792aff6910f88","src/ir/instructions.rs":"be6493d0a507f1a9a9ec37a3bb976998ee8e1355c44ae7c656c82a6edacfbec7","src/ir/jumptable.rs":"3fc108096e5404c4c30220cfaa4e359caa83bad747268bea88bbc0ac4b1bcd13","src/ir/layout.rs":"77210d256e39d339736ced5518c8d666da6359f656b972d6b6b19581ccaec329","src/ir/libcall.rs":"b35c8d0c90e686a176f9bd157ef6ab3819e8a0b974d0d24007a910ffb0d15f51","src/ir/memflags.rs":"5819e1171c620f171020bf26df9513eb6bee9890da8a7ebabbd1506b1d123f91","src/ir/mod.rs":"16566fb92fc16498d5a2699fa76dfdbc39665a4e8bae3040c03e4f3d2f07e3cb","src/ir/progpoint.rs":"d5191447f82bb612ae25ebceb5ecc2099a902be5aaecd5b9d418dcbd8a2747a5","src/ir/sourceloc.rs":"79eb71609b844839994fc735cd72edf53179eb659303a4150634928e207cee4f","src/ir/stackslot.rs":"d5d0c61555bf7060c58603047356b7db53b5b296497daed8eac356b9e724902d","src/ir/table.rs":"810e92631257e1e54577563df1da9709134438d0eab3db5e540500e69437a16b","src/ir/trapcode.rs":"233d73e4a2abbfc767aac7868d4adbb24cedaf8e7e42a640d590bda2e776784a","src/ir/types.rs":"1f93f886dba75f6bc267b35e2fc6ed1564074a8885af13d6c85c28574acf8436","src/ir/valueloc.rs":"5055897d9acba6d9c396b126889f9b2c7ff3f54a27c1ec5fe70d1a059d633b36","src/isa/arm32/abi.rs":"50ca3161a0f11ba1c2d5b0ff7523d332503cb6a6182695246e4284a486e18cab","src/isa/arm32/binemit.rs":"3197df7b15c223f3a9f2708311375ff423bb247381cf21e26da079f7933f5279","src/isa/arm32/enc_tables.rs":"dacb50bdacfa2085a6283818563e19874590d223e5decb5c91b968e0348e2bf7","src/isa/arm32/mod.rs":"798049325ca439444a5508f63ebb53bf2e0ab16b128c43417017bbdb2fd95742","src/isa/arm32/registers.rs":"0e5c32a218d685c6d37fb46788baedf6bede6be7d4f715808c13620636dfc472","src/isa/arm32/settings.rs":"145f59227c6087e7872f66a6d2183c66e061c40466e7b427a733136e41e41207","src/isa/arm64/abi.rs":"bfd0065a6c26eb407872959c9d7f64169591afa4d69816370e0900aa1ad4e46f","src/isa/arm64/binemit.rs":"159ab9eca03ac4aa7f55d51ab20585a5971d95a74c61953d1899ac863b06e2ec","src/isa/arm64/enc_tables.rs":"00ec8f53402f6cb73716db1adb3aca564574833cab58dc12b4dc6ba8c4529a73","src/isa/arm64/mod.rs":"4eef5f904f2219262c59dae7056af5adb7764074309dffc0be5b2357781dd1a6","src/isa/arm64/registers.rs":"7a8b207ed28737efc737e8e65ce79e7e7d3eecd23599890230dca8474c985026","src/isa/arm64/settings.rs":"7b466fcc2c58bc1846a72f08ec58900b3cf622ab2922ee9128e6dfe254907bf5","src/isa/call_conv.rs":"4bc8f8cc540ed54cf1e4c4688a1a8a975ed49a039a48d44a2c6b97f847b65ea8","src/isa/constraints.rs":"324d7c8655565f13b90a6c9587c9fb6c545ab3086201f434e1324fc5d6e5b3c7","src/isa/enc_tables.rs":"c8e9b1293917d061fcb26899cc21bd6f6c99f29ef5d1da8e2c537f343cf4ec64","src/isa/encoding.rs":"032347d4e624449af7a35f7ba012339bc49fabae97b971818e922d6ca4510e59","src/isa/mod.rs":"e3cbdf52862ac052292965dc399d832e9684a42099df5d5fd06f5fcdf5781cba","src/isa/registers.rs":"c0014dc940e8a6da628c60e49f6261cebaee1e06e0ea1c172de5f797e600535c","src/isa/riscv/abi.rs":"1de6d0070126e0127ca6a63551a14d1b5c030cf9628538fd732301fd2bd34b5e","src/isa/riscv/binemit.rs":"3bdad2791447f51bfe5ecedb73b1aed8a6a8809790b1f26e3ff624a89163a026","src/isa/riscv/enc_tables.rs":"6bc179f95ef5634b64fb42ab67929c0aeb70ac8efccfc47dd8c9b1dbfe64a446","src/isa/riscv/mod.rs":"de0dd32005f6b0510e3c8a31bb7e58ab7e7cffb674169a08558794950db87126","src/isa/riscv/registers.rs":"794ac61343a8db66dc99b2ca964ea3986b47b37fe8b72575c644c1cdaabd2991","src/isa/riscv/settings.rs":"78ced69b82d89f83b5612a91d0acdac2616f9091b380ee3e4715adb31f95b232","src/isa/stack.rs":"ec96130c446cd7d637722f1603e38d5164498368b652f4b0454baf3227385ad4","src/isa/x86/abi.rs":"82d592bfae4810813f7d1328e172376f7679f077834c0150d776d0d08842d089","src/isa/x86/binemit.rs":"f90820a1f9c4ad02f3507625d35f014f644d8cea93b0216bcc60cc05cc84eacc","src/isa/x86/enc_tables.rs":"06c625ceef65e395d8134597b20496f3ea0874e13ecf84fa2ff2a8e9e623b2b6","src/isa/x86/mod.rs":"bc83c0e619e8603885359c472b4113bc83b8867dd2d8e83b27f798301c6df93c","src/isa/x86/registers.rs":"783ebbe4c3b4711fe1eac2cfd3bbea7c31a53c15c6028397c038ef4eb0b2aa06","src/isa/x86/settings.rs":"dcce098045c1115cd55f256dcd3e0ccaa5a0c9ad93b14fb8a4c680e95caf2b73","src/iterators.rs":"f85f52d3fa707a0eb974c92215b3e976923ce8f9481219f7812e0f2869c2bd37","src/legalizer/boundary.rs":"ff36220e78d9639046b1c9741c93f5333aa412256949b8842b6c31f97a6e441b","src/legalizer/call.rs":"12f380d126765f0bc2da1cf298088fa98451e2d6bf56c34b755ff7077d14a4f1","src/legalizer/globalvalue.rs":"be6fc6e310dedde48e172453eccaa7cb416baa92e1adfc55f565d51159c930cc","src/legalizer/heap.rs":"c44a0845254187dfe7456b0b9efbfea25ae566772bc64b41ed93dd32a71f8e8a","src/legalizer/libcall.rs":"bf18267f502bf9bfbc3ff51bc05df480293a84422ea7f4c37dd0c75e97952766","src/legalizer/mod.rs":"f516c4e22fb66099678f753121dfa92128f2c4524ea4196e1b400e06e6649d44","src/legalizer/split.rs":"ae07854aad2ff2aa83a6ba08276b49a462dda0591faa9a61bdc7ca787451078f","src/legalizer/table.rs":"2aca27ea564c2ef02ed833c495156b9e1ddcee3c8a1b1e70347ab5907a381605","src/lib.rs":"1542f5cae0d80c408f190d225890da959e0b4033687b6c2480e83254341cba83","src/licm.rs":"9657ccfdcf7a52eca1ba201d455f1d538f17aaa6295b9651282de9f7c79a53b9","src/loop_analysis.rs":"ab74f702649ddd16d3d91400c3c2aafed4f09d9af210f5e180dff15a82caf8ac","src/nan_canonicalization.rs":"e2b1f9935d14af9abe553de1eda5483cffdaa7098dd1a17ba9a98fa04280b22c","src/partition_slice.rs":"55b9e857f452baf4d6312779861f9ef93b3d5300467e752230ec6af14943efe3","src/postopt.rs":"f1fe06398c644cad19fd427323c74acdb237b5853ffb72148a2b2012b906e2a3","src/predicates.rs":"8e4c4afde65420d33621aedd80e4ce270d334c1b62a17d7879273a1719d49b41","src/print_errors.rs":"60f9ba4ca69a0c307915d9e7290dbf15c6622e688a3c02911b67f9e8568b4111","src/ref_slice.rs":"9be914b705eefcc6b4e38db573f56ad7b978f4b65c2f6f8f5516df78fb2206a4","src/regalloc/affinity.rs":"47e28f9ae7cebfc9b1006480143a3a5ab1b118ec761a163c4a670b63fdc47d0a","src/regalloc/coalescing.rs":"253e3fb916c37453f0fa4f963caf5336712d60447e39f63a6696c2ad22cb102f","src/regalloc/coloring.rs":"baf4861cabfc897755bef0b25a8367148bd2468717b3571763a5cc599407e5c2","src/regalloc/context.rs":"794f9f0fb3b980feb3be57b95c152767cb318b81aca48c27197b01b7d529c48d","src/regalloc/diversion.rs":"cbb942a197081f9e537f3fed71a7ec6d6d1edc18b8536fa46a1dda316f46c776","src/regalloc/live_value_tracker.rs":"054efd9e8da0f33a158082f67a7c2c14f7c8632b1fc28d54941ca7bc9d5a46d6","src/regalloc/liveness.rs":"6886e52e68aee5b2e26fb0b6e073905e7fa963eb597657fc966e5758cda4c254","src/regalloc/liverange.rs":"3c6a34e35a912dce48fa9a579e82e14a7e64334d5572b0d74dbfbf42dd380804","src/regalloc/mod.rs":"6254df639f9289fd578e01b7dca99bc9c9e3c6680c6d031405e8df8d0cff31ad","src/regalloc/pressure.rs":"7c73ca1f54559b1d9f8ce587bdc067e74f3d47901058f7ae1e9277516624236f","src/regalloc/register_set.rs":"e1554d01a3a5a13acc4e0092681eb3fc090d9c68eb71f8a9985c01c7a3f2e3e2","src/regalloc/reload.rs":"82040d3a3115f9117e11a77ee4e6d2437c1af84e0ee0b541ca286c5434c10e98","src/regalloc/solver.rs":"853c6f16f68e75add56981b132d92e556a94d8cbd13fed311df2d75da08de03a","src/regalloc/spilling.rs":"8ca113a149090c864df63e70a7f3a6c68c2edc655a5dd057724d63fc6319a8de","src/regalloc/virtregs.rs":"af5a0604557760a469f4aafd1047b73a8aaf5a1c19f6914a989a1a71662627a4","src/result.rs":"d43abf9b22c5ad772200889bba339bcc4455c7abb9f2f3a2af65fbbaf1130009","src/scoped_hash_map.rs":"102797c380a588f7c16d26bf3b6c9cff28d37c2d8168a382b265194cd8969212","src/settings.rs":"18f3b43b5ec916b5969a62a6bbf0b7b8f039a5f7930e406bb7e8f181f2dc0d2d","src/simple_gvn.rs":"fae3d71f7ab684044d8710e2193f26bf81e4b8a6f28de87b5caf1ca95eedc7ff","src/simple_preopt.rs":"cfafd0398bba0b3e2b91b5bf10617bd4048ba2b22345b3e5bfc403239903960a","src/stack_layout.rs":"ce0b4b188cc46fa5070139124ffb2d263d44acd08703e7043a40b5c1afa952fb","src/timing.rs":"79acc12600ace2b144f1d7d82e01c023596e418a84042cf70ef93df928cdcabf","src/topo_order.rs":"73ec442db1cc9a282cf9c5b715ad2f60c4d2872080c16fd04ef7091d56816fbd","src/unreachable_code.rs":"6fdea8f9afe9fbffe411bfef48fec7937cb41d51036fd190a3d0a5f0cc2894c6","src/verifier/cssa.rs":"8f41765d18474575faa7c44a0345549dabe0af07141e2f004a7db1c67486ce77","src/verifier/flags.rs":"0665b4cbeef762c3871ba3cc55b0b1a27c513e25cbd3f93a725aa3d636a23c72","src/verifier/liveness.rs":"6e827f05461bd6fb21b0ce99f02fae374f2d6ea6e7e14ba61e88983a1c6fac4b","src/verifier/locations.rs":"a83f7d58118a838651c80f55e2455736e79235691692488d8431b77be8093a58","src/verifier/mod.rs":"88e89da3a893a2c31c56596f49a0b5e4f4c92766115d661eb1f770d562454ac0","src/write.rs":"02995cbc87e2b15ed4021b88bcb36782975bedacc89282c5129923d20b4abc37"},"package":"4437ec8212686e6cdacfea75aaedb4ab8b013869be1e8693a4cb97a60f135035"}
\ No newline at end of file
+{"files":{"Cargo.toml":"d6b246e5928dba1141afc7402f2ac29dfd6e467640efc77282e5cb9080f1bf99","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"e5127227a7db4a8aa92fa6613ed71801025790e696bb41b0323fb7f3c6f7495a","build.rs":"dc816beb002843cd9fcdb47dae9a0a8e3612882411f18bed34d7fda1aa108d90","meta-python/base/__init__.py":"4fac8bb055541dc964383bb04223bae6dfbfe348abf5e23f83655966cbb4aa8f","meta-python/base/entities.py":"0e146dd56dfb93cac88f9557a3501c9804cff584c2723db27435842bb5e2a1b7","meta-python/base/formats.py":"f9fb41210bc1f99a78cb7a60ee9f01c603412c6b1db7e69abbcc0f573cf9fb40","meta-python/base/immediates.py":"f42682d86bda7b569ec2fc2debd9036355999e61caaa9fbf8307e0be8a164814","meta-python/base/instructions.py":"4c3f8ee6c29e8cc9e19172f707890d613ed4173bda9b9de7857dae2b28babcbd","meta-python/base/legalize.py":"57b71ec3599fbf998c1926e4b48566661b7feec01dbd8bd177d0d2aaa26a44c2","meta-python/base/predicates.py":"53a5a9a37021a9762f0faec9f9e3c5b713411d47dd9192423cfe0f7a61916809","meta-python/base/semantics.py":"b90cbca9a143676ac37496c83634a66a83360248e4505ff7bda12b0d454efd92","meta-python/base/settings.py":"97fca9ddaab347f50f1594c93283f8f474e53a7232eae65949f56a6a702c2bba","meta-python/base/types.py":"9616d6fe4cab050827ab02eeb9843eacebbb8f7555521f504b5ee2ddf7214fdb","meta-python/build.py":"b72a80a54e09366878e92dca3a1508af394bf71a0c4b07a05e54058901373d34","meta-python/cdsl/__init__.py":"b531693b8228553ca8bd07e1dcd1aa5855f1ad3741b431d758fc27fdd162b024","meta-python/cdsl/ast.py":"b7c09f69b28b5754f494912ca5b77722dbd4ee416d5fad79cb48322eb544ea9f","meta-python/cdsl/formats.py":"fedfeaec754b40d6a9cc92b827976782c615d8eab1c7f47f6b47510cbef585f4","meta-python/cdsl/instructions.py":"b0ddfd8fd22889bd1e610c103d47087c9c6ae5882862ed44921dafc2ae0463a0","meta-python/cdsl/isa.py":"dc530a4dd5642e3379398dfc8a90ad6ae1692302de63851370bdfa8abf4cdce0","meta-python/cdsl/operands.py":"e24914eae4059b88781bf5a5d7a14ecf98b10a701ed6cf6e88d15981b2ccbfdf","meta-python/cdsl/predicates.py":"def3f91712744671df9cf3d4f9c255a2061f341198689e31addf7db4efb63e36","meta-python/cdsl/registers.py":"939dafd1b8976a6cd456c9a5e4b374af81fafb9da979ea3a1f6d14e4645914a6","meta-python/cdsl/settings.py":"18dc27dd98a82c814c6aeb2686b40d1fed23661bef5e8b4cbf0fb4e7d39f4755","meta-python/cdsl/test_ast.py":"947e934e2862445a158bf266dff58a8c88aae31fb34a7f823309ee58a15c5393","meta-python/cdsl/test_package.py":"ffa53d20e023ecb89137294bb13614f4de9b09e1bf05d9772131570bf78f7987","meta-python/cdsl/test_ti.py":"57966c9eb027fa73bbc7ad81094ff55232053fbb2e16d78849ae3b6e9b1c2989","meta-python/cdsl/test_typevar.py":"714b2d564af1a843629279501436d681cd6590d1988b59e9f50ec940506538bb","meta-python/cdsl/test_xform.py":"ddb6633c7941bbf68570701cb887a81d6b4b27f4bc45eabccf2ce287ad9b77e9","meta-python/cdsl/ti.py":"a1a7ff79f8a2196aee491a3aafbd4f1b231004bbb5281992fc8f4e43f4fb951f","meta-python/cdsl/types.py":"adee4bbc1a9478288fa4b53ee1edeb5ee3296dba2c70bfbe01e923895064999e","meta-python/cdsl/typevar.py":"b5669934eddaf5b9cc0c27b966e2566b5f669f1c5a345f005960930fb499097e","meta-python/cdsl/xform.py":"5cdad80f12d50aa9491cd3d39797e6c0444936bb0874199d7c34e6d735658b34","meta-python/check.sh":"9e2f70f2d762c840f1d49519b024b4c1b93168137184b5e3e605e55813c62ea5","meta-python/constant_hash.py":"c752e6dadf3a9a5bd00c978e85ab27a20c49138a1ccdc6fc9a1904797a4bfe48","meta-python/gen_binemit.py":"76472fb199a330b934ba9ad0a1bbacfb52f0eae7c9a66d83f0d7890970323a2d","meta-python/gen_build_deps.py":"3920c5c89451c26102f7d87c61de64c94e915a545bc8a35d2e49106aecf019ec","meta-python/gen_encoding.py":"0b57d9d74a72a1b3b11721166fdbaa8b8c4b2d7493fc10b88736ac330b83256f","meta-python/gen_instr.py":"7ccd6a6bb1ce1800ea9c2c37e462ac7ded4f908e311d708080f7d21d92578316","meta-python/gen_legalizer.py":"187a47f1702e07487fb8a13076aadcf9c2de3e801d367424dc847ff7b0ed70f1","meta-python/gen_settings.py":"44c231ab8d2aa4f18cbe4fb5a33fb72103503d58f5af22c7b545eeffbf97da79","meta-python/isa/__init__.py":"e499c1206cd095a926fa0ca7eb9d0a50a802ed71c8eb7598e5d3a0f939c8ada5","meta-python/isa/arm32/__init__.py":"eecba73231aa398ded7304690bdba3450dc163afd4360f1b0ad02a28e2380363","meta-python/isa/arm32/defs.py":"01c41dbd7406c624e26229df6befa0992194bddcc7d11e8f6174abfe2b33bf61","meta-python/isa/arm32/registers.py":"c03ca6435828ad5f262049e42f1f71bcf74903831f85daa92c3f322a6c1050ea","meta-python/isa/arm32/settings.py":"afd5a04a9d029f578d6f62dc7c539191886cc9f9dea15d65fc66bf37a63b8814","meta-python/isa/arm64/__init__.py":"f6877253cf786d7ee972881e7d9b3c78c11e6b024e4e227487340dd01d0c44e4","meta-python/isa/arm64/defs.py":"797c5bb6d11fc7a44afe67476136dbd11c40f5e13a1c8f52f9f96be4441677b2","meta-python/isa/arm64/registers.py":"9bdd06edaa382be96042e1ac36d63137e73292292b61dcf4becb7d1428130317","meta-python/isa/arm64/settings.py":"f7b1f8733e775ea8005372ee35f1c2a627b3a69d722e837295599e4cf1f5eb43","meta-python/isa/riscv/__init__.py":"c11607c9eef0bc2707daa3edd4174e934c7a0dcc8ce90cee2c9292a85b1ac596","meta-python/isa/riscv/defs.py":"e73740055c4fb123c45453fc149a807e9720466de848022d5375049bdcfc311c","meta-python/isa/riscv/encodings.py":"ecaad5ea98273ade1cb10606354e893342c495bb48771df50121f789566d7be6","meta-python/isa/riscv/recipes.py":"3852e5b7aa6995fa721ba91744a0470343ce1834651e7b9cc97b5d69af7dfdc5","meta-python/isa/riscv/registers.py":"ef9aca3a6ec2b08ee8f5952186d232861b64a919b671b41911a365e7672b01bd","meta-python/isa/riscv/settings.py":"dfe29722d67be0620a70e08cfb802829a26f5fd339a9342a8ac2dd419daf8a85","meta-python/isa/x86/__init__.py":"ad579de68ea7bf5dc2bce0e3a6f09e7978b1697f1afec8a5ce5dc591136e590d","meta-python/isa/x86/defs.py":"b5eb7889b6f5e5b221ed3923d0137bbb1566c55b5961448cc39e4ea2f13cf4b7","meta-python/isa/x86/encodings.py":"dc758c5bf95b9271e70203c481df0dc9b3363c4f730cfc564e4e3f5f275a6433","meta-python/isa/x86/instructions.py":"530cde78e6b9f6e4ea2192985f4c5c77a987cdc19001d50fb47fa8e36a62f52e","meta-python/isa/x86/legalize.py":"1375ded072c29459e7c0e40ecb02f28d5395d9d8c603eb70e338b2bf2991c9cd","meta-python/isa/x86/recipes.py":"ca56edb2bb87389e2db95d0f0e0fdbf9b27242192de764d60971828bb9a02e60","meta-python/isa/x86/registers.py":"ff934491d07ec6b51fbfd454b865a7c7c191ffbd31b1804615735266b120f4b2","meta-python/isa/x86/settings.py":"d779a768475cf00c2a8d3ddb5cd0a70ce34662e0ebb52ee26a7e1a495ec41aa2","meta-python/mypy.ini":"5ec2f7cc0bbc4fd0435643d6b72e715bd9568a3a0fe14c043f9e559c405b66fb","meta-python/semantics/__init__.py":"e8a25a111f2d9cc9fc7aa498a572a86403d31fe50a7ba59dd2e2560a17804e92","meta-python/semantics/elaborate.py":"3a3fbba83a6818c2d1ce236fd0413111380875a0307f7a5f4b5dd66d8ef714b1","meta-python/semantics/macros.py":"b218c52e1bd4f019dc14a27d315b4f3405a10e5bdc6f2523fe709c8faf91b418","meta-python/semantics/primitives.py":"4e5eb0c90fcc295686732c8c66ad7a793997645c9a676c97babf06823fd2b60d","meta-python/semantics/smtlib.py":"825edfbb9221bf59c02fea26e55d17cf32194da7a9f56ed0e035c44353481055","meta-python/semantics/test_elaborate.py":"3a4c850a7385007422c7549661b211903cd1dd1606dad7a86262ae27e697bca6","meta-python/srcgen.py":"999557d683e808a2ca90688c489ec4aff65798f44ac321ecf7de34d307261913","meta-python/stubs/z3/__init__.pyi":"6aaeb80f783b29c4364dee21da45f6df041c0a4807189a15777ee5447f6515dc","meta-python/stubs/z3/z3core.pyi":"c01a41d468e07cc4f8b405c292ed7f8c82bc1077f8b82dfde1e474577ade3335","meta-python/stubs/z3/z3types.pyi":"30009c951af99b9028d47cd4cabae95ff9742b77b690bd8dd63f6b7dba580759","meta-python/test_constant_hash.py":"157cf4f8964e0f04c041ffd349e889ce565b144453436690578c5d03c3a60216","meta-python/test_gen_legalizer.py":"f16edce7cb2ce53e55b1fc56b6f5ba6a0fc61b291ee4513ec859e36d69f0e285","meta-python/test_srcgen.py":"d6d7775e19a5b2621360c00eb6d92dfcb4568e49220993e0ceaac9628dbfd661","meta-python/unique_table.py":"5bd500667430c15f6ae586603d8612fb3bda07b072e40d86286e08392bdc3127","src/abi.rs":"29f505fdfcb6ec14e561bb408b99ab30ab69b96d1e283a1dcd55db9aff02dbe4","src/binemit/memorysink.rs":"8437e5f5c1b3e68b8e2d0de6fb3a4982f7a06390a0f8820b6379492408df8964","src/binemit/mod.rs":"2f95ea5f6ee20b8d56bdedcacdd41a609c5b999c02affca341d6a71eb59bc113","src/binemit/relaxation.rs":"5facfa8e15a26cba42210102a6fd735df1ba291adf512dabc85c0951239291f8","src/binemit/shrink.rs":"428679a02e44a7b3621a43c7d2e8d2f3b2cb50a36179a4d9862205c0ba34ae50","src/bitset.rs":"67fd02dd2acb9af73e45426e5cab1d2a74d568a11d11ee17ae6a4421f96cf741","src/cfg_printer.rs":"8c0fda88060c204985a6406ba46d7f0a69be96bb18c9fcfc70055d50986068ab","src/constant_hash.rs":"493cdf8f607eab01bb52f93d616fb6190c7c86d3a02e530b0ced30993d4bfda0","src/context.rs":"a44197bd5e05599b643c420d87ca4ad218a8c3ab2fb7b88655b2479014b117b2","src/cursor.rs":"523899307d471f63e9ca35ee4b3340cf55041561a05b199e11cc60f6ad2714f4","src/dbg.rs":"bae915e1f7544f725817b368aed00a6aaa9e394a454dc847d65ad44e54d78cb9","src/dce.rs":"6d015824ae0325f01bb523606d7e15dd5feeb72a75b947f40385feeba94555c8","src/divconst_magic_numbers.rs":"eac50e2353e17ab6f7d1da3bd8e0e8dc9e3122a160efba594d407eb6a8936cc7","src/dominator_tree.rs":"73032e0e7a0ab694aa3181222bccb40630bd6fbda33885a391fd662f7de7d540","src/flowgraph.rs":"fccfade2b24038e18d469e273976f418757159fde140642b5faeb3c664a756ce","src/fx.rs":"2fb53f141b3e6be1882a1e4afac4bc607ce694f045d9329ee823e0aca415898e","src/ir/builder.rs":"19aa7cef76b7577bdd9d769fb1260080a959f9bfdbac569fb1e38307a721a03c","src/ir/condcodes.rs":"5456a25798516245b0923c9e12ae0af5cc98c097fc6f3bc0bf2d7af5008667f7","src/ir/dfg.rs":"cf44ceda665e32d5bd4563d90094fdf519937adbd29096c7291065a2ebdcfbfe","src/ir/entities.rs":"1505347c2baa256b04f69384d1391f52e007d533cb4319d3826cf3046ec1df27","src/ir/extfunc.rs":"9a3535730a39a6b71ca9f1ed679f588e6c3fa48ee7a50489d90803f3134db4a6","src/ir/extname.rs":"5b50dddd0801dfe736433191502e405c879221a6e362be0e2919176b90b4d74c","src/ir/function.rs":"55feb0b0a2bf4a0d194a4d11fc297616c78d5edfa41504795742fd25e7af1399","src/ir/globalvalue.rs":"bf9b76430f6ba564d4e5db85dbebfddf952678be6914326a5549b569c064d03d","src/ir/heap.rs":"dc9d4f0eade20d58b3e2678c329452fbd5965c46d6121cbf5889f2588ae88772","src/ir/immediates.rs":"5f57bc2a46b7ca11e1e495e657cedbf493194025eceb6591ba8792aff6910f88","src/ir/instructions.rs":"2dd2ad70947122e791f41f6cbc7879fd201d4f96d19c138b56559428ba655dab","src/ir/jumptable.rs":"3fc108096e5404c4c30220cfaa4e359caa83bad747268bea88bbc0ac4b1bcd13","src/ir/layout.rs":"77210d256e39d339736ced5518c8d666da6359f656b972d6b6b19581ccaec329","src/ir/libcall.rs":"b35c8d0c90e686a176f9bd157ef6ab3819e8a0b974d0d24007a910ffb0d15f51","src/ir/memflags.rs":"5819e1171c620f171020bf26df9513eb6bee9890da8a7ebabbd1506b1d123f91","src/ir/mod.rs":"16566fb92fc16498d5a2699fa76dfdbc39665a4e8bae3040c03e4f3d2f07e3cb","src/ir/progpoint.rs":"d5191447f82bb612ae25ebceb5ecc2099a902be5aaecd5b9d418dcbd8a2747a5","src/ir/sourceloc.rs":"79eb71609b844839994fc735cd72edf53179eb659303a4150634928e207cee4f","src/ir/stackslot.rs":"d5d0c61555bf7060c58603047356b7db53b5b296497daed8eac356b9e724902d","src/ir/table.rs":"810e92631257e1e54577563df1da9709134438d0eab3db5e540500e69437a16b","src/ir/trapcode.rs":"233d73e4a2abbfc767aac7868d4adbb24cedaf8e7e42a640d590bda2e776784a","src/ir/types.rs":"1f93f886dba75f6bc267b35e2fc6ed1564074a8885af13d6c85c28574acf8436","src/ir/valueloc.rs":"5055897d9acba6d9c396b126889f9b2c7ff3f54a27c1ec5fe70d1a059d633b36","src/isa/arm32/abi.rs":"50ca3161a0f11ba1c2d5b0ff7523d332503cb6a6182695246e4284a486e18cab","src/isa/arm32/binemit.rs":"3197df7b15c223f3a9f2708311375ff423bb247381cf21e26da079f7933f5279","src/isa/arm32/enc_tables.rs":"dacb50bdacfa2085a6283818563e19874590d223e5decb5c91b968e0348e2bf7","src/isa/arm32/mod.rs":"798049325ca439444a5508f63ebb53bf2e0ab16b128c43417017bbdb2fd95742","src/isa/arm32/registers.rs":"0e5c32a218d685c6d37fb46788baedf6bede6be7d4f715808c13620636dfc472","src/isa/arm32/settings.rs":"145f59227c6087e7872f66a6d2183c66e061c40466e7b427a733136e41e41207","src/isa/arm64/abi.rs":"bfd0065a6c26eb407872959c9d7f64169591afa4d69816370e0900aa1ad4e46f","src/isa/arm64/binemit.rs":"159ab9eca03ac4aa7f55d51ab20585a5971d95a74c61953d1899ac863b06e2ec","src/isa/arm64/enc_tables.rs":"00ec8f53402f6cb73716db1adb3aca564574833cab58dc12b4dc6ba8c4529a73","src/isa/arm64/mod.rs":"4eef5f904f2219262c59dae7056af5adb7764074309dffc0be5b2357781dd1a6","src/isa/arm64/registers.rs":"7a8b207ed28737efc737e8e65ce79e7e7d3eecd23599890230dca8474c985026","src/isa/arm64/settings.rs":"7b466fcc2c58bc1846a72f08ec58900b3cf622ab2922ee9128e6dfe254907bf5","src/isa/call_conv.rs":"4bc8f8cc540ed54cf1e4c4688a1a8a975ed49a039a48d44a2c6b97f847b65ea8","src/isa/constraints.rs":"324d7c8655565f13b90a6c9587c9fb6c545ab3086201f434e1324fc5d6e5b3c7","src/isa/enc_tables.rs":"946a9fcdf7d0541e7e65aeafdf18b6a5cb9e3ea29a1ce3bf05c155f910acca3a","src/isa/encoding.rs":"032347d4e624449af7a35f7ba012339bc49fabae97b971818e922d6ca4510e59","src/isa/mod.rs":"a7f966ec68dd709f685157812c7cb40ed012b175666509b9d05fec57b60fdb37","src/isa/registers.rs":"c0014dc940e8a6da628c60e49f6261cebaee1e06e0ea1c172de5f797e600535c","src/isa/riscv/abi.rs":"1de6d0070126e0127ca6a63551a14d1b5c030cf9628538fd732301fd2bd34b5e","src/isa/riscv/binemit.rs":"3bdad2791447f51bfe5ecedb73b1aed8a6a8809790b1f26e3ff624a89163a026","src/isa/riscv/enc_tables.rs":"6bc179f95ef5634b64fb42ab67929c0aeb70ac8efccfc47dd8c9b1dbfe64a446","src/isa/riscv/mod.rs":"de0dd32005f6b0510e3c8a31bb7e58ab7e7cffb674169a08558794950db87126","src/isa/riscv/registers.rs":"794ac61343a8db66dc99b2ca964ea3986b47b37fe8b72575c644c1cdaabd2991","src/isa/riscv/settings.rs":"78ced69b82d89f83b5612a91d0acdac2616f9091b380ee3e4715adb31f95b232","src/isa/stack.rs":"ec96130c446cd7d637722f1603e38d5164498368b652f4b0454baf3227385ad4","src/isa/x86/abi.rs":"6a9f8a3c9ee0f09118be1f962c473f8f5269cc4eba25519ca84df25b8835cceb","src/isa/x86/binemit.rs":"f90820a1f9c4ad02f3507625d35f014f644d8cea93b0216bcc60cc05cc84eacc","src/isa/x86/enc_tables.rs":"aa4bd2992d08ad97e94aafa022cafd853e0978c7c139558885715f57bfcf49e7","src/isa/x86/mod.rs":"bc83c0e619e8603885359c472b4113bc83b8867dd2d8e83b27f798301c6df93c","src/isa/x86/registers.rs":"783ebbe4c3b4711fe1eac2cfd3bbea7c31a53c15c6028397c038ef4eb0b2aa06","src/isa/x86/settings.rs":"dcce098045c1115cd55f256dcd3e0ccaa5a0c9ad93b14fb8a4c680e95caf2b73","src/iterators.rs":"f85f52d3fa707a0eb974c92215b3e976923ce8f9481219f7812e0f2869c2bd37","src/legalizer/boundary.rs":"e86400b42ef60d42e05ed7d2c24dc815f16652b49ab0ee9048edadd460bd411d","src/legalizer/call.rs":"12f380d126765f0bc2da1cf298088fa98451e2d6bf56c34b755ff7077d14a4f1","src/legalizer/globalvalue.rs":"be6fc6e310dedde48e172453eccaa7cb416baa92e1adfc55f565d51159c930cc","src/legalizer/heap.rs":"c44a0845254187dfe7456b0b9efbfea25ae566772bc64b41ed93dd32a71f8e8a","src/legalizer/libcall.rs":"bf18267f502bf9bfbc3ff51bc05df480293a84422ea7f4c37dd0c75e97952766","src/legalizer/mod.rs":"f516c4e22fb66099678f753121dfa92128f2c4524ea4196e1b400e06e6649d44","src/legalizer/split.rs":"6869c2cc436215ed22abffa85c783ae205374eb74f6ec0fc0ddec2b983e799fe","src/legalizer/table.rs":"2aca27ea564c2ef02ed833c495156b9e1ddcee3c8a1b1e70347ab5907a381605","src/lib.rs":"1542f5cae0d80c408f190d225890da959e0b4033687b6c2480e83254341cba83","src/licm.rs":"dcdf4744a01489939955dd02d43be3522cfbc448d92b30796d512b10e784c503","src/loop_analysis.rs":"ab74f702649ddd16d3d91400c3c2aafed4f09d9af210f5e180dff15a82caf8ac","src/nan_canonicalization.rs":"e2b1f9935d14af9abe553de1eda5483cffdaa7098dd1a17ba9a98fa04280b22c","src/partition_slice.rs":"55b9e857f452baf4d6312779861f9ef93b3d5300467e752230ec6af14943efe3","src/postopt.rs":"f1fe06398c644cad19fd427323c74acdb237b5853ffb72148a2b2012b906e2a3","src/predicates.rs":"8e4c4afde65420d33621aedd80e4ce270d334c1b62a17d7879273a1719d49b41","src/print_errors.rs":"54282bd8480b0bab29cbf3c257cdb3faafb566f0c40f88e1ff6c41e742f99ff6","src/ref_slice.rs":"9be914b705eefcc6b4e38db573f56ad7b978f4b65c2f6f8f5516df78fb2206a4","src/regalloc/affinity.rs":"47e28f9ae7cebfc9b1006480143a3a5ab1b118ec761a163c4a670b63fdc47d0a","src/regalloc/coalescing.rs":"5ffab5529e5840e0dc3f13930788caf75ae9e15ce90d4f64f9f625b2ee495605","src/regalloc/coloring.rs":"baf4861cabfc897755bef0b25a8367148bd2468717b3571763a5cc599407e5c2","src/regalloc/context.rs":"794f9f0fb3b980feb3be57b95c152767cb318b81aca48c27197b01b7d529c48d","src/regalloc/diversion.rs":"cbb942a197081f9e537f3fed71a7ec6d6d1edc18b8536fa46a1dda316f46c776","src/regalloc/live_value_tracker.rs":"054efd9e8da0f33a158082f67a7c2c14f7c8632b1fc28d54941ca7bc9d5a46d6","src/regalloc/liveness.rs":"6886e52e68aee5b2e26fb0b6e073905e7fa963eb597657fc966e5758cda4c254","src/regalloc/liverange.rs":"3c6a34e35a912dce48fa9a579e82e14a7e64334d5572b0d74dbfbf42dd380804","src/regalloc/mod.rs":"6254df639f9289fd578e01b7dca99bc9c9e3c6680c6d031405e8df8d0cff31ad","src/regalloc/pressure.rs":"7c73ca1f54559b1d9f8ce587bdc067e74f3d47901058f7ae1e9277516624236f","src/regalloc/register_set.rs":"294a66b676189e4da3cbb9c66474e0dd1a86a00b8cc71d03762994ae0654e11f","src/regalloc/reload.rs":"6525e9488e797b49b7892ac7596d6100793bb1db97c5025b17e6b32546fbe2fe","src/regalloc/solver.rs":"853c6f16f68e75add56981b132d92e556a94d8cbd13fed311df2d75da08de03a","src/regalloc/spilling.rs":"aae3faab22dcd8704179941a5b9b8e2b160d43a7daa02cebca1d31b9d368794b","src/regalloc/virtregs.rs":"23447a8e6196681cfb2388e0204626a0ac992735eb01f3eed4781c1cdfb688e4","src/result.rs":"d43abf9b22c5ad772200889bba339bcc4455c7abb9f2f3a2af65fbbaf1130009","src/scoped_hash_map.rs":"102797c380a588f7c16d26bf3b6c9cff28d37c2d8168a382b265194cd8969212","src/settings.rs":"18f3b43b5ec916b5969a62a6bbf0b7b8f039a5f7930e406bb7e8f181f2dc0d2d","src/simple_gvn.rs":"05576f7e90555c668c91df0b63a0468fbf2ed1aee9bc4118b73461f8719ead1a","src/simple_preopt.rs":"cfafd0398bba0b3e2b91b5bf10617bd4048ba2b22345b3e5bfc403239903960a","src/stack_layout.rs":"ce0b4b188cc46fa5070139124ffb2d263d44acd08703e7043a40b5c1afa952fb","src/timing.rs":"79acc12600ace2b144f1d7d82e01c023596e418a84042cf70ef93df928cdcabf","src/topo_order.rs":"73ec442db1cc9a282cf9c5b715ad2f60c4d2872080c16fd04ef7091d56816fbd","src/unreachable_code.rs":"6fdea8f9afe9fbffe411bfef48fec7937cb41d51036fd190a3d0a5f0cc2894c6","src/verifier/cssa.rs":"8f41765d18474575faa7c44a0345549dabe0af07141e2f004a7db1c67486ce77","src/verifier/flags.rs":"0665b4cbeef762c3871ba3cc55b0b1a27c513e25cbd3f93a725aa3d636a23c72","src/verifier/liveness.rs":"6e827f05461bd6fb21b0ce99f02fae374f2d6ea6e7e14ba61e88983a1c6fac4b","src/verifier/locations.rs":"a83f7d58118a838651c80f55e2455736e79235691692488d8431b77be8093a58","src/verifier/mod.rs":"4e17623e454bf115661ddaf0be0c2554e87dd4fc83a0a7a18dc8337d66ee5de5","src/write.rs":"1e810d79ff90aa37c76e16df8d6e69af6e35f5d7c6fae325243d8e2d0568ac4d"},"package":"e92fa0fa287cf00a6739c46aba114957e0a8eeeb4f0d1aa65d6ed0699c34ca6b"}
\ No newline at end of file
--- a/third_party/rust/cranelift-codegen/Cargo.toml
+++ b/third_party/rust/cranelift-codegen/Cargo.toml
@@ -7,32 +7,32 @@
 #
 # If you believe there's an error in this file please file an
 # issue against the rust-lang/cargo repository. If you're
 # editing this file be aware that the upstream Cargo.toml
 # will likely look very different (and much more reasonable)
 
 [package]
 name = "cranelift-codegen"
-version = "0.23.0"
+version = "0.25.0"
 authors = ["The Cranelift Project Developers"]
 build = "build.rs"
 description = "Low-level code generator library"
 documentation = "https://cranelift.readthedocs.io/"
 readme = "README.md"
 keywords = ["compile", "compiler", "jit"]
 categories = ["no-std"]
 license = "Apache-2.0 WITH LLVM-exception"
 repository = "https://github.com/CraneStation/cranelift"
 [dependencies.cranelift-bforest]
-version = "0.23.0"
+version = "0.25.0"
 default-features = false
 
 [dependencies.cranelift-entity]
-version = "0.23.0"
+version = "0.25.0"
 default-features = false
 
 [dependencies.failure]
 version = "0.1.1"
 features = ["derive"]
 default-features = false
 
 [dependencies.failure_derive]
@@ -46,17 +46,17 @@ optional = true
 [dependencies.log]
 version = "0.4.4"
 default-features = false
 
 [dependencies.target-lexicon]
 version = "0.2.0"
 default-features = false
 [build-dependencies.cranelift-codegen-meta]
-version = "0.23.0"
+version = "0.25.0"
 
 [features]
 core = ["hashmap_core"]
 default = ["std"]
 std = ["cranelift-entity/std", "cranelift-bforest/std", "target-lexicon/std"]
 testing_hooks = []
 [badges.maintenance]
 status = "experimental"
--- a/third_party/rust/cranelift-codegen/build.rs
+++ b/third_party/rust/cranelift-codegen/build.rs
@@ -19,21 +19,17 @@
 // current directory is used to find the sources.
 
 extern crate cranelift_codegen_meta as meta;
 
 use meta::isa::Isa;
 use std::env;
 use std::process;
 
-use std::time::Instant;
-
 fn main() {
-    let start_time = Instant::now();
-
     let out_dir = env::var("OUT_DIR").expect("The OUT_DIR environment variable must be set");
     let target_triple = env::var("TARGET").expect("The TARGET environment variable must be set");
     let cranelift_targets = env::var("CRANELIFT_TARGETS").ok();
     let cranelift_targets = cranelift_targets.as_ref().map(|s| s.as_ref());
     let python = identify_python();
 
     // Configure isa targets cfg.
     match isa_targets(cranelift_targets, &target_triple) {
@@ -91,25 +87,16 @@ fn main() {
     }
 
     for isa in isas {
         if let Err(err) = meta::gen_registers::generate(isa, "registers", &out_dir) {
             eprintln!("Error: {}", err);
             process::exit(1);
         }
     }
-
-    println!(
-        "cargo:warning=Cranelift meta-build step took {:?}",
-        Instant::now() - start_time
-    );
-    println!(
-        "cargo:warning=Meta-build script generated files in {}",
-        out_dir
-    );
 }
 
 fn identify_python() -> &'static str {
     for python in &["python", "python3", "python2.7"] {
         if process::Command::new(python)
             .arg("--version")
             .status()
             .is_ok()
--- a/third_party/rust/cranelift-codegen/meta-python/cdsl/isa.py
+++ b/third_party/rust/cranelift-codegen/meta-python/cdsl/isa.py
@@ -43,17 +43,16 @@ class TargetISA(object):
 
     def __init__(self, name, instruction_groups):
         # type: (str, Sequence[InstructionGroup]) -> None
         self.name = name
         self.settings = None  # type: SettingGroup
         self.instruction_groups = instruction_groups
         self.cpumodes = list()  # type: List[CPUMode]
         self.regbanks = list()  # type: List[RegBank]
-        self.regclasses = list()  # type: List[RegClass]
         self.legalize_codes = OrderedDict()  # type: OrderedDict[XFormGroup, int]  # noqa
         # Unique copies of all predicates.
         self._predicates = dict()  # type: Dict[PredKey, PredNode]
 
         assert InstructionGroup._current is None,\
             "InstructionGroup {} is still open"\
             .format(InstructionGroup._current.name)
 
@@ -69,17 +68,16 @@ class TargetISA(object):
 
         This computes some derived properties that are used in multiple
         places.
 
         :returns self:
         """
         self._collect_encoding_recipes()
         self._collect_predicates()
-        self._collect_regclasses()
         self._collect_legalize_codes()
         return self
 
     def _collect_encoding_recipes(self):
         # type: () -> None
         """
         Collect and number all encoding recipes in use.
         """
@@ -117,59 +115,16 @@ class TargetISA(object):
                     self.instp_number[instp] = n
 
                 # All referenced ISA predicates must have a number in
                 # `self.settings`. This may cause some parent predicates to be
                 # replicated here, which is OK.
                 if enc.isap:
                     self.settings.number_predicate(enc.isap)
 
-    def _collect_regclasses(self):
-        # type: () -> None
-        """
-        Collect and number register classes.
-
-        Every register class needs a unique index, and the classes need to be
-        topologically ordered.
-
-        We also want all the top-level register classes to be first.
-        """
-        # Compute subclasses and top-level classes in each bank.
-        # Collect the top-level classes so they get numbered consecutively.
-        for bank in self.regbanks:
-            bank.finish_regclasses()
-            # Always get the pressure tracking classes in first.
-            if bank.pressure_tracking:
-                self.regclasses.extend(bank.toprcs)
-
-        # The limit on the number of top-level register classes can be raised.
-        # This should be coordinated with the `MAX_TRACKED_TOPRCS` constant in
-        # `isa/registers.rs`.
-        assert len(self.regclasses) <= 4, "Too many top-level register classes"
-
-        # Get the remaining top-level register classes which may exceed
-        # `MAX_TRACKED_TOPRCS`.
-        for bank in self.regbanks:
-            if not bank.pressure_tracking:
-                self.regclasses.extend(bank.toprcs)
-
-        # Collect all of the non-top-level register classes.
-        # They are numbered strictly after the top-level classes.
-        for bank in self.regbanks:
-            self.regclasses.extend(
-                    rc for rc in bank.classes if not rc.is_toprc())
-
-        for idx, rc in enumerate(self.regclasses):
-            rc.index = idx
-
-        # The limit on the number of register classes can be changed. It should
-        # be coordinated with the `RegClassMask` and `RegClassIndex` types in
-        # `isa/registers.rs`.
-        assert len(self.regclasses) <= 32, "Too many register classes"
-
     def _collect_legalize_codes(self):
         # type: () -> None
         """
         Make sure all legalization transforms have been assigned a code.
         """
         for cpumode in self.cpumodes:
             self.legalize_code(cpumode.default_legalize)
             for x in cpumode.type_legalize.values():
--- a/third_party/rust/cranelift-codegen/meta-python/isa/x86/recipes.py
+++ b/third_party/rust/cranelift-codegen/meta-python/isa/x86/recipes.py
@@ -801,23 +801,26 @@ spaddr8_id = TailRecipe(
 # Store recipes.
 #
 
 # XX /r register-indirect store with no offset.
 st = TailRecipe(
         'st', Store, base_size=1, ins=(GPR, GPR), outs=(),
         instp=IsEqual(Store.offset, 0),
         clobbers_flags=False,
-        compute_size="size_plus_maybe_offset_for_in_reg_1",
+        compute_size="size_plus_maybe_sib_or_offset_for_in_reg_1",
         emit='''
         if !flags.notrap() {
             sink.trap(TrapCode::HeapOutOfBounds, func.srclocs[inst]);
         }
         PUT_OP(bits, rex2(in_reg1, in_reg0), sink);
-        if needs_offset(in_reg1) {
+        if needs_sib_byte(in_reg1) {
+            modrm_sib(in_reg0, sink);
+            sib_noindex(in_reg1, sink);
+        } else if needs_offset(in_reg1) {
             modrm_disp8(in_reg1, in_reg0, sink);
             sink.put1(0);
         } else {
             modrm_rm(in_reg1, in_reg0, sink);
         }
         ''')
 
 # XX /r register-indirect store with index and no offset.
@@ -828,16 +831,17 @@ stWithIndex = TailRecipe(
     instp=IsEqual(StoreComplex.offset, 0),
     clobbers_flags=False,
     compute_size="size_plus_maybe_offset_for_in_reg_1",
     emit='''
     if !flags.notrap() {
         sink.trap(TrapCode::HeapOutOfBounds, func.srclocs[inst]);
     }
     PUT_OP(bits, rex3(in_reg1, in_reg0, in_reg2), sink);
+    // The else branch always inserts an SIB byte.
     if needs_offset(in_reg1) {
         modrm_sib_disp8(in_reg0, sink);
         sib(0, in_reg2, in_reg1, sink);
         sink.put1(0);
     } else {
         modrm_sib(in_reg0, sink);
         sib(0, in_reg2, in_reg1, sink);
     }
@@ -845,60 +849,73 @@ stWithIndex = TailRecipe(
 
 # XX /r register-indirect store with no offset.
 # Only ABCD allowed for stored value. This is for byte stores with no REX.
 st_abcd = TailRecipe(
         'st_abcd', Store, base_size=1, ins=(ABCD, GPR), outs=(),
         instp=IsEqual(Store.offset, 0),
         when_prefixed=st,
         clobbers_flags=False,
+        compute_size="size_plus_maybe_sib_or_offset_for_in_reg_1",
         emit='''
         if !flags.notrap() {
             sink.trap(TrapCode::HeapOutOfBounds, func.srclocs[inst]);
         }
         PUT_OP(bits, rex2(in_reg1, in_reg0), sink);
-        modrm_rm(in_reg1, in_reg0, sink);
+        if needs_sib_byte(in_reg1) {
+            modrm_sib(in_reg0, sink);
+            sib_noindex(in_reg1, sink);
+        } else if needs_offset(in_reg1) {
+            modrm_disp8(in_reg1, in_reg0, sink);
+            sink.put1(0);
+        } else {
+            modrm_rm(in_reg1, in_reg0, sink);
+        }
         ''')
 
 # XX /r register-indirect store with index and no offset.
 # Only ABCD allowed for stored value. This is for byte stores with no REX.
 stWithIndex_abcd = TailRecipe(
     'stWithIndex_abcd', StoreComplex, base_size=2,
     ins=(ABCD, GPR, GPR),
     outs=(),
     instp=IsEqual(StoreComplex.offset, 0),
     clobbers_flags=False,
     compute_size="size_plus_maybe_offset_for_in_reg_1",
     emit='''
     if !flags.notrap() {
         sink.trap(TrapCode::HeapOutOfBounds, func.srclocs[inst]);
     }
     PUT_OP(bits, rex3(in_reg1, in_reg0, in_reg2), sink);
+    // The else branch always inserts an SIB byte.
     if needs_offset(in_reg1) {
         modrm_sib_disp8(in_reg0, sink);
         sib(0, in_reg2, in_reg1, sink);
         sink.put1(0);
     } else {
         modrm_sib(in_reg0, sink);
         sib(0, in_reg2, in_reg1, sink);
     }
     ''')
 
 # XX /r register-indirect store of FPR with no offset.
 fst = TailRecipe(
         'fst', Store, base_size=1, ins=(FPR, GPR), outs=(),
         instp=IsEqual(Store.offset, 0),
         clobbers_flags=False,
-        compute_size="size_plus_maybe_offset_for_in_reg_1",
+        compute_size="size_plus_maybe_sib_or_offset_for_in_reg_1",
         emit='''
         if !flags.notrap() {
             sink.trap(TrapCode::HeapOutOfBounds, func.srclocs[inst]);
         }
         PUT_OP(bits, rex2(in_reg1, in_reg0), sink);
-        if needs_offset(in_reg1) {
+        if needs_sib_byte(in_reg1) {
+            modrm_sib(in_reg0, sink);
+            sib_noindex(in_reg1, sink);
+        } else if needs_offset(in_reg1) {
             modrm_disp8(in_reg1, in_reg0, sink);
             sink.put1(0);
         } else {
             modrm_rm(in_reg1, in_reg0, sink);
         }
         ''')
 # XX /r register-indirect store with index and no offset of FPR.
 fstWithIndex = TailRecipe(
@@ -907,16 +924,17 @@ fstWithIndex = TailRecipe(
         instp=IsEqual(StoreComplex.offset, 0),
         clobbers_flags=False,
         compute_size="size_plus_maybe_offset_for_in_reg_1",
         emit='''
         if !flags.notrap() {
             sink.trap(TrapCode::HeapOutOfBounds, func.srclocs[inst]);
         }
         PUT_OP(bits, rex3(in_reg1, in_reg0, in_reg2), sink);
+        // The else branch always inserts an SIB byte.
         if needs_offset(in_reg1) {
             modrm_sib_disp8(in_reg0, sink);
             sib(0, in_reg2, in_reg1, sink);
             sink.put1(0);
         } else {
             modrm_sib(in_reg0, sink);
             sib(0, in_reg2, in_reg1, sink);
         }
@@ -963,22 +981,28 @@ stWithIndexDisp8 = TailRecipe(
 
 # XX /r register-indirect store with 8-bit offset.
 # Only ABCD allowed for stored value. This is for byte stores with no REX.
 stDisp8_abcd = TailRecipe(
         'stDisp8_abcd', Store, base_size=2, ins=(ABCD, GPR), outs=(),
         instp=IsSignedInt(Store.offset, 8),
         when_prefixed=stDisp8,
         clobbers_flags=False,
+        compute_size="size_plus_maybe_sib_for_in_reg_1",
         emit='''
         if !flags.notrap() {
             sink.trap(TrapCode::HeapOutOfBounds, func.srclocs[inst]);
         }
         PUT_OP(bits, rex2(in_reg1, in_reg0), sink);
-        modrm_disp8(in_reg1, in_reg0, sink);
+        if needs_sib_byte(in_reg1) {
+            modrm_sib_disp8(in_reg0, sink);
+            sib_noindex(in_reg1, sink);
+        } else {
+            modrm_disp8(in_reg1, in_reg0, sink);
+        }
         let offset: i32 = offset.into();
         sink.put1(offset as u8);
         ''')
 
 # XX /r register-indirect store with index and 8-bit offset.
 # Only ABCD allowed for stored value. This is for byte stores with no REX.
 stWithIndexDisp8_abcd = TailRecipe(
     'stWithIndexDisp8_abcd', StoreComplex, base_size=3,
@@ -1075,22 +1099,28 @@ stWithIndexDisp32 = TailRecipe(
     ''')
 
 # XX /r register-indirect store with 32-bit offset.
 # Only ABCD allowed for stored value. This is for byte stores with no REX.
 stDisp32_abcd = TailRecipe(
         'stDisp32_abcd', Store, base_size=5, ins=(ABCD, GPR), outs=(),
         when_prefixed=stDisp32,
         clobbers_flags=False,
+        compute_size="size_plus_maybe_sib_for_in_reg_1",
         emit='''
         if !flags.notrap() {
             sink.trap(TrapCode::HeapOutOfBounds, func.srclocs[inst]);
         }
         PUT_OP(bits, rex2(in_reg1, in_reg0), sink);
-        modrm_disp32(in_reg1, in_reg0, sink);
+        if needs_sib_byte(in_reg1) {
+            modrm_sib_disp32(in_reg0, sink);
+            sib_noindex(in_reg1, sink);
+        } else {
+            modrm_disp32(in_reg1, in_reg0, sink);
+        }
         let offset: i32 = offset.into();
         sink.put4(offset as u32);
         ''')
 
 # XX /r register-indirect store with index and 32-bit offset.
 # Only ABCD allowed for stored value. This is for byte stores with no REX.
 stWithIndexDisp32_abcd = TailRecipe(
     'stWithIndexDisp32_abcd', StoreComplex, base_size=6,
@@ -1205,23 +1235,26 @@ fregspill32 = TailRecipe(
 # Load recipes
 #
 
 # XX /r load with no offset.
 ld = TailRecipe(
         'ld', Load, base_size=1, ins=(GPR), outs=(GPR),
         instp=IsEqual(Load.offset, 0),
         clobbers_flags=False,
-        compute_size="size_plus_maybe_offset_for_in_reg_0",
+        compute_size="size_plus_maybe_sib_or_offset_for_in_reg_0",
         emit='''
         if !flags.notrap() {
             sink.trap(TrapCode::HeapOutOfBounds, func.srclocs[inst]);
         }
         PUT_OP(bits, rex2(in_reg0, out_reg0), sink);
-        if needs_offset(in_reg0) {
+        if needs_sib_byte(in_reg0) {
+            modrm_sib(out_reg0, sink);
+            sib_noindex(in_reg0, sink);
+        } else if needs_offset(in_reg0) {
             modrm_disp8(in_reg0, out_reg0, sink);
             sink.put1(0);
         } else {
             modrm_rm(in_reg0, out_reg0, sink);
         }
         ''')
 
 # XX /r load with index and no offset.
@@ -1232,38 +1265,42 @@ ldWithIndex = TailRecipe(
     instp=IsEqual(LoadComplex.offset, 0),
     clobbers_flags=False,
     compute_size="size_plus_maybe_offset_for_in_reg_0",
     emit='''
     if !flags.notrap() {
         sink.trap(TrapCode::HeapOutOfBounds, func.srclocs[inst]);
     }
     PUT_OP(bits, rex3(in_reg0, out_reg0, in_reg1), sink);
+    // The else branch always inserts an SIB byte.
     if needs_offset(in_reg0) {
         modrm_sib_disp8(out_reg0, sink);
         sib(0, in_reg1, in_reg0, sink);
         sink.put1(0);
     } else {
         modrm_sib(out_reg0, sink);
         sib(0, in_reg1, in_reg0, sink);
     }
     ''')
 
 # XX /r float load with no offset.
 fld = TailRecipe(
         'fld', Load, base_size=1, ins=(GPR), outs=(FPR),
         instp=IsEqual(Load.offset, 0),
         clobbers_flags=False,
-        compute_size="size_plus_maybe_offset_for_in_reg_0",
+        compute_size="size_plus_maybe_sib_or_offset_for_in_reg_0",
         emit='''
         if !flags.notrap() {
             sink.trap(TrapCode::HeapOutOfBounds, func.srclocs[inst]);
         }
         PUT_OP(bits, rex2(in_reg0, out_reg0), sink);
-        if needs_offset(in_reg0) {
+        if needs_sib_byte(in_reg0) {
+            modrm_sib(out_reg0, sink);
+            sib_noindex(in_reg0, sink);
+        } else if needs_offset(in_reg0) {
             modrm_disp8(in_reg0, out_reg0, sink);
             sink.put1(0);
         } else {
             modrm_rm(in_reg0, out_reg0, sink);
         }
         ''')
 
 # XX /r float load with index and no offset.
@@ -1274,16 +1311,17 @@ fldWithIndex = TailRecipe(
     instp=IsEqual(LoadComplex.offset, 0),
     clobbers_flags=False,
     compute_size="size_plus_maybe_offset_for_in_reg_0",
     emit='''
     if !flags.notrap() {
         sink.trap(TrapCode::HeapOutOfBounds, func.srclocs[inst]);
     }
     PUT_OP(bits, rex3(in_reg0, out_reg0, in_reg1), sink);
+    // The else branch always inserts an SIB byte.
     if needs_offset(in_reg0) {
         modrm_sib_disp8(out_reg0, sink);
         sib(0, in_reg1, in_reg0, sink);
         sink.put1(0);
     } else {
         modrm_sib(out_reg0, sink);
         sib(0, in_reg1, in_reg0, sink);
     }
--- a/third_party/rust/cranelift-codegen/src/context.rs
+++ b/third_party/rust/cranelift-codegen/src/context.rs
@@ -270,24 +270,25 @@ impl Context {
 
     /// Perform simple GVN on the function.
     pub fn simple_gvn<'a, FOI: Into<FlagsOrIsa<'a>>>(&mut self, fisa: FOI) -> CodegenResult<()> {
         do_simple_gvn(&mut self.func, &mut self.domtree);
         self.verify_if(fisa)
     }
 
     /// Perform LICM on the function.
-    pub fn licm<'a, FOI: Into<FlagsOrIsa<'a>>>(&mut self, fisa: FOI) -> CodegenResult<()> {
+    pub fn licm(&mut self, isa: &TargetIsa) -> CodegenResult<()> {
         do_licm(
+            isa,
             &mut self.func,
             &mut self.cfg,
             &mut self.domtree,
             &mut self.loop_analysis,
         );
-        self.verify_if(fisa)
+        self.verify_if(isa)
     }
 
     /// Perform unreachable code elimination.
     pub fn eliminate_unreachable_code<'a, FOI>(&mut self, fisa: FOI) -> CodegenResult<()>
     where
         FOI: Into<FlagsOrIsa<'a>>,
     {
         eliminate_unreachable_code(&mut self.func, &mut self.cfg, &self.domtree);
--- a/third_party/rust/cranelift-codegen/src/ir/dfg.rs
+++ b/third_party/rust/cranelift-codegen/src/ir/dfg.rs
@@ -425,36 +425,48 @@ impl DataFlowGraph {
 
     /// Get all value arguments on `inst` as a mutable slice.
     pub fn inst_args_mut(&mut self, inst: Inst) -> &mut [Value] {
         self.insts[inst].arguments_mut(&mut self.value_lists)
     }
 
     /// Get the fixed value arguments on `inst` as a slice.
     pub fn inst_fixed_args(&self, inst: Inst) -> &[Value] {
-        let fixed_args = self[inst].opcode().constraints().fixed_value_arguments();
-        &self.inst_args(inst)[..fixed_args]
+        let num_fixed_args = self[inst]
+            .opcode()
+            .constraints()
+            .num_fixed_value_arguments();
+        &self.inst_args(inst)[..num_fixed_args]
     }
 
     /// Get the fixed value arguments on `inst` as a mutable slice.
     pub fn inst_fixed_args_mut(&mut self, inst: Inst) -> &mut [Value] {
-        let fixed_args = self[inst].opcode().constraints().fixed_value_arguments();
-        &mut self.inst_args_mut(inst)[..fixed_args]
+        let num_fixed_args = self[inst]
+            .opcode()
+            .constraints()
+            .num_fixed_value_arguments();
+        &mut self.inst_args_mut(inst)[..num_fixed_args]
     }
 
     /// Get the variable value arguments on `inst` as a slice.
     pub fn inst_variable_args(&self, inst: Inst) -> &[Value] {
-        let fixed_args = self[inst].opcode().constraints().fixed_value_arguments();
-        &self.inst_args(inst)[fixed_args..]
+        let num_fixed_args = self[inst]
+            .opcode()
+            .constraints()
+            .num_fixed_value_arguments();
+        &self.inst_args(inst)[num_fixed_args..]
     }
 
     /// Get the variable value arguments on `inst` as a mutable slice.
     pub fn inst_variable_args_mut(&mut self, inst: Inst) -> &mut [Value] {
-        let fixed_args = self[inst].opcode().constraints().fixed_value_arguments();
-        &mut self.inst_args_mut(inst)[fixed_args..]
+        let num_fixed_args = self[inst]
+            .opcode()
+            .constraints()
+            .num_fixed_value_arguments();
+        &mut self.inst_args_mut(inst)[num_fixed_args..]
     }
 
     /// Create result values for an instruction that produces multiple results.
     ///
     /// Instructions that produce no result values only need to be created with `make_inst`,
     /// otherwise call `make_inst_results` to allocate value table entries for the results.
     ///
     /// The result value types are determined from the instruction's value type constraints and the
@@ -484,32 +496,35 @@ impl DataFlowGraph {
     {
         let mut reuse = reuse.fuse();
 
         self.results[inst].clear(&mut self.value_lists);
 
         // Get the call signature if this is a function call.
         if let Some(sig) = self.call_signature(inst) {
             // Create result values corresponding to the call return types.
-            debug_assert_eq!(self.insts[inst].opcode().constraints().fixed_results(), 0);
+            debug_assert_eq!(
+                self.insts[inst].opcode().constraints().num_fixed_results(),
+                0
+            );
             let num_results = self.signatures[sig].returns.len();
             for res_idx in 0..num_results {
                 let ty = self.signatures[sig].returns[res_idx].value_type;
                 if let Some(Some(v)) = reuse.next() {
                     debug_assert_eq!(self.value_type(v), ty, "Reused {} is wrong type", ty);
                     self.attach_result(inst, v);
                 } else {
                     self.append_result(inst, ty);
                 }
             }
             num_results
         } else {
             // Create result values corresponding to the opcode's constraints.
             let constraints = self.insts[inst].opcode().constraints();
-            let num_results = constraints.fixed_results();
+            let num_results = constraints.num_fixed_results();
             for res_idx in 0..num_results {
                 let ty = constraints.result_type(res_idx, ctrl_typevar);
                 if let Some(Some(v)) = reuse.next() {
                     debug_assert_eq!(self.value_type(v), ty, "Reused {} is wrong type", ty);
                     self.attach_result(inst, v);
                 } else {
                     self.append_result(inst, ty);
                 }
@@ -657,27 +672,27 @@ impl DataFlowGraph {
     /// Returns `None` if asked about a result index that is too large.
     pub fn compute_result_type(
         &self,
         inst: Inst,
         result_idx: usize,
         ctrl_typevar: Type,
     ) -> Option<Type> {
         let constraints = self.insts[inst].opcode().constraints();
-        let fixed_results = constraints.fixed_results();
+        let num_fixed_results = constraints.num_fixed_results();
 
-        if result_idx < fixed_results {
+        if result_idx < num_fixed_results {
             return Some(constraints.result_type(result_idx, ctrl_typevar));
         }
 
         // Not a fixed result, try to extract a return type from the call signature.
         self.call_signature(inst).and_then(|sigref| {
             self.signatures[sigref]
                 .returns
-                .get(result_idx - fixed_results)
+                .get(result_idx - num_fixed_results)
                 .map(|&arg| arg.value_type)
         })
     }
 
     /// Get the controlling type variable, or `INVALID` if `inst` isn't polymorphic.
     pub fn ctrl_typevar(&self, inst: Inst) -> Type {
         let constraints = self[inst].opcode().constraints();
 
@@ -929,26 +944,29 @@ impl DataFlowGraph {
     pub fn make_inst_results_for_parser(
         &mut self,
         inst: Inst,
         ctrl_typevar: Type,
         reuse: &[Value],
     ) -> usize {
         // Get the call signature if this is a function call.
         if let Some(sig) = self.call_signature(inst) {
-            assert_eq!(self.insts[inst].opcode().constraints().fixed_results(), 0);
+            assert_eq!(
+                self.insts[inst].opcode().constraints().num_fixed_results(),
+                0
+            );
             for res_idx in 0..self.signatures[sig].returns.len() {
                 let ty = self.signatures[sig].returns[res_idx].value_type;
                 if let Some(v) = reuse.get(res_idx) {
                     self.set_value_type_for_parser(*v, ty);
                 }
             }
         } else {
             let constraints = self.insts[inst].opcode().constraints();
-            for res_idx in 0..constraints.fixed_results() {
+            for res_idx in 0..constraints.num_fixed_results() {
                 let ty = constraints.result_type(res_idx, ctrl_typevar);
                 if let Some(v) = reuse.get(res_idx) {
                     self.set_value_type_for_parser(*v, ty);
                 }
             }
         }
 
         self.make_inst_results_reusing(inst, ctrl_typevar, reuse.iter().map(|x| Some(*x)))
--- a/third_party/rust/cranelift-codegen/src/ir/extname.rs
+++ b/third_party/rust/cranelift-codegen/src/ir/extname.rs
@@ -8,17 +8,17 @@ use ir::LibCall;
 use std::cmp;
 use std::fmt::{self, Write};
 use std::str::FromStr;
 
 const TESTCASE_NAME_LENGTH: usize = 16;
 
 /// The name of an external is either a reference to a user-defined symbol
 /// table, or a short sequence of ascii bytes so that test cases do not have
-/// to keep track of a sy mbol table.
+/// to keep track of a symbol table.
 ///
 /// External names are primarily used as keys by code using Cranelift to map
 /// from a `cranelift_codegen::ir::FuncRef` or similar to additional associated
 /// data.
 ///
 /// External names can also serve as a primitive testing and debugging tool.
 /// In particular, many `.clif` test files use function names to identify
 /// functions.
@@ -63,22 +63,22 @@ impl ExternalName {
         bytes[0..len].copy_from_slice(&vec[0..len]);
 
         ExternalName::TestCase {
             length: len as u8,
             ascii: bytes,
         }
     }
 
-    /// Create a new external name from user-provided integer indicies.
+    /// Create a new external name from user-provided integer indices.
     ///
     /// # Examples
     /// ```rust
     /// # use cranelift_codegen::ir::ExternalName;
-    /// // Create `ExternalName` from integer indicies
+    /// // Create `ExternalName` from integer indices
     /// let name = ExternalName::user(123, 456);
     /// assert_eq!(name.to_string(), "u123:456");
     /// ```
     pub fn user(namespace: u32, index: u32) -> Self {
         ExternalName::User { namespace, index }
     }
 }
 
--- a/third_party/rust/cranelift-codegen/src/ir/instructions.rs
+++ b/third_party/rust/cranelift-codegen/src/ir/instructions.rs
@@ -330,18 +330,18 @@ pub struct OpcodeConstraints {
     /// Bits 5-7:
     ///     Number of fixed value arguments. The minimum required number of value operands.
     flags: u8,
 
     /// Permitted set of types for the controlling type variable as an index into `TYPE_SETS`.
     typeset_offset: u8,
 
     /// Offset into `OPERAND_CONSTRAINT` table of the descriptors for this opcode. The first
-    /// `fixed_results()` entries describe the result constraints, then follows constraints for the
-    /// fixed `Value` input operands. (`fixed_value_arguments()` of them).
+    /// `num_fixed_results()` entries describe the result constraints, then follows constraints for the
+    /// fixed `Value` input operands. (`num_fixed_value_arguments()` of them).
     constraint_offset: u16,
 }
 
 impl OpcodeConstraints {
     /// Can the controlling type variable for this opcode be inferred from the designated value
     /// input operand?
     /// This also implies that this opcode is polymorphic.
     pub fn use_typevar_operand(self) -> bool {
@@ -355,28 +355,28 @@ impl OpcodeConstraints {
     /// variable. A few polymorphic instructions either don't produce any results, or produce
     /// results with a fixed type. These instructions return `true`.
     pub fn requires_typevar_operand(self) -> bool {
         (self.flags & 0x10) != 0
     }
 
     /// Get the number of *fixed* result values produced by this opcode.
     /// This does not include `variable_args` produced by calls.
-    pub fn fixed_results(self) -> usize {
+    pub fn num_fixed_results(self) -> usize {
         (self.flags & 0x7) as usize
     }
 
     /// Get the number of *fixed* input values required by this opcode.
     ///
     /// This does not include `variable_args` arguments on call and branch instructions.
     ///
     /// The number of fixed input values is usually implied by the instruction format, but
     /// instruction formats that use a `ValueList` put both fixed and variable arguments in the
     /// list. This method returns the *minimum* number of values required in the value list.
-    pub fn fixed_value_arguments(self) -> usize {
+    pub fn num_fixed_value_arguments(self) -> usize {
         ((self.flags >> 5) & 0x7) as usize
     }
 
     /// Get the offset into `TYPE_SETS` for the controlling type variable.
     /// Returns `None` if the instruction is not polymorphic.
     fn typeset_offset(self) -> Option<usize> {
         let offset = usize::from(self.typeset_offset);
         if offset < TYPE_SETS.len() {
@@ -389,37 +389,37 @@ impl OpcodeConstraints {
     /// Get the offset into OPERAND_CONSTRAINTS where the descriptors for this opcode begin.
     fn constraint_offset(self) -> usize {
         self.constraint_offset as usize
     }
 
     /// Get the value type of result number `n`, having resolved the controlling type variable to
     /// `ctrl_type`.
     pub fn result_type(self, n: usize, ctrl_type: Type) -> Type {
-        debug_assert!(n < self.fixed_results(), "Invalid result index");
+        debug_assert!(n < self.num_fixed_results(), "Invalid result index");
         if let ResolvedConstraint::Bound(t) =
             OPERAND_CONSTRAINTS[self.constraint_offset() + n].resolve(ctrl_type)
         {
             t
         } else {
             panic!("Result constraints can't be free");
         }
     }
 
     /// Get the value type of input value number `n`, having resolved the controlling type variable
     /// to `ctrl_type`.
     ///
     /// Unlike results, it is possible for some input values to vary freely within a specific
     /// `ValueTypeSet`. This is represented with the `ArgumentConstraint::Free` variant.
     pub fn value_argument_constraint(self, n: usize, ctrl_type: Type) -> ResolvedConstraint {
         debug_assert!(
-            n < self.fixed_value_arguments(),
+            n < self.num_fixed_value_arguments(),
             "Invalid value argument index"
         );
-        let offset = self.constraint_offset() + self.fixed_results();
+        let offset = self.constraint_offset() + self.num_fixed_results();
         OPERAND_CONSTRAINTS[offset + n].resolve(ctrl_type)
     }
 
     /// Get the typeset of allowed types for the controlling type variable in a polymorphic
     /// instruction.
     pub fn ctrl_typeset(self) -> Option<ValueTypeSet> {
         self.typeset_offset().map(|offset| TYPE_SETS[offset])
     }
@@ -598,54 +598,54 @@ mod tests {
         assert_eq!(mem::size_of::<InstructionData>(), 16);
     }
 
     #[test]
     fn constraints() {
         let a = Opcode::Iadd.constraints();
         assert!(a.use_typevar_operand());
         assert!(!a.requires_typevar_operand());
-        assert_eq!(a.fixed_results(), 1);
-        assert_eq!(a.fixed_value_arguments(), 2);
+        assert_eq!(a.num_fixed_results(), 1);
+        assert_eq!(a.num_fixed_value_arguments(), 2);
         assert_eq!(a.result_type(0, types::I32), types::I32);
         assert_eq!(a.result_type(0, types::I8), types::I8);
         assert_eq!(
             a.value_argument_constraint(0, types::I32),
             ResolvedConstraint::Bound(types::I32)
         );
         assert_eq!(
             a.value_argument_constraint(1, types::I32),
             ResolvedConstraint::Bound(types::I32)
         );
 
         let b = Opcode::Bitcast.constraints();
         assert!(!b.use_typevar_operand());
         assert!(!b.requires_typevar_operand());
-        assert_eq!(b.fixed_results(), 1);
-        assert_eq!(b.fixed_value_arguments(), 1);
+        assert_eq!(b.num_fixed_results(), 1);
+        assert_eq!(b.num_fixed_value_arguments(), 1);
         assert_eq!(b.result_type(0, types::I32), types::I32);
         assert_eq!(b.result_type(0, types::I8), types::I8);
         match b.value_argument_constraint(0, types::I32) {
             ResolvedConstraint::Free(vts) => assert!(vts.contains(types::F32)),
             _ => panic!("Unexpected constraint from value_argument_constraint"),
         }
 
         let c = Opcode::Call.constraints();
-        assert_eq!(c.fixed_results(), 0);
-        assert_eq!(c.fixed_value_arguments(), 0);
+        assert_eq!(c.num_fixed_results(), 0);
+        assert_eq!(c.num_fixed_value_arguments(), 0);
 
         let i = Opcode::CallIndirect.constraints();
-        assert_eq!(i.fixed_results(), 0);
-        assert_eq!(i.fixed_value_arguments(), 1);
+        assert_eq!(i.num_fixed_results(), 0);
+        assert_eq!(i.num_fixed_value_arguments(), 1);
 
         let cmp = Opcode::Icmp.constraints();
         assert!(cmp.use_typevar_operand());
         assert!(cmp.requires_typevar_operand());
-        assert_eq!(cmp.fixed_results(), 1);
-        assert_eq!(cmp.fixed_value_arguments(), 2);
+        assert_eq!(cmp.num_fixed_results(), 1);
+        assert_eq!(cmp.num_fixed_value_arguments(), 2);
     }
 
     #[test]
     fn value_set() {
         use ir::types::*;
 
         let vts = ValueTypeSet {
             lanes: BitSet16::from_range(0, 8),
--- a/third_party/rust/cranelift-codegen/src/isa/enc_tables.rs
+++ b/third_party/rust/cranelift-codegen/src/isa/enc_tables.rs
@@ -35,17 +35,17 @@ pub type LegalizeCode = u8;
 /// The hash table values are references to level 2 hash tables, encoded as an offset in `LEVEL2`
 /// where the table begins, and the binary logarithm of its length. All the level 2 hash tables
 /// have a power-of-two size.
 ///
 /// Entries are generic over the offset type. It will typically be `u32` or `u16`, depending on the
 /// size of the `LEVEL2` table.
 ///
 /// Empty entries are encoded with a `!0` value for `log2len` which will always be out of range.
-/// Entries that have a `legalize` value but no level 2 table have an `offset` field that is out f
+/// Entries that have a `legalize` value but no level 2 table have an `offset` field that is out of
 /// bounds.
 pub struct Level1Entry<OffT: Into<u32> + Copy> {
     pub ty: Type,
     pub log2len: u8,
     pub legalize: LegalizeCode,
     pub offset: OffT,
 }
 
--- a/third_party/rust/cranelift-codegen/src/isa/mod.rs
+++ b/third_party/rust/cranelift-codegen/src/isa/mod.rs
@@ -191,17 +191,17 @@ impl TargetFrontendConfig {
     /// Get the width of pointers on this target, in units of bytes.
     pub fn pointer_bytes(self) -> u8 {
         self.pointer_width.bytes()
     }
 }
 
 /// Methods that are specialized to a target ISA. Implies a Display trait that shows the
 /// shared flags, as well as any isa-specific flags.
-pub trait TargetIsa: fmt::Display {
+pub trait TargetIsa: fmt::Display + Sync {
     /// Get the name of this ISA.
     fn name(&self) -> &'static str;
 
     /// Get the target triple that was used to make this trait object.
     fn triple(&self) -> &Triple;
 
     /// Get the ISA-independent flags that were used to make this trait object.
     fn flags(&self) -> &settings::Flags;
--- a/third_party/rust/cranelift-codegen/src/isa/x86/abi.rs
+++ b/third_party/rust/cranelift-codegen/src/isa/x86/abi.rs
@@ -265,17 +265,17 @@ pub fn prologue_epilogue(func: &mut ir::
             system_v_prologue_epilogue(func, isa)
         }
         CallConv::WindowsFastcall => fastcall_prologue_epilogue(func, isa),
         CallConv::Baldrdash => baldrdash_prologue_epilogue(func, isa),
         CallConv::Probestack => unimplemented!("probestack calling convention"),
     }
 }
 
-pub fn baldrdash_prologue_epilogue(func: &mut ir::Function, isa: &TargetIsa) -> CodegenResult<()> {
+fn baldrdash_prologue_epilogue(func: &mut ir::Function, isa: &TargetIsa) -> CodegenResult<()> {
     debug_assert!(
         !isa.flags().probestack_enabled(),
         "baldrdash does not expect cranelift to emit stack probes"
     );
 
     // Baldrdash on 32-bit x86 always aligns its stack pointer to 16 bytes.
     let stack_align = 16;
     let word_size = StackSize::from(isa.pointer_bytes());
@@ -286,17 +286,17 @@ pub fn baldrdash_prologue_epilogue(func:
     func.stack_slots.push(ss);
 
     layout_stack(&mut func.stack_slots, stack_align)?;
     Ok(())
 }
 
 /// Implementation of the fastcall-based Win64 calling convention described at [1]
 /// [1] https://msdn.microsoft.com/en-us/library/ms235286.aspx
-pub fn fastcall_prologue_epilogue(func: &mut ir::Function, isa: &TargetIsa) -> CodegenResult<()> {
+fn fastcall_prologue_epilogue(func: &mut ir::Function, isa: &TargetIsa) -> CodegenResult<()> {
     if isa.triple().pointer_width().unwrap() != PointerWidth::U64 {
         panic!("TODO: windows-fastcall: x86-32 not implemented yet");
     }
 
     // [1] "The primary exceptions are the stack pointer and malloc or alloca memory,
     // which are aligned to 16 bytes in order to aid performance"
     let stack_align = 16;
 
@@ -358,17 +358,17 @@ pub fn fastcall_prologue_epilogue(func: 
     // Reset the cursor and insert the epilogue
     let mut pos = pos.at_position(CursorPosition::Nowhere);
     insert_common_epilogues(&mut pos, local_stack_size, reg_type, &csrs);
 
     Ok(())
 }
 
 /// Insert a System V-compatible prologue and epilogue.
-pub fn system_v_prologue_epilogue(func: &mut ir::Function, isa: &TargetIsa) -> CodegenResult<()> {
+fn system_v_prologue_epilogue(func: &mut ir::Function, isa: &TargetIsa) -> CodegenResult<()> {
     // The original 32-bit x86 ELF ABI had a 4-byte aligned stack pointer, but
     // newer versions use a 16-byte aligned stack pointer.
     let stack_align = 16;
     let pointer_width = isa.triple().pointer_width().unwrap();
     let word_size = pointer_width.bytes() as usize;
     let reg_type = ir::Type::int(u16::from(pointer_width.bits())).unwrap();
 
     let csrs = callee_saved_gprs_used(isa, func);
--- a/third_party/rust/cranelift-codegen/src/isa/x86/enc_tables.rs
+++ b/third_party/rust/cranelift-codegen/src/isa/x86/enc_tables.rs
@@ -18,16 +18,19 @@ include!(concat!(env!("OUT_DIR"), "/enco
 include!(concat!(env!("OUT_DIR"), "/legalize-x86.rs"));
 
 pub fn needs_sib_byte(reg: RegUnit) -> bool {
     reg == RU::r12 as RegUnit || reg == RU::rsp as RegUnit
 }
 pub fn needs_offset(reg: RegUnit) -> bool {
     reg == RU::r13 as RegUnit || reg == RU::rbp as RegUnit
 }
+pub fn needs_sib_byte_or_offset(reg: RegUnit) -> bool {
+    needs_sib_byte(reg) || needs_offset(reg)
+}
 
 fn additional_size_if(
     op_index: usize,
     inst: Inst,
     divert: &RegDiversions,
     func: &Function,
     condition_func: fn(RegUnit) -> bool,
 ) -> u8 {
@@ -66,16 +69,32 @@ fn size_plus_maybe_sib_for_in_reg_0(
 fn size_plus_maybe_sib_for_in_reg_1(
     sizing: &RecipeSizing,
     inst: Inst,
     divert: &RegDiversions,
     func: &Function,
 ) -> u8 {
     sizing.base_size + additional_size_if(1, inst, divert, func, needs_sib_byte)
 }
+fn size_plus_maybe_sib_or_offset_for_in_reg_0(
+    sizing: &RecipeSizing,
+    inst: Inst,
+    divert: &RegDiversions,
+    func: &Function,
+) -> u8 {
+    sizing.base_size + additional_size_if(0, inst, divert, func, needs_sib_byte_or_offset)
+}
+fn size_plus_maybe_sib_or_offset_for_in_reg_1(
+    sizing: &RecipeSizing,
+    inst: Inst,
+    divert: &RegDiversions,
+    func: &Function,
+) -> u8 {
+    sizing.base_size + additional_size_if(1, inst, divert, func, needs_sib_byte_or_offset)
+}
 
 /// Expand the `sdiv` and `srem` instructions using `x86_sdivmodx`.
 fn expand_sdivrem(
     inst: ir::Inst,
     func: &mut ir::Function,
     cfg: &mut ControlFlowGraph,
     isa: &isa::TargetIsa,
 ) {
--- a/third_party/rust/cranelift-codegen/src/legalizer/boundary.rs
+++ b/third_party/rust/cranelift-codegen/src/legalizer/boundary.rs
@@ -196,18 +196,24 @@ where
     ResType: FnMut(&Function, usize) -> AbiParam,
 {
     let call = pos
         .current_inst()
         .expect("Cursor must point to a call instruction");
 
     // We theoretically allow for call instructions that return a number of fixed results before
     // the call return values. In practice, it doesn't happen.
-    let fixed_results = pos.func.dfg[call].opcode().constraints().fixed_results();
-    debug_assert_eq!(fixed_results, 0, "Fixed results on calls not supported");
+    debug_assert_eq!(
+        pos.func.dfg[call]
+            .opcode()
+            .constraints()
+            .num_fixed_results(),
+        0,
+        "Fixed results on calls not supported"
+    );
 
     let results = pos.func.dfg.detach_results(call);
     let mut next_res = 0;
     let mut abi_res = 0;
 
     // Point immediately after the call.
     pos.next_inst();
 
@@ -435,21 +441,21 @@ fn legalize_inst_arguments<ArgType>(
     // Lift the value list out of the call instruction so we modify it.
     let mut vlist = pos.func.dfg[inst]
         .take_value_list()
         .expect("Call must have a value list");
 
     // The value list contains all arguments to the instruction, including the callee on an
     // indirect call which isn't part of the call arguments that must match the ABI signature.
     // Figure out how many fixed values are at the front of the list. We won't touch those.
-    let fixed_values = pos.func.dfg[inst]
+    let num_fixed_values = pos.func.dfg[inst]
         .opcode()
         .constraints()
-        .fixed_value_arguments();
-    let have_args = vlist.len(&pos.func.dfg.value_lists) - fixed_values;
+        .num_fixed_value_arguments();
+    let have_args = vlist.len(&pos.func.dfg.value_lists) - num_fixed_values;
 
     // Grow the value list to the right size and shift all the existing arguments to the right.
     // This lets us write the new argument values into the list without overwriting the old
     // arguments.
     //
     // Before:
     //
     //    <-->              fixed_values
@@ -467,32 +473,32 @@ fn legalize_inst_arguments<ArgType>(
     //
     // After writing the new arguments:
     //
     //    <-->                     fixed_values
     //        <------------------> abi_args
     //   [FFFFNNNNNNNNNNNNNNNNNNNN]
     //
     vlist.grow_at(
-        fixed_values,
+        num_fixed_values,
         abi_args - have_args,
         &mut pos.func.dfg.value_lists,
     );
-    let old_arg_offset = fixed_values + abi_args - have_args;
+    let old_arg_offset = num_fixed_values + abi_args - have_args;
 
     let mut abi_arg = 0;
     for old_arg in 0..have_args {
         let old_value = vlist
             .get(old_arg_offset + old_arg, &pos.func.dfg.value_lists)
             .unwrap();
         let mut put_arg = |func: &mut Function, arg| {
             let abi_type = get_abi_type(func, abi_arg);
             if func.dfg.value_type(arg) == abi_type.value_type {
                 // This is the argument type we need.
-                vlist.as_mut_slice(&mut func.dfg.value_lists)[fixed_values + abi_arg] = arg;
+                vlist.as_mut_slice(&mut func.dfg.value_lists)[num_fixed_values + abi_arg] = arg;
                 abi_arg += 1;
                 Ok(())
             } else {
                 Err(abi_type)
             }
         };
         convert_to_abi(pos, cfg, old_value, &mut put_arg);
     }
--- a/third_party/rust/cranelift-codegen/src/legalizer/split.rs
+++ b/third_party/rust/cranelift-codegen/src/legalizer/split.rs
@@ -128,53 +128,55 @@ fn split_any(
     while let Some(repair) = repairs.pop() {
         for BasicBlock { inst, .. } in cfg.pred_iter(repair.ebb) {
             let branch_opc = pos.func.dfg[inst].opcode();
             debug_assert!(
                 branch_opc.is_branch(),
                 "Predecessor not a branch: {}",
                 pos.func.dfg.display_inst(inst, None)
             );
-            let fixed_args = branch_opc.constraints().fixed_value_arguments();
+            let num_fixed_args = branch_opc.constraints().num_fixed_value_arguments();
             let mut args = pos.func.dfg[inst]
                 .take_value_list()
                 .expect("Branches must have value lists.");
             let num_args = args.len(&pos.func.dfg.value_lists);
             // Get the old value passed to the EBB argument we're repairing.
             let old_arg = args
-                .get(fixed_args + repair.num, &pos.func.dfg.value_lists)
+                .get(num_fixed_args + repair.num, &pos.func.dfg.value_lists)
                 .expect("Too few branch arguments");
 
             // It's possible that the CFG's predecessor list has duplicates. Detect them here.
             if pos.func.dfg.value_type(old_arg) == repair.split_type {
                 pos.func.dfg[inst].put_value_list(args);
                 continue;
             }
 
             // Split the old argument, possibly causing more repairs to be scheduled.
             pos.goto_inst(inst);
             let (lo, hi) = split_value(pos, old_arg, repair.concat, &mut repairs);
 
             // The `lo` part replaces the original argument.
             *args
-                .get_mut(fixed_args + repair.num, &mut pos.func.dfg.value_lists)
+                .get_mut(num_fixed_args + repair.num, &mut pos.func.dfg.value_lists)
                 .unwrap() = lo;
 
             // The `hi` part goes at the end. Since multiple repairs may have been scheduled to the
             // same EBB, there could be multiple arguments missing.
-            if num_args > fixed_args + repair.hi_num {
+            if num_args > num_fixed_args + repair.hi_num {
                 *args
-                    .get_mut(fixed_args + repair.hi_num, &mut pos.func.dfg.value_lists)
-                    .unwrap() = hi;
+                    .get_mut(
+                        num_fixed_args + repair.hi_num,
+                        &mut pos.func.dfg.value_lists,
+                    ).unwrap() = hi;
             } else {
                 // We need to append one or more arguments. If we're adding more than one argument,
                 // there must be pending repairs on the stack that will fill in the correct values
                 // instead of `hi`.
                 args.extend(
-                    iter::repeat(hi).take(1 + fixed_args + repair.hi_num - num_args),
+                    iter::repeat(hi).take(1 + num_fixed_args + repair.hi_num - num_args),
                     &mut pos.func.dfg.value_lists,
                 );
             }
 
             // Put the value list back after manipulating it.
             pos.func.dfg[inst].put_value_list(args);
         }
     }
--- a/third_party/rust/cranelift-codegen/src/licm.rs
+++ b/third_party/rust/cranelift-codegen/src/licm.rs
@@ -1,24 +1,26 @@
 //! A Loop Invariant Code Motion optimization pass
 
-use cursor::{Cursor, FuncCursor};
+use cursor::{Cursor, EncCursor, FuncCursor};
 use dominator_tree::DominatorTree;
 use entity::{EntityList, ListPool};
 use flowgraph::{BasicBlock, ControlFlowGraph};
 use fx::FxHashSet;
 use ir::{DataFlowGraph, Ebb, Function, Inst, InstBuilder, Layout, Opcode, Type, Value};
+use isa::TargetIsa;
 use loop_analysis::{Loop, LoopAnalysis};
 use std::vec::Vec;
 use timing;
 
 /// Performs the LICM pass by detecting loops within the CFG and moving
 /// loop-invariant instructions out of them.
 /// Changes the CFG and domtree in-place during the operation.
 pub fn do_licm(
+    isa: &TargetIsa,
     func: &mut Function,
     cfg: &mut ControlFlowGraph,
     domtree: &mut DominatorTree,
     loop_analysis: &mut LoopAnalysis,
 ) {
     let _tt = timing::licm();
     debug_assert!(cfg.is_valid());
     debug_assert!(domtree.is_valid());
@@ -31,17 +33,17 @@ pub fn do_licm(
         // Then we create the loop's pre-header and fill it with the invariant instructions
         // Then we remove the invariant instructions from the loop body
         if !invariant_insts.is_empty() {
             // If the loop has a natural pre-header we use it, otherwise we create it.
             let mut pos;
             match has_pre_header(&func.layout, cfg, domtree, loop_analysis.loop_header(lp)) {
                 None => {
                     let pre_header =
-                        create_pre_header(loop_analysis.loop_header(lp), func, cfg, domtree);
+                        create_pre_header(isa, loop_analysis.loop_header(lp), func, cfg, domtree);
                     pos = FuncCursor::new(func).at_last_inst(pre_header);
                 }
                 // If there is a natural pre-header we insert new instructions just before the
                 // related jumping instruction (which is not necessarily at the end).
                 Some((_, last_inst)) => {
                     pos = FuncCursor::new(func).at_inst(last_inst);
                 }
             };
@@ -55,16 +57,17 @@ pub fn do_licm(
     // We have to recompute the domtree to account for the changes
     cfg.compute(func);
     domtree.compute(func, cfg);
 }
 
 // Insert a pre-header before the header, modifying the function layout and CFG to reflect it.
 // A jump instruction to the header is placed at the end of the pre-header.
 fn create_pre_header(
+    isa: &TargetIsa,
     header: Ebb,
     func: &mut Function,
     cfg: &mut ControlFlowGraph,
     domtree: &DominatorTree,
 ) -> Ebb {
     let pool = &mut ListPool::<Value>::new();
     let header_args_values: Vec<Value> = func.dfg.ebb_params(header).into_iter().cloned().collect();
     let header_args_types: Vec<Type> = header_args_values
@@ -82,17 +85,17 @@ fn create_pre_header(
     } in cfg.pred_iter(header)
     {
         // We only follow normal edges (not the back edges)
         if !domtree.dominates(header, last_inst, &func.layout) {
             change_branch_jump_destination(last_inst, pre_header, func);
         }
     }
     {
-        let mut pos = FuncCursor::new(func).at_top(header);
+        let mut pos = EncCursor::new(func, isa).at_top(header);
         // Inserts the pre-header at the right place in the layout.
         pos.insert_ebb(pre_header);
         pos.next_inst();
         pos.ins().jump(header, pre_header_args_value.as_slice(pool));
     }
     pre_header
 }
 
@@ -103,31 +106,34 @@ fn create_pre_header(
 // Returns the pre-header Ebb and the instruction jumping to the header.
 fn has_pre_header(
     layout: &Layout,
     cfg: &ControlFlowGraph,
     domtree: &DominatorTree,
     header: Ebb,
 ) -> Option<(Ebb, Inst)> {
     let mut result = None;
-    let mut found = false;
     for BasicBlock {
         ebb: pred_ebb,
-        inst: last_inst,
+        inst: branch_inst,
     } in cfg.pred_iter(header)
     {
         // We only count normal edges (not the back edges)
-        if !domtree.dominates(header, last_inst, layout) {
-            if found {
+        if !domtree.dominates(header, branch_inst, layout) {
+            if result.is_some() {
                 // We have already found one, there are more than one
                 return None;
-            } else {
-                result = Some((pred_ebb, last_inst));
-                found = true;
             }
+            if branch_inst != layout.last_inst(pred_ebb).unwrap()
+                || cfg.succ_iter(pred_ebb).nth(1).is_some()
+            {
+                // It's along a critical edge, so don't use it.
+                return None;
+            }
+            result = Some((pred_ebb, branch_inst));
         }
     }
     result
 }
 
 // Change the destination of a jump or branch instruction. Does nothing if called with a non-jump
 // or non-branch instruction.
 fn change_branch_jump_destination(inst: Inst, new_ebb: Ebb, func: &mut Function) {
--- a/third_party/rust/cranelift-codegen/src/print_errors.rs
+++ b/third_party/rust/cranelift-codegen/src/print_errors.rs
@@ -1,13 +1,13 @@
 //! Utility routines for pretty-printing error messages.
 
 use entity::SecondaryMap;
 use ir;
-use ir::entities::{AnyEntity, Inst, Value};
+use ir::entities::{AnyEntity, Ebb, Inst, Value};
 use ir::function::Function;
 use isa::TargetIsa;
 use result::CodegenError;
 use std::boxed::Box;
 use std::fmt;
 use std::fmt::Write;
 use std::string::{String, ToString};
 use std::vec::Vec;
@@ -18,29 +18,49 @@ use write::{decorate_function, FuncWrite
 pub fn pretty_verifier_error<'a>(
     func: &ir::Function,
     isa: Option<&TargetIsa>,
     func_w: Option<Box<FuncWriter + 'a>>,
     errors: VerifierErrors,
 ) -> String {
     let mut errors = errors.0;
     let mut w = String::new();
+    let num_errors = errors.len();
 
     decorate_function(
         &mut PrettyVerifierError(func_w.unwrap_or_else(|| Box::new(PlainWriter)), &mut errors),
         &mut w,
         func,
         isa,
     ).unwrap();
+
+    writeln!(
+        w,
+        "\n; {} verifier error{} detected (see above). Compilation aborted.",
+        num_errors,
+        if num_errors == 1 { "" } else { "s" }
+    ).unwrap();
+
     w
 }
 
 struct PrettyVerifierError<'a>(Box<FuncWriter + 'a>, &'a mut Vec<VerifierError>);
 
 impl<'a> FuncWriter for PrettyVerifierError<'a> {
+    fn write_ebb_header(
+        &mut self,
+        w: &mut Write,
+        func: &Function,
+        isa: Option<&TargetIsa>,
+        ebb: Ebb,
+        indent: usize,
+    ) -> fmt::Result {
+        pretty_ebb_header_error(w, func, isa, ebb, indent, &mut *self.0, self.1)
+    }
+
     fn write_instruction(
         &mut self,
         w: &mut Write,
         func: &Function,
         aliases: &SecondaryMap<Value, Vec<Value>>,
         isa: Option<&TargetIsa>,
         inst: Inst,
         indent: usize,
@@ -54,110 +74,149 @@ impl<'a> FuncWriter for PrettyVerifierEr
         func: &Function,
         entity: AnyEntity,
         value: &fmt::Display,
     ) -> fmt::Result {
         pretty_preamble_error(w, func, entity, value, &mut *self.0, self.1)
     }
 }
 
-/// Pretty-print a function verifier error.
+/// Pretty-print a function verifier error for a given EBB.
+fn pretty_ebb_header_error(
+    w: &mut Write,
+    func: &Function,
+    isa: Option<&TargetIsa>,
+    cur_ebb: Ebb,
+    indent: usize,
+    func_w: &mut FuncWriter,
+    errors: &mut Vec<VerifierError>,
+) -> fmt::Result {
+    let mut s = String::new();
+    func_w.write_ebb_header(&mut s, func, isa, cur_ebb, indent)?;
+    write!(w, "{}", s)?;
+
+    // TODO: Use drain_filter here when it gets stabilized
+    let mut i = 0;
+    let mut printed_error = false;
+    while i != errors.len() {
+        match errors[i].location {
+            ir::entities::AnyEntity::Ebb(ebb) if ebb == cur_ebb => {
+                if !printed_error {
+                    print_arrow(w, &s)?;
+                    printed_error = true;
+                }
+                let err = errors.remove(i);
+                print_error(w, err)?;
+            }
+            _ => i += 1,
+        }
+    }
+
+    if printed_error {
+        w.write_char('\n')?;
+    }
+
+    Ok(())
+}
+
+/// Pretty-print a function verifier error for a given instruction.
 fn pretty_instruction_error(
     w: &mut Write,
     func: &Function,
     aliases: &SecondaryMap<Value, Vec<Value>>,
     isa: Option<&TargetIsa>,
     cur_inst: Inst,
     indent: usize,
     func_w: &mut FuncWriter,
     errors: &mut Vec<VerifierError>,
 ) -> fmt::Result {
+    let mut s = String::new();
+    func_w.write_instruction(&mut s, func, aliases, isa, cur_inst, indent)?;
+    write!(w, "{}", s)?;
+
     // TODO: Use drain_filter here when it gets stabilized
     let mut i = 0;
-    let mut printed_instr = false;
-
+    let mut printed_error = false;
     while i != errors.len() {
         match errors[i].location {
             ir::entities::AnyEntity::Inst(inst) if inst == cur_inst => {
-                let err = errors.remove(i);
-
-                if !printed_instr {
-                    func_w.write_instruction(w, func, aliases, isa, cur_inst, indent)?;
-                    printed_instr = true;
+                if !printed_error {
+                    print_arrow(w, &s)?;
+                    printed_error = true;
                 }
-
-                print_error(w, indent, cur_inst.to_string(), err)?;
+                let err = errors.remove(i);
+                print_error(w, err)?;
             }
-            ir::entities::AnyEntity::Inst(_) => i += 1,
-            _ => unreachable!(),
+            _ => i += 1,
         }
     }
 
-    if printed_instr {
+    if printed_error {
         w.write_char('\n')?;
-    } else {
-        writeln!(
-            w,
-            "{1:0$}{2}",
-            indent,
-            "",
-            func.dfg.display_inst(cur_inst, isa)
-        )?;
     }
 
     Ok(())
 }
 
 fn pretty_preamble_error(
     w: &mut Write,
     func: &Function,
     entity: AnyEntity,
     value: &fmt::Display,
     func_w: &mut FuncWriter,
     errors: &mut Vec<VerifierError>,
 ) -> fmt::Result {
-    // TODO: Use drain_filter here when it gets stabilized
-    let indent = 4;
+    let mut s = String::new();
+    func_w.write_entity_definition(&mut s, func, entity, value)?;
+    write!(w, "{}", s)?;
 
+    // TODO: Use drain_filter here when it gets stabilized
     let mut i = 0;
-    let mut printed_entity = false;
-
+    let mut printed_error = false;
     while i != errors.len() {
         if entity == errors[i].location {
+            if !printed_error {
+                print_arrow(w, &s)?;
+                printed_error = true;
+            }
             let err = errors.remove(i);
-
-            if !printed_entity {
-                func_w.write_entity_definition(w, func, entity, value)?;
-                printed_entity = true;
-            }
-
-            print_error(w, indent, entity.to_string(), err)?;
+            print_error(w, err)?;
         } else {
             i += 1
         }
     }
 
-    if printed_entity {
+    if printed_error {
         w.write_char('\n')?;
-    } else {
-        func_w.write_entity_definition(w, func, entity, value)?;
     }
 
     Ok(())
 }
 
-/// Prints ;   ^~~~~~ verifier [ERROR BODY]
-fn print_error(w: &mut Write, indent: usize, s: String, err: VerifierError) -> fmt::Result {
-    let indent = if indent < 1 { 0 } else { indent - 1 };
+/// Prints:
+///    ;   ^~~~~~
+fn print_arrow(w: &mut Write, entity: &str) -> fmt::Result {
+    write!(w, ";")?;
 
-    write!(w, ";{1:0$}^", indent, "")?;
-    for _c in s.chars() {
+    let indent = entity.len() - entity.trim_start().len();
+    if indent != 0 {
+        write!(w, "{1:0$}^", indent - 1, "")?;
+    }
+
+    for _ in 0..entity.trim().len() - 1 {
         write!(w, "~")?;
     }
-    writeln!(w, " verifier {}", err.to_string())?;
+
+    writeln!(w)
+}
+
+/// Prints:
+///    ; error: [ERROR BODY]
+fn print_error(w: &mut Write, err: VerifierError) -> fmt::Result {
+    writeln!(w, "; error: {}", err.to_string())?;
     Ok(())
 }
 
 /// Pretty-print a Cranelift error.
 pub fn pretty_error(func: &ir::Function, isa: Option<&TargetIsa>, err: CodegenError) -> String {
     if let CodegenError::Verifier(e) = err {
         pretty_verifier_error(func, isa, None, e)
     } else {
--- a/third_party/rust/cranelift-codegen/src/regalloc/coalescing.rs
+++ b/third_party/rust/cranelift-codegen/src/regalloc/coalescing.rs
@@ -370,17 +370,17 @@ impl<'a> Context<'a> {
             pred_ebb,
             pos.display_inst(pred_inst)
         );
 
         copy
     }
 
     /// Finish the union-find part of the coalescing algorithm.
-    ///     ///
+    ///
     /// This builds the initial set of virtual registers as the transitive/reflexive/symmetric
     /// closure of the relation formed by EBB parameter-argument pairs found by `union_find_ebb()`.
     fn finish_union_find(&mut self) {
         self.virtregs.finish_union_find(None);
         debug!("After union-find phase:{}", self.virtregs);
     }
 }
 
--- a/third_party/rust/cranelift-codegen/src/regalloc/register_set.rs
+++ b/third_party/rust/cranelift-codegen/src/regalloc/register_set.rs
@@ -67,17 +67,17 @@ impl RegisterSet {
         self.avail[idx] &= !bits;
     }
 
     /// Return `reg` and all of its register units to the set of available registers.
     pub fn free(&mut self, rc: RegClass, reg: RegUnit) {
         let (idx, bits) = bitmask(rc, reg);
         debug_assert!(
             (self.avail[idx] & bits) == 0,
-            "{}:{} not allocated in {}",
+            "{}:{} is already free in {}",
             rc,
             rc.info.display_regunit(reg),
             self.display(rc.info)
         );
         self.avail[idx] |= bits;
     }
 
     /// Return an iterator over all available registers belonging to the register class `rc`.
--- a/third_party/rust/cranelift-codegen/src/regalloc/reload.rs
+++ b/third_party/rust/cranelift-codegen/src/regalloc/reload.rs
@@ -261,17 +261,17 @@ impl<'a> Context<'a> {
                 }
             }
         }
 
         // Same thing for spilled call return values.
         let retvals = &defs[self.cur.func.dfg[inst]
                                 .opcode()
                                 .constraints()
-                                .fixed_results()..];
+                                .num_fixed_results()..];
         if !retvals.is_empty() {
             let sig = self
                 .cur
                 .func
                 .dfg
                 .call_signature(inst)
                 .expect("Extra results on non-call instruction");
             for (i, lv) in retvals.iter().enumerate() {
@@ -362,17 +362,17 @@ impl<'a> Context<'a> {
                 }
             }
         }
 
         // If we only have the fixed arguments, we're done now.
         let offset = self.cur.func.dfg[inst]
             .opcode()
             .constraints()
-            .fixed_value_arguments();
+            .num_fixed_value_arguments();
         if args.len() == offset {
             return;
         }
         let var_args = &args[offset..];
 
         // Handle ABI arguments.
         if let Some(sig) = self.cur.func.dfg.call_signature(inst) {
             handle_abi_args(
--- a/third_party/rust/cranelift-codegen/src/regalloc/spilling.rs
+++ b/third_party/rust/cranelift-codegen/src/regalloc/spilling.rs
@@ -129,21 +129,18 @@ impl<'a> Context<'a> {
     fn visit_ebb(&mut self, ebb: Ebb, tracker: &mut LiveValueTracker) {
         debug!("Spilling {}:", ebb);
         self.cur.goto_top(ebb);
         self.visit_ebb_header(ebb, tracker);
         tracker.drop_dead_params();
         self.process_spills(tracker);
 
         while let Some(inst) = self.cur.next_inst() {
-            if let Some(constraints) = self
-                .encinfo
-                .operand_constraints(self.cur.func.encodings[inst])
-            {
-                self.visit_inst(inst, ebb, constraints, tracker);
+            if !self.cur.func.dfg[inst].opcode().is_ghost() {
+                self.visit_inst(inst, ebb, tracker);
             } else {
                 let (_throughs, kills) = tracker.process_ghost(inst);
                 self.free_regs(kills);
             }
             tracker.drop_dead(inst);
             self.process_spills(tracker);
         }
     }
@@ -232,27 +229,25 @@ impl<'a> Context<'a> {
             }
         }
 
         // The transient pressure counts for the EBB arguments are accurate. Just preserve them.
         self.pressure.preserve_transient();
         self.free_dead_regs(params);
     }
 
-    fn visit_inst(
-        &mut self,
-        inst: Inst,
-        ebb: Ebb,
-        constraints: &RecipeConstraints,
-        tracker: &mut LiveValueTracker,
-    ) {
+    fn visit_inst(&mut self, inst: Inst, ebb: Ebb, tracker: &mut LiveValueTracker) {
         debug!("Inst {}, {}", self.cur.display_inst(inst), self.pressure);
         debug_assert_eq!(self.cur.current_inst(), Some(inst));
         debug_assert_eq!(self.cur.current_ebb(), Some(ebb));
 
+        let constraints = self
+            .encinfo
+            .operand_constraints(self.cur.func.encodings[inst]);
+
         // We may need to resolve register constraints if there are any noteworthy uses.
         debug_assert!(self.reg_uses.is_empty());
         self.collect_reg_uses(inst, ebb, constraints);
 
         // Calls usually have fixed register uses.
         let call_sig = self.cur.func.dfg.call_signature(inst);
         if let Some(sig) = call_sig {
             self.collect_abi_reg_uses(inst, sig);
@@ -277,91 +272,100 @@ impl<'a> Context<'a> {
                     self.spill_reg(lv.value);
                 }
             }
         }
 
         // Make sure we have enough registers for the register defs.
         // Dead defs are included here. They need a register too.
         // No need to process call return values, they are in fixed registers.
-        for op in constraints.outs {
-            if op.kind != ConstraintKind::Stack {
-                // Add register def to pressure, spill if needed.
-                while let Err(mask) = self.pressure.take_transient(op.regclass) {
-                    debug!("Need {} reg from {} throughs", op.regclass, throughs.len());
-                    match self.spill_candidate(mask, throughs) {
-                        Some(cand) => self.spill_reg(cand),
-                        None => panic!(
-                            "Ran out of {} registers for {}",
-                            op.regclass,
-                            self.cur.display_inst(inst)
-                        ),
+        if let Some(constraints) = constraints {
+            for op in constraints.outs {
+                if op.kind != ConstraintKind::Stack {
+                    // Add register def to pressure, spill if needed.
+                    while let Err(mask) = self.pressure.take_transient(op.regclass) {
+                        debug!("Need {} reg from {} throughs", op.regclass, throughs.len());
+                        match self.spill_candidate(mask, throughs) {
+                            Some(cand) => self.spill_reg(cand),
+                            None => panic!(
+                                "Ran out of {} registers for {}",
+                                op.regclass,
+                                self.cur.display_inst(inst)
+                            ),
+                        }
                     }
                 }
             }
+            self.pressure.reset_transient();
         }
-        self.pressure.reset_transient();
 
         // Restore pressure state, compute pressure with affinities from `defs`.
         // Exclude dead defs. Includes call return values.
         // This won't cause spilling.
         self.take_live_regs(defs);
     }
 
     // Collect register uses that are noteworthy in one of the following ways:
     //
     // 1. It's a fixed register constraint.
     // 2. It's a use of a spilled value.
     // 3. It's a tied register constraint and the value isn't killed.
     //
     // We are assuming here that if a value is used both by a fixed register operand and a register
     // class operand, they two are compatible. We are also assuming that two register class
     // operands are always compatible.
-    fn collect_reg_uses(&mut self, inst: Inst, ebb: Ebb, constraints: &RecipeConstraints) {
+    fn collect_reg_uses(&mut self, inst: Inst, ebb: Ebb, constraints: Option<&RecipeConstraints>) {
         let args = self.cur.func.dfg.inst_args(inst);
-        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);
+        let num_fixed_ins = if let Some(constraints) = constraints {
+            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);
+                    }
+                    ConstraintKind::FixedTied(_) => {
+                        reguse.fixed = true;
+                        reguse.tied = !lr.killed_at(inst, ebb, ctx);
+                    }
+                    ConstraintKind::Reg => {}
                 }
-                ConstraintKind::FixedTied(_) => {
-                    reguse.fixed = true;
-                    reguse.tied = !lr.killed_at(inst, ebb, ctx);
+                if lr.affinity.is_stack() {
+                    reguse.spilled = true;
                 }
-                ConstraintKind::Reg => {}
+
+                // Only collect the interesting register uses.
+                if reguse.fixed || reguse.tied || reguse.spilled {
+                    debug!("  reguse: {}", reguse);
+                    self.reg_uses.push(reguse);
+                }
             }
-            if lr.affinity.is_stack() {
-                reguse.spilled = true;
-            }
-
-            // Only collect the interesting register uses.
-            if reguse.fixed || reguse.tied || reguse.spilled {
-                debug!("  reguse: {}", reguse);
-                self.reg_uses.push(reguse);
-            }
-        }
+            constraints.ins.len()
+        } else {
+            // A non-ghost instruction with no constraints can't have any
+            // fixed operands.
+            0
+        };
 
         // Similarly, for return instructions, collect uses of ABI-defined
         // return values.
         if self.cur.func.dfg[inst].opcode().is_return() {
             debug_assert_eq!(
                 self.cur.func.dfg.inst_variable_args(inst).len(),
                 self.cur.func.signature.returns.len(),
                 "The non-fixed arguments in a return should follow the function's signature."
             );
             for (ret_idx, (ret, &arg)) in
                 self.cur.func.signature.returns.iter().zip(args).enumerate()
             {
-                let idx = constraints.ins.len() + ret_idx;
+                let idx = num_fixed_ins + ret_idx;
                 let unit = match ret.location {
                     ArgumentLoc::Unassigned => {
                         panic!("function return signature should be legalized")
                     }
                     ArgumentLoc::Reg(unit) => unit,
                     ArgumentLoc::Stack(_) => continue,
                 };
                 let toprc = toprc_containing_regunit(unit, &self.reginfo);
@@ -371,37 +375,37 @@ impl<'a> Context<'a> {
                 debug!("  reguse: {}", reguse);
                 self.reg_uses.push(reguse);
             }
         }
     }
 
     // Collect register uses from the ABI input constraints.
     fn collect_abi_reg_uses(&mut self, inst: Inst, sig: SigRef) {
-        let fixed_args = self.cur.func.dfg[inst]
+        let num_fixed_args = self.cur.func.dfg[inst]
             .opcode()
             .constraints()
-            .fixed_value_arguments();
+            .num_fixed_value_arguments();
         let args = self.cur.func.dfg.inst_variable_args(inst);
         for (idx, (abi, &arg)) in self.cur.func.dfg.signatures[sig]
             .params
             .iter()
             .zip(args)
             .enumerate()
         {
             if abi.location.is_reg() {
                 let (rci, spilled) = match self.liveness[arg].affinity {
                     Affinity::Reg(rci) => (rci, false),
                     Affinity::Stack => (
                         self.cur.isa.regclass_for_abi_type(abi.value_type).into(),
                         true,
                     ),
                     Affinity::Unassigned => panic!("Missing affinity for {}", arg),
                 };
-                let mut reguse = RegUse::new(arg, fixed_args + idx, rci);
+                let mut reguse = RegUse::new(arg, num_fixed_args + idx, rci);
                 reguse.fixed = true;
                 reguse.spilled = spilled;
                 self.reg_uses.push(reguse);
             }
         }
     }
 
     // Process multiple register uses to resolve potential conflicts.
--- a/third_party/rust/cranelift-codegen/src/regalloc/virtregs.rs
+++ b/third_party/rust/cranelift-codegen/src/regalloc/virtregs.rs
@@ -286,30 +286,32 @@ impl UFEntry {
 /// For more information on the algorithm implemented here, see Chapter 21 "Data Structures for
 /// Disjoint Sets" of Cormen, Leiserson, Rivest, Stein, "Introduction to algorithms", 3rd Ed.
 ///
 /// The [Wikipedia entry on disjoint-set data
 /// structures](https://en.wikipedia.org/wiki/Disjoint-set_data_structure) is also good.
 impl VirtRegs {
     /// Find the leader value and rank of the set containing `v`.
     /// Compress the path if needed.
-    fn find(&mut self, val: Value) -> (Value, u32) {
-        match UFEntry::decode(self.union_find[val]) {
-            UFEntry::Rank(rank) => (val, rank),
-            UFEntry::Link(parent) => {
-                // TODO: This recursion would be more efficient as an iteration that pushes
-                // elements onto a SmallVector.
-                let found = self.find(parent);
-                // Compress the path if needed.
-                if found.0 != parent {
-                    self.union_find[val] = UFEntry::encode_link(found.0);
+    fn find(&mut self, mut val: Value) -> (Value, u32) {
+        let mut val_stack = vec![];
+        let found = loop {
+            match UFEntry::decode(self.union_find[val]) {
+                UFEntry::Rank(rank) => break (val, rank),
+                UFEntry::Link(parent) => {
+                    val_stack.push(val);
+                    val = parent;
                 }
-                found
             }
+        };
+        // Compress the path
+        while let Some(val) = val_stack.pop() {
+            self.union_find[val] = UFEntry::encode_link(found.0);
         }
+        found
     }
 
     /// Union the two sets containing `a` and `b`.
     ///
     /// This ensures that `a` and `b` will belong to the same virtual register after calling
     /// `finish_union_find()`.
     pub fn union(&mut self, a: Value, b: Value) {
         let (leader_a, rank_a) = self.find(a);
--- a/third_party/rust/cranelift-codegen/src/simple_gvn.rs
+++ b/third_party/rust/cranelift-codegen/src/simple_gvn.rs
@@ -105,32 +105,29 @@ pub fn do_simple_gvn(func: &mut Function
                 scope_stack.push(func.layout.next_inst(inst).unwrap());
                 visible_values.increment_depth();
             }
 
             if trivially_unsafe_for_gvn(opcode) {
                 continue;
             }
 
-            let inst_data = func.dfg[inst].clone();
-
             // These are split up to separate concerns.
-            if is_load_and_not_readonly(&inst_data) {
+            if is_load_and_not_readonly(&func.dfg[inst]) {
                 continue;
             }
 
             let ctrl_typevar = func.dfg.ctrl_typevar(inst);
             let key = HashKey {
                 inst: func.dfg[inst].clone(),
                 ty: ctrl_typevar,
                 pos: &pos,
             };
-            let entry = visible_values.entry(key);
             use scoped_hash_map::Entry::*;
-            match entry {
+            match visible_values.entry(key) {
                 Occupied(entry) => {
                     debug_assert!(domtree.dominates(*entry.get(), inst, &func.layout));
                     // If the redundant instruction is representing the current
                     // scope, pick a new representative.
                     let old = scope_stack.last_mut().unwrap();
                     if *old == inst {
                         *old = func.layout.next_inst(inst).unwrap();
                     }
--- a/third_party/rust/cranelift-codegen/src/verifier/mod.rs
+++ b/third_party/rust/cranelift-codegen/src/verifier/mod.rs
@@ -519,22 +519,22 @@ impl<'a> Verifier<'a> {
         if inst_data.opcode().format() != InstructionFormat::from(inst_data) {
             return fatal!(
                 errors,
                 inst,
                 "instruction opcode doesn't match instruction format"
             );
         }
 
-        let fixed_results = inst_data.opcode().constraints().fixed_results();
+        let num_fixed_results = inst_data.opcode().constraints().num_fixed_results();
         // var_results is 0 if we aren't a call instruction
         let var_results = dfg
             .call_signature(inst)
             .map_or(0, |sig| dfg.signatures[sig].returns.len());
-        let total_results = fixed_results + var_results;
+        let total_results = num_fixed_results + var_results;
 
         // All result values for multi-valued instructions are created
         let got_results = dfg.inst_results(inst).len();
         if got_results != total_results {
             return fatal!(
                 errors,
                 inst,
                 "expected {} result values, found {}",
@@ -856,28 +856,23 @@ impl<'a> Verifier<'a> {
                 if is_reachable {
                     if !self
                         .expected_domtree
                         .dominates(def_inst, loc_inst, &self.func.layout)
                     {
                         return fatal!(
                             errors,
                             loc_inst,
-                            "uses value from non-dominating {}",
+                            "uses value {} from non-dominating {}",
+                            v,
                             def_inst
                         );
                     }
                     if def_inst == loc_inst {
-                        return fatal!(
-                            errors,
-                            loc_inst,
-                            "uses value from itself {},  {}",
-                            def_inst,
-                            loc_inst
-                        );
+                        return fatal!(errors, loc_inst, "uses value {} from itself", v);
                     }
                 }
             }
             ValueDef::Param(ebb, _) => {
                 // Value is defined by an existing EBB.
                 if !dfg.ebb_is_valid(ebb) {
                     return fatal!(errors, loc_inst, "{} is defined by invalid EBB {}", v, ebb);
                 }
--- a/third_party/rust/cranelift-codegen/src/write.rs
+++ b/third_party/rust/cranelift-codegen/src/write.rs
@@ -9,25 +9,35 @@ use ir::{DataFlowGraph, Ebb, Function, I
 use isa::{RegInfo, TargetIsa};
 use packed_option::ReservedValue;
 use std::fmt::{self, Write};
 use std::string::String;
 use std::vec::Vec;
 
 /// A `FuncWriter` used to decorate functions during printing.
 pub trait FuncWriter {
+    /// Write the extended basic block header for the current function.
+    fn write_ebb_header(
+        &mut self,
+        w: &mut Write,
+        func: &Function,
+        isa: Option<&TargetIsa>,
+        ebb: Ebb,
+        indent: usize,
+    ) -> fmt::Result;
+
     /// Write the given `inst` to `w`.
     fn write_instruction(
         &mut self,
         w: &mut Write,
         func: &Function,
         aliases: &SecondaryMap<Value, Vec<Value>>,
         isa: Option<&TargetIsa>,
         inst: Inst,
-        ident: usize,
+        indent: usize,
     ) -> fmt::Result;
 
     /// Write the preamble to `w`. By default, this uses `write_entity_definition`.
     fn write_preamble(
         &mut self,
         w: &mut Write,
         func: &Function,
         regs: Option<&RegInfo>,
@@ -103,16 +113,27 @@ impl FuncWriter for PlainWriter {
         func: &Function,
         aliases: &SecondaryMap<Value, Vec<Value>>,
         isa: Option<&TargetIsa>,
         inst: Inst,
         indent: usize,
     ) -> fmt::Result {
         write_instruction(w, func, aliases, isa, inst, indent)
     }
+
+    fn write_ebb_header(
+        &mut self,
+        w: &mut Write,
+        func: &Function,
+        isa: Option<&TargetIsa>,
+        ebb: Ebb,
+        indent: usize,
+    ) -> fmt::Result {
+        write_ebb_header(w, func, isa, ebb, indent)
+    }
 }
 
 /// Write `func` to `w` as equivalent text.
 /// Use `isa` to emit ISA-dependent annotations.
 pub fn write_function(w: &mut Write, func: &Function, isa: Option<&TargetIsa>) -> fmt::Result {
     decorate_function(&mut PlainWriter, w, func, isa)
 }
 
@@ -222,17 +243,17 @@ fn decorate_ebb<FW: FuncWriter>(
 ) -> fmt::Result {
     // Indent all instructions if any encodings are present.
     let indent = if func.encodings.is_empty() && func.srclocs.is_empty() {
         4
     } else {
         36
     };
 
-    write_ebb_header(w, func, isa, ebb, indent)?;
+    func_w.write_ebb_header(w, func, isa, ebb, indent)?;
     for a in func.dfg.ebb_params(ebb).iter().cloned() {
         write_value_aliases(w, aliases, a, indent)?;
     }
     for inst in func.layout.ebb_insts(ebb) {
         func_w.write_instruction(w, func, aliases, isa, inst, indent)?;
     }
 
     Ok(())
--- a/third_party/rust/cranelift-entity/.cargo-checksum.json
+++ b/third_party/rust/cranelift-entity/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{"Cargo.toml":"1e808860e82183786baf0f34301d7de848ddc5932ddc2ff2f7ccc56a7c94cd61","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"96ceffbfd88fb06e3b41aa4d3087cffbbf8441d04eba7ab09662a72ab600a321","src/iter.rs":"cd2336dc29891e4e5060fb24f1d2f885a4606ea6580e9bd0f261843f12e31a1b","src/keys.rs":"5eca885b3e7ba19936c24066253bf47ebbd9d0a808a84dc910041e8e7be86349","src/lib.rs":"ccbf78e58d56ef1cb811e5ba451d6e8aa69a84c95f5cfe89c0d1f7ecdd26d15b","src/list.rs":"15d9762396439eb2e835401a7b85e190e097fa5eb863decfb67fb677f1093335","src/map.rs":"bcf7a78077056e4194581cbeb4b9d6bdd263ae1c6b261a0fc011ccda5f39bb4f","src/packed_option.rs":"19b2d49e0233e05e3dc39424187644af546934fe92b7200543fe10728ec831f6","src/primary.rs":"0954bbae2dcbd4cc173f15be473ecece94af278917f0f94e5dd289ccbfac66da","src/set.rs":"fd687531bb01db9a22ed09486e378fdfe5842c84b603620f83fe8a42109df3cb","src/sparse.rs":"d2b7bd25c7e2b5ef2194feb08c635447953a4548d42ae26d080bb4ca44dfcc20"},"package":"9be3f82369346201c2e0cff720522e6eb55459e51c916b2199f25cff2058ca96"}
\ No newline at end of file
+{"files":{"Cargo.toml":"18b45cd5e51eaa9c5591e303a4fcdb759e740be967d02aaa154aaafc25281daa","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"96ceffbfd88fb06e3b41aa4d3087cffbbf8441d04eba7ab09662a72ab600a321","src/iter.rs":"cd2336dc29891e4e5060fb24f1d2f885a4606ea6580e9bd0f261843f12e31a1b","src/keys.rs":"5eca885b3e7ba19936c24066253bf47ebbd9d0a808a84dc910041e8e7be86349","src/lib.rs":"ccbf78e58d56ef1cb811e5ba451d6e8aa69a84c95f5cfe89c0d1f7ecdd26d15b","src/list.rs":"15d9762396439eb2e835401a7b85e190e097fa5eb863decfb67fb677f1093335","src/map.rs":"bcf7a78077056e4194581cbeb4b9d6bdd263ae1c6b261a0fc011ccda5f39bb4f","src/packed_option.rs":"19b2d49e0233e05e3dc39424187644af546934fe92b7200543fe10728ec831f6","src/primary.rs":"457f72222869abfc06109473d8a7435cf8acaef3888b4bd559608e135aa96395","src/set.rs":"fd687531bb01db9a22ed09486e378fdfe5842c84b603620f83fe8a42109df3cb","src/sparse.rs":"d2b7bd25c7e2b5ef2194feb08c635447953a4548d42ae26d080bb4ca44dfcc20"},"package":"fc9a0329208e5e0d7d4d6e64cd50985d4c4cbfdbeeb594ae2157a094b98e8dcc"}
\ No newline at end of file
--- a/third_party/rust/cranelift-entity/Cargo.toml
+++ b/third_party/rust/cranelift-entity/Cargo.toml
@@ -7,17 +7,17 @@
 #
 # If you believe there's an error in this file please file an
 # issue against the rust-lang/cargo repository. If you're
 # editing this file be aware that the upstream Cargo.toml
 # will likely look very different (and much more reasonable)
 
 [package]
 name = "cranelift-entity"
-version = "0.23.0"
+version = "0.25.0"
 authors = ["The Cranelift Project Developers"]
 description = "Data structures using entity references as mapping keys"
 documentation = "https://cranelift.readthedocs.io/"
 readme = "README.md"
 keywords = ["entity", "set", "map"]
 categories = ["no-std"]
 license = "Apache-2.0 WITH LLVM-exception"
 repository = "https://github.com/CraneStation/cranelift"
--- a/third_party/rust/cranelift-entity/src/primary.rs
+++ b/third_party/rust/cranelift-entity/src/primary.rs
@@ -106,16 +106,26 @@ where
         self.elems.push(v);
         k
     }
 
     /// Returns the last element that was inserted in the map.
     pub fn last(&self) -> Option<&V> {
         self.elems.last()
     }
+
+    /// Reserves capacity for at least `additional` more elements to be inserted.
+    pub fn reserve(&mut self, additional: usize) {
+        self.elems.reserve(additional)
+    }
+
+    /// Reserves the minimum capacity for exactly `additional` more elements to be inserted.
+    pub fn reserve_exact(&mut self, additional: usize) {
+        self.elems.reserve_exact(additional)
+    }
 }
 
 /// Immutable indexing into an `PrimaryMap`.
 /// The indexed value must be in the map.
 impl<K, V> Index<K> for PrimaryMap<K, V>
 where
     K: EntityRef,
 {
--- a/third_party/rust/cranelift-frontend/.cargo-checksum.json
+++ b/third_party/rust/cranelift-frontend/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{"Cargo.toml":"86e80c8ba33f01a87083d8abf7de8ebcf2e8c065aa5c3a4276e5154d3e02af35","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"dea43e8044284df50f8b8772e9b48ba8b109b45c74111ff73619775d57ad8d67","src/frontend.rs":"32c32130a988cf636a26abd6ddeb993f6c11f3c259c5c0b21997a72ab7f8c90b","src/lib.rs":"9c223914fb7530a669a7487b3b1cf3138df0aed79d152da3d3e03012382244f2","src/ssa.rs":"2b03fd5c88cda8a318827282ed960a61192d6685881ebd8b3d6e8fa92ca6bdc6","src/switch.rs":"bda005663d7976353250c8016ec1f46d0aa03ef289542e4db1b87a071387f7a4","src/variable.rs":"b8de0a43f72ca45bfa0833aee312f3c3f396cf3920545bbdcb9da98fb0de26df"},"package":"7d5d18ab2bc89a09b4275442a9559dc0f947b9a8ad9ae9ee89452a057df54ced"}
\ No newline at end of file
+{"files":{"Cargo.toml":"597db8d588c5ed61feb5d54e82f9750575f41211de66c965241186694aec244f","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"dea43e8044284df50f8b8772e9b48ba8b109b45c74111ff73619775d57ad8d67","src/frontend.rs":"98fed7c08319790af423c40498ed8dd856a52b3535d2ecaf4a835392bd951996","src/lib.rs":"9c223914fb7530a669a7487b3b1cf3138df0aed79d152da3d3e03012382244f2","src/ssa.rs":"2b03fd5c88cda8a318827282ed960a61192d6685881ebd8b3d6e8fa92ca6bdc6","src/switch.rs":"bda005663d7976353250c8016ec1f46d0aa03ef289542e4db1b87a071387f7a4","src/variable.rs":"b8de0a43f72ca45bfa0833aee312f3c3f396cf3920545bbdcb9da98fb0de26df"},"package":"98d9eb4a2343435d520499236c805725c88d6d55eefb9a6ad0819b7970c76bdd"}
\ No newline at end of file
--- a/third_party/rust/cranelift-frontend/Cargo.toml
+++ b/third_party/rust/cranelift-frontend/Cargo.toml
@@ -7,26 +7,26 @@
 #
 # If you believe there's an error in this file please file an
 # issue against the rust-lang/cargo repository. If you're
 # editing this file be aware that the upstream Cargo.toml
 # will likely look very different (and much more reasonable)
 
 [package]
 name = "cranelift-frontend"
-version = "0.23.0"
+version = "0.25.0"
 authors = ["The Cranelift Project Developers"]
 description = "Cranelift IR builder helper"
 documentation = "https://cranelift.readthedocs.io/"
 readme = "README.md"
 categories = ["no-std"]
 license = "Apache-2.0 WITH LLVM-exception"
 repository = "https://github.com/CraneStation/cranelift"
 [dependencies.cranelift-codegen]
-version = "0.23.0"
+version = "0.25.0"
 default-features = false
 
 [dependencies.hashmap_core]
 version = "0.1.9"
 optional = true
 
 [dependencies.log]
 version = "0.4.4"
--- a/third_party/rust/cranelift-frontend/src/frontend.rs
+++ b/third_party/rust/cranelift-frontend/src/frontend.rs
@@ -600,22 +600,22 @@ impl<'a> FunctionBuilder<'a> {
         let load_and_store_amount = size / access_size;
 
         if load_and_store_amount > THRESHOLD {
             let size_value = self.ins().iconst(config.pointer_type(), size as i64);
             self.call_memcpy(config, dest, src, size_value);
             return;
         }
 
+        let int_type = Type::int((access_size * 8) as u16).unwrap();
         let mut flags = MemFlags::new();
         flags.set_aligned();
 
         for i in 0..load_and_store_amount {
             let offset = (access_size * i) as i32;
-            let int_type = Type::int(access_size as u16).unwrap();
             let value = self.ins().load(int_type, flags, src, offset);
             self.ins().store(flags, value, dest, offset);
         }
     }
 
     /// Calls libc.memset
     ///
     /// Writes `size` bytes of value `ch` to memory starting at `buffer`.
@@ -674,17 +674,17 @@ impl<'a> FunctionBuilder<'a> {
             let ch = self.ins().iconst(types::I32, ch as i64);
             let size = self.ins().iconst(config.pointer_type(), size as i64);
             self.call_memset(config, buffer, ch, size);
         } else {
             let mut flags = MemFlags::new();
             flags.set_aligned();
 
             let ch = ch as u64;
-            let int_type = Type::int(access_size as u16).unwrap();
+            let int_type = Type::int((access_size * 8) as u16).unwrap();
             let raw_value = if int_type == types::I64 {
                 (ch << 32) | (ch << 16) | (ch << 8) | ch
             } else if int_type == types::I32 {
                 (ch << 16) | (ch << 8) | ch
             } else if int_type == types::I16 {
                 (ch << 8) | ch
             } else {
                 assert_eq!(int_type, types::I8);
@@ -760,17 +760,20 @@ impl<'a> FunctionBuilder<'a> {
 
         let mut flags = MemFlags::new();
         flags.set_aligned();
 
         // Load all of the memory first in case `dest` overlaps.
         let registers: Vec<_> = (0..load_and_store_amount)
             .map(|i| {
                 let offset = (access_size * i) as i32;
-                (self.ins().load(types::I8, flags, src, offset), offset)
+                (
+                    self.ins().load(config.pointer_type(), flags, src, offset),
+                    offset,
+                )
             }).collect();
 
         for (value, offset) in registers {
             self.ins().store(flags, value, dest, offset);
         }
     }
 }
 
@@ -983,15 +986,72 @@ ebb0:
     call fn0(v1, v0, v1)
     return v1
 }
 "
         );
     }
 
     #[test]
+    fn small_memcpy() {
+        use cranelift_codegen::{isa, settings};
+        use std::str::FromStr;
+
+        let shared_builder = settings::builder();
+        let shared_flags = settings::Flags::new(shared_builder);
+
+        let triple = ::target_lexicon::Triple::from_str("arm").expect("Couldn't create arm triple");
+
+        let target = isa::lookup(triple)
+            .ok()
+            .map(|b| b.finish(shared_flags))
+            .expect("This test requires arm support.");
+
+        let mut sig = Signature::new(target.default_call_conv());
+        sig.returns.push(AbiParam::new(I32));
+
+        let mut fn_ctx = FunctionBuilderContext::new();
+        let mut func = Function::with_name_signature(ExternalName::testcase("sample"), sig);
+        {
+            let mut builder = FunctionBuilder::new(&mut func, &mut fn_ctx);
+
+            let block0 = builder.create_ebb();
+            let x = Variable::new(0);
+            let y = Variable::new(16);
+            builder.declare_var(x, target.pointer_type());
+            builder.declare_var(y, target.pointer_type());
+            builder.append_ebb_params_for_function_params(block0);
+            builder.switch_to_block(block0);
+
+            let src = builder.use_var(x);
+            let dest = builder.use_var(y);
+            let size = 8;
+            builder.emit_small_memcpy(target.frontend_config(), dest, src, size, 8, 8);
+            builder.ins().return_(&[dest]);
+
+            builder.seal_all_blocks();
+            builder.finalize();
+        }
+
+        assert_eq!(
+            func.display(None).to_string(),
+            "function %sample() -> i32 system_v {
+ebb0:
+    v4 = iconst.i32 0
+    v1 -> v4
+    v3 = iconst.i32 0
+    v0 -> v3
+    v2 = load.i64 aligned v0
+    store aligned v2, v1
+    return v1
+}
+"
+        );
+    }
+
+    #[test]
     fn test_greatest_divisible_power_of_two() {
         assert_eq!(64, greatest_divisible_power_of_two(64));
         assert_eq!(16, greatest_divisible_power_of_two(48));
         assert_eq!(8, greatest_divisible_power_of_two(24));
         assert_eq!(1, greatest_divisible_power_of_two(25));
     }
 }
--- a/third_party/rust/cranelift-wasm/.cargo-checksum.json
+++ b/third_party/rust/cranelift-wasm/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{"Cargo.toml":"1a769c7a06aca3d88b4792a2ac46c6416902f0fa1176bf0fbdec4b4ebc29be6c","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"046f81212a5705bfaa925b6de195652141b727d63ef602af57d5073659deea64","src/code_translator.rs":"36bf4010cbd89774fd8f8ba75c3535887585b11624ae2f20b05ec60d43e2954d","src/environ/dummy.rs":"1eafb40cc09f04cc673c387ff960c373ad15ff091d14638799ad12ab1e3fc6ba","src/environ/mod.rs":"8c5287366c354acb144593fadbbe45c14106e0b7ec101077c4f3f213901c584d","src/environ/spec.rs":"49e43ff35083f87d518ee02b4a18c1c2079552069eeaa4c2f7c9776a2f5ba5a6","src/func_translator.rs":"1c6b7d0d3da14c1ff7df1c22d2ade14da5d87d0be70f647145ea180da762aa2f","src/lib.rs":"5db10cae9fb9c792fa278a1795b4f5ec412ad481f52391e481d688c2e55533ce","src/module_translator.rs":"8e441cc4cb05d6bdd7be41f2ba937390f85f3e3b07578e03a0f9e642f963bc02","src/sections_translator.rs":"799754ccdd0e8572b8c0d775193ce1b279c89c92a284687dce86268ee316b83b","src/state.rs":"4523d611d2c4889eb809ee6c2bfbf29d4d83230580be3c724009ba8988cc25b6","src/translation_utils.rs":"3e8d486c7acccad5e269628add77338702e43464780945c8767559d836d72a10","tests/wasm_testsuite.rs":"9ea05ab8d188f047f3307e5ca0c1ea10784d65d338f7ea3544d59e6fa6a202f2"},"package":"e5906a111814d43d84002ef974eb0c023804fd4d1866b34f43c1bb588a759ad8"}
\ No newline at end of file
+{"files":{"Cargo.toml":"aca5579a3fbaa96d6cfda23012215879f7df0a07313e2e9acdc49e167d31e1c3","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"046f81212a5705bfaa925b6de195652141b727d63ef602af57d5073659deea64","src/code_translator.rs":"474d07684fee27fcbd48997a7772458d8eff0a69a31b74293066a892c87067f9","src/environ/dummy.rs":"aafca1a2cda88cb67d4c082f7ccb6296812586216f417c501224b6790d345446","src/environ/mod.rs":"8c5287366c354acb144593fadbbe45c14106e0b7ec101077c4f3f213901c584d","src/environ/spec.rs":"a627a1a92a2a652d037f63a9def019ebbf4c953de1cb194f2e73095744d07476","src/func_translator.rs":"1c6b7d0d3da14c1ff7df1c22d2ade14da5d87d0be70f647145ea180da762aa2f","src/lib.rs":"b94abdc2fe638aff7b5fc00ffb2fc4812590a68241b8462b82888aa9114c2f64","src/module_translator.rs":"8e441cc4cb05d6bdd7be41f2ba937390f85f3e3b07578e03a0f9e642f963bc02","src/sections_translator.rs":"62d7d53abc88060c4d63721a99530d26a3ed09cb99e1f19238bcefd8b86b958a","src/state.rs":"4523d611d2c4889eb809ee6c2bfbf29d4d83230580be3c724009ba8988cc25b6","src/translation_utils.rs":"363d75509bca5d87548881dcbb3c52642980be8fa6d62c2ea4b39524560ac65c","tests/wasm_testsuite.rs":"9ea05ab8d188f047f3307e5ca0c1ea10784d65d338f7ea3544d59e6fa6a202f2"},"package":"5022a3a3d1044fdc8c97909b5e8d701884982dcfb43885034d004cfdd9b7d577"}
\ No newline at end of file
--- a/third_party/rust/cranelift-wasm/Cargo.toml
+++ b/third_party/rust/cranelift-wasm/Cargo.toml
@@ -7,34 +7,34 @@
 #
 # If you believe there's an error in this file please file an
 # issue against the rust-lang/cargo repository. If you're
 # editing this file be aware that the upstream Cargo.toml
 # will likely look very different (and much more reasonable)
 
 [package]
 name = "cranelift-wasm"
-version = "0.23.0"
+version = "0.25.0"
 authors = ["The Cranelift Project Developers"]
 description = "Translator from WebAssembly to Cranelift IR"
 readme = "README.md"
 keywords = ["webassembly", "wasm"]
 categories = ["no-std", "wasm"]
 license = "Apache-2.0 WITH LLVM-exception"
 repository = "https://github.com/CraneStation/cranelift"
 [dependencies.cranelift-codegen]
-version = "0.23.0"
+version = "0.25.0"
 default-features = false
 
 [dependencies.cranelift-entity]
-version = "0.23.0"
+version = "0.25.0"
 default-features = false
 
 [dependencies.cranelift-frontend]
-version = "0.23.0"
+version = "0.25.0"
 default-features = false
 
 [dependencies.failure]
 version = "0.1.1"
 features = ["derive"]
 default-features = false
 
 [dependencies.failure_derive]
@@ -45,17 +45,17 @@ default-features = false
 version = "0.1.9"
 optional = true
 
 [dependencies.log]
 version = "0.4.4"
 default-features = false
 
 [dependencies.wasmparser]
-version = "0.21.4"
+version = "0.22.0"
 default-features = false
 [dev-dependencies.target-lexicon]
 version = "0.2.0"
 
 [dev-dependencies.wabt]
 version = "0.7.0"
 
 [features]
--- a/third_party/rust/cranelift-wasm/src/code_translator.rs
+++ b/third_party/rust/cranelift-wasm/src/code_translator.rs
@@ -248,17 +248,17 @@ pub fn translate_operator<FE: FuncEnviro
             builder
                 .ins()
                 .jump(br_destination, state.peekn(return_count));
             state.popn(return_count);
             state.reachable = false;
         }
         Operator::BrIf { relative_depth } => translate_br_if(relative_depth, builder, state),
         Operator::BrTable { table } => {
-            let (depths, default) = table.read_table();
+            let (depths, default) = table.read_table()?;
             let mut min_depth = default;
             for depth in &*depths {
                 if *depth < min_depth {
                     min_depth = *depth;
                 }
             }
             let jump_args_count = {
                 let i = state.control_stack.len() - 1 - (min_depth as usize);
--- a/third_party/rust/cranelift-wasm/src/environ/dummy.rs
+++ b/third_party/rust/cranelift-wasm/src/environ/dummy.rs
@@ -47,16 +47,25 @@ pub struct DummyModuleInfo {
     config: TargetFrontendConfig,
 
     /// Signatures as provided by `declare_signature`.
     pub signatures: PrimaryMap<SignatureIndex, ir::Signature>,
 
     /// Module and field names of imported functions as provided by `declare_func_import`.
     pub imported_funcs: Vec<(String, String)>,
 
+    /// Module and field names of imported globals as provided by `declare_global_import`.
+    pub imported_globals: Vec<(String, String)>,
+
+    /// Module and field names of imported tables as provided by `declare_table_import`.
+    pub imported_tables: Vec<(String, String)>,
+
+    /// Module and field names of imported memories as provided by `declare_memory_import`.
+    pub imported_memories: Vec<(String, String)>,
+
     /// Functions, imported and local.
     pub functions: PrimaryMap<FuncIndex, Exportable<SignatureIndex>>,
 
     /// Function bodies.
     pub function_bodies: PrimaryMap<DefinedFuncIndex, ir::Function>,
 
     /// Tables as provided by `declare_table`.
     pub tables: PrimaryMap<TableIndex, Exportable<Table>>,
@@ -73,16 +82,19 @@ pub struct DummyModuleInfo {
 
 impl DummyModuleInfo {
     /// Creates a new `DummyModuleInfo` instance.
     pub fn new(config: TargetFrontendConfig) -> Self {
         Self {
             config,
             signatures: PrimaryMap::new(),
             imported_funcs: Vec::new(),
+            imported_globals: Vec::new(),
+            imported_tables: Vec::new(),
+            imported_memories: Vec::new(),
             functions: PrimaryMap::new(),
             function_bodies: PrimaryMap::new(),
             tables: PrimaryMap::new(),
             memories: PrimaryMap::new(),
             globals: PrimaryMap::new(),
             start_func: None,
         }
     }
@@ -321,18 +333,18 @@ impl<'dummy_environment> FuncEnvironment
     }
 
     fn return_mode(&self) -> ReturnMode {
         self.return_mode
     }
 }
 
 impl<'data> ModuleEnvironment<'data> for DummyEnvironment {
-    fn target_config(&self) -> &TargetFrontendConfig {
-        &self.info.config
+    fn target_config(&self) -> TargetFrontendConfig {
+        self.info.config
     }
 
     fn get_func_name(&self, func_index: FuncIndex) -> ir::ExternalName {
         get_func_name(func_index)
     }
 
     fn declare_signature(&mut self, sig: &ir::Signature) {
         self.info.signatures.push(sig.clone());
@@ -370,35 +382,59 @@ impl<'data> ModuleEnvironment<'data> for
     fn get_func_type(&self, func_index: FuncIndex) -> SignatureIndex {
         self.info.functions[func_index].entity
     }
 
     fn declare_global(&mut self, global: Global) {
         self.info.globals.push(Exportable::new(global));
     }
 
+    fn declare_global_import(&mut self, global: Global, module: &'data str, field: &'data str) {
+        self.info.globals.push(Exportable::new(global));
+        self.info
+            .imported_globals
+            .push((String::from(module), String::from(field)));
+    }
+
     fn get_global(&self, global_index: GlobalIndex) -> &Global {
         &self.info.globals[global_index].entity
     }
 
     fn declare_table(&mut self, table: Table) {
         self.info.tables.push(Exportable::new(table));
     }
+
+    fn declare_table_import(&mut self, table: Table, module: &'data str, field: &'data str) {
+        self.info.tables.push(Exportable::new(table));
+        self.info
+            .imported_tables
+            .push((String::from(module), String::from(field)));
+    }
+
     fn declare_table_elements(
         &mut self,
         _table_index: TableIndex,
         _base: Option<GlobalIndex>,
         _offset: usize,
         _elements: Vec<FuncIndex>,
     ) {
         // We do nothing
     }
+
     fn declare_memory(&mut self, memory: Memory) {
         self.info.memories.push(Exportable::new(memory));
     }
+
+    fn declare_memory_import(&mut self, memory: Memory, module: &'data str, field: &'data str) {
+        self.info.memories.push(Exportable::new(memory));
+        self.info
+            .imported_memories
+            .push((String::from(module), String::from(field)));
+    }
+
     fn declare_data_initialization(
         &mut self,
         _memory_index: MemoryIndex,
         _base: Option<GlobalIndex>,
         _offset: usize,
         _data: &'data [u8],
     ) {
         // We do nothing
--- a/third_party/rust/cranelift-wasm/src/environ/spec.rs
+++ b/third_party/rust/cranelift-wasm/src/environ/spec.rs
@@ -232,17 +232,17 @@ pub trait FuncEnvironment {
     }
 }
 
 /// An object satisfying the `ModuleEnvironment` trait can be passed as argument to the
 /// [`translate_module`](fn.translate_module.html) function. These methods should not be called
 /// by the user, they are only for `cranelift-wasm` internal use.
 pub trait ModuleEnvironment<'data> {
     /// Get the information needed to produce Cranelift IR for the current target.
-    fn target_config(&self) -> &TargetFrontendConfig;
+    fn target_config(&self) -> TargetFrontendConfig;
 
     /// Return the name for the given function index.
     fn get_func_name(&self, func_index: FuncIndex) -> ir::ExternalName;
 
     /// Declares a function signature to the environment.
     fn declare_signature(&mut self, sig: &ir::Signature);
 
     /// Return the signature with the given index.
@@ -263,31 +263,42 @@ pub trait ModuleEnvironment<'data> {
     fn declare_func_type(&mut self, sig_index: SignatureIndex);
 
     /// Return the signature index for the given function index.
     fn get_func_type(&self, func_index: FuncIndex) -> SignatureIndex;
 
     /// Declares a global to the environment.
     fn declare_global(&mut self, global: Global);
 
+    /// Declares a global import to the environment.
+    fn declare_global_import(&mut self, global: Global, module: &'data str, field: &'data str);
+
     /// Return the global for the given global index.
     fn get_global(&self, global_index: GlobalIndex) -> &Global;
 
     /// Declares a table to the environment.
     fn declare_table(&mut self, table: Table);
+
+    /// Declares a table import to the environment.
+    fn declare_table_import(&mut self, table: Table, module: &'data str, field: &'data str);
+
     /// Fills a declared table with references to functions in the module.
     fn declare_table_elements(
         &mut self,
         table_index: TableIndex,
         base: Option<GlobalIndex>,
         offset: usize,
         elements: Vec<FuncIndex>,
     );
     /// Declares a memory to the environment
     fn declare_memory(&mut self, memory: Memory);
+
+    /// Declares a memory import to the environment.
+    fn declare_memory_import(&mut self, memory: Memory, module: &'data str, field: &'data str);
+
     /// Fills a declared memory with bytes at module instantiation.
     fn declare_data_initialization(
         &mut self,
         memory_index: MemoryIndex,
         base: Option<GlobalIndex>,
         offset: usize,
         data: &'data [u8],
     );
--- a/third_party/rust/cranelift-wasm/src/lib.rs
+++ b/third_party/rust/cranelift-wasm/src/lib.rs
@@ -61,18 +61,18 @@ mod translation_utils;
 
 pub use environ::{
     DummyEnvironment, FuncEnvironment, GlobalVariable, ModuleEnvironment, ReturnMode, WasmError,
     WasmResult,
 };
 pub use func_translator::FuncTranslator;
 pub use module_translator::translate_module;
 pub use translation_utils::{
-    DefinedFuncIndex, FuncIndex, Global, GlobalIndex, GlobalInit, Memory, MemoryIndex,
-    SignatureIndex, Table, TableIndex,
+    DefinedFuncIndex, DefinedGlobalIndex, DefinedMemoryIndex, DefinedTableIndex, FuncIndex, Global,
+    GlobalIndex, GlobalInit, Memory, MemoryIndex, SignatureIndex, Table, TableIndex,
 };
 
 #[cfg(not(feature = "std"))]
 mod std {
     extern crate alloc;
 
     pub use self::alloc::string;
     pub use self::alloc::vec;
--- a/third_party/rust/cranelift-wasm/src/sections_translator.rs
+++ b/third_party/rust/cranelift-wasm/src/sections_translator.rs
@@ -14,18 +14,18 @@ use std::str::from_utf8;
 use std::vec::Vec;
 use translation_utils::{
     type_to_type, FuncIndex, Global, GlobalIndex, GlobalInit, Memory, MemoryIndex, SignatureIndex,
     Table, TableElementType, TableIndex,
 };
 use wasmparser::{
     self, CodeSectionReader, Data, DataSectionReader, Element, ElementSectionReader, Export,
     ExportSectionReader, ExternalKind, FuncType, FunctionSectionReader, GlobalSectionReader,
-    GlobalType, Import, ImportSectionEntryType, ImportSectionReader, MemorySectionReader,
-    MemoryType, Operator, TableSectionReader, TypeSectionReader,
+    GlobalType, ImportSectionEntryType, ImportSectionReader, MemorySectionReader, MemoryType,
+    Operator, TableSectionReader, TypeSectionReader,
 };
 
 /// Parses the Type section of the wasm module.
 pub fn parse_type_section(
     types: TypeSectionReader,
     environ: &mut ModuleEnvironment,
 ) -> WasmResult<()> {
     for entry in types {
@@ -55,68 +55,71 @@ pub fn parse_type_section(
 }
 
 /// Parses the Import section of the wasm module.
 pub fn parse_import_section<'data>(
     imports: ImportSectionReader<'data>,
     environ: &mut ModuleEnvironment<'data>,
 ) -> WasmResult<()> {
     for entry in imports {
-        match entry? {
-            Import {
-                module,
-                field,
-                ty: ImportSectionEntryType::Function(sig),
-            } => {
-                // The input has already been validated, so we should be able to
-                // assume valid UTF-8 and use `from_utf8_unchecked` if performance
-                // becomes a concern here.
-                let module_name = from_utf8(module).unwrap();
-                let field_name = from_utf8(field).unwrap();
+        let import = entry?;
+
+        // The input has already been validated, so we should be able to
+        // assume valid UTF-8 and use `from_utf8_unchecked` if performance
+        // becomes a concern here.
+        let module_name = from_utf8(import.module).unwrap();
+        let field_name = from_utf8(import.field).unwrap();
+
+        match import.ty {
+            ImportSectionEntryType::Function(sig) => {
                 environ.declare_func_import(
                     SignatureIndex::new(sig as usize),
                     module_name,
                     field_name,
                 );
             }
-            Import {
-                ty:
-                    ImportSectionEntryType::Memory(MemoryType {
-                        limits: ref memlimits,
+            ImportSectionEntryType::Memory(MemoryType {
+                limits: ref memlimits,
+                shared,
+            }) => {
+                environ.declare_memory_import(
+                    Memory {
+                        pages_count: memlimits.initial as usize,
+                        maximum: memlimits.maximum.map(|x| x as usize),
                         shared,
-                    }),
-                ..
-            } => {
-                environ.declare_memory(Memory {
-                    pages_count: memlimits.initial as usize,
-                    maximum: memlimits.maximum.map(|x| x as usize),
-                    shared,
-                });
+                    },
+                    module_name,
+                    field_name,
+                );
             }
-            Import {
-                ty: ImportSectionEntryType::Global(ref ty),
-                ..
-            } => {
-                environ.declare_global(Global {
-                    ty: type_to_type(ty.content_type).unwrap(),
-                    mutability: ty.mutable,
-                    initializer: GlobalInit::Import(),
-                });
+            ImportSectionEntryType::Global(ref ty) => {
+                environ.declare_global_import(
+                    Global {
+                        ty: type_to_type(ty.content_type).unwrap(),
+                        mutability: ty.mutable,
+                        initializer: GlobalInit::Import(),
+                    },
+                    module_name,
+                    field_name,
+                );
             }
-            Import {
-                ty: ImportSectionEntryType::Table(ref tab),
-                ..
-            } => environ.declare_table(Table {
-                ty: match type_to_type(tab.element_type) {
-                    Ok(t) => TableElementType::Val(t),
-                    Err(()) => TableElementType::Func(),
-                },
-                size: tab.limits.initial as usize,
-                maximum: tab.limits.maximum.map(|x| x as usize),
-            }),
+            ImportSectionEntryType::Table(ref tab) => {
+                environ.declare_table_import(
+                    Table {
+                        ty: match type_to_type(tab.element_type) {
+                            Ok(t) => TableElementType::Val(t),
+                            Err(()) => TableElementType::Func(),
+                        },
+                        size: tab.limits.initial as usize,
+                        maximum: tab.limits.maximum.map(|x| x as usize),
+                    },
+                    module_name,
+                    field_name,
+                );
+            }
         }
     }
     Ok(())
 }
 
 /// Parses the Function section of the wasm module.
 pub fn parse_function_section(
     functions: FunctionSectionReader,
--- a/third_party/rust/cranelift-wasm/src/translation_utils.rs
+++ b/third_party/rust/cranelift-wasm/src/translation_utils.rs
@@ -8,16 +8,31 @@ use wasmparser;
 pub struct FuncIndex(u32);
 entity_impl!(FuncIndex);
 
 /// Index type of a defined function inside the WebAssembly module.
 #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
 pub struct DefinedFuncIndex(u32);
 entity_impl!(DefinedFuncIndex);
 
+/// Index type of a defined table inside the WebAssembly module.
+#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
+pub struct DefinedTableIndex(u32);
+entity_impl!(DefinedTableIndex);
+
+/// Index type of a defined memory inside the WebAssembly module.
+#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
+pub struct DefinedMemoryIndex(u32);
+entity_impl!(DefinedMemoryIndex);
+
+/// Index type of a defined global inside the WebAssembly module.
+#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
+pub struct DefinedGlobalIndex(u32);
+entity_impl!(DefinedGlobalIndex);
+
 /// Index type of a table (imported or defined) inside the WebAssembly module.
 #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
 pub struct TableIndex(u32);
 entity_impl!(TableIndex);
 
 /// Index type of a global variable (imported or defined) inside the WebAssembly module.
 #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
 pub struct GlobalIndex(u32);
--- a/third_party/rust/wasmparser/.cargo-checksum.json
+++ b/third_party/rust/wasmparser/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{"Cargo.toml":"bfb9c0686d78c97a864c39d8d5015e779547ce2c15188fa849a6d9b6a552a5e7","LICENSE":"a6c48161a09acc75a0e25503bab66a731eb5fba5392ed4bb4743e4ba5085327a","README.md":"4d883e8917a348973ce29f668182d9443d6ef61c258e5e37107609d20e9adeb6","examples/dump.rs":"b0a4fbc3dd85df85f5eca39861b09f89716c55ff97657e7a32cf6fdee7a88e60","examples/simple.rs":"9726621cd8314ed3c7e293913b06847208ff98e43e1b4d5c79708a7b71c7a768","format-all.sh":"6b02a40629ef3d2c0b9671222582a6217d526317a41262ae06c7a95de53bcbeb","src/binary_reader.rs":"ef4abddea226c624b50cd892ca16fad0423f7af99112deb7ba4f7ae18c3b6f94","src/lib.rs":"04185314f9e61975eb507638c85b0f399f87bc4cf994dd91fd9e73a569dddfb3","src/limits.rs":"2cf22e266c2828d68bb521485b8bd604a2ecb7a023204d7874b3da5837ec44f9","src/parser.rs":"ffb9a83926b8d8f2837d295b4ef0c5c51a3fa905c5b9e80a0b3bd1da50eb612c","src/primitives.rs":"32d3662d7473bc770bcb14a2878ce9d21a00635d928ee142ae4bdbfbb741b159","src/readers/code_section.rs":"7ded16c3e703d71d71b384629488aaa050d0f9b4d419a78eaef8ef481be4b4f3","src/readers/data_section.rs":"74e751ea3cecbe29eb6d6b1b0119f859a5aec1a3240c4a71c381e7409378fa45","src/readers/element_section.rs":"b8f2e367b08f0a7097a9eece6a27e7170c175a13c007b7c4cb3517fa81250ff4","src/readers/export_section.rs":"dc11c96c4955cf18d1fdd50c2a6dddabd915c0ee8fc998e12130b534c9c2b621","src/readers/function_section.rs":"57c0479ba8d7f61908ed74e86cbc26553fdd6d2d952f032ce29385a39f82efd3","src/readers/global_section.rs":"5fa18bed0fffadcc2dbdcbaedbe4e4398992fd1ce9e611b0319333a7681082ac","src/readers/import_section.rs":"4dc8ec40c237c30b951bb31a7150a5159430e01d62c91d58ef4922bec65b0f6a","src/readers/init_expr.rs":"7020c80013dad4518a5f969c3ab4d624b46d778f03e632871cf343964f63441c","src/readers/linking_section.rs":"9df71f3ee5356f0d273c099212213353080001e261ca697caddf6b847fb5af09","src/readers/memory_section.rs":"83212f86cfc40d18fb392e9234c880afdf443f4af38a727ba346f9c740ef8718","src/readers/mod.rs":"15d15305ba1c3cfee3107c5119b12853803a2257ac533be9b58adcf51623d4b8","src/readers/module.rs":"8eb1d05e7cf7393f5c10272123e3aa3fd18fb4ada648014ff519555d08450915","src/readers/name_section.rs":"e61633a3a43f4626f15cd85d53f66a5e2bab0f016658ca792b0c94574f84b57c","src/readers/operators.rs":"f9f5fee7405c332439b4bd3b594f7fd58b08842a9db8752a7734023bfe4dec4a","src/readers/reloc_section.rs":"0ef818a8b83a4542c4c29c23642436a92d3e7c37bc0248e817ed5a9d65ec38ce","src/readers/section_reader.rs":"3d2260449fa0455d710ba6d97810372ec36cba70722c10dd236c3a18ca0eb56f","src/readers/sourcemappingurl_section.rs":"742602c2537ba3ed50f830b1929fe2d19bb68ea04ddb59f77dc47109e84f262a","src/readers/start_section.rs":"3eeae00e1aa0fcb2e0d93b7b0eaac30a60d3f1431c71c589cd3f73adb363d532","src/readers/table_section.rs":"e564876825a7b31df2b5dc850279b523e26dc50a08da935cc8d635a49e809951","src/readers/type_section.rs":"2fa33a7b793f3bfa01c259b5dbc38633b7343931886ab41f0cb96dd78db3bf6e","src/tests.rs":"1f6353bd3fdd6f0e004ce440bfbe454bec0c6cffa8bacf1b777cdca690cbdd6a","src/validator.rs":"51410deced9a051767b98891ac304c300ec651f4848df6d02985b3b329b505c3","test-all.sh":"ff894f4e5e34389ad6ef697bd4ade28a2483dd456eabba8b757945546568f4c9","test-no_std.sh":"f8bc939b378fe618b7ec6297152708e7c8740858eb94e5756464934a38796b8c"},"package":"202e4cd4d99aa8adb8fe6280e099fdd2e5003c8d09c27de6969ff04dba60ef39"}
\ No newline at end of file
+{"files":{"Cargo.toml":"4c26a23166e9aedf319c9e0175e2be495718d44dd78816582d429377b63c6dc5","LICENSE":"a6c48161a09acc75a0e25503bab66a731eb5fba5392ed4bb4743e4ba5085327a","README.md":"13ea373a411dfa7371cd994736289bb000db51957da92315fecbcc9fe7dcab92","examples/dump.rs":"b0a4fbc3dd85df85f5eca39861b09f89716c55ff97657e7a32cf6fdee7a88e60","examples/simple.rs":"9726621cd8314ed3c7e293913b06847208ff98e43e1b4d5c79708a7b71c7a768","format-all.sh":"6b02a40629ef3d2c0b9671222582a6217d526317a41262ae06c7a95de53bcbeb","src/binary_reader.rs":"d6b0dd34c2a97babae84d1758df75515de372c5228450267141ebbad402c8acd","src/lib.rs":"44d30e30e2b844bcb1d048c5adcaf1057326f7b9b042824631020fbf128d0669","src/limits.rs":"2cf22e266c2828d68bb521485b8bd604a2ecb7a023204d7874b3da5837ec44f9","src/parser.rs":"8f29497795ef8b93134680ff9cb38dbb4f0520ceba270c1d6cee22694362b270","src/primitives.rs":"32d3662d7473bc770bcb14a2878ce9d21a00635d928ee142ae4bdbfbb741b159","src/readers/code_section.rs":"d71a798dce497838c8d6b3aa9744a2cae818b7aff99d45a31a4accb892985fd1","src/readers/data_section.rs":"74e751ea3cecbe29eb6d6b1b0119f859a5aec1a3240c4a71c381e7409378fa45","src/readers/element_section.rs":"b8f2e367b08f0a7097a9eece6a27e7170c175a13c007b7c4cb3517fa81250ff4","src/readers/export_section.rs":"dc11c96c4955cf18d1fdd50c2a6dddabd915c0ee8fc998e12130b534c9c2b621","src/readers/function_section.rs":"57c0479ba8d7f61908ed74e86cbc26553fdd6d2d952f032ce29385a39f82efd3","src/readers/global_section.rs":"5fa18bed0fffadcc2dbdcbaedbe4e4398992fd1ce9e611b0319333a7681082ac","src/readers/import_section.rs":"4dc8ec40c237c30b951bb31a7150a5159430e01d62c91d58ef4922bec65b0f6a","src/readers/init_expr.rs":"7020c80013dad4518a5f969c3ab4d624b46d778f03e632871cf343964f63441c","src/readers/linking_section.rs":"9df71f3ee5356f0d273c099212213353080001e261ca697caddf6b847fb5af09","src/readers/memory_section.rs":"83212f86cfc40d18fb392e9234c880afdf443f4af38a727ba346f9c740ef8718","src/readers/mod.rs":"9de31285cded591651108f16b9463cee7289536c722dbcf49a33847047a82bd1","src/readers/module.rs":"31329dabf177f29b40fa53fa44b19ab545c47bae8bc1e29ef995f413f572e303","src/readers/name_section.rs":"e61633a3a43f4626f15cd85d53f66a5e2bab0f016658ca792b0c94574f84b57c","src/readers/operators.rs":"da43ee8afcb0c1d6e7f1e19e8a10143101f0c598b1e533a394c7397f43881a82","src/readers/reloc_section.rs":"0ef818a8b83a4542c4c29c23642436a92d3e7c37bc0248e817ed5a9d65ec38ce","src/readers/section_reader.rs":"3d2260449fa0455d710ba6d97810372ec36cba70722c10dd236c3a18ca0eb56f","src/readers/sourcemappingurl_section.rs":"742602c2537ba3ed50f830b1929fe2d19bb68ea04ddb59f77dc47109e84f262a","src/readers/start_section.rs":"3eeae00e1aa0fcb2e0d93b7b0eaac30a60d3f1431c71c589cd3f73adb363d532","src/readers/table_section.rs":"e564876825a7b31df2b5dc850279b523e26dc50a08da935cc8d635a49e809951","src/readers/type_section.rs":"2fa33a7b793f3bfa01c259b5dbc38633b7343931886ab41f0cb96dd78db3bf6e","src/tests.rs":"1f6353bd3fdd6f0e004ce440bfbe454bec0c6cffa8bacf1b777cdca690cbdd6a","src/validator.rs":"e55cdabb44689fa780ca639c5e287be99eef9dd203f523b769842df6310f3eb4","test-all.sh":"ff894f4e5e34389ad6ef697bd4ade28a2483dd456eabba8b757945546568f4c9","test-no_std.sh":"f8bc939b378fe618b7ec6297152708e7c8740858eb94e5756464934a38796b8c"},"package":"1b4e0f66e314a8e63ff5c3cc5103f7d0a3de9ee98bb61a960adcf7f1d9debd2f"}
\ No newline at end of file
--- a/third_party/rust/wasmparser/Cargo.toml
+++ b/third_party/rust/wasmparser/Cargo.toml
@@ -7,17 +7,17 @@
 #
 # If you believe there's an error in this file please file an
 # issue against the rust-lang/cargo repository. If you're
 # editing this file be aware that the upstream Cargo.toml
 # will likely look very different (and much more reasonable)
 
 [package]
 name = "wasmparser"
-version = "0.21.8"
+version = "0.22.0"
 authors = ["Yury Delendik <ydelendik@mozilla.com>"]
 exclude = ["fuzz/**/*", "tests/**/*"]
 description = "A simple event-driven library for parsing WebAssembly binary files.\n"
 keywords = ["parser", "WebAssembly", "wasm"]
 license = "Apache-2.0 WITH LLVM-exception"
 repository = "https://github.com/yurydelendik/wasmparser.rs"
 [dependencies.hashmap_core]
 version = "0.1.9"
--- a/third_party/rust/wasmparser/README.md
+++ b/third_party/rust/wasmparser/README.md
@@ -1,15 +1,25 @@
-# Simple wasm parser in Rust
+# The WebAssembly binary file decoder in Rust
 
 [![Build Status](https://travis-ci.org/yurydelendik/wasmparser.rs.svg?branch=master)](https://travis-ci.org/yurydelendik/wasmparser.rs)
 [![crates.io link](https://img.shields.io/crates/v/wasmparser.svg)](https://crates.io/crates/wasmparser)
 
+The decoder library provides lightwight 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.
+
 See also its sibling at https://github.com/wasdk/wasmparser
 
+
+## Documentation
+
+The documentation and examples can be found at the https://docs.rs/wasmparser/
+
+
 ## Example
 
 ```rust
 use wasmparser::WasmDecoder;
 use wasmparser::Parser;
 use wasmparser::ParserState;
 
 fn get_name(bytes: &[u8]) -> &str {
@@ -33,16 +43,17 @@ fn main() {
         }
         ParserState::EndWasm => break,
         _ => ( /* println!(" Other {:?}", state) */ )
     }
   }
 }
 ```
 
+
 ## Fuzzing
 
 To fuzz test wasmparser.rs, switch to a nightly Rust compiler and install [cargo-fuzz]:
 
 ```
 cargo install cargo-fuzz
 ```
 
--- a/third_party/rust/wasmparser/src/binary_reader.rs
+++ b/third_party/rust/wasmparser/src/binary_reader.rs
@@ -18,17 +18,17 @@ use std::vec::Vec;
 
 use limits::{
     MAX_WASM_FUNCTION_LOCALS, MAX_WASM_FUNCTION_PARAMS, MAX_WASM_FUNCTION_RETURNS,
     MAX_WASM_FUNCTION_SIZE, MAX_WASM_STRING_SIZE,
 };
 
 use primitives::{
     BinaryReaderError, BrTable, CustomSectionKind, ExternalKind, FuncType, GlobalType, Ieee32,
-    Ieee64, LinkingType, MemoryImmediate, MemoryType, NameType, Naming, Operator, RelocType,
+    Ieee64, LinkingType, MemoryImmediate, MemoryType, NameType, Operator, RelocType,
     ResizableLimits, Result, SectionCode, TableType, Type,
 };
 
 const MAX_WASM_BR_TABLE_SIZE: usize = MAX_WASM_FUNCTION_SIZE;
 
 fn is_name(name: &[u8], expected: &'static str) -> bool {
     if name.len() != expected.len() {
         return false;
@@ -60,16 +60,34 @@ const WASM_EXPERIMENTAL_VERSION: u32 = 0
 const WASM_SUPPORTED_VERSION: u32 = 0x1;
 
 pub struct SectionHeader<'a> {
     pub code: SectionCode<'a>,
     pub payload_start: usize,
     pub payload_len: usize,
 }
 
+/// Bytecode range in the WebAssembly module.
+#[derive(Debug, Copy, Clone)]
+pub struct Range {
+    pub start: usize,
+    pub end: usize,
+}
+
+impl Range {
+    pub fn new(start: usize, end: usize) -> Range {
+        assert!(start <= end);
+        Range { start, end }
+    }
+
+    pub fn slice<'a>(&self, data: &'a [u8]) -> &'a [u8] {
+        &data[self.start..self.end]
+    }
+}
+
 /// A binary reader of the WebAssembly structures and types.
 #[derive(Clone)]
 pub struct BinaryReader<'a> {
     pub(crate) buffer: &'a [u8],
     pub(crate) position: usize,
     pub(crate) original_offset: usize,
 }
 
@@ -356,33 +374,16 @@ impl<'a> BinaryReader<'a> {
             self.skip_var_32()?;
         }
         self.skip_var_32()?;
         Ok(BrTable {
             buffer: &self.buffer[start..self.position],
         })
     }
 
-    pub(crate) fn read_name_map(&mut self, limit: usize) -> Result<Box<[Naming<'a>]>> {
-        let count = self.read_var_u32()? as usize;
-        if count > limit {
-            return Err(BinaryReaderError {
-                message: "name map size is out of bound",
-                offset: self.original_position() - 1,
-            });
-        }
-        let mut result = Vec::with_capacity(count);
-        for _ in 0..count {
-            let index = self.read_var_u32()?;
-            let name = self.read_string()?;
-            result.push(Naming { index, name });
-        }
-        Ok(result.into_boxed_slice())
-    }
-
     pub fn eof(&self) -> bool {
         self.position >= self.buffer.len()
     }
 
     pub fn current_position(&self) -> usize {
         self.position
     }
 
@@ -1183,31 +1184,34 @@ impl<'a> BrTable<'a> {
     /// Reads br_table entries.
     ///
     /// # Examples
     /// ```rust
     /// let buf = vec![0x0e, 0x02, 0x01, 0x02, 0x00];
     /// let mut reader = wasmparser::BinaryReader::new(&buf);
     /// let op = reader.read_operator().unwrap();
     /// if let wasmparser::Operator::BrTable { ref table } = op {
-    ///     let br_table_depths = table.read_table();
+    ///     let br_table_depths = table.read_table().unwrap();
     ///     assert!(br_table_depths.0 == vec![1,2].into_boxed_slice() &&
     ///             br_table_depths.1 == 0);
     /// } else {
     ///     unreachable!();
     /// }
     /// ```
-    pub fn read_table(&self) -> (Box<[u32]>, u32) {
+    pub fn read_table(&self) -> Result<(Box<[u32]>, u32)> {
         let mut reader = BinaryReader::new(self.buffer);
         let mut table = Vec::new();
         while !reader.eof() {
-            table.push(reader.read_var_u32().unwrap());
+            table.push(reader.read_var_u32()?);
         }
-        let default_target = table.pop().unwrap();
-        (table.into_boxed_slice(), default_target)
+        let default_target = table.pop().ok_or_else(|| BinaryReaderError {
+            message: "br_table missing default target",
+            offset: reader.original_position(),
+        })?;
+        Ok((table.into_boxed_slice(), default_target))
     }
 }
 
 /// Iterator for `BrTable`.
 ///
 /// #Examples
 /// ```rust
 /// let buf = vec![0x0e, 0x02, 0x01, 0x02, 0x00];
@@ -1236,11 +1240,11 @@ impl<'a> IntoIterator for &'a BrTable<'a
 
 impl<'a> Iterator for BrTableIterator<'a> {
     type Item = u32;
 
     fn next(&mut self) -> Option<u32> {
         if self.reader.eof() {
             return None;
         }
-        Some(self.reader.read_var_u32().unwrap())
+        self.reader.read_var_u32().ok()
     }
 }
--- a/third_party/rust/wasmparser/src/lib.rs
+++ b/third_party/rust/wasmparser/src/lib.rs
@@ -29,24 +29,24 @@
 #[cfg(not(feature = "std"))]
 extern crate hashmap_core;
 
 #[cfg(not(feature = "std"))]
 #[macro_use]
 extern crate alloc;
 
 pub use binary_reader::BinaryReader;
+pub use binary_reader::Range;
 use binary_reader::SectionHeader;
 
 pub use parser::LocalName;
 pub use parser::NameEntry;
 pub use parser::Parser;
 pub use parser::ParserInput;
 pub use parser::ParserState;
-pub use parser::Range;
 pub use parser::RelocEntry;
 pub use parser::WasmDecoder;
 
 pub use primitives::BinaryReaderError;
 pub use primitives::BrTable;
 pub use primitives::CustomSectionKind;
 pub use primitives::ExternalKind;
 pub use primitives::FuncType;
--- a/third_party/rust/wasmparser/src/parser.rs
+++ b/third_party/rust/wasmparser/src/parser.rs
@@ -18,21 +18,29 @@ use std::boxed::Box;
 use std::vec::Vec;
 
 use limits::{
     MAX_WASM_FUNCTIONS, MAX_WASM_FUNCTION_LOCALS, MAX_WASM_STRING_SIZE, MAX_WASM_TABLE_ENTRIES,
 };
 
 use primitives::{
     BinaryReaderError, CustomSectionKind, ExternalKind, FuncType, GlobalType,
-    ImportSectionEntryType, LinkingType, MemoryType, NameType, Naming, Operator, RelocType, Result,
+    ImportSectionEntryType, LinkingType, MemoryType, Naming, Operator, RelocType, Result,
     SectionCode, TableType, Type,
 };
 
-use binary_reader::{BinaryReader, SectionHeader};
+use readers::{
+    CodeSectionReader, Data, DataSectionReader, Element, ElementItems, ElementSectionReader,
+    Export, ExportSectionReader, FunctionBody, FunctionSectionReader, Global, GlobalSectionReader,
+    Import, ImportSectionReader, LinkingSectionReader, MemorySectionReader, ModuleReader, Name,
+    NameSectionReader, NamingReader, OperatorsReader, Reloc, RelocSectionReader, Section,
+    SectionReader, TableSectionReader, TypeSectionReader,
+};
+
+use binary_reader::{BinaryReader, Range};
 
 const MAX_DATA_CHUNK_SIZE: usize = MAX_WASM_STRING_SIZE;
 
 #[derive(Debug)]
 pub struct LocalName<'a> {
     pub index: u32,
     pub locals: Box<[Naming<'a>]>,
 }
@@ -53,34 +61,16 @@ pub struct RelocEntry {
 }
 
 enum InitExpressionContinuation {
     GlobalSection,
     ElementSection,
     DataSection,
 }
 
-/// Bytecode range in the WebAssembly module.
-#[derive(Debug, Copy, Clone)]
-pub struct Range {
-    pub start: usize,
-    pub end: usize,
-}
-
-impl Range {
-    pub fn new(start: usize, end: usize) -> Range {
-        assert!(start <= end);
-        Range { start, end }
-    }
-
-    pub fn slice<'a>(&self, data: &'a [u8]) -> &'a [u8] {
-        &data[self.start..self.end]
-    }
-}
-
 #[derive(Debug)]
 pub enum ParserState<'a> {
     Error(BinaryReaderError),
     Initial,
     BeginWasm {
         version: u32,
     },
     EndWasm,
@@ -159,546 +149,721 @@ pub trait WasmDecoder<'a> {
     fn push_input(&mut self, input: ParserInput);
     fn read_with_input(&mut self, input: ParserInput) -> &ParserState<'a>;
     fn create_binary_reader<'b>(&mut self) -> BinaryReader<'b>
     where
         'a: 'b;
     fn last_state(&self) -> &ParserState<'a>;
 }
 
+enum ParserSectionReader<'a> {
+    None,
+    CodeSectionReader(CodeSectionReader<'a>),
+    DataSectionReader(DataSectionReader<'a>),
+    ElementSectionReader(ElementSectionReader<'a>),
+    ExportSectionReader(ExportSectionReader<'a>),
+    FunctionSectionReader(FunctionSectionReader<'a>),
+    GlobalSectionReader(GlobalSectionReader<'a>),
+    ImportSectionReader(ImportSectionReader<'a>),
+    MemorySectionReader(MemorySectionReader<'a>),
+    TableSectionReader(TableSectionReader<'a>),
+    TypeSectionReader(TypeSectionReader<'a>),
+    NameSectionReader(NameSectionReader<'a>),
+    LinkingSectionReader(LinkingSectionReader<'a>),
+    RelocSectionReader(RelocSectionReader<'a>),
+}
+
+macro_rules! section_reader {
+    ($self:ident, $ty_and_name:ident) => {
+        if let ParserSectionReader::$ty_and_name(ref mut reader) = $self.section_reader {
+            reader
+        } else {
+            panic!("expected {} reader", stringify!($ty_and_name));
+        }
+    };
+}
+
+macro_rules! start_section_reader {
+    ($self:ident, $ty_and_name:ident, $factory:ident) => {{
+        let reader = $self
+            .current_section
+            .as_ref()
+            .expect("section")
+            .$factory()?;
+        $self.section_entries_left = reader.get_count();
+        $self.section_reader = ParserSectionReader::$ty_and_name(reader);
+    }};
+}
+
 /// The `Parser` type. A simple event-driven parser of WebAssembly binary
 /// format. The `read(&mut self)` is used to iterate through WebAssembly records.
 pub struct Parser<'a> {
-    reader: BinaryReader<'a>,
+    data: &'a [u8],
     state: ParserState<'a>,
-    section_range: Option<Range>,
-    function_range: Option<Range>,
+    module_reader: Option<ModuleReader<'a>>,
+    current_section: Option<Section<'a>>,
+    section_reader: ParserSectionReader<'a>,
+    element_items: Option<ElementItems<'a>>,
+    current_function_body: Option<FunctionBody<'a>>,
     init_expr_continuation: Option<InitExpressionContinuation>,
-    read_data_bytes: Option<u32>,
+    current_data_segment: Option<&'a [u8]>,
+    binary_reader: Option<BinaryReader<'a>>,
+    operators_reader: Option<OperatorsReader<'a>>,
     section_entries_left: u32,
 }
 
 impl<'a> Parser<'a> {
     /// Constructs `Parser` type.
     ///
     /// # Examples
     /// ```
     /// let data: &[u8] = &[0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00,
     ///     0x01, 0x4, 0x01, 0x60, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00,
     ///     0x0a, 0x05, 0x01, 0x03, 0x00, 0x01, 0x0b];
     /// let mut parser = wasmparser::Parser::new(data);
     /// ```
     pub fn new(data: &[u8]) -> Parser {
         Parser {
-            reader: BinaryReader::new(data),
+            data,
             state: ParserState::Initial,
-            section_range: None,
-            function_range: None,
+            module_reader: None,
+            current_section: None,
+            section_reader: ParserSectionReader::None,
+            element_items: None,
+            current_function_body: None,
             init_expr_continuation: None,
-            read_data_bytes: None,
+            current_data_segment: None,
+            binary_reader: None,
+            operators_reader: None,
             section_entries_left: 0,
         }
     }
 
     pub fn eof(&self) -> bool {
-        self.reader.eof()
+        match self.state {
+            ParserState::EndWasm => true,
+            ParserState::BeginWasm { .. } | ParserState::EndSection => {
+                self.module_reader.as_ref().expect("module reader").eof()
+            }
+            _ => false, // in-process of reading
+        }
     }
 
     pub fn current_position(&self) -> usize {
-        self.reader.current_position()
+        if let ParserState::Initial = self.state {
+            return 0;
+        }
+        if self.binary_reader.is_some() {
+            return self
+                .binary_reader
+                .as_ref()
+                .expect("binary reader")
+                .original_position();
+        }
+        if self.operators_reader.is_some() {
+            return self
+                .operators_reader
+                .as_ref()
+                .expect("operators reader")
+                .original_position();
+        }
+        match self.section_reader {
+            ParserSectionReader::CodeSectionReader(ref reader) => return reader.original_position(),
+            ParserSectionReader::DataSectionReader(ref reader) => return reader.original_position(),
+            ParserSectionReader::ElementSectionReader(ref reader) => {
+                return reader.original_position()
+            }
+            ParserSectionReader::ExportSectionReader(ref reader) => {
+                return reader.original_position()
+            }
+            ParserSectionReader::FunctionSectionReader(ref reader) => {
+                return reader.original_position()
+            }
+            ParserSectionReader::GlobalSectionReader(ref reader) => {
+                return reader.original_position()
+            }
+            ParserSectionReader::ImportSectionReader(ref reader) => {
+                return reader.original_position()
+            }
+            ParserSectionReader::MemorySectionReader(ref reader) => {
+                return reader.original_position()
+            }
+            ParserSectionReader::TableSectionReader(ref reader) => {
+                return reader.original_position()
+            }
+            ParserSectionReader::TypeSectionReader(ref reader) => return reader.original_position(),
+            ParserSectionReader::NameSectionReader(ref reader) => return reader.original_position(),
+            ParserSectionReader::LinkingSectionReader(ref reader) => {
+                return reader.original_position()
+            }
+            ParserSectionReader::RelocSectionReader(ref reader) => {
+                return reader.original_position()
+            }
+            _ => (),
+        };
+        // TODO might not cover all cases
+        self.module_reader
+            .as_ref()
+            .expect("module reader")
+            .current_position()
     }
 
-    fn read_header(&mut self) -> Result<()> {
-        let version = self.reader.read_file_header()?;
+    fn read_module(&mut self) -> Result<()> {
+        let module_reader = ModuleReader::new(self.data)?;
+        let version = module_reader.get_version();
+        self.module_reader = Some(module_reader);
         self.state = ParserState::BeginWasm { version };
         Ok(())
     }
 
     fn read_section_header(&mut self) -> Result<()> {
-        let SectionHeader {
-            code,
-            payload_start,
-            payload_len,
-        } = self.reader.read_section_header()?;
-        let payload_end = payload_start + payload_len;
-        if self.reader.buffer.len() < payload_end {
-            return Err(BinaryReaderError {
-                message: "Section body extends past end of file",
-                offset: self.reader.buffer.len(),
-            });
-        }
-        if self.reader.position > payload_end {
-            return Err(BinaryReaderError {
-                message: "Section header is too big to fit into section body",
-                offset: payload_end,
-            });
-        }
-        let range = Range {
-            start: self.reader.position,
-            end: payload_end,
-        };
+        let section = self.module_reader.as_mut().expect("module reader").read()?;
+        let code = section.code;
+        let range = section.get_range();
+        self.current_section = Some(section);
         self.state = ParserState::BeginSection { code, range };
-        self.section_range = Some(range);
         Ok(())
     }
 
     fn read_type_entry(&mut self) -> Result<()> {
         if self.section_entries_left == 0 {
-            return self.position_to_section_end();
+            return self.check_section_end();
         }
-        self.state = ParserState::TypeSectionEntry(self.reader.read_func_type()?);
+        let type_entry = section_reader!(self, TypeSectionReader).read()?;
+        self.state = ParserState::TypeSectionEntry(type_entry);
         self.section_entries_left -= 1;
         Ok(())
     }
 
     fn read_import_entry(&mut self) -> Result<()> {
         if self.section_entries_left == 0 {
-            return self.position_to_section_end();
+            return self.check_section_end();
         }
-        let module = self.reader.read_string()?;
-        let field = self.reader.read_string()?;
-        let kind = self.reader.read_external_kind()?;
-        let ty: ImportSectionEntryType;
-        match kind {
-            ExternalKind::Function => {
-                ty = ImportSectionEntryType::Function(self.reader.read_var_u32()?)
-            }
-            ExternalKind::Table => {
-                ty = ImportSectionEntryType::Table(self.reader.read_table_type()?)
-            }
-            ExternalKind::Memory => {
-                ty = ImportSectionEntryType::Memory(self.reader.read_memory_type()?)
-            }
-            ExternalKind::Global => {
-                ty = ImportSectionEntryType::Global(self.reader.read_global_type()?)
-            }
-        }
-
+        let Import { module, field, ty } = section_reader!(self, ImportSectionReader).read()?;
         self.state = ParserState::ImportSectionEntry { module, field, ty };
         self.section_entries_left -= 1;
         Ok(())
     }
 
     fn read_function_entry(&mut self) -> Result<()> {
         if self.section_entries_left == 0 {
-            return self.position_to_section_end();
+            return self.check_section_end();
         }
-        self.state = ParserState::FunctionSectionEntry(self.reader.read_var_u32()?);
+        let func_type = section_reader!(self, FunctionSectionReader).read()?;
+        self.state = ParserState::FunctionSectionEntry(func_type);
         self.section_entries_left -= 1;
         Ok(())
     }
 
     fn read_memory_entry(&mut self) -> Result<()> {
         if self.section_entries_left == 0 {
-            return self.position_to_section_end();
+            return self.check_section_end();
         }
-        self.state = ParserState::MemorySectionEntry(self.reader.read_memory_type()?);
+        let memory_type = section_reader!(self, MemorySectionReader).read()?;
+        self.state = ParserState::MemorySectionEntry(memory_type);
         self.section_entries_left -= 1;
         Ok(())
     }
 
     fn read_global_entry(&mut self) -> Result<()> {
         if self.section_entries_left == 0 {
-            return self.position_to_section_end();
+            return self.check_section_end();
         }
-        self.state = ParserState::BeginGlobalSectionEntry(self.reader.read_global_type()?);
+        let Global { ty, init_expr } = section_reader!(self, GlobalSectionReader).read()?;
+        self.state = ParserState::BeginGlobalSectionEntry(ty);
+        self.operators_reader = Some(init_expr.get_operators_reader());
         self.section_entries_left -= 1;
         Ok(())
     }
 
     fn read_init_expression_body(&mut self, cont: InitExpressionContinuation) {
         self.state = ParserState::BeginInitExpressionBody;
         self.init_expr_continuation = Some(cont);
     }
 
     fn read_init_expression_operator(&mut self) -> Result<()> {
-        let op = self.reader.read_operator()?;
+        let op = self
+            .operators_reader
+            .as_mut()
+            .expect("operator reader")
+            .read()?;
         if let Operator::End = op {
+            self.operators_reader = None;
             self.state = ParserState::EndInitExpressionBody;
             return Ok(());
         }
         self.state = ParserState::InitExpressionOperator(op);
         Ok(())
     }
 
     fn read_export_entry(&mut self) -> Result<()> {
         if self.section_entries_left == 0 {
-            return self.position_to_section_end();
+            return self.check_section_end();
         }
-        let field = self.reader.read_string()?;
-        let kind = self.reader.read_external_kind()?;
-        let index = self.reader.read_var_u32()?;
+        let Export { field, kind, index } = section_reader!(self, ExportSectionReader).read()?;
         self.state = ParserState::ExportSectionEntry { field, kind, index };
         self.section_entries_left -= 1;
         Ok(())
     }
 
     fn read_element_entry(&mut self) -> Result<()> {
         if self.section_entries_left == 0 {
-            return self.position_to_section_end();
+            return self.check_section_end();
         }
-        self.state = ParserState::BeginElementSectionEntry(self.reader.read_var_u32()?);
+        let Element {
+            table_index,
+            init_expr,
+            items,
+        } = section_reader!(self, ElementSectionReader).read()?;
+        self.state = ParserState::BeginElementSectionEntry(table_index);
+        self.operators_reader = Some(init_expr.get_operators_reader());
+        self.element_items = Some(items);
         self.section_entries_left -= 1;
         Ok(())
     }
 
     fn read_element_entry_body(&mut self) -> Result<()> {
-        let num_elements = self.reader.read_var_u32()? as usize;
+        let mut reader = self
+            .element_items
+            .take()
+            .expect("element items")
+            .get_items_reader()?;
+        let num_elements = reader.get_count() as usize;
         if num_elements > MAX_WASM_TABLE_ENTRIES {
             return Err(BinaryReaderError {
                 message: "num_elements is out of bounds",
-                offset: self.reader.position - 1,
+                offset: 0, // reader.position - 1, // TODO offset
             });
         }
         let mut elements: Vec<u32> = Vec::with_capacity(num_elements);
         for _ in 0..num_elements {
-            elements.push(self.reader.read_var_u32()?);
+            elements.push(reader.read()?);
         }
         self.state = ParserState::ElementSectionEntryBody(elements.into_boxed_slice());
         Ok(())
     }
 
     fn read_function_body(&mut self) -> Result<()> {
         if self.section_entries_left == 0 {
-            return self.position_to_section_end();
+            self.current_function_body = None;
+            return self.check_section_end();
         }
-        let size = self.reader.read_var_u32()? as usize;
-        let body_end = self.reader.position + size;
-        let range = Range {
-            start: self.reader.position,
-            end: body_end,
-        };
+        let function_body = section_reader!(self, CodeSectionReader).read()?;
+        let range = function_body.get_range();
         self.state = ParserState::BeginFunctionBody { range };
-        self.function_range = Some(range);
+        self.current_function_body = Some(function_body);
         self.section_entries_left -= 1;
         Ok(())
     }
 
     fn read_function_body_locals(&mut self) -> Result<()> {
-        let local_count = self.reader.read_local_count()?;
+        let function_body = self.current_function_body.as_mut().expect("function body");
+        let mut reader = function_body.get_locals_reader()?;
+        let local_count = reader.get_count() as usize;
+        if local_count > MAX_WASM_FUNCTION_LOCALS {
+            return Err(BinaryReaderError {
+                message: "local_count is out of bounds",
+                offset: reader.original_position() - 1,
+            });
+        }
         let mut locals: Vec<(u32, Type)> = Vec::with_capacity(local_count);
-        let mut locals_total = 0;
+        let mut locals_total: usize = 0;
         for _ in 0..local_count {
-            let (count, ty) = self.reader.read_local_decl(&mut locals_total)?;
+            let (count, ty) = reader.read()?;
+            locals_total =
+                locals_total
+                    .checked_add(count as usize)
+                    .ok_or_else(|| BinaryReaderError {
+                        message: "locals_total is out of bounds",
+                        offset: reader.original_position() - 1,
+                    })?;
+            if locals_total > MAX_WASM_FUNCTION_LOCALS {
+                return Err(BinaryReaderError {
+                    message: "locals_total is out of bounds",
+                    offset: reader.original_position() - 1,
+                });
+            }
             locals.push((count, ty));
         }
+        self.operators_reader = Some(function_body.get_operators_reader()?);
         self.state = ParserState::FunctionBodyLocals {
             locals: locals.into_boxed_slice(),
         };
         Ok(())
     }
 
     fn read_code_operator(&mut self) -> Result<()> {
-        if self.reader.position >= self.function_range.unwrap().end {
+        if self
+            .operators_reader
+            .as_ref()
+            .expect("operator reader")
+            .eof()
+        {
             if let ParserState::CodeOperator(Operator::End) = self.state {
                 self.state = ParserState::EndFunctionBody;
-                self.function_range = None;
+                self.operators_reader = None;
+                self.current_function_body = None;
                 return Ok(());
             }
+            let reader = self.operators_reader.as_ref().expect("operator reader");
             return Err(BinaryReaderError {
                 message: "Expected end of function marker",
-                offset: self.function_range.unwrap().end,
+                offset: reader.original_position(),
             });
         }
-        let op = self.reader.read_operator()?;
+        let reader = self.operators_reader.as_mut().expect("operator reader");
+        let op = reader.read()?;
         self.state = ParserState::CodeOperator(op);
         Ok(())
     }
 
     fn read_table_entry(&mut self) -> Result<()> {
         if self.section_entries_left == 0 {
-            return self.position_to_section_end();
+            return self.check_section_end();
         }
-        self.state = ParserState::TableSectionEntry(self.reader.read_table_type()?);
+        let table_entry = section_reader!(self, TableSectionReader).read()?;
+        self.state = ParserState::TableSectionEntry(table_entry);
         self.section_entries_left -= 1;
         Ok(())
     }
 
     fn read_data_entry(&mut self) -> Result<()> {
         if self.section_entries_left == 0 {
-            return self.position_to_section_end();
+            return self.check_section_end();
         }
-        let index = self.reader.read_var_u32()?;
-        self.state = ParserState::BeginDataSectionEntry(index);
+        let Data {
+            memory_index,
+            init_expr,
+            data,
+        } = section_reader!(self, DataSectionReader).read()?;
+        self.state = ParserState::BeginDataSectionEntry(memory_index);
+        self.operators_reader = Some(init_expr.get_operators_reader());
+        self.current_data_segment = Some(data);
         self.section_entries_left -= 1;
         Ok(())
     }
 
     fn read_data_entry_body(&mut self) -> Result<()> {
-        let size = self.reader.read_var_u32()?;
-        self.state = ParserState::BeginDataSectionEntryBody(size);
-        self.read_data_bytes = Some(size);
+        let size = self.current_data_segment.expect("data entry").len();
+        self.state = ParserState::BeginDataSectionEntryBody(size as u32);
         Ok(())
     }
 
+    fn read_naming<'b>(
+        mut naming_reader: NamingReader<'a>,
+        limit: usize,
+    ) -> Result<Box<[Naming<'b>]>>
+    where
+        'a: 'b,
+    {
+        let count = naming_reader.get_count() as usize;
+        if count > limit {
+            return Err(BinaryReaderError {
+                message: "name map size is out of bound",
+                offset: naming_reader.original_position() - 1,
+            });
+        }
+        let mut result = Vec::with_capacity(count);
+        for _ in 0..count {
+            result.push(naming_reader.read()?);
+        }
+        Ok(result.into_boxed_slice())
+    }
+
     fn read_name_entry(&mut self) -> Result<()> {
-        if self.reader.position >= self.section_range.unwrap().end {
+        if section_reader!(self, NameSectionReader).eof() {
             return self.position_to_section_end();
         }
-        let ty = self.reader.read_name_type()?;
-        self.reader.read_var_u32()?; // payload_len
-        let entry = match ty {
-            NameType::Module => NameEntry::Module(self.reader.read_string()?),
-            NameType::Function => {
-                NameEntry::Function(self.reader.read_name_map(MAX_WASM_FUNCTIONS)?)
+        let entry = match section_reader!(self, NameSectionReader).read()? {
+            Name::Module(name) => NameEntry::Module(name.get_name()?),
+            Name::Function(func) => {
+                NameEntry::Function(Self::read_naming(func.get_map()?, MAX_WASM_FUNCTIONS)?)
             }
-            NameType::Local => {
-                let funcs_len = self.reader.read_var_u32()? as usize;
+            Name::Local(locals) => {
+                let mut reader = locals.get_function_local_reader()?;
+                let funcs_len = reader.get_count() as usize;
                 if funcs_len > MAX_WASM_FUNCTIONS {
                     return Err(BinaryReaderError {
                         message: "function count is out of bounds",
-                        offset: self.reader.position - 1,
+                        offset: reader.original_position() - 1,
                     });
                 }
                 let mut funcs: Vec<LocalName<'a>> = Vec::with_capacity(funcs_len);
                 for _ in 0..funcs_len {
+                    let func = reader.read()?;
                     funcs.push(LocalName {
-                        index: self.reader.read_var_u32()?,
-                        locals: self.reader.read_name_map(MAX_WASM_FUNCTION_LOCALS)?,
+                        index: func.func_index,
+                        locals: Self::read_naming(func.get_map()?, MAX_WASM_FUNCTION_LOCALS)?,
                     });
                 }
                 NameEntry::Local(funcs.into_boxed_slice())
             }
         };
         self.state = ParserState::NameSectionEntry(entry);
         Ok(())
     }
 
     fn read_source_mapping(&mut self) -> Result<()> {
-        self.state = ParserState::SourceMappingURL(self.reader.read_string()?);
+        let url = self
+            .current_section
+            .as_ref()
+            .expect("section")
+            .get_sourcemappingurl_section_content()?;
+        self.state = ParserState::SourceMappingURL(url);
         Ok(())
     }
 
     // See https://github.com/WebAssembly/tool-conventions/blob/master/Linking.md
     fn read_reloc_header(&mut self) -> Result<()> {
-        let section_id_position = self.reader.position;
-        let section_id = self.reader.read_var_u7()?;
-        let section_code = self
-            .reader
-            .read_section_code(section_id, section_id_position)?;
+        let section_code = section_reader!(self, RelocSectionReader).get_section_code();
         self.state = ParserState::RelocSectionHeader(section_code);
         Ok(())
     }
 
     fn read_reloc_entry(&mut self) -> Result<()> {
         if self.section_entries_left == 0 {
-            return self.position_to_section_end();
+            return self.check_section_end();
         }
-        let ty = self.reader.read_reloc_type()?;
-        let offset = self.reader.read_var_u32()?;
-        let index = self.reader.read_var_u32()?;
-        let addend = match ty {
-            RelocType::FunctionIndexLEB
-            | RelocType::TableIndexSLEB
-            | RelocType::TableIndexI32
-            | RelocType::TypeIndexLEB
-            | RelocType::GlobalIndexLEB => None,
-            RelocType::GlobalAddrLEB | RelocType::GlobalAddrSLEB | RelocType::GlobalAddrI32 => {
-                Some(self.reader.read_var_u32()?)
-            }
-        };
+        let Reloc {
+            ty,
+            offset,
+            index,
+            addend,
+        } = section_reader!(self, RelocSectionReader).read()?;
         self.state = ParserState::RelocSectionEntry(RelocEntry {
             ty,
             offset,
             index,
             addend,
         });
         self.section_entries_left -= 1;
         Ok(())
     }
 
     fn read_linking_entry(&mut self) -> Result<()> {
         if self.section_entries_left == 0 {
-            return self.position_to_section_end();
+            return self.check_section_end();
         }
-        let entry = self.reader.read_linking_type()?;
+        let entry = section_reader!(self, LinkingSectionReader).read()?;
         self.state = ParserState::LinkingSectionEntry(entry);
         self.section_entries_left -= 1;
         Ok(())
     }
 
     fn read_section_body(&mut self) -> Result<()> {
         match self.state {
             ParserState::BeginSection {
                 code: SectionCode::Type,
                 ..
             } => {
-                self.section_entries_left = self.reader.read_var_u32()?;
+                start_section_reader!(self, TypeSectionReader, get_type_section_reader);
                 self.read_type_entry()?;
             }
             ParserState::BeginSection {
                 code: SectionCode::Import,
                 ..
             } => {
-                self.section_entries_left = self.reader.read_var_u32()?;
+                start_section_reader!(self, ImportSectionReader, get_import_section_reader);
                 self.read_import_entry()?;
             }
             ParserState::BeginSection {
                 code: SectionCode::Function,
                 ..
             } => {
-                self.section_entries_left = self.reader.read_var_u32()?;
+                start_section_reader!(self, FunctionSectionReader, get_function_section_reader);
                 self.read_function_entry()?;
             }
             ParserState::BeginSection {
                 code: SectionCode::Memory,
                 ..
             } => {
-                self.section_entries_left = self.reader.read_var_u32()?;
+                start_section_reader!(self, MemorySectionReader, get_memory_section_reader);
                 self.read_memory_entry()?;
             }
             ParserState::BeginSection {
                 code: SectionCode::Global,
                 ..
             } => {
-                self.section_entries_left = self.reader.read_var_u32()?;
+                start_section_reader!(self, GlobalSectionReader, get_global_section_reader);
                 self.read_global_entry()?;
             }
             ParserState::BeginSection {
                 code: SectionCode::Export,
                 ..
             } => {
-                self.section_entries_left = self.reader.read_var_u32()?;
+                start_section_reader!(self, ExportSectionReader, get_export_section_reader);
                 self.read_export_entry()?;
             }
             ParserState::BeginSection {
                 code: SectionCode::Element,
                 ..
             } => {
-                self.section_entries_left = self.reader.read_var_u32()?;
+                start_section_reader!(self, ElementSectionReader, get_element_section_reader);
                 self.read_element_entry()?;
             }
             ParserState::BeginSection {
                 code: SectionCode::Code,
                 ..
             } => {
-                self.section_entries_left = self.reader.read_var_u32()?;
+                start_section_reader!(self, CodeSectionReader, get_code_section_reader);
                 self.read_function_body()?;
             }
             ParserState::BeginSection {
                 code: SectionCode::Table,
                 ..
             } => {
-                self.section_entries_left = self.reader.read_var_u32()?;
+                start_section_reader!(self, TableSectionReader, get_table_section_reader);
                 self.read_table_entry()?;
             }
             ParserState::BeginSection {
                 code: SectionCode::Data,
                 ..
             } => {
-                self.section_entries_left = self.reader.read_var_u32()?;
+                start_section_reader!(self, DataSectionReader, get_data_section_reader);
                 self.read_data_entry()?;
             }
             ParserState::BeginSection {
                 code: SectionCode::Start,
                 ..
             } => {
-                self.state = ParserState::StartSectionEntry(self.reader.read_var_u32()?);
+                let func_index = self
+                    .current_section
+                    .as_ref()
+                    .expect("section")
+                    .get_start_section_content()?;
+                self.state = ParserState::StartSectionEntry(func_index);
             }
             ParserState::BeginSection {
                 code: SectionCode::Custom { .. },
                 ..
             } => {
+                self.create_custom_section_binary_reader();
                 self.read_section_body_bytes()?;
             }
             _ => unreachable!(),
         }
         Ok(())
     }
 
+    fn create_custom_section_binary_reader(&mut self) {
+        let reader = self
+            .current_section
+            .as_ref()
+            .expect("section")
+            .get_binary_reader();
+        self.binary_reader = Some(reader);
+    }
+
     fn read_custom_section_body(&mut self) -> Result<()> {
         match self.state {
             ParserState::ReadingCustomSection(CustomSectionKind::Name) => {
+                let reader = self
+                    .current_section
+                    .as_ref()
+                    .expect("section")
+                    .get_name_section_reader()?;
+                self.section_reader = ParserSectionReader::NameSectionReader(reader);
                 self.read_name_entry()?;
             }
             ParserState::ReadingCustomSection(CustomSectionKind::SourceMappingURL) => {
                 self.read_source_mapping()?;
             }
             ParserState::ReadingCustomSection(CustomSectionKind::Reloc) => {
+                start_section_reader!(self, RelocSectionReader, get_reloc_section_reader);
                 self.read_reloc_header()?;
             }
             ParserState::ReadingCustomSection(CustomSectionKind::Linking) => {
-                self.section_entries_left = self.reader.read_var_u32()?;
+                start_section_reader!(self, LinkingSectionReader, get_linking_section_reader);
                 self.read_linking_entry()?;
             }
             ParserState::ReadingCustomSection(CustomSectionKind::Unknown) => {
+                self.create_custom_section_binary_reader();
                 self.read_section_body_bytes()?;
             }
             _ => unreachable!(),
         }
         Ok(())
     }
 
-    fn ensure_reader_position_in_section_range(&self) -> Result<()> {
-        if self.section_range.unwrap().end < self.reader.position {
-            return Err(BinaryReaderError {
-                message: "Position past the section end",
-                offset: self.section_range.unwrap().end,
-            });
-        }
-        Ok(())
-    }
-
     fn position_to_section_end(&mut self) -> Result<()> {
-        self.ensure_reader_position_in_section_range()?;
-        self.reader.skip_to(self.section_range.unwrap().end);
-        self.section_range = None;
+        self.current_section = None;
+        self.binary_reader = None;
         self.state = ParserState::EndSection;
         Ok(())
     }
 
+    fn check_section_end(&mut self) -> Result<()> {
+        match self.section_reader {
+            ParserSectionReader::CodeSectionReader(ref reader) => reader.ensure_end()?,
+            ParserSectionReader::DataSectionReader(ref reader) => reader.ensure_end()?,
+            ParserSectionReader::ElementSectionReader(ref reader) => reader.ensure_end()?,
+            ParserSectionReader::ExportSectionReader(ref reader) => reader.ensure_end()?,
+            ParserSectionReader::FunctionSectionReader(ref reader) => reader.ensure_end()?,
+            ParserSectionReader::GlobalSectionReader(ref reader) => reader.ensure_end()?,
+            ParserSectionReader::ImportSectionReader(ref reader) => reader.ensure_end()?,
+            ParserSectionReader::MemorySectionReader(ref reader) => reader.ensure_end()?,
+            ParserSectionReader::TableSectionReader(ref reader) => reader.ensure_end()?,
+            ParserSectionReader::TypeSectionReader(ref reader) => reader.ensure_end()?,
+            ParserSectionReader::LinkingSectionReader(ref reader) => reader.ensure_end()?,
+            ParserSectionReader::RelocSectionReader(ref reader) => reader.ensure_end()?,
+            _ => unreachable!(),
+        }
+        self.position_to_section_end()
+    }
+
     fn read_section_body_bytes(&mut self) -> Result<()> {
-        self.ensure_reader_position_in_section_range()?;
-        if self.section_range.unwrap().end == self.reader.position {
+        if self.binary_reader.as_ref().expect("binary reader").eof() {
             self.state = ParserState::EndSection;
-            self.section_range = None;
+            self.binary_reader = None;
             return Ok(());
         }
-        let to_read =
-            if self.section_range.unwrap().end - self.reader.position < MAX_DATA_CHUNK_SIZE {
-                self.section_range.unwrap().end - self.reader.position
-            } else {
-                MAX_DATA_CHUNK_SIZE
-            };
-        let bytes = self.reader.read_bytes(to_read)?;
+        let binary_reader = self.binary_reader.as_mut().expect("binary reader");
+        let to_read = if binary_reader.buffer.len() - binary_reader.position < MAX_DATA_CHUNK_SIZE {
+            binary_reader.buffer.len() - binary_reader.position
+        } else {
+            MAX_DATA_CHUNK_SIZE
+        };
+        let bytes = binary_reader.read_bytes(to_read)?;
         self.state = ParserState::SectionRawData(bytes);
         Ok(())
     }
 
     fn read_data_chunk(&mut self) -> Result<()> {
-        if self.read_data_bytes.unwrap() == 0 {
+        let data = self.current_data_segment.expect("data");
+        if data.len() == 0 {
             self.state = ParserState::EndDataSectionEntryBody;
-            self.read_data_bytes = None;
+            self.current_data_segment = None;
             return Ok(());
         }
-        let to_read = if self.read_data_bytes.unwrap() as usize > MAX_DATA_CHUNK_SIZE {
+        let to_read = if data.len() > MAX_DATA_CHUNK_SIZE {
             MAX_DATA_CHUNK_SIZE
         } else {
-            self.read_data_bytes.unwrap() as usize
+            data.len()
         };
-        let chunk = self.reader.read_bytes(to_read)?;
-        *self.read_data_bytes.as_mut().unwrap() -= to_read as u32;
-        self.state = ParserState::DataSectionEntryBodyChunk(chunk);
+        let (head, tail) = data.split_at(to_read);
+        self.current_data_segment = Some(tail);
+        self.state = ParserState::DataSectionEntryBodyChunk(head);
         Ok(())
     }
 
     fn read_next_section(&mut self) -> Result<()> {
-        if self.reader.eof() {
+        if self.module_reader.as_ref().expect("module_reader").eof() {
+            self.current_section = None;
             self.state = ParserState::EndWasm;
         } else {
             self.read_section_header()?;
         }
         Ok(())
     }
 
     fn read_wrapped(&mut self) -> Result<()> {
         match self.state {
             ParserState::EndWasm => panic!("Parser in end state"),
             ParserState::Error(_) => panic!("Parser in error state"),
-            ParserState::Initial => self.read_header()?,
+            ParserState::Initial => self.read_module()?,
             ParserState::BeginWasm { .. } | ParserState::EndSection => self.read_next_section()?,
             ParserState::BeginSection { .. } => self.read_section_body()?,
             ParserState::SkippingSection => {
                 self.position_to_section_end()?;
                 self.read_next_section()?;
             }
             ParserState::TypeSectionEntry(_) => self.read_type_entry()?,
             ParserState::ImportSectionEntry { .. } => self.read_import_entry()?,
@@ -733,36 +898,40 @@ impl<'a> Parser<'a> {
                 self.init_expr_continuation = None;
             }
             ParserState::BeginFunctionBody { .. } => self.read_function_body_locals()?,
             ParserState::FunctionBodyLocals { .. } | ParserState::CodeOperator(_) => {
                 self.read_code_operator()?
             }
             ParserState::EndFunctionBody => self.read_function_body()?,
             ParserState::SkippingFunctionBody => {
-                assert!(self.reader.position <= self.function_range.unwrap().end);
-                self.reader.skip_to(self.function_range.unwrap().end);
-                self.function_range = None;
+                self.current_function_body = None;
                 self.read_function_body()?;
             }
             ParserState::EndDataSectionEntry => self.read_data_entry()?,
             ParserState::BeginDataSectionEntryBody(_)
             | ParserState::DataSectionEntryBodyChunk(_) => self.read_data_chunk()?,
             ParserState::EndDataSectionEntryBody => {
                 self.state = ParserState::EndDataSectionEntry;
             }
             ParserState::ElementSectionEntryBody(_) => {
                 self.state = ParserState::EndElementSectionEntry;
             }
             ParserState::EndElementSectionEntry => self.read_element_entry()?,
             ParserState::StartSectionEntry(_) => self.position_to_section_end()?,
             ParserState::NameSectionEntry(_) => self.read_name_entry()?,
             ParserState::SourceMappingURL(_) => self.position_to_section_end()?,
             ParserState::RelocSectionHeader(_) => {
-                self.section_entries_left = self.reader.read_var_u32()?;
+                let mut reader = self
+                    .current_section
+                    .as_ref()
+                    .expect("section")
+                    .get_binary_reader();
+                self.section_entries_left = reader.read_var_u32()?;
+                self.binary_reader = Some(reader);
                 self.read_reloc_entry()?;
             }
             ParserState::RelocSectionEntry(_) => self.read_reloc_entry()?,
             ParserState::LinkingSectionEntry(_) => self.read_linking_entry()?,
             ParserState::ReadingCustomSection(_) => self.read_custom_section_body()?,
             ParserState::ReadingSectionRawData | ParserState::SectionRawData(_) => {
                 self.read_section_body_bytes()?
             }
@@ -799,17 +968,25 @@ impl<'a> Parser<'a> {
                 self.state = ParserState::ReadingCustomSection(kind);
             }
             _ => panic!("Invalid reader state during reading custom section"),
         }
     }
 
     fn read_raw_section_data(&mut self) {
         match self.state {
-            ParserState::BeginSection { .. } => self.state = ParserState::ReadingSectionRawData,
+            ParserState::BeginSection { .. } => {
+                self.binary_reader = Some(
+                    self.current_section
+                        .as_ref()
+                        .expect("section")
+                        .get_binary_reader(),
+                );
+                self.state = ParserState::ReadingSectionRawData;
+            }
             _ => panic!("Invalid reader state during reading raw section data"),
         }
     }
 }
 
 impl<'a> WasmDecoder<'a> for Parser<'a> {
     /// Reads next record from the WebAssembly binary data. The methods returns
     /// reference to current state of the parser. See `ParserState` num.
@@ -879,29 +1056,29 @@ impl<'a> WasmDecoder<'a> for Parser<'a> 
     ///       println!("  {:?}", op);
     ///     }
     /// }
     /// ```
     fn create_binary_reader<'b>(&mut self) -> BinaryReader<'b>
     where
         'a: 'b,
     {
-        let range;
         match self.state {
-            ParserState::BeginSection { .. } => {
-                range = self.section_range.unwrap();
-                self.skip_section();
-            }
-            ParserState::BeginFunctionBody { .. } | ParserState::FunctionBodyLocals { .. } => {
-                range = self.function_range.unwrap();
-                self.skip_function_body();
-            }
+            ParserState::BeginSection { .. } => self
+                .current_section
+                .as_ref()
+                .expect("section")
+                .get_binary_reader(),
+            ParserState::BeginFunctionBody { .. } | ParserState::FunctionBodyLocals { .. } => self
+                .current_function_body
+                .as_ref()
+                .expect("function body")
+                .get_binary_reader(),
             _ => panic!("Invalid reader state during get binary reader operation"),
-        };
-        BinaryReader::new(range.slice(self.reader.buffer))
+        }
     }
 
     /// Reads next record from the WebAssembly binary data. It also allows to
     /// control how parser will treat the next record(s). The method accepts the
     /// `ParserInput` parameter that allows e.g. to skip section or function
     /// operators. The methods returns reference to current state of the parser.
     ///
     /// # Examples
--- a/third_party/rust/wasmparser/src/readers/code_section.rs
+++ b/third_party/rust/wasmparser/src/readers/code_section.rs
@@ -9,17 +9,17 @@
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
 use super::{
-    BinaryReader, BinaryReaderError, OperatorsReader, Result, SectionIteratorLimited,
+    BinaryReader, BinaryReaderError, OperatorsReader, Range, Result, SectionIteratorLimited,
     SectionReader, SectionWithLimitedItems, Type,
 };
 
 #[derive(Debug)]
 pub struct FunctionBody<'a> {
     offset: usize,
     data: &'a [u8],
 }
@@ -58,28 +58,39 @@ impl<'a> FunctionBody<'a> {
     where
         'a: 'b,
     {
         let mut reader = BinaryReader::new_with_offset(self.data, self.offset);
         Self::skip_locals(&mut reader)?;
         let pos = reader.position;
         Ok(OperatorsReader::new(&self.data[pos..], self.offset + pos))
     }
+
+    pub(crate) fn get_range(&self) -> Range {
+        Range {
+            start: self.offset,
+            end: self.offset + self.data.len(),
+        }
+    }
 }
 
 pub struct LocalsReader<'a> {
     reader: BinaryReader<'a>,
     count: u32,
 }
 
 impl<'a> LocalsReader<'a> {
     pub fn get_count(&self) -> u32 {
         self.count
     }
 
+    pub fn original_position(&self) -> usize {
+        self.reader.original_position()
+    }
+
     pub fn read(&mut self) -> Result<(u32, Type)> {
         let count = self.reader.read_var_u32()?;
         let value_type = self.reader.read_type()?;
         Ok((count, value_type))
     }
 }
 
 pub struct CodeSectionReader<'a> {
--- a/third_party/rust/wasmparser/src/readers/mod.rs
+++ b/third_party/rust/wasmparser/src/readers/mod.rs
@@ -10,18 +10,18 @@
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
 use super::{
     BinaryReader, BinaryReaderError, CustomSectionKind, ExternalKind, FuncType, GlobalType,
-    ImportSectionEntryType, LinkingType, MemoryType, NameType, Naming, Operator, RelocType, Result,
-    SectionCode, TableType, Type,
+    ImportSectionEntryType, LinkingType, MemoryType, NameType, Naming, Operator, Range, RelocType,
+    Result, SectionCode, TableType, Type,
 };
 
 use super::SectionHeader;
 
 pub use self::code_section::CodeSectionReader;
 pub use self::code_section::FunctionBody;
 pub use self::code_section::LocalsReader;
 pub use self::data_section::Data;
--- a/third_party/rust/wasmparser/src/readers/module.rs
+++ b/third_party/rust/wasmparser/src/readers/module.rs
@@ -11,17 +11,17 @@
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
 use std::iter::{IntoIterator, Iterator};
 
 use super::{
-    BinaryReader, BinaryReaderError, CustomSectionKind, Result, SectionCode, SectionHeader,
+    BinaryReader, BinaryReaderError, CustomSectionKind, Range, Result, SectionCode, SectionHeader,
 };
 
 use super::{
     read_sourcemappingurl_section_content, read_start_section_content, CodeSectionReader,
     DataSectionReader, ElementSectionReader, ExportSectionReader, FunctionSectionReader,
     GlobalSectionReader, ImportSectionReader, LinkingSectionReader, MemorySectionReader,
     NameSectionReader, RelocSectionReader, TableSectionReader, TypeSectionReader,
 };
@@ -214,16 +214,23 @@ impl<'a> Section<'a> {
     }
 
     pub fn get_binary_reader<'b>(&self) -> BinaryReader<'b>
     where
         'a: 'b,
     {
         BinaryReader::new_with_offset(self.data, self.offset)
     }
+
+    pub(crate) fn get_range(&self) -> Range {
+        Range {
+            start: self.offset,
+            end: self.offset + self.data.len(),
+        }
+    }
 }
 
 /// Reads top-level WebAssembly file structure: header and sections.
 pub struct ModuleReader<'a> {
     reader: BinaryReader<'a>,
     version: u32,
     read_ahead: Option<(usize, SectionHeader<'a>)>,
 }
--- a/third_party/rust/wasmparser/src/readers/operators.rs
+++ b/third_party/rust/wasmparser/src/readers/operators.rs
@@ -28,32 +28,54 @@ impl<'a> OperatorsReader<'a> {
             reader: BinaryReader::new_with_offset(data, offset),
         }
     }
 
     pub fn eof(&self) -> bool {
         self.reader.eof()
     }
 
+    pub fn original_position(&self) -> usize {
+        self.reader.original_position()
+    }
+
     pub fn ensure_end(&self) -> Result<()> {
         if self.eof() {
             return Ok(());
         }
         Err(BinaryReaderError {
             message: "Unexpected data at the end of operators",
             offset: self.reader.original_position(),
         })
     }
 
     pub fn read<'b>(&mut self) -> Result<Operator<'b>>
     where
         'a: 'b,
     {
         self.reader.read_operator()
     }
+
+    pub fn into_iter_with_offsets<'b>(self) -> OperatorsIteratorWithOffsets<'b>
+    where
+        'a: 'b,
+    {
+        OperatorsIteratorWithOffsets {
+            reader: self,
+            err: false,
+        }
+    }
+
+    pub fn read_with_offset<'b>(&mut self) -> Result<(Operator<'b>, usize)>
+    where
+        'a: 'b,
+    {
+        let pos = self.reader.original_position();
+        Ok((self.read()?, pos))
+    }
 }
 
 impl<'a> IntoIterator for OperatorsReader<'a> {
     type Item = Result<Operator<'a>>;
     type IntoIter = OperatorsIterator<'a>;
 
     /// Reads content of the code section.
     ///
@@ -99,8 +121,50 @@ impl<'a> Iterator for OperatorsIterator<
         if self.err || self.reader.eof() {
             return None;
         }
         let result = self.reader.read();
         self.err = result.is_err();
         Some(result)
     }
 }
+
+pub struct OperatorsIteratorWithOffsets<'a> {
+    reader: OperatorsReader<'a>,
+    err: bool,
+}
+
+impl<'a> Iterator for OperatorsIteratorWithOffsets<'a> {
+    type Item = Result<(Operator<'a>, usize)>;
+
+    /// Reads content of the code section with offsets.
+    ///
+    /// # Examples
+    /// ```
+    /// # let data: &[u8] = &[0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00,
+    /// #     0x01, 0x4, 0x01, 0x60, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00,
+    /// #     0x0a, 0x05, 0x01, 0x03, 0x00, /* offset = 23 */ 0x01, 0x0b];
+    /// use wasmparser::{ModuleReader, Result, Operator};
+    /// let mut reader = ModuleReader::new(data).expect("module reader");
+    /// let section = reader.read().expect("type section");
+    /// let section = reader.read().expect("function section");
+    /// let section = reader.read().expect("code section");
+    /// let mut code_reader = section.get_code_section_reader().expect("code section reader");
+    /// for _ in 0..code_reader.get_count() {
+    ///     let body = code_reader.read().expect("function body");
+    ///     let mut op_reader = body.get_operators_reader().expect("op reader");
+    ///     let ops = op_reader.into_iter_with_offsets().collect::<Result<Vec<(Operator, usize)>>>().expect("ops");
+    ///     assert!(
+    ///         if let [(Operator::Nop, 23), (Operator::End, 24)] = ops.as_slice() { true } else { false },
+    ///         "found {:?}",
+    ///         ops
+    ///     );
+    /// }
+    /// ```
+    fn next(&mut self) -> Option<Self::Item> {
+        if self.err || self.reader.eof() {
+            return None;
+        }
+        let result = self.reader.read_with_offset();
+        self.err = result.is_err();
+        Some(result)
+    }
+}
--- a/third_party/rust/wasmparser/src/validator.rs
+++ b/third_party/rust/wasmparser/src/validator.rs
@@ -168,38 +168,44 @@ enum OperatorAction {
     PushBlock(Type, BlockType),
     PopBlock,
     ResetBlock,
     DeadCode,
     EndFunction,
 }
 
 impl OperatorAction {
-    fn remove_frame_stack_types(func_state: &mut FuncState, remove_count: usize) {
+    fn remove_frame_stack_types(
+        func_state: &mut FuncState,
+        remove_count: usize,
+    ) -> OperatorValidatorResult<()> {
         if remove_count == 0 {
-            return;
+            return Ok(());
         }
         let last_block = func_state.blocks.last_mut().unwrap();
         if last_block.is_stack_polymorphic() {
             let len = func_state.stack_types.len();
-            let non_polymorphic_len = len - last_block.stack_starts_at;
-            let remove_non_polymorphic = min(non_polymorphic_len, remove_count);
+            let remove_non_polymorphic = len
+                .checked_sub(last_block.stack_starts_at)
+                .ok_or("invalid block signature")?
+                .min(remove_count);
             func_state
                 .stack_types
                 .truncate(len - remove_non_polymorphic);
             let polymorphic_values = last_block.polymorphic_values.unwrap();
             let remove_polymorphic = min(remove_count - remove_non_polymorphic, polymorphic_values);
             last_block.polymorphic_values = Some(polymorphic_values - remove_polymorphic);
         } else {
             assert!(func_state.stack_types.len() >= last_block.stack_starts_at + remove_count);
             let keep = func_state.stack_types.len() - remove_count;
             func_state.stack_types.truncate(keep);
         }
+        Ok(())
     }
-    fn update(&self, func_state: &mut FuncState) {
+    fn update(&self, func_state: &mut FuncState) -> OperatorValidatorResult<()> {
         match *self {
             OperatorAction::None => (),
             OperatorAction::PushBlock(ty, block_type) => {
                 let return_types = match ty {
                     Type::EmptyBlockType => Vec::with_capacity(0),
                     _ => vec![ty],
                 };
                 if block_type == BlockType::If {
@@ -239,58 +245,59 @@ impl OperatorAction {
                 assert!(func_state.last_block().is_else_allowed);
                 let last_block = func_state.blocks.last_mut().unwrap();
                 let keep = last_block.stack_starts_at;
                 func_state.stack_types.truncate(keep);
                 last_block.is_else_allowed = false;
                 last_block.polymorphic_values = None;
             }
             OperatorAction::ChangeFrame(remove_count) => {
-                OperatorAction::remove_frame_stack_types(func_state, remove_count);
+                OperatorAction::remove_frame_stack_types(func_state, remove_count)?
             }
             OperatorAction::ChangeFrameWithType(remove_count, ty) => {
-                OperatorAction::remove_frame_stack_types(func_state, remove_count);
+                OperatorAction::remove_frame_stack_types(func_state, remove_count)?;
                 func_state.stack_types.push(ty);
             }
             OperatorAction::ChangeFrameWithTypes(remove_count, ref new_items) => {
-                OperatorAction::remove_frame_stack_types(func_state, remove_count);
+                OperatorAction::remove_frame_stack_types(func_state, remove_count)?;
                 if new_items.is_empty() {
-                    return;
+                    return Ok(());
                 }
                 func_state.stack_types.extend_from_slice(new_items);
             }
             OperatorAction::ChangeFrameToExactTypes(ref items) => {
                 let last_block = func_state.blocks.last_mut().unwrap();
                 let keep = last_block.stack_starts_at;
                 func_state.stack_types.truncate(keep);
                 func_state.stack_types.extend_from_slice(items);
                 last_block.polymorphic_values = None;
             }
             OperatorAction::ChangeFrameAfterSelect(ty) => {
-                OperatorAction::remove_frame_stack_types(func_state, 3);
+                OperatorAction::remove_frame_stack_types(func_state, 3)?;
                 if ty.is_none() {
                     let last_block = func_state.blocks.last_mut().unwrap();
                     assert!(last_block.is_stack_polymorphic());
                     last_block.polymorphic_values =
                         Some(last_block.polymorphic_values.unwrap() + 1);
-                    return;
+                    return Ok(());
                 }
-                func_state.stack_types.push(ty.unwrap())
+                func_state.stack_types.push(ty.unwrap());
             }
             OperatorAction::DeadCode => {
                 let last_block = func_state.blocks.last_mut().unwrap();
                 let keep = last_block.stack_starts_at;
                 func_state.stack_types.truncate(keep);
                 last_block.is_dead_code = true;
                 last_block.polymorphic_values = Some(0);
             }
             OperatorAction::EndFunction => {
                 func_state.end_function = true;
             }
         }
+        Ok(())
     }
 }
 
 pub trait WasmModuleResources {
     fn types(&self) -> &[FuncType];
     fn tables(&self) -> &[TableType];
     fn memories(&self) -> &[MemoryType];
     fn globals(&self) -> &[GlobalType];
@@ -557,17 +564,22 @@ impl OperatorValidator {
             _ => Err("invalid block return type"),
         }
     }
 
     fn check_select(&self, func_state: &FuncState) -> OperatorValidatorResult<Option<Type>> {
         self.check_frame_size(func_state, 3)?;
         let last_block = func_state.last_block();
         Ok(if last_block.is_stack_polymorphic() {
-            match func_state.stack_types.len() - last_block.stack_starts_at {
+            match func_state
+                .stack_types
+                .len()
+                .checked_sub(last_block.stack_starts_at)
+                .ok_or("invalid block signature")?
+            {
                 0 => None,
                 1 => {
                     self.check_operands_1(func_state, Type::I32)?;
                     None
                 }
                 2 => {
                     self.check_operands_1(func_state, Type::I32)?;
                     Some(func_state.stack_types[func_state.stack_types.len() - 2])
@@ -1692,21 +1704,27 @@ impl<'a> ValidatingParser<'a> {
                     Some(OperatorValidator::new(func_type, locals, operator_config));
             }
             ParserState::CodeOperator(ref operator) => {
                 let check = self
                     .current_operator_validator
                     .as_ref()
                     .unwrap()
                     .process_operator(operator, self);
-                if check.is_err() {
-                    self.validation_error = self.create_validation_error(check.err().unwrap());
-                } else {
-                    let action = check.ok().unwrap();
-                    action.update(&mut self.current_operator_validator.as_mut().unwrap().func_state)
+                match check {
+                    Ok(action) => {
+                        if let Err(err) = action.update(
+                            &mut self.current_operator_validator.as_mut().unwrap().func_state,
+                        ) {
+                            self.create_validation_error(err);
+                        }
+                    }
+                    Err(err) => {
+                        self.validation_error = self.create_validation_error(err);
+                    }
                 }
             }
             ParserState::EndFunctionBody => {
                 let check = self
                     .current_operator_validator
                     .as_ref()
                     .unwrap()
                     .process_end_function();